forked from melod1n/fast-messenger
api refactored and cleaned
This commit is contained in:
@@ -1,160 +0,0 @@
|
|||||||
package com.meloda.fast
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.annotation.WorkerThread
|
|
||||||
import com.meloda.fast.concurrent.EventInfo
|
|
||||||
import com.meloda.fast.concurrent.TaskManager
|
|
||||||
import com.meloda.fast.api.VKApiKeys
|
|
||||||
import com.meloda.fast.api.model.VKMessage
|
|
||||||
import com.meloda.fast.api.VKUtil
|
|
||||||
import org.json.JSONArray
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
object VKLongPollParser {
|
|
||||||
|
|
||||||
|
|
||||||
@WorkerThread
|
|
||||||
fun parse(updates: JSONArray) {
|
|
||||||
if (updates.length() == 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i in 0 until updates.length()) {
|
|
||||||
val item = updates.optJSONArray(i)
|
|
||||||
when (item.optInt(0)) {
|
|
||||||
2 -> messageSetFlags(item)
|
|
||||||
3 -> messageClearFlags(item)
|
|
||||||
4 -> messageEvent(item)
|
|
||||||
5 -> messageEdit(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun parseEvent(eventInfo: EventInfo<*>, onMessagesListener: OnMessagesListener) {
|
|
||||||
when (eventInfo.key) {
|
|
||||||
VKApiKeys.NEW_MESSAGE.value -> onMessagesListener.onNewMessage(eventInfo.data as VKMessage)
|
|
||||||
VKApiKeys.EDIT_MESSAGE.value -> onMessagesListener.onEditMessage(eventInfo.data as VKMessage)
|
|
||||||
VKApiKeys.RESTORE_MESSAGE.value -> onMessagesListener.onRestoredMessage(eventInfo.data as VKMessage)
|
|
||||||
VKApiKeys.DELETE_MESSAGE.value -> {
|
|
||||||
val array = eventInfo.data as Array<Int>
|
|
||||||
onMessagesListener.onDeleteMessage(array[0], array[1])
|
|
||||||
}
|
|
||||||
VKApiKeys.READ_MESSAGE.value -> {
|
|
||||||
val array = eventInfo.data as Array<Int>
|
|
||||||
onMessagesListener.onReadMessage(array[0], array[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val TAG = "VKLongPollParser"
|
|
||||||
|
|
||||||
private fun messageEvent(item: JSONArray) {
|
|
||||||
val message = VKUtil.parseLongPollMessage(item)
|
|
||||||
|
|
||||||
TaskManager.execute {
|
|
||||||
if (message.isFromUser()) {
|
|
||||||
// VKUtil.searchUser(message.fromId)?.let { message.fromUser = it }
|
|
||||||
} else {
|
|
||||||
// VKUtil.searchGroup(message.fromId)?.let { message.fromGroup = it }
|
|
||||||
}
|
|
||||||
|
|
||||||
// MemoryCache.getConversationById(message.peerId)?.let {
|
|
||||||
// it.lastMessage = message
|
|
||||||
// it.lastMessageId = message.messageId
|
|
||||||
//
|
|
||||||
// MemoryCache.put(it)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// MemoryCache.put(message)
|
|
||||||
|
|
||||||
val info = EventInfo(VKApiKeys.NEW_MESSAGE.name, message)
|
|
||||||
|
|
||||||
sendEvent(info)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun messageEdit(item: JSONArray) {
|
|
||||||
val message = VKUtil.parseLongPollMessage(item)
|
|
||||||
val info = EventInfo(VKApiKeys.EDIT_MESSAGE.name, message)
|
|
||||||
|
|
||||||
// MemoryCache.put(message)
|
|
||||||
|
|
||||||
sendEvent(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun messageDelete(item: JSONArray) {
|
|
||||||
val messageId = item.optInt(1)
|
|
||||||
val peerId = item.optInt(3)
|
|
||||||
val info = EventInfo(VKApiKeys.DELETE_MESSAGE.name, arrayOf(peerId, messageId))
|
|
||||||
|
|
||||||
// MemoryCache.deleteMessage(messageId)
|
|
||||||
|
|
||||||
sendEvent(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun messageRestored(item: JSONArray) {
|
|
||||||
val message = VKUtil.parseLongPollMessage(item)
|
|
||||||
val info = EventInfo(VKApiKeys.RESTORE_MESSAGE.name, message)
|
|
||||||
|
|
||||||
// MemoryCache.put(message)
|
|
||||||
|
|
||||||
sendEvent(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun messageRead(item: JSONArray) {
|
|
||||||
val messageId = item.optInt(1)
|
|
||||||
val peerId = item.optInt(3)
|
|
||||||
val info = EventInfo(VKApiKeys.READ_MESSAGE.name, arrayOf(peerId, messageId))
|
|
||||||
|
|
||||||
// MemoryCache.edit(MemoryCache.getMessageById(messageId)?.apply { isRead = true })
|
|
||||||
|
|
||||||
sendEvent(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun messageClearFlags(item: JSONArray) {
|
|
||||||
val id = item.optInt(1)
|
|
||||||
val flags = item.optInt(2)
|
|
||||||
if (VKUtil.isMessageHasFlag(flags, "cancel_spam")) {
|
|
||||||
Log.i(TAG, "Message with id $id: Not spam")
|
|
||||||
}
|
|
||||||
if (VKUtil.isMessageHasFlag(flags, "deleted")) {
|
|
||||||
messageRestored(item)
|
|
||||||
}
|
|
||||||
if (VKUtil.isMessageHasFlag(flags, "important")) {
|
|
||||||
Log.i(TAG, "Message with id $id: Not Important")
|
|
||||||
}
|
|
||||||
if (VKUtil.isMessageHasFlag(flags, "unread")) {
|
|
||||||
messageRead(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun messageSetFlags(item: JSONArray) {
|
|
||||||
val id = item.optInt(1)
|
|
||||||
val flags = item.optInt(2)
|
|
||||||
if (VKUtil.isMessageHasFlag(flags, "delete_for_all")) {
|
|
||||||
messageDelete(item)
|
|
||||||
}
|
|
||||||
if (VKUtil.isMessageHasFlag(flags, "deleted")) {
|
|
||||||
messageDelete(item)
|
|
||||||
}
|
|
||||||
if (VKUtil.isMessageHasFlag(flags, "spam")) {
|
|
||||||
Log.i(TAG, "Message with id $id: Spam")
|
|
||||||
}
|
|
||||||
if (VKUtil.isMessageHasFlag(flags, "important")) {
|
|
||||||
Log.i(TAG, "Message with id $id: Important")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun sendEvent(eventInfo: EventInfo<*>) {
|
|
||||||
TaskManager.sendEvent(eventInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface OnMessagesListener {
|
|
||||||
fun onNewMessage(message: VKMessage)
|
|
||||||
fun onEditMessage(message: VKMessage)
|
|
||||||
fun onRestoredMessage(message: VKMessage)
|
|
||||||
fun onDeleteMessage(peerId: Int, messageId: Int)
|
|
||||||
fun onReadMessage(peerId: Int, messageId: Int)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.meloda.fast.api
|
|
||||||
|
|
||||||
interface OnResponseListener<T> {
|
|
||||||
|
|
||||||
fun onResponse(response: T)
|
|
||||||
|
|
||||||
fun onError(t: Throwable)
|
|
||||||
|
|
||||||
}
|
|
||||||
+1
-2
@@ -1,6 +1,5 @@
|
|||||||
package com.meloda.fast
|
package com.meloda.fast.api
|
||||||
|
|
||||||
import android.text.TextUtils
|
|
||||||
import com.meloda.fast.common.AppGlobal
|
import com.meloda.fast.common.AppGlobal
|
||||||
|
|
||||||
object UserConfig {
|
object UserConfig {
|
||||||
@@ -1,506 +0,0 @@
|
|||||||
package com.meloda.fast.api
|
|
||||||
|
|
||||||
import android.os.Handler
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.annotation.WorkerThread
|
|
||||||
import com.meloda.fast.BuildConfig
|
|
||||||
import com.meloda.fast.api.method.MessageMethodSetter
|
|
||||||
import com.meloda.fast.api.method.MethodSetter
|
|
||||||
import com.meloda.fast.api.method.UserMethodSetter
|
|
||||||
import com.meloda.fast.api.network.ErrorCodes
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.asFlow
|
|
||||||
import org.json.JSONArray
|
|
||||||
import org.json.JSONObject
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
import kotlin.coroutines.resume
|
|
||||||
import kotlin.coroutines.resumeWithException
|
|
||||||
import kotlin.coroutines.suspendCoroutine
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
object VKApi {
|
|
||||||
|
|
||||||
private const val TAG = "VKM:VKApi"
|
|
||||||
|
|
||||||
const val BASE_URL = "https://api.vk.com/method/"
|
|
||||||
|
|
||||||
const val API_VERSION = "5.132"
|
|
||||||
|
|
||||||
var language: String = ""
|
|
||||||
var token: String = ""
|
|
||||||
|
|
||||||
private lateinit var handler: Handler
|
|
||||||
|
|
||||||
fun init(language: String, token: String, handler: Handler) {
|
|
||||||
VKApi.language = language
|
|
||||||
VKApi.token = token
|
|
||||||
VKApi.handler = handler
|
|
||||||
}
|
|
||||||
|
|
||||||
@WorkerThread
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
fun <T> execute(url: String, cls: Class<T>?): ArrayList<T>? {
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.w(TAG, "url: $url")
|
|
||||||
}
|
|
||||||
|
|
||||||
val buffer = com.meloda.fast.net.HttpRequest[url].asString()
|
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.i(TAG, "response: $buffer")
|
|
||||||
}
|
|
||||||
|
|
||||||
val json = JSONObject(buffer)
|
|
||||||
|
|
||||||
try {
|
|
||||||
checkError(json, url)
|
|
||||||
} catch (ex: VKException) {
|
|
||||||
throw ex
|
|
||||||
// if (ex.code == ErrorCodes.TOO_MANY_REQUESTS) {
|
|
||||||
// Timer().schedule(object : TimerTask() {
|
|
||||||
// override fun run() {
|
|
||||||
// execute(url, cls)
|
|
||||||
// }
|
|
||||||
// }, 1000)
|
|
||||||
// } else throw ex
|
|
||||||
}
|
|
||||||
|
|
||||||
when (cls) {
|
|
||||||
null -> return null
|
|
||||||
|
|
||||||
com.meloda.fast.api.model.VKLongPollServer::class.java -> {
|
|
||||||
json.optJSONObject("response")?.let {
|
|
||||||
return arrayListOf(com.meloda.fast.api.model.VKLongPollServer(it)) as ArrayList<T>?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean::class.java -> {
|
|
||||||
val value = json.optInt("response") == 1
|
|
||||||
return arrayListOf(value) as ArrayList<T>?
|
|
||||||
}
|
|
||||||
|
|
||||||
Long::class.java -> {
|
|
||||||
val value = json.optLong("response")
|
|
||||||
return arrayListOf(value) as ArrayList<T>?
|
|
||||||
}
|
|
||||||
|
|
||||||
Int::class.java -> {
|
|
||||||
val value = json.optInt("response")
|
|
||||||
return arrayListOf(value) as ArrayList<T>?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val response = json.opt("response") ?: return null
|
|
||||||
|
|
||||||
val array = optItems(json) ?: return null
|
|
||||||
val models = ArrayList<T>(array.length())
|
|
||||||
|
|
||||||
when (cls) {
|
|
||||||
com.meloda.fast.api.model.VKUser::class.java -> {
|
|
||||||
json.optJSONObject("response")?.let { r ->
|
|
||||||
com.meloda.fast.api.model.VKUser.friendsCount = r.optInt("count")
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i in 0 until array.length()) {
|
|
||||||
models.add(com.meloda.fast.api.model.VKUser(array.optJSONObject(i)) as T)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
com.meloda.fast.api.model.VKMessage::class.java -> {
|
|
||||||
response as JSONObject
|
|
||||||
|
|
||||||
if (url.contains("messages.getHistory")) {
|
|
||||||
com.meloda.fast.api.model.VKMessage.lastHistoryCount = response.optInt("count")
|
|
||||||
|
|
||||||
response.optJSONArray("profiles")?.let {
|
|
||||||
val profiles = arrayListOf<com.meloda.fast.api.model.VKUser>()
|
|
||||||
|
|
||||||
for (j in 0 until it.length()) {
|
|
||||||
profiles.add(com.meloda.fast.api.model.VKUser(it.optJSONObject(j)))
|
|
||||||
}
|
|
||||||
|
|
||||||
com.meloda.fast.api.model.VKMessage.profiles = profiles
|
|
||||||
}
|
|
||||||
|
|
||||||
response.optJSONArray("groups")?.let {
|
|
||||||
val groups = arrayListOf<com.meloda.fast.api.model.VKGroup>()
|
|
||||||
|
|
||||||
for (j in 0 until it.length()) {
|
|
||||||
groups.add(com.meloda.fast.api.model.VKGroup(it.optJSONObject(j)))
|
|
||||||
}
|
|
||||||
|
|
||||||
com.meloda.fast.api.model.VKMessage.groups = groups
|
|
||||||
}
|
|
||||||
|
|
||||||
response.optJSONArray("conversations")?.let {
|
|
||||||
val conversations = arrayListOf<com.meloda.fast.api.model.VKConversation>()
|
|
||||||
|
|
||||||
for (j in 0 until it.length()) {
|
|
||||||
conversations.add(
|
|
||||||
com.meloda.fast.api.model.VKConversation(
|
|
||||||
it.optJSONObject(
|
|
||||||
j
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
com.meloda.fast.api.model.VKMessage.conversations = conversations
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i in 0 until array.length()) {
|
|
||||||
var source = array.optJSONObject(i)
|
|
||||||
if (source.has("message")) {
|
|
||||||
source = source.optJSONObject("message")
|
|
||||||
}
|
|
||||||
|
|
||||||
val message = com.meloda.fast.api.model.VKMessage(source)
|
|
||||||
models.add(message as T)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
com.meloda.fast.api.model.VKGroup::class.java -> {
|
|
||||||
for (i in 0 until array.length()) {
|
|
||||||
models.add(com.meloda.fast.api.model.VKGroup(array.optJSONObject(i)) as T)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
com.meloda.fast.api.model.VKModel::class.java -> {
|
|
||||||
if (url.contains("messages.getHistoryAttachments")) {
|
|
||||||
return com.meloda.fast.api.model.VKAttachments.parse(array) as ArrayList<T>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
com.meloda.fast.api.model.VKConversation::class.java -> {
|
|
||||||
if (url.contains("getConversationsById")) {
|
|
||||||
for (i in 0 until array.length()) {
|
|
||||||
val source = array.optJSONObject(i)
|
|
||||||
models.add(com.meloda.fast.api.model.VKConversation(source) as T)
|
|
||||||
}
|
|
||||||
|
|
||||||
return models
|
|
||||||
}
|
|
||||||
|
|
||||||
json.optJSONObject("response")?.let { r ->
|
|
||||||
com.meloda.fast.api.model.VKConversation.conversationsCount = r.optInt("count")
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i in 0 until array.length()) {
|
|
||||||
response as JSONObject
|
|
||||||
|
|
||||||
val source = array.optJSONObject(i)
|
|
||||||
val oConversation = source.optJSONObject("conversation") ?: return null
|
|
||||||
val oLastMessage = source.optJSONObject("last_message") ?: return null
|
|
||||||
|
|
||||||
val conversation = com.meloda.fast.api.model.VKConversation(oConversation).also {
|
|
||||||
it.lastMessage = com.meloda.fast.api.model.VKMessage(oLastMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
response.optJSONArray("profiles")?.let {
|
|
||||||
val profiles = arrayListOf<com.meloda.fast.api.model.VKUser>()
|
|
||||||
|
|
||||||
for (j in 0 until it.length()) {
|
|
||||||
profiles.add(com.meloda.fast.api.model.VKUser(it.optJSONObject(j)))
|
|
||||||
}
|
|
||||||
|
|
||||||
com.meloda.fast.api.model.VKConversation.profiles = profiles
|
|
||||||
}
|
|
||||||
|
|
||||||
response.optJSONArray("groups")?.let {
|
|
||||||
val groups = arrayListOf<com.meloda.fast.api.model.VKGroup>()
|
|
||||||
|
|
||||||
for (j in 0 until it.length()) {
|
|
||||||
groups.add(com.meloda.fast.api.model.VKGroup(it.optJSONObject(j)))
|
|
||||||
}
|
|
||||||
|
|
||||||
com.meloda.fast.api.model.VKConversation.groups = groups
|
|
||||||
}
|
|
||||||
|
|
||||||
models.add(conversation as T)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return models
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <E> execute(url: String, cls: Class<E>, listener: OnResponseListener<E>?) {
|
|
||||||
com.meloda.fast.concurrent.TaskManager.execute {
|
|
||||||
try {
|
|
||||||
val models = execute(url, cls) ?: return@execute
|
|
||||||
|
|
||||||
// listener?.onResponse(models)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
listener?.onError(e)
|
|
||||||
// it.resumeWithException(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun <E> suspendExecute(url: String, cls: Class<E>): Flow<E> {
|
|
||||||
return suspendCoroutine {
|
|
||||||
try {
|
|
||||||
val models = execute(url, cls)?.asFlow() ?: return@suspendCoroutine
|
|
||||||
|
|
||||||
it.resume(models)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
it.resumeWithException(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <E> executeArray(url: String, cls: Class<E>, listener: OnResponseListener<ArrayList<E>>) {
|
|
||||||
com.meloda.fast.concurrent.TaskManager.execute {
|
|
||||||
try {
|
|
||||||
val models = execute(url, cls)
|
|
||||||
|
|
||||||
handler.post { listener.onResponse(models as ArrayList<E>) }
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
|
|
||||||
listener.onError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun optItems(source: JSONObject): JSONArray? {
|
|
||||||
val response = source.opt("response")
|
|
||||||
|
|
||||||
return when (response) {
|
|
||||||
is JSONArray -> response
|
|
||||||
is JSONObject -> response.optJSONArray("items")
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkError(json: JSONObject, url: String) {
|
|
||||||
if (json.has("error")) {
|
|
||||||
val error = json.optJSONObject("error") ?: return
|
|
||||||
|
|
||||||
val code = error.optInt("error_code", -1)
|
|
||||||
val message = error.optString("error_msg", "")
|
|
||||||
// val e = VKException(url, message, code)
|
|
||||||
|
|
||||||
//TODO: add checking invalid session
|
|
||||||
if (code == 5 && message.contains("invalid session")) {
|
|
||||||
// context?.startActivity(Intent(context, DropUserDataActivity::class.java).apply {
|
|
||||||
// addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (code == ErrorCodes.CAPTCHA_NEEDED) {
|
|
||||||
// e.captchaImg = error.optString("captcha_img")
|
|
||||||
// e.captchaSid = error.optString("captcha_sid")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (code == ErrorCodes.VALIDATION_REQUIRED) {
|
|
||||||
// e.redirectUri = error.optString("redirect_uri")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun users(): VKUsers {
|
|
||||||
return VKUsers()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun friends(): VKFriends {
|
|
||||||
return VKFriends()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun messages(): VKMessages {
|
|
||||||
return VKMessages()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun groups(): VKGroups {
|
|
||||||
return VKGroups()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun account(): VKAccounts {
|
|
||||||
return VKAccounts()
|
|
||||||
}
|
|
||||||
|
|
||||||
class VKFriends {
|
|
||||||
fun get(): MethodSetter {
|
|
||||||
return MethodSetter("friends.get")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VKUsers {
|
|
||||||
fun get(): UserMethodSetter {
|
|
||||||
return UserMethodSetter("users.get")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VKMessages {
|
|
||||||
fun get(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.get")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getConversations(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.getConversations")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getConversationsById(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.getConversationsById")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getById(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.getById")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun search(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.search")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getHistory(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.getHistory")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getHistoryAttachments(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.getHistoryAttachments")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun send(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.send")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendSticker(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.sendSticker")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun delete(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.delete")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteDialog(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.deleteDialog")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun restore(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.restore")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun markAsRead(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.markAsRead")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun markAsImportant(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.markAsImportant")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLongPollServer(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.getLongPollServer")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns updates in user's private messages.
|
|
||||||
* To speed up handling of private messages,
|
|
||||||
* it can be useful to cache previously loaded messages on
|
|
||||||
* a user's mobile device/desktop, to prevent re-receipt at each call.
|
|
||||||
* With this method, you can synchronize a local copy of
|
|
||||||
* the message list with the actual version.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Result:
|
|
||||||
* Returns an object that contains the following fields:
|
|
||||||
* 1 — history: An array similar to updates field returned
|
|
||||||
* from the Long Poll server,
|
|
||||||
* with these exceptions:
|
|
||||||
* - For events with code 4 (addition of a new message),
|
|
||||||
* there are no fields except the first three.
|
|
||||||
* - There are no events with codes 8, 9 (friend goes online/offline)
|
|
||||||
* or with codes 61, 62 (typing during conversation/chat).
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* 2 — messages: An array of private message objects that were found
|
|
||||||
* among events with code 4 (addition of a new message)
|
|
||||||
* from the history field.
|
|
||||||
* Each object of message contains a set of fields described here.
|
|
||||||
* The first array element is the total number of messages
|
|
||||||
*/
|
|
||||||
fun getLongPollHistory(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.getLongPollHistory")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getChat(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.getChat")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createChat(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.createChat")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun editChat(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.editChat")
|
|
||||||
}
|
|
||||||
|
|
||||||
val chatUsers: MessageMethodSetter
|
|
||||||
get() = MessageMethodSetter("messages.getChatUsers")
|
|
||||||
|
|
||||||
fun setActivity(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.setActivity").type(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addChatUser(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.addChatUser")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeChatUser(): MessageMethodSetter {
|
|
||||||
return MessageMethodSetter("messages.removeChatUser")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VKGroups {
|
|
||||||
fun getById(): MethodSetter {
|
|
||||||
return MethodSetter("groups.getById")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun join(): MethodSetter {
|
|
||||||
return MethodSetter("groups.join")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VKAccounts {
|
|
||||||
fun setOffline(): MethodSetter {
|
|
||||||
return MethodSetter("account.setOffline")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setOnline(): MethodSetter {
|
|
||||||
return MethodSetter("account.setOnline")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SuccessCallback<E>(
|
|
||||||
private val listener: OnResponseListener<E>?,
|
|
||||||
private val response: E
|
|
||||||
) : Runnable {
|
|
||||||
override fun run() {
|
|
||||||
listener?.onResponse(response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SuccessArrayCallback<E>(
|
|
||||||
private val listener: OnResponseListener<ArrayList<E>>?,
|
|
||||||
private val response: ArrayList<E>
|
|
||||||
) : Runnable {
|
|
||||||
override fun run() {
|
|
||||||
listener?.onResponse(response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ErrorCallback<E>(
|
|
||||||
private val listener: OnResponseListener<E>?,
|
|
||||||
private val exception: Exception
|
|
||||||
) : Runnable {
|
|
||||||
override fun run() {
|
|
||||||
listener?.onError(exception)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package com.meloda.fast.api
|
|
||||||
|
|
||||||
enum class VKApiKeys(val value: String) {
|
|
||||||
READ_MESSAGE("_read_message"),
|
|
||||||
RESTORE_MESSAGE("_restore_message"),
|
|
||||||
NEW_MESSAGE("_new_message"),
|
|
||||||
EDIT_MESSAGE("_edit_message"),
|
|
||||||
DELETE_MESSAGE("_delete_message"),
|
|
||||||
|
|
||||||
UPDATE_MESSAGE("_update_message"),
|
|
||||||
UPDATE_CONVERSATION("_update_conversation"),
|
|
||||||
UPDATE_USER("_update_user"),
|
|
||||||
UPDATE_GROUP("_update_group")
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
package com.meloda.fast.api
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import com.meloda.fast.BuildConfig
|
|
||||||
import com.meloda.fast.UserConfig
|
|
||||||
import java.net.URLEncoder
|
|
||||||
|
|
||||||
object VKAuth {
|
|
||||||
|
|
||||||
private const val TAG = "VKM.VKAuth"
|
|
||||||
|
|
||||||
object GrantType {
|
|
||||||
const val PASSWORD = "password"
|
|
||||||
}
|
|
||||||
|
|
||||||
const val scope = "notify," +
|
|
||||||
"friends," +
|
|
||||||
"photos," +
|
|
||||||
"audio," +
|
|
||||||
"video," +
|
|
||||||
"docs," +
|
|
||||||
"status," +
|
|
||||||
"notes," +
|
|
||||||
"pages," +
|
|
||||||
"wall," +
|
|
||||||
"groups," +
|
|
||||||
"messages," +
|
|
||||||
"offline," +
|
|
||||||
"notifications"
|
|
||||||
|
|
||||||
private const val redirectUrl = "https://oauth.vk.com/blank.html"
|
|
||||||
|
|
||||||
fun getDirectAuthUrl(
|
|
||||||
login: String,
|
|
||||||
password: String,
|
|
||||||
twoFa: Boolean = false,
|
|
||||||
twoFaCode: String = "",
|
|
||||||
captcha: Pair<String, String>? = null
|
|
||||||
) = "https://oauth.vk.com/token?" +
|
|
||||||
"grant_type=password&" +
|
|
||||||
"client_id=${VKConstants.VK_APP_ID}&" +
|
|
||||||
"client_secret=${VKConstants.VK_SECRET}&" +
|
|
||||||
"username=$login&" +
|
|
||||||
"password=$password&" +
|
|
||||||
"scope=$scope&" +
|
|
||||||
"2fa_supported=1&" +
|
|
||||||
"force_sms=${if (twoFa) "1" else "0"}" +
|
|
||||||
(if (twoFa) "code=$twoFaCode" else "") +
|
|
||||||
(if (captcha == null) "" else "&captcha_sid=${captcha.first}&captcha_key=${captcha.second}") +
|
|
||||||
"&v=${URLEncoder.encode(VKApi.API_VERSION, "utf-8")}"
|
|
||||||
|
|
||||||
fun getSendSmsCodeUrl(sid: String) = "https://api.vk.com/method/auth.validatePhone?" +
|
|
||||||
"sid=$sid&" +
|
|
||||||
"&v=${URLEncoder.encode(VKApi.API_VERSION, "utf-8")}"
|
|
||||||
|
|
||||||
fun getOAuthUrl(settings: String) = "https://oauth.vk.com/authorize?" +
|
|
||||||
"client_id=${UserConfig.FAST_APP_ID}&" +
|
|
||||||
"display=mobile&" +
|
|
||||||
"scope=$settings&" +
|
|
||||||
"redirect_uri=${
|
|
||||||
URLEncoder.encode(
|
|
||||||
redirectUrl,
|
|
||||||
"utf-8"
|
|
||||||
)
|
|
||||||
}&" +
|
|
||||||
"response_type=token&" +
|
|
||||||
"v=${URLEncoder.encode(VKApi.API_VERSION, "utf-8")}"
|
|
||||||
|
|
||||||
fun parseRedirectUrl(url: String): Pair<String, Int> {
|
|
||||||
val accessToken = VKUtil.extractPattern(url, "access_token=(.*?)&") ?: ""
|
|
||||||
val userId = VKUtil.extractPattern(url, "user_id=(\\d*)")?.toIntOrNull() ?: -1
|
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.i(TAG, "access_token=$accessToken")
|
|
||||||
Log.i(TAG, "user_id=$userId")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (accessToken.isEmpty() || userId == -1) throw Exception(
|
|
||||||
"Failed to parse redirect url: $url"
|
|
||||||
)
|
|
||||||
|
|
||||||
return accessToken to userId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,30 @@ object VKConstants {
|
|||||||
const val USER_FIELDS =
|
const val USER_FIELDS =
|
||||||
"photo_50,photo_100,photo_200,status,screen_name,online,online_mobile,last_seen,verified,sex"
|
"photo_50,photo_100,photo_200,status,screen_name,online,online_mobile,last_seen,verified,sex"
|
||||||
|
|
||||||
|
|
||||||
|
const val API_VERSION = "5.132"
|
||||||
const val VK_APP_ID = "2274003"
|
const val VK_APP_ID = "2274003"
|
||||||
const val VK_SECRET = "hHbZxrka2uZ6jB1inYsH"
|
const val VK_SECRET = "hHbZxrka2uZ6jB1inYsH"
|
||||||
|
|
||||||
|
|
||||||
|
object Auth {
|
||||||
|
const val SCOPE = "notify," +
|
||||||
|
"friends," +
|
||||||
|
"photos," +
|
||||||
|
"audio," +
|
||||||
|
"video," +
|
||||||
|
"docs," +
|
||||||
|
"status," +
|
||||||
|
"notes," +
|
||||||
|
"pages," +
|
||||||
|
"wall," +
|
||||||
|
"groups," +
|
||||||
|
"messages," +
|
||||||
|
"offline," +
|
||||||
|
"notifications"
|
||||||
|
|
||||||
|
object GrantType {
|
||||||
|
const val PASSWORD = "password"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,8 +7,8 @@ import org.json.JSONArray
|
|||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.regex.Pattern
|
|
||||||
|
|
||||||
|
// TODO: 8/31/2021 review
|
||||||
object VKUtil {
|
object VKUtil {
|
||||||
|
|
||||||
private const val TAG = "VKUtil"
|
private const val TAG = "VKUtil"
|
||||||
@@ -23,26 +23,6 @@ object VKUtil {
|
|||||||
return throwable.error == VKErrors.NEED_CAPTCHA
|
return throwable.error == VKErrors.NEED_CAPTCHA
|
||||||
}
|
}
|
||||||
|
|
||||||
fun extractValidationSid(throwable: Throwable): String? {
|
|
||||||
if (throwable !is VKException) return null
|
|
||||||
return throwable.json?.optString("validation_sid")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun extractPattern(string: String, pattern: String): String? {
|
|
||||||
val p = Pattern.compile(pattern)
|
|
||||||
val m = p.matcher(string)
|
|
||||||
return if (!m.find()) null else m.toMatchResult().group(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val pattern_string_profile_id = "^(id)?(\\d{1,10})$"
|
|
||||||
|
|
||||||
private val pattern_profile_id = Pattern.compile(pattern_string_profile_id)
|
|
||||||
|
|
||||||
fun parseProfileId(text: String): String? {
|
|
||||||
val m = pattern_profile_id.matcher(text)
|
|
||||||
return if (!m.find()) null else m.group(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sortMessagesByDate(
|
fun sortMessagesByDate(
|
||||||
values: ArrayList<VKMessage>,
|
values: ArrayList<VKMessage>,
|
||||||
firstOnTop: Boolean
|
firstOnTop: Boolean
|
||||||
@@ -292,7 +272,7 @@ object VKUtil {
|
|||||||
message.text = text
|
message.text = text
|
||||||
|
|
||||||
// val fromId =
|
// val fromId =
|
||||||
// if (isMessageHasFlag(flags, "outbox")) com.meloda.fast.UserConfig.userId
|
// if (isMessageHasFlag(flags, "outbox")) com.meloda.fast.api.UserConfig.userId
|
||||||
// else peerId
|
// else peerId
|
||||||
|
|
||||||
message.fromId = peerId
|
message.fromId = peerId
|
||||||
@@ -357,7 +337,7 @@ object VKUtil {
|
|||||||
val editTime = array.optInt(10)
|
val editTime = array.optInt(10)
|
||||||
message.editTime = editTime
|
message.editTime = editTime
|
||||||
|
|
||||||
// val out = fromId == com.meloda.fast.UserConfig.userId
|
// val out = fromId == com.meloda.fast.api.UserConfig.userId
|
||||||
// message.isOut = out
|
// message.isOut = out
|
||||||
//
|
//
|
||||||
// if (message.isFromUser()) {
|
// if (message.isFromUser()) {
|
||||||
|
|||||||
@@ -1,205 +0,0 @@
|
|||||||
package com.meloda.fast.api.method
|
|
||||||
|
|
||||||
import com.meloda.fast.util.ArrayUtils
|
|
||||||
|
|
||||||
class MessageMethodSetter(name: String) : MethodSetter(name) {
|
|
||||||
|
|
||||||
fun out(value: Boolean): MessageMethodSetter {
|
|
||||||
put("out", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun timeOffset(value: Int): MessageMethodSetter {
|
|
||||||
put("time_offset", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun filters(value: Int): MessageMethodSetter {
|
|
||||||
put("filters", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun previewLength(value: Int): MessageMethodSetter {
|
|
||||||
put("preview_length", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun lastMessageId(value: Int): MessageMethodSetter {
|
|
||||||
put("last_message_id", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun unread(value: Boolean): MessageMethodSetter {
|
|
||||||
put("unread", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun messageIds(vararg ids: Int): MessageMethodSetter {
|
|
||||||
put("message_ids", ArrayUtils.asString(ids))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun messageIds(ids: ArrayList<Int>): MessageMethodSetter {
|
|
||||||
put("message_ids", ArrayUtils.asString(ids))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun q(query: String): MessageMethodSetter {
|
|
||||||
put("q", query)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun startMessageId(id: Int): MessageMethodSetter {
|
|
||||||
put("start_message_id", id)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun peerId(value: Int): MessageMethodSetter {
|
|
||||||
put("peer_id", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun peerIds(vararg values: Int): MessageMethodSetter {
|
|
||||||
put("peer_ids", com.meloda.fast.util.ArrayUtils.asString(values))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reversed(value: Boolean): MessageMethodSetter {
|
|
||||||
put("rev", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun domain(value: String): MessageMethodSetter {
|
|
||||||
put("domain", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun chatId(value: Int): MessageMethodSetter {
|
|
||||||
put("chat_id", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun message(message: String): MessageMethodSetter {
|
|
||||||
put("message", message)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun randomId(value: Int): MessageMethodSetter {
|
|
||||||
put("random_id", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun lat(lat: Double): MessageMethodSetter {
|
|
||||||
put("lat", lat)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun longitude(value: Long): MessageMethodSetter {
|
|
||||||
put("LONG", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun attachment(attachments: Collection<String>): MessageMethodSetter {
|
|
||||||
put("attachment", com.meloda.fast.util.ArrayUtils.asString(attachments))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun attachment(vararg attachments: String): MessageMethodSetter {
|
|
||||||
put("attachment", com.meloda.fast.util.ArrayUtils.asString(*attachments))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun forwardMessages(ids: Collection<String>): MessageMethodSetter {
|
|
||||||
put("forward_messages", com.meloda.fast.util.ArrayUtils.asString(ids))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun forwardMessages(vararg ids: Int): MessageMethodSetter {
|
|
||||||
put("forward_messages", com.meloda.fast.util.ArrayUtils.asString(ids))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun stickerId(value: Int): MessageMethodSetter {
|
|
||||||
put("sticker_id", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun messageId(value: Int): MessageMethodSetter {
|
|
||||||
put("message_id", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun important(value: Boolean): MessageMethodSetter {
|
|
||||||
put("important", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ts(value: Long): MessageMethodSetter {
|
|
||||||
put("ts", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun pts(value: Int): MessageMethodSetter {
|
|
||||||
put("pts", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun msgsLimit(limit: Int): MessageMethodSetter {
|
|
||||||
put("msgs_limit", limit)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onlines(onlines: Boolean): MessageMethodSetter {
|
|
||||||
put("onlines", onlines)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun maxMsgId(id: Int): MessageMethodSetter {
|
|
||||||
put("max_msg_id", id)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun chatIds(vararg ids: Int): MessageMethodSetter {
|
|
||||||
put("max_msg_id", com.meloda.fast.util.ArrayUtils.asString(ids))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun chatIds(ids: Collection<Int>): MessageMethodSetter {
|
|
||||||
put("max_msg_id", com.meloda.fast.util.ArrayUtils.asString(ids))
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun title(title: String): MessageMethodSetter {
|
|
||||||
put("title", title)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun type(typing: Boolean): MessageMethodSetter {
|
|
||||||
if (typing) {
|
|
||||||
put("type", "typing")
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun mediaType(type: String): MessageMethodSetter {
|
|
||||||
put("media_type", type)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun photoSizes(value: Boolean): MessageMethodSetter {
|
|
||||||
return put("photo_sizes", value) as MessageMethodSetter
|
|
||||||
}
|
|
||||||
|
|
||||||
fun filter(value: String): MessageMethodSetter {
|
|
||||||
return put("filter", value) as MessageMethodSetter
|
|
||||||
}
|
|
||||||
|
|
||||||
fun extended(value: Boolean): MessageMethodSetter {
|
|
||||||
return put("extended", value) as MessageMethodSetter
|
|
||||||
}
|
|
||||||
|
|
||||||
fun markConversationAsRead(asRead: Boolean): MessageMethodSetter {
|
|
||||||
put("mark_conversation_as_read", asRead)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,169 +0,0 @@
|
|||||||
package com.meloda.fast.api.method
|
|
||||||
|
|
||||||
import android.util.ArrayMap
|
|
||||||
import android.util.Log
|
|
||||||
import com.meloda.fast.BuildConfig
|
|
||||||
import com.meloda.fast.api.OnResponseListener
|
|
||||||
import com.meloda.fast.api.VKApi
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import java.net.URLEncoder
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
open class MethodSetter(private val name: String) {
|
|
||||||
|
|
||||||
private val params: ArrayMap<String, String> = ArrayMap()
|
|
||||||
|
|
||||||
fun put(key: String, value: Any): MethodSetter {
|
|
||||||
params[key] = value.toString()
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun put(key: String, value: String): MethodSetter {
|
|
||||||
params[key] = value
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun put(key: String, value: Int): MethodSetter {
|
|
||||||
params[key] = value.toString()
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun put(key: String, value: Long): MethodSetter {
|
|
||||||
params[key] = value.toString()
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun put(key: String, value: Boolean): MethodSetter {
|
|
||||||
params[key] = if (value) "1" else "0"
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getSignedUrl(): String {
|
|
||||||
if (!params.containsKey("access_token")) {
|
|
||||||
params["access_token"] = VKApi.token
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!params.containsKey("v")) {
|
|
||||||
params["v"] = VKApi.API_VERSION
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!params.containsKey("lang")) {
|
|
||||||
params["lang"] = VKApi.language
|
|
||||||
}
|
|
||||||
|
|
||||||
return "${VKApi.BASE_URL}$name?${retrieveParams()}"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun retrieveParams(): String {
|
|
||||||
val builder = StringBuilder()
|
|
||||||
|
|
||||||
for (i in 0 until params.size) {
|
|
||||||
val key = params.keyAt(i)
|
|
||||||
val value = params.valueAt(i)
|
|
||||||
|
|
||||||
if (builder.isNotEmpty()) {
|
|
||||||
builder.append("&")
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append(key)
|
|
||||||
builder.append("=")
|
|
||||||
builder.append(URLEncoder.encode(value, "UTF-8"))
|
|
||||||
}
|
|
||||||
|
|
||||||
val params = builder.toString()
|
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.i("MethodSetter", "retrieved params: $params")
|
|
||||||
}
|
|
||||||
|
|
||||||
return params
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun <E> executeSuspend(cls: Class<E>): Flow<E> {
|
|
||||||
return VKApi.suspendExecute(getSignedUrl(), cls)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <E> execute(cls: Class<E>): ArrayList<E>? {
|
|
||||||
return VKApi.execute(getSignedUrl(), cls)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <E> executeArray(cls: Class<E>, listener: OnResponseListener<ArrayList<E>>) {
|
|
||||||
VKApi.executeArray(getSignedUrl(), cls, listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <E> execute(cls: Class<E>, listener: OnResponseListener<E>?) {
|
|
||||||
VKApi.execute(getSignedUrl(), cls, listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun userId(value: Int): MethodSetter {
|
|
||||||
return put("user_id", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun userIds(vararg ids: Int): MethodSetter {
|
|
||||||
return put("user_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun userIds(ids: ArrayList<Int>): MethodSetter {
|
|
||||||
return put("user_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ownerId(value: Int): MethodSetter {
|
|
||||||
return put("owner_id", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun groupId(value: Int): MethodSetter {
|
|
||||||
return put("group_id", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun groupIds(vararg ids: Int): MethodSetter {
|
|
||||||
return put("group_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun groupIds(ids: ArrayList<Int>): MethodSetter {
|
|
||||||
return put("group_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun fields(values: String): MethodSetter {
|
|
||||||
return put("fields", values)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun count(value: Int): MethodSetter {
|
|
||||||
return put("count", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sort(value: Int): MethodSetter {
|
|
||||||
put("sort", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* hints — сортировать по рейтингу, аналогично тому, как друзья сортируются в разделе Мои друзья
|
|
||||||
* random — возвращает друзей в случайном порядке.
|
|
||||||
* mobile — возвращает выше тех друзей, у которых установлены мобильные приложения.
|
|
||||||
* name — сортировать по имени (долго)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
fun order(value: String): MethodSetter {
|
|
||||||
put("order", value)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun offset(value: Int = 0): MethodSetter {
|
|
||||||
return put("offset", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun nameCase(value: String): MethodSetter {
|
|
||||||
return put("name_case", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun captchaSid(value: String): MethodSetter {
|
|
||||||
return put("captcha_sid", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun captchaKey(value: String): MethodSetter {
|
|
||||||
return put("captcha_key", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package com.meloda.fast.api.method
|
|
||||||
|
|
||||||
class UserMethodSetter(name: String) : MethodSetter(name) {
|
|
||||||
|
|
||||||
fun extended(extended: Boolean): UserMethodSetter {
|
|
||||||
put("extended", extended)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun type(type: String): UserMethodSetter {
|
|
||||||
put("type", type)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun comment(comment: String): UserMethodSetter {
|
|
||||||
put("comment", comment)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun latitude(latitude: Float): UserMethodSetter {
|
|
||||||
put("latitude", latitude)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun longitude(longitude: Float): UserMethodSetter {
|
|
||||||
put("longitude", longitude)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun accuracy(accuracy: Int): UserMethodSetter {
|
|
||||||
put("accuracy", accuracy)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun timeout(timeout: Int): UserMethodSetter {
|
|
||||||
put("timeout", timeout)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun radius(radius: Int): UserMethodSetter {
|
|
||||||
put("radius", radius)
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.meloda.fast.api.network
|
package com.meloda.fast.api.network
|
||||||
|
|
||||||
import com.meloda.fast.api.VKApi
|
import com.meloda.fast.api.VKConstants
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
@@ -9,7 +9,7 @@ class AuthInterceptor : Interceptor {
|
|||||||
|
|
||||||
override fun intercept(chain: Interceptor.Chain): Response {
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
val builder = chain.request().url.newBuilder()
|
val builder = chain.request().url.newBuilder()
|
||||||
.addQueryParameter("v", URLEncoder.encode(VKApi.API_VERSION, "utf-8"))
|
.addQueryParameter("v", URLEncoder.encode(VKConstants.API_VERSION, "utf-8"))
|
||||||
return chain.proceed(chain.request().newBuilder().apply { url(builder.build()) }.build())
|
return chain.proceed(chain.request().newBuilder().apply { url(builder.build()) }.build())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ import com.meloda.fast.base.viewmodel.VKEvent
|
|||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
|
||||||
abstract class BaseVMFragment<VM : BaseViewModel> : BaseFragment {
|
abstract class BaseViewModelFragment<VM : BaseViewModel> : BaseFragment {
|
||||||
|
|
||||||
constructor() : super()
|
constructor() : super()
|
||||||
|
|
||||||
@@ -9,3 +9,5 @@ data class ShowDialogInfoEvent(
|
|||||||
|
|
||||||
object StartProgressEvent : VKEvent()
|
object StartProgressEvent : VKEvent()
|
||||||
object StopProgressEvent : VKEvent()
|
object StopProgressEvent : VKEvent()
|
||||||
|
|
||||||
|
abstract class VKEvent
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package com.meloda.fast.base.viewmodel
|
|
||||||
|
|
||||||
abstract class VKEvent
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
package com.meloda.fast.common
|
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import androidx.fragment.app.FragmentManager
|
|
||||||
import com.meloda.fast.R
|
|
||||||
|
|
||||||
object FragmentSwitcher {
|
|
||||||
|
|
||||||
fun getCurrentFragment(fragmentManager: FragmentManager): Fragment? {
|
|
||||||
val fragments = fragmentManager.fragments
|
|
||||||
|
|
||||||
if (fragments.isEmpty()) throw RuntimeException("FragmentManager's fragments is empty")
|
|
||||||
|
|
||||||
for (fragment in fragments) {
|
|
||||||
if (fragment.isVisible) {
|
|
||||||
return fragment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addFragments(
|
|
||||||
fragmentManager: FragmentManager,
|
|
||||||
containerId: Int,
|
|
||||||
fragments: Collection<Fragment>
|
|
||||||
) {
|
|
||||||
val transaction = fragmentManager.beginTransaction()
|
|
||||||
|
|
||||||
for (fragment in fragments) {
|
|
||||||
transaction.add(containerId, fragment, fragment.javaClass.simpleName)
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction.commitNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showFragment(fragmentManager: FragmentManager, tag: String) {
|
|
||||||
showFragment(fragmentManager, tag, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showFragment(
|
|
||||||
fragmentManager: FragmentManager,
|
|
||||||
tag: String,
|
|
||||||
hideOthers: Boolean,
|
|
||||||
containerId: Int = R.id.fragmentContainer
|
|
||||||
) {
|
|
||||||
val fragments = fragmentManager.fragments
|
|
||||||
|
|
||||||
if (fragments.isEmpty()) throw RuntimeException("FragmentManager's fragments is empty")
|
|
||||||
|
|
||||||
var fragmentToShow: Fragment? = null
|
|
||||||
|
|
||||||
for (fragment in fragments) {
|
|
||||||
if (fragment.tag != null && fragment.tag == tag) {
|
|
||||||
fragmentToShow = fragment
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val transaction = fragmentManager.beginTransaction()
|
|
||||||
|
|
||||||
if (fragmentToShow == null) {
|
|
||||||
throw NullPointerException("Required fragment is null")
|
|
||||||
} else {
|
|
||||||
transaction.show(fragmentToShow)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hideOthers) {
|
|
||||||
for (fragment in fragments) {
|
|
||||||
if (fragment.tag != null && fragment.tag == tag) continue
|
|
||||||
transaction.hide(fragment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction.commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clearFragments(fragmentManager: FragmentManager) {
|
|
||||||
val fragments = fragmentManager.fragments
|
|
||||||
|
|
||||||
if (fragments.isEmpty()) throw RuntimeException("FragmentManager's fragments is empty")
|
|
||||||
|
|
||||||
val transaction = fragmentManager.beginTransaction()
|
|
||||||
|
|
||||||
for (fragment in fragments) {
|
|
||||||
transaction.remove(fragment)
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction.commitNow()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hideFragments(fragmentManager: FragmentManager) {
|
|
||||||
val fragments = fragmentManager.fragments
|
|
||||||
|
|
||||||
if (fragments.isEmpty()) throw RuntimeException("FragmentManager's fragments is empty")
|
|
||||||
|
|
||||||
val transaction = fragmentManager.beginTransaction()
|
|
||||||
|
|
||||||
for (fragment in fragments) {
|
|
||||||
transaction.hide(fragment)
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction.commitNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
package com.meloda.fast.common
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.collection.arrayMapOf
|
|
||||||
import com.meloda.fast.concurrent.TaskManager
|
|
||||||
import com.meloda.fast.BuildConfig
|
|
||||||
import com.meloda.fast.model.NewUpdateInfo
|
|
||||||
import com.meloda.fast.net.HttpRequest
|
|
||||||
import org.json.JSONArray
|
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
object UpdateManager {
|
|
||||||
|
|
||||||
interface OnUpdateListener {
|
|
||||||
fun onNewUpdate(updateInfo: NewUpdateInfo)
|
|
||||||
|
|
||||||
fun onNoUpdates()
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val checkLink = "https://melodev.procsec.top/vkm/project_vkm_ota.json"
|
|
||||||
|
|
||||||
private const val PRODUCT_NAME = "project_vkm"
|
|
||||||
private const val BRANCH = "alpha"
|
|
||||||
private const val OFFSET = 0
|
|
||||||
|
|
||||||
private const val TAG = "UpdateManager"
|
|
||||||
|
|
||||||
fun checkUpdates(onUpdateListener: OnUpdateListener) {
|
|
||||||
TaskManager.execute {
|
|
||||||
val newLink = "https://temply.procsec.top/prop/deploy/api/method/getOTA"
|
|
||||||
|
|
||||||
val params = arrayMapOf<String, String>()
|
|
||||||
params["product"] = PRODUCT_NAME
|
|
||||||
params["branch"] = BRANCH
|
|
||||||
params["offset"] = OFFSET.toString()
|
|
||||||
params["code"] = AppGlobal.versionCode.toString()
|
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.d(TAG, "Request started")
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpRequest[newLink, params].asString().let {
|
|
||||||
AppGlobal.post {
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.d(TAG, "response: $it")
|
|
||||||
}
|
|
||||||
|
|
||||||
val response: Any = if (it == "[]") JSONArray(it) else JSONObject(it)
|
|
||||||
|
|
||||||
val newUpdateInfo: NewUpdateInfo? =
|
|
||||||
if (response is JSONArray) null else NewUpdateInfo(response as JSONObject)
|
|
||||||
|
|
||||||
if (response is JSONArray || newUpdateInfo?.version?.isEmpty() == true || newUpdateInfo?.version == AppGlobal.versionName) {
|
|
||||||
onUpdateListener.onNoUpdates()
|
|
||||||
return@post
|
|
||||||
} else {
|
|
||||||
newUpdateInfo?.let { onUpdateListener.onNewUpdate(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HttpRequest[checkLink].asString().let {
|
|
||||||
// val response = JSONObject(it)
|
|
||||||
//
|
|
||||||
// val updateInfo = UpdateInfo(response)
|
|
||||||
//
|
|
||||||
// AppGlobal.handler.post {
|
|
||||||
// if (updateInfo.version.isEmpty() || updateInfo.version == AppGlobal.versionName) {
|
|
||||||
// onUpdateListener.onNoUpdates()
|
|
||||||
// return@post
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (AppGlobal.versionName != updateInfo.version) {
|
|
||||||
// onUpdateListener.onNewUpdate(updateInfo)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package com.meloda.fast.concurrent
|
|
||||||
|
|
||||||
class EventInfo<T> constructor(var key: String, var data: T? = null)
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.meloda.fast.concurrent
|
|
||||||
|
|
||||||
import android.os.Process
|
|
||||||
|
|
||||||
class LowThread(runnable: Runnable?) : Thread(runnable) {
|
|
||||||
|
|
||||||
override fun run() {
|
|
||||||
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)
|
|
||||||
super.run()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.meloda.fast.concurrent
|
|
||||||
|
|
||||||
object TaskManager {
|
|
||||||
|
|
||||||
private const val TAG = "TaskManager"
|
|
||||||
|
|
||||||
private val listeners = arrayListOf<OnEventListener>()
|
|
||||||
|
|
||||||
fun addOnEventListener(listener: OnEventListener) {
|
|
||||||
listeners.add(listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeOnEventListener(listener: OnEventListener?) {
|
|
||||||
listeners.remove(listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun execute(runnable: Runnable?) {
|
|
||||||
LowThread(runnable).start()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendEvent(eventInfo: EventInfo<*>) {
|
|
||||||
for (listener in listeners) {
|
|
||||||
listener.onNewEvent(eventInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface OnEventListener {
|
|
||||||
fun onNewEvent(info: EventInfo<*>)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,9 +5,10 @@ import android.database.Cursor
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import com.meloda.fast.UserConfig
|
import com.meloda.fast.api.UserConfig
|
||||||
|
import com.meloda.fast.api.VKUtil
|
||||||
|
import com.meloda.fast.api.model.VKUser
|
||||||
import com.meloda.fast.database.CacheStorage
|
import com.meloda.fast.database.CacheStorage
|
||||||
import com.meloda.fast.database.CacheStorage.selectCursor
|
|
||||||
import com.meloda.fast.database.DatabaseKeys.DEACTIVATED
|
import com.meloda.fast.database.DatabaseKeys.DEACTIVATED
|
||||||
import com.meloda.fast.database.DatabaseKeys.FIRST_NAME
|
import com.meloda.fast.database.DatabaseKeys.FIRST_NAME
|
||||||
import com.meloda.fast.database.DatabaseKeys.FRIEND_ID
|
import com.meloda.fast.database.DatabaseKeys.FRIEND_ID
|
||||||
@@ -25,8 +26,6 @@ import com.meloda.fast.database.DatabaseUtils.TABLE_FRIENDS
|
|||||||
import com.meloda.fast.database.DatabaseUtils.TABLE_USERS
|
import com.meloda.fast.database.DatabaseUtils.TABLE_USERS
|
||||||
import com.meloda.fast.database.QueryBuilder
|
import com.meloda.fast.database.QueryBuilder
|
||||||
import com.meloda.fast.database.base.Storage
|
import com.meloda.fast.database.base.Storage
|
||||||
import com.meloda.fast.api.model.VKUser
|
|
||||||
import com.meloda.fast.api.VKUtil
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
@@ -78,7 +77,7 @@ class UsersStorage : Storage<VKUser>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getAllValues(): ArrayList<VKUser> {
|
override fun getAllValues(): ArrayList<VKUser> {
|
||||||
val cursor = selectCursor(TABLE_USERS)
|
val cursor = CacheStorage.selectCursor(TABLE_USERS)
|
||||||
val users = ArrayList<VKUser>()
|
val users = ArrayList<VKUser>()
|
||||||
|
|
||||||
while (cursor.moveToNext()) users.add(parseValue(cursor))
|
while (cursor.moveToNext()) users.add(parseValue(cursor))
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package com.meloda.fast.extensions
|
package com.meloda.fast.extensions
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.util.SparseArray
|
import androidx.collection.SparseArrayCompat
|
||||||
import androidx.core.util.forEach
|
import androidx.collection.forEach
|
||||||
|
import androidx.collection.set
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
@@ -11,7 +12,7 @@ import androidx.navigation.NavController
|
|||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import com.meloda.fast.R
|
import com.meloda.fast.R
|
||||||
import com.meloda.fast.UserConfig
|
import com.meloda.fast.api.UserConfig
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the various graphs needed for a [BottomNavigationView].
|
* Manages the various graphs needed for a [BottomNavigationView].
|
||||||
@@ -28,7 +29,7 @@ object NavigationExtensions {
|
|||||||
): LiveData<NavController> {
|
): LiveData<NavController> {
|
||||||
|
|
||||||
// Map of tags
|
// Map of tags
|
||||||
val graphIdToTagMap = SparseArray<String>()
|
val graphIdToTagMap = SparseArrayCompat<String>()
|
||||||
// Result. Mutable live data with the selected controlled
|
// Result. Mutable live data with the selected controlled
|
||||||
val selectedNavController = MutableLiveData<NavController>()
|
val selectedNavController = MutableLiveData<NavController>()
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ object NavigationExtensions {
|
|||||||
|
|
||||||
// Now connect selecting an item with swapping Fragments
|
// Now connect selecting an item with swapping Fragments
|
||||||
var selectedItemTag = graphIdToTagMap[this.selectedItemId]
|
var selectedItemTag = graphIdToTagMap[this.selectedItemId]
|
||||||
val firstFragmentTag = graphIdToTagMap[firstFragmentGraphId]
|
val firstFragmentTag = graphIdToTagMap[firstFragmentGraphId] ?: ""
|
||||||
var isOnFirstFragment = selectedItemTag == firstFragmentTag
|
var isOnFirstFragment = selectedItemTag == firstFragmentTag
|
||||||
|
|
||||||
setOnItemSelectedListener { item ->
|
setOnItemSelectedListener { item ->
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.meloda.fast.model
|
|
||||||
|
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
class NewUpdateInfo() {
|
|
||||||
|
|
||||||
var id: Int = 0
|
|
||||||
var version: String = ""
|
|
||||||
var code: Int = 0
|
|
||||||
var time: Int = 0
|
|
||||||
var changelog: String = ""
|
|
||||||
|
|
||||||
// var branchId: Int = 0
|
|
||||||
// var branchName: String = ""
|
|
||||||
|
|
||||||
var downloadLink: String = ""
|
|
||||||
|
|
||||||
// var state: Boolean = true
|
|
||||||
|
|
||||||
constructor(o: JSONObject) : this() {
|
|
||||||
id = o.optInt("id")
|
|
||||||
version = o.optString("version")
|
|
||||||
code = o.optInt("code")
|
|
||||||
time = o.optInt("time")
|
|
||||||
changelog = o.optString("changelog")
|
|
||||||
|
|
||||||
downloadLink = o.optString("download")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.meloda.fast.model
|
|
||||||
|
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
class UpdateInfo() {
|
|
||||||
|
|
||||||
var version: String = ""
|
|
||||||
var code: Int = 0
|
|
||||||
var changelog: String = ""
|
|
||||||
var downloadLink: String = ""
|
|
||||||
var date: Int = 0
|
|
||||||
|
|
||||||
constructor(o: JSONObject) : this() {
|
|
||||||
version = o.optString("lastVersionName")
|
|
||||||
code = o.optInt("lastVersionCode")
|
|
||||||
changelog = o.optString("changelog")
|
|
||||||
downloadLink = o.optString("downloadLink")
|
|
||||||
date = o.optInt("buildDate")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
package com.meloda.fast.net
|
|
||||||
|
|
||||||
import androidx.collection.ArrayMap
|
|
||||||
import java.io.IOException
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.io.UnsupportedEncodingException
|
|
||||||
import java.net.HttpURLConnection
|
|
||||||
import java.net.URL
|
|
||||||
import java.net.URLEncoder
|
|
||||||
|
|
||||||
class HttpRequest(
|
|
||||||
private val url: String,
|
|
||||||
private val method: String,
|
|
||||||
private val params: ArrayMap<String, String> = ArrayMap<String, String>()
|
|
||||||
) {
|
|
||||||
companion object {
|
|
||||||
const val GET = "GET"
|
|
||||||
const val POST = "POST"
|
|
||||||
|
|
||||||
operator fun get(
|
|
||||||
url: String,
|
|
||||||
params: ArrayMap<String, String> = ArrayMap()
|
|
||||||
): HttpRequest {
|
|
||||||
return HttpRequest(url, GET, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun get(url: String): HttpRequest {
|
|
||||||
return Companion[url, ArrayMap()]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private var connection: HttpURLConnection? = null
|
|
||||||
|
|
||||||
@Throws(IOException::class)
|
|
||||||
fun asString(): String {
|
|
||||||
val input = getStream()
|
|
||||||
|
|
||||||
val content = com.meloda.fast.io.EasyStreams.read(input)
|
|
||||||
|
|
||||||
connection?.disconnect()
|
|
||||||
|
|
||||||
return content
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(IOException::class)
|
|
||||||
fun asBytes(): ByteArray {
|
|
||||||
val input = getStream()
|
|
||||||
val content = com.meloda.fast.io.EasyStreams.readBytes(input)
|
|
||||||
|
|
||||||
connection?.disconnect()
|
|
||||||
|
|
||||||
return content
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(IOException::class)
|
|
||||||
fun getStream(): InputStream {
|
|
||||||
if (connection == null) {
|
|
||||||
connection = createConnection()
|
|
||||||
}
|
|
||||||
|
|
||||||
var input = connection!!.inputStream
|
|
||||||
val encoding = connection!!.getHeaderField("Content-Encoding")
|
|
||||||
if ("gzip".equals(encoding, ignoreCase = true)) {
|
|
||||||
input = com.meloda.fast.io.EasyStreams.gzip(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
return input
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(UnsupportedEncodingException::class)
|
|
||||||
private fun getParams(): String {
|
|
||||||
val buffer = StringBuilder()
|
|
||||||
|
|
||||||
for (i in 0 until params.size) {
|
|
||||||
val key = params.keyAt(i)
|
|
||||||
val value = params.valueAt(i)
|
|
||||||
buffer.append(key).append("=")
|
|
||||||
buffer.append(URLEncoder.encode(value, "UTF-8"))
|
|
||||||
buffer.append("&")
|
|
||||||
}
|
|
||||||
return buffer.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(UnsupportedEncodingException::class)
|
|
||||||
private fun getUrl(): String {
|
|
||||||
return if (params.isNotEmpty() && "GET".equals(method, ignoreCase = true)) {
|
|
||||||
url + "?" + getParams()
|
|
||||||
} else url
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(IOException::class)
|
|
||||||
private fun createConnection(): HttpURLConnection? {
|
|
||||||
connection = URL(getUrl()).openConnection() as HttpURLConnection
|
|
||||||
connection!!.readTimeout = 60000
|
|
||||||
connection!!.connectTimeout = 60000
|
|
||||||
connection!!.useCaches = true
|
|
||||||
connection!!.doInput = true
|
|
||||||
connection!!.doOutput =
|
|
||||||
!GET.equals(method, ignoreCase = true)
|
|
||||||
connection!!.requestMethod = method
|
|
||||||
connection!!.setRequestProperty("Accept-Encoding", "gzip")
|
|
||||||
return connection
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
try {
|
|
||||||
return asString()
|
|
||||||
} catch (e: IOException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.meloda.fast.receiver
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import com.meloda.fast.api.OnResponseListener
|
|
||||||
|
|
||||||
open class DownloadUpdateReceiver : BroadcastReceiver() {
|
|
||||||
|
|
||||||
var listener: OnResponseListener<Any?>? = null
|
|
||||||
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
|
||||||
listener?.onResponse(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -19,7 +19,7 @@ import com.google.android.material.snackbar.Snackbar
|
|||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import com.meloda.fast.BuildConfig
|
import com.meloda.fast.BuildConfig
|
||||||
import com.meloda.fast.R
|
import com.meloda.fast.R
|
||||||
import com.meloda.fast.base.BaseVMFragment
|
import com.meloda.fast.base.BaseViewModelFragment
|
||||||
import com.meloda.fast.base.viewmodel.StartProgressEvent
|
import com.meloda.fast.base.viewmodel.StartProgressEvent
|
||||||
import com.meloda.fast.base.viewmodel.StopProgressEvent
|
import com.meloda.fast.base.viewmodel.StopProgressEvent
|
||||||
import com.meloda.fast.base.viewmodel.VKEvent
|
import com.meloda.fast.base.viewmodel.VKEvent
|
||||||
@@ -36,7 +36,7 @@ import java.util.*
|
|||||||
import kotlin.concurrent.schedule
|
import kotlin.concurrent.schedule
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class LoginFragment : BaseVMFragment<LoginViewModel>(R.layout.fragment_login) {
|
class LoginFragment : BaseViewModelFragment<LoginViewModel>(R.layout.fragment_login) {
|
||||||
|
|
||||||
override val viewModel: LoginViewModel by viewModels()
|
override val viewModel: LoginViewModel by viewModels()
|
||||||
private val binding: FragmentLoginBinding by viewBinding()
|
private val binding: FragmentLoginBinding by viewBinding()
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package com.meloda.fast.screens.login
|
package com.meloda.fast.screens.login
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.meloda.fast.UserConfig
|
import com.meloda.fast.api.UserConfig
|
||||||
import com.meloda.fast.api.VKAuth
|
|
||||||
import com.meloda.fast.api.VKConstants
|
import com.meloda.fast.api.VKConstants
|
||||||
import com.meloda.fast.api.VKException
|
import com.meloda.fast.api.VKException
|
||||||
import com.meloda.fast.api.VKUtil
|
import com.meloda.fast.api.VKUtil
|
||||||
@@ -15,10 +13,7 @@ import com.meloda.fast.base.viewmodel.StartProgressEvent
|
|||||||
import com.meloda.fast.base.viewmodel.StopProgressEvent
|
import com.meloda.fast.base.viewmodel.StopProgressEvent
|
||||||
import com.meloda.fast.base.viewmodel.VKEvent
|
import com.meloda.fast.base.viewmodel.VKEvent
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.json.JSONObject
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
@@ -36,12 +31,12 @@ class LoginViewModel @Inject constructor(
|
|||||||
{
|
{
|
||||||
repo.auth(
|
repo.auth(
|
||||||
RequestAuthDirect(
|
RequestAuthDirect(
|
||||||
grantType = VKAuth.GrantType.PASSWORD,
|
grantType = VKConstants.Auth.GrantType.PASSWORD,
|
||||||
clientId = VKConstants.VK_APP_ID,
|
clientId = VKConstants.VK_APP_ID,
|
||||||
clientSecret = VKConstants.VK_SECRET,
|
clientSecret = VKConstants.VK_SECRET,
|
||||||
username = login,
|
username = login,
|
||||||
password = password,
|
password = password,
|
||||||
scope = VKAuth.scope,
|
scope = VKConstants.Auth.SCOPE,
|
||||||
twoFaForceSms = true,
|
twoFaForceSms = true,
|
||||||
twoFaCode = twoFaCode,
|
twoFaCode = twoFaCode,
|
||||||
captchaSid = captcha?.first,
|
captchaSid = captcha?.first,
|
||||||
@@ -64,6 +59,8 @@ class LoginViewModel @Inject constructor(
|
|||||||
checkErrors(it)
|
checkErrors(it)
|
||||||
if (it !is VKException) return@makeJob
|
if (it !is VKException) return@makeJob
|
||||||
|
|
||||||
|
twoFaCode?.let { sendEvent(CodeSent) }
|
||||||
|
|
||||||
if (VKUtil.isValidationRequired(it)) {
|
if (VKUtil.isValidationRequired(it)) {
|
||||||
it.validationSid?.let { sid ->
|
it.validationSid?.let { sid ->
|
||||||
sendEvent(ValidationRequired(validationSid = sid))
|
sendEvent(ValidationRequired(validationSid = sid))
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
package com.meloda.fast.screens.login
|
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.viewbinding.library.fragment.viewBinding
|
|
||||||
import android.webkit.CookieManager
|
|
||||||
import android.webkit.WebView
|
|
||||||
import android.webkit.WebViewClient
|
|
||||||
import androidx.core.os.bundleOf
|
|
||||||
import androidx.navigation.fragment.findNavController
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.api.VKAuth
|
|
||||||
import com.meloda.fast.base.BaseFragment
|
|
||||||
import com.meloda.fast.databinding.FragmentValidationBinding
|
|
||||||
|
|
||||||
class ValidationFragment : BaseFragment(R.layout.fragment_validation) {
|
|
||||||
|
|
||||||
private val binding: FragmentValidationBinding by viewBinding()
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
val redirectUrl = getRedirectUrl()
|
|
||||||
|
|
||||||
binding.webView.webViewClient = object : WebViewClient() {
|
|
||||||
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
|
||||||
Log.d("Fast::Validation", "onPageStarted: url: $url")
|
|
||||||
parseUrl(url ?: "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.webView.settings.domStorageEnabled = true
|
|
||||||
binding.webView.clearCache(true)
|
|
||||||
binding.webView.layoutParams = ViewGroup.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
|
||||||
)
|
|
||||||
|
|
||||||
val manager = CookieManager.getInstance()
|
|
||||||
manager.removeAllCookies(null)
|
|
||||||
manager.flush()
|
|
||||||
manager.setAcceptCookie(true)
|
|
||||||
|
|
||||||
binding.webView.loadUrl(redirectUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getRedirectUrl() = requireArguments().getString("redirectUrl", "")
|
|
||||||
|
|
||||||
private fun parseUrl(url: String) {
|
|
||||||
if (url.startsWith("https://oauth.vk.com/blank.html#success=1")) {
|
|
||||||
if (!url.contains("error=")) {
|
|
||||||
val data = VKAuth.parseRedirectUrl(url)
|
|
||||||
|
|
||||||
val accessToken = data.first
|
|
||||||
val userId = data.second
|
|
||||||
|
|
||||||
parentFragmentManager.setFragmentResult(
|
|
||||||
"validation",
|
|
||||||
bundleOf(
|
|
||||||
"accessToken" to accessToken,
|
|
||||||
"userId" to userId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
findNavController().navigate(R.id.toLogin)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.d("Fast::Validation", "parseUrl: $url")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -6,14 +6,14 @@ import android.viewbinding.library.fragment.viewBinding
|
|||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.meloda.fast.R
|
import com.meloda.fast.R
|
||||||
import com.meloda.fast.UserConfig
|
import com.meloda.fast.api.UserConfig
|
||||||
import com.meloda.fast.base.BaseVMFragment
|
import com.meloda.fast.base.BaseViewModelFragment
|
||||||
import com.meloda.fast.databinding.FragmentMainBinding
|
import com.meloda.fast.databinding.FragmentMainBinding
|
||||||
import com.meloda.fast.extensions.NavigationExtensions.setupWithNavController
|
import com.meloda.fast.extensions.NavigationExtensions.setupWithNavController
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainFragment : BaseVMFragment<MainViewModel>(R.layout.fragment_main) {
|
class MainFragment : BaseViewModelFragment<MainViewModel>(R.layout.fragment_main) {
|
||||||
|
|
||||||
override val viewModel: MainViewModel by viewModels()
|
override val viewModel: MainViewModel by viewModels()
|
||||||
private val binding: FragmentMainBinding by viewBinding()
|
private val binding: FragmentMainBinding by viewBinding()
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import android.viewbinding.library.fragment.viewBinding
|
|||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import com.meloda.fast.R
|
import com.meloda.fast.R
|
||||||
import com.meloda.fast.base.BaseVMFragment
|
import com.meloda.fast.base.BaseViewModelFragment
|
||||||
import com.meloda.fast.base.viewmodel.StartProgressEvent
|
import com.meloda.fast.base.viewmodel.StartProgressEvent
|
||||||
import com.meloda.fast.base.viewmodel.StopProgressEvent
|
import com.meloda.fast.base.viewmodel.StopProgressEvent
|
||||||
import com.meloda.fast.base.viewmodel.VKEvent
|
import com.meloda.fast.base.viewmodel.VKEvent
|
||||||
@@ -16,7 +16,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class ConversationsFragment : BaseVMFragment<ConversationsViewModel>(R.layout.fragment_conversations) {
|
class ConversationsFragment : BaseViewModelFragment<ConversationsViewModel>(R.layout.fragment_conversations) {
|
||||||
|
|
||||||
override val viewModel: ConversationsViewModel by viewModels()
|
override val viewModel: ConversationsViewModel by viewModels()
|
||||||
private val binding: FragmentConversationsBinding by viewBinding()
|
private val binding: FragmentConversationsBinding by viewBinding()
|
||||||
|
|||||||
@@ -5,17 +5,13 @@ import android.content.Intent
|
|||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.collection.arrayMapOf
|
import com.meloda.fast.api.UserConfig
|
||||||
import com.meloda.fast.UserConfig
|
|
||||||
import com.meloda.fast.VKLongPollParser
|
|
||||||
import com.meloda.fast.api.VKApi
|
|
||||||
import com.meloda.fast.api.model.VKLongPollServer
|
import com.meloda.fast.api.model.VKLongPollServer
|
||||||
import com.meloda.fast.concurrent.LowThread
|
|
||||||
import com.meloda.fast.net.HttpRequest
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
import com.meloda.fast.util.AndroidUtils
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
// TODO: 8/31/2021 rewrite
|
||||||
@Deprecated("Absolutely obsolete")
|
@Deprecated("Absolutely obsolete")
|
||||||
class LongPollService : Service() {
|
class LongPollService : Service() {
|
||||||
private var thread: Thread? = null
|
private var thread: Thread? = null
|
||||||
@@ -26,7 +22,7 @@ class LongPollService : Service() {
|
|||||||
|
|
||||||
running = false
|
running = false
|
||||||
|
|
||||||
thread = LowThread(Updater())
|
// thread = LowThread(Updater())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBind(intent: Intent?): IBinder? {
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
@@ -75,8 +71,9 @@ class LongPollService : Service() {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (server == null) {
|
if (server == null) {
|
||||||
server = VKApi.messages().getLongPollServer()
|
server = null
|
||||||
.execute(VKLongPollServer::class.java)!![0]
|
// server = VKApi.messages().getLongPollServer()
|
||||||
|
// .execute(VKLongPollServer::class.java)!![0]
|
||||||
}
|
}
|
||||||
|
|
||||||
val response = getResponse(server)
|
val response = getResponse(server)
|
||||||
@@ -92,7 +89,7 @@ class LongPollService : Service() {
|
|||||||
|
|
||||||
Log.i(TAG, "updates: $updates")
|
Log.i(TAG, "updates: $updates")
|
||||||
|
|
||||||
server.ts = tsResponse
|
server?.ts = tsResponse
|
||||||
|
|
||||||
if (updates.length() != 0) {
|
if (updates.length() != 0) {
|
||||||
process(updates)
|
process(updates)
|
||||||
@@ -110,23 +107,23 @@ class LongPollService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
private fun getResponse(server: VKLongPollServer): JSONObject {
|
private fun getResponse(server: VKLongPollServer?): JSONObject {
|
||||||
val params = arrayMapOf<String, String>()
|
return JSONObject("")
|
||||||
params["act"] = "a_check"
|
// val params = arrayMapOf<String, String>()
|
||||||
params["key"] = server.key
|
// params["act"] = "a_check"
|
||||||
params["ts"] = server.ts.toString()
|
// params["key"] = server.key
|
||||||
params["wait"] = "10"
|
// params["ts"] = server.ts.toString()
|
||||||
params["mode"] = "490"
|
// params["wait"] = "10"
|
||||||
params["version"] = "9"
|
// params["mode"] = "490"
|
||||||
|
// params["version"] = "9"
|
||||||
val buffer = HttpRequest["https://" + server.server, params].asString()
|
//
|
||||||
|
// val buffer = HttpRequest["https://" + server.server, params].asString()
|
||||||
return JSONObject(buffer)
|
//
|
||||||
|
// return JSONObject(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
private fun process(updates: JSONArray) {
|
private fun process(updates: JSONArray) {
|
||||||
VKLongPollParser.parse(updates)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,18 +2,15 @@ package com.meloda.fast.util
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import androidx.annotation.WorkerThread
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.meloda.fast.concurrent.TaskManager
|
import com.meloda.fast.R
|
||||||
|
import com.meloda.fast.api.VKUtil
|
||||||
|
import com.meloda.fast.api.model.*
|
||||||
|
import com.meloda.fast.common.AppGlobal
|
||||||
import com.meloda.fast.extensions.ContextExtensions.color
|
import com.meloda.fast.extensions.ContextExtensions.color
|
||||||
import com.meloda.fast.extensions.ContextExtensions.drawable
|
import com.meloda.fast.extensions.ContextExtensions.drawable
|
||||||
import com.meloda.fast.extensions.DrawableExtensions.tint
|
import com.meloda.fast.extensions.DrawableExtensions.tint
|
||||||
import com.meloda.fast.extensions.StringExtensions.lowerCase
|
import com.meloda.fast.extensions.StringExtensions.lowerCase
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.api.model.*
|
|
||||||
import com.meloda.fast.common.AppGlobal
|
|
||||||
import com.meloda.fast.api.OnResponseListener
|
|
||||||
import com.meloda.fast.api.VKUtil
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
@@ -81,41 +78,6 @@ object VKUtils {
|
|||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@Deprecated("")
|
|
||||||
@WorkerThread
|
|
||||||
fun searchUser(id: Int, onResponseListener: OnResponseListener<VKUser>? = null): VKUser? {
|
|
||||||
return if (VKUtil.isGroupId(id) || VKUtil.isChatId(id)) {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
// MemoryCache.getUserById(id)?.let { return it }
|
|
||||||
//
|
|
||||||
// if (BuildConfig.DEBUG) {
|
|
||||||
// Log.d(VKUtil.TAG, "User with id $id not found")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// TaskManager.loadUser(VKApiKeys.UPDATE_USER, id, onResponseListener)
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("")
|
|
||||||
@WorkerThread
|
|
||||||
fun searchGroup(id: Int, onResponseListener: OnResponseListener<VKGroup>? = null): VKGroup? {
|
|
||||||
return if (!VKUtil.isGroupId(id) || VKUtil.isChatId(id)) {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
// MemoryCache.getGroupById(abs(id))?.let { return it }
|
|
||||||
//
|
|
||||||
// if (BuildConfig.DEBUG) {
|
|
||||||
// Log.d(VKUtil.TAG, "Group with id $id not found")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// TaskManager.loadGroup(VKApiKeys.UPDATE_GROUP, abs(id), onResponseListener)
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAttachmentText(context: Context, attachments: List<VKModel>): String {
|
fun getAttachmentText(context: Context, attachments: List<VKModel>): String {
|
||||||
val resId: Int
|
val resId: Int
|
||||||
@@ -158,7 +120,7 @@ object VKUtils {
|
|||||||
if (resId == -1) "Unknown attachments" else context.getString(
|
if (resId == -1) "Unknown attachments" else context.getString(
|
||||||
resId,
|
resId,
|
||||||
attachments.size
|
attachments.size
|
||||||
).toLowerCase(Locale.getDefault())
|
).lowerCase()
|
||||||
} else {
|
} else {
|
||||||
context.getString(R.string.message_attachments_many)
|
context.getString(R.string.message_attachments_many)
|
||||||
}
|
}
|
||||||
@@ -226,62 +188,60 @@ object VKUtils {
|
|||||||
@Deprecated("need to rewrite")
|
@Deprecated("need to rewrite")
|
||||||
fun getActionText(
|
fun getActionText(
|
||||||
context: Context,
|
context: Context,
|
||||||
lastMessage: VKMessage,
|
lastMessage: VKMessage
|
||||||
onResponseListener: OnResponseListener<String>
|
|
||||||
) {
|
) {
|
||||||
TaskManager.execute {
|
|
||||||
lastMessage.action?.let {
|
|
||||||
var result = ""
|
|
||||||
|
|
||||||
when (it.type) {
|
lastMessage.action?.let {
|
||||||
VKMessageAction.Type.CHAT_CREATE -> result = context.getString(
|
var result = ""
|
||||||
R.string.message_action_created_chat,
|
|
||||||
|
when (it.type) {
|
||||||
|
VKMessageAction.Type.CHAT_CREATE -> result = context.getString(
|
||||||
|
R.string.message_action_created_chat,
|
||||||
|
""
|
||||||
|
)
|
||||||
|
VKMessageAction.Type.INVITE_USER -> result =
|
||||||
|
if (lastMessage.fromId == lastMessage.action!!.memberId) {
|
||||||
|
context.getString(R.string.message_action_returned_to_chat, "")
|
||||||
|
} else {
|
||||||
""
|
""
|
||||||
)
|
|
||||||
VKMessageAction.Type.INVITE_USER -> result =
|
|
||||||
if (lastMessage.fromId == lastMessage.action!!.memberId) {
|
|
||||||
context.getString(R.string.message_action_returned_to_chat, "")
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
// val invited = MemoryCache.getUserById(lastMessage.action!!.memberId)
|
// val invited = MemoryCache.getUserById(lastMessage.action!!.memberId)
|
||||||
// context.getString(R.string.message_action_invited_user, invited)
|
// context.getString(R.string.message_action_invited_user, invited)
|
||||||
}
|
}
|
||||||
VKMessageAction.Type.INVITE_USER_BY_LINK -> result = context.getString(
|
VKMessageAction.Type.INVITE_USER_BY_LINK -> result = context.getString(
|
||||||
R.string.message_action_invited_by_link,
|
R.string.message_action_invited_by_link,
|
||||||
|
""
|
||||||
|
)
|
||||||
|
VKMessageAction.Type.KICK_USER -> result =
|
||||||
|
if (lastMessage.fromId == lastMessage.action!!.memberId) {
|
||||||
|
context.getString(R.string.message_action_left_from_chat, "")
|
||||||
|
} else {
|
||||||
""
|
""
|
||||||
)
|
|
||||||
VKMessageAction.Type.KICK_USER -> result =
|
|
||||||
if (lastMessage.fromId == lastMessage.action!!.memberId) {
|
|
||||||
context.getString(R.string.message_action_left_from_chat, "")
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
// val kicked = MemoryCache.getUserById(lastMessage.action!!.memberId)
|
// val kicked = MemoryCache.getUserById(lastMessage.action!!.memberId)
|
||||||
// context.getString(R.string.message_action_kicked_user, kicked)
|
// context.getString(R.string.message_action_kicked_user, kicked)
|
||||||
}
|
}
|
||||||
VKMessageAction.Type.PHOTO_REMOVE -> result = context.getString(
|
VKMessageAction.Type.PHOTO_REMOVE -> result = context.getString(
|
||||||
R.string.message_action_removed_photo,
|
R.string.message_action_removed_photo,
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
VKMessageAction.Type.PHOTO_UPDATE -> result = context.getString(
|
VKMessageAction.Type.PHOTO_UPDATE -> result = context.getString(
|
||||||
R.string.message_action_updated_photo,
|
R.string.message_action_updated_photo,
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
VKMessageAction.Type.PIN_MESSAGE -> result = context.getString(
|
VKMessageAction.Type.PIN_MESSAGE -> result = context.getString(
|
||||||
R.string.message_action_pinned_message,
|
R.string.message_action_pinned_message,
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
VKMessageAction.Type.UNPIN_MESSAGE -> result = context.getString(
|
VKMessageAction.Type.UNPIN_MESSAGE -> result = context.getString(
|
||||||
R.string.message_action_unpinned_message,
|
R.string.message_action_unpinned_message,
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
VKMessageAction.Type.TITLE_UPDATE -> result = context.getString(
|
VKMessageAction.Type.TITLE_UPDATE -> result = context.getString(
|
||||||
R.string.message_action_updated_title,
|
R.string.message_action_updated_title,
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
AppGlobal.post { onResponseListener.onResponse(result) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
package com.meloda.fast.viewmodel
|
|
||||||
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.meloda.fast.database.CacheStorage
|
|
||||||
import com.meloda.fast.api.VKApi
|
|
||||||
import com.meloda.fast.api.VKConstants
|
|
||||||
import com.meloda.fast.api.model.VKConversation
|
|
||||||
import com.meloda.fast.api.model.VKMessage
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.collect
|
|
||||||
import kotlinx.coroutines.flow.toList
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
class ChatsViewModel : ViewModel() {
|
|
||||||
|
|
||||||
val chatsAnswer = MutableLiveData<ChatsAnswer?>()
|
|
||||||
|
|
||||||
data class ChatsAnswer(var status: Status, var message: String? = "") {
|
|
||||||
companion object {
|
|
||||||
val SUCCESS get() = ChatsAnswer(Status.SUCCESS)
|
|
||||||
val FAIL get() = ChatsAnswer(Status.FAIL)
|
|
||||||
val LOADING get() = ChatsAnswer(Status.LOADING)
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class Status {
|
|
||||||
SUCCESS, FAIL, LOADING
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadChats() = viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
chatsAnswer.postValue(ChatsAnswer.LOADING)
|
|
||||||
|
|
||||||
try {
|
|
||||||
val chats = VKApi.messages()
|
|
||||||
.getConversations()
|
|
||||||
.filter("all")
|
|
||||||
.extended(true)
|
|
||||||
.fields(VKConstants.USER_FIELDS + ',' + VKConstants.GROUP_FIELDS)
|
|
||||||
.offset(0)
|
|
||||||
.count(30)
|
|
||||||
.executeSuspend(VKConversation::class.java)
|
|
||||||
|
|
||||||
// CacheStorage.chatsStorage.insertValues(chats)
|
|
||||||
|
|
||||||
val lastMessages = arrayListOf<VKMessage>()
|
|
||||||
chats.collect {
|
|
||||||
lastMessages.add(it.lastMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
CacheStorage.messagesStorage.insertValues(lastMessages)
|
|
||||||
CacheStorage.usersStorage.insertValues(VKConversation.profiles)
|
|
||||||
CacheStorage.groupsStorage.insertValues(VKConversation.groups)
|
|
||||||
//
|
|
||||||
// chatsAnswer.value = ChatsAnswer.SUCCESS
|
|
||||||
|
|
||||||
chatsAnswer.postValue(ChatsAnswer.SUCCESS)
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
// adapter.updateValues(chats.toList())
|
|
||||||
// adapter.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
chatsAnswer.postValue(ChatsAnswer.FAIL.also { it.message = e.message })
|
|
||||||
// chatsAnswer.value = ChatsAnswer.FAIL.also { it.message = e.message }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,6 +8,7 @@ import android.util.AttributeSet
|
|||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
|
||||||
|
// TODO: 8/31/2021 extend ShapeableImageView and set corners for half of size
|
||||||
class CircleImageView : AppCompatImageView {
|
class CircleImageView : AppCompatImageView {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -1,141 +0,0 @@
|
|||||||
package com.meloda.fast.widget
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.Gravity
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.ImageButton
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.annotation.ColorInt
|
|
||||||
import androidx.annotation.DrawableRes
|
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import com.google.android.material.appbar.MaterialToolbar
|
|
||||||
import com.google.android.material.theme.overlay.MaterialThemeOverlay
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
|
||||||
|
|
||||||
class Toolbar : MaterialToolbar {
|
|
||||||
|
|
||||||
constructor(context: Context) : this(context, null)
|
|
||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
|
|
||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
|
||||||
MaterialThemeOverlay.wrap(
|
|
||||||
context,
|
|
||||||
attrs,
|
|
||||||
defStyleAttr,
|
|
||||||
com.google.android.material.R.style.Widget_MaterialComponents_Toolbar
|
|
||||||
),
|
|
||||||
attrs,
|
|
||||||
defStyleAttr
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun init() {
|
|
||||||
//...
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTitle(resId: Int) {
|
|
||||||
title = context.getString(resId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTitle(title: CharSequence?) {
|
|
||||||
findViewById<TextView>(R.id.toolbarTitle).text = title
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTitleTextColor(color: Int) {
|
|
||||||
findViewById<TextView>(R.id.toolbarTitle).setTextColor(color)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDraw(canvas: Canvas?) {
|
|
||||||
super.onDraw(canvas)
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setNavigationIcon(icon: Drawable?) {
|
|
||||||
findViewById<ImageButton>(R.id.toolbarNavigationIcon).setImageDrawable(icon)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setNavigationIcon(@DrawableRes resId: Int) {
|
|
||||||
findViewById<ImageButton>(R.id.toolbarNavigationIcon).setImageResource(resId)
|
|
||||||
}
|
|
||||||
|
|
||||||
// fun setNavigationIconTintList(tintList: ColorStateList?) {
|
|
||||||
// findViewById<ImageButton>(R.id.toolbarNavigationIcon).drawable?.setTintList(tintList)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setNavigationIconTint(@ColorInt tintColor: Int) {
|
|
||||||
// findViewById<ImageButton>(R.id.toolbarNavigationIcon).drawable?.setTint(tintColor)
|
|
||||||
// }
|
|
||||||
|
|
||||||
fun setNavigationClickListener(listener: OnClickListener?) {
|
|
||||||
findViewById<View>(R.id.toolbarNavigation).setOnClickListener(listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setNavigationOnBackClickListener(activity: Activity) {
|
|
||||||
findViewById<View>(R.id.toolbarNavigation).setOnClickListener { activity.onBackPressed() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setNavigationVisibility(visible: Boolean) {
|
|
||||||
findViewById<View>(R.id.toolbarNavigation).visibility = if (visible) VISIBLE else GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun tintNavigationIcon(@ColorInt color: Int) {
|
|
||||||
findViewById<ImageButton>(R.id.toolbarNavigationIcon).imageTintList =
|
|
||||||
ColorStateList.valueOf(color)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setAvatarIcon(icon: Drawable?) {
|
|
||||||
findViewById<ImageView>(R.id.toolbarAvatar).setImageDrawable(icon)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setAvatarIcon(@DrawableRes resId: Int) {
|
|
||||||
// findViewById<SimpleDraweeView>(R.id.toolbarAvatar).setActualImageResource(resId)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setAvatarClickListener(listener: OnClickListener?) {
|
|
||||||
findViewById<View>(R.id.toolbarAvatar).setOnClickListener(listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setAvatarVisibility(visible: Boolean) {
|
|
||||||
findViewById<View>(R.id.toolbarAvatar).visibility = if (visible) VISIBLE else GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
// fun getAvatar(): SimpleDraweeView {
|
|
||||||
// return findViewById(R.id.toolbarAvatar)
|
|
||||||
// }
|
|
||||||
|
|
||||||
fun setTitleMode(titleMode: TitleMode) {
|
|
||||||
val title = findViewById<TextView>(R.id.toolbarTitle)
|
|
||||||
|
|
||||||
when (titleMode) {
|
|
||||||
TitleMode.SIMPLE -> {
|
|
||||||
title.gravity = Gravity.CENTER
|
|
||||||
title.typeface = ResourcesCompat.getFont(context, R.font.google_sans_medium)
|
|
||||||
title.setTextColor(AndroidUtils.getThemeAttrColor(context, R.attr.colorAccent))
|
|
||||||
title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 22f)
|
|
||||||
}
|
|
||||||
TitleMode.HINT -> {
|
|
||||||
title.gravity = Gravity.CENTER_VERTICAL and Gravity.START
|
|
||||||
title.typeface = ResourcesCompat.getFont(context, R.font.google_sans_regular)
|
|
||||||
title.setTextColor(
|
|
||||||
AndroidUtils.getThemeAttrColor(
|
|
||||||
context,
|
|
||||||
R.attr.textColorSecondary
|
|
||||||
)
|
|
||||||
)
|
|
||||||
title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class TitleMode {
|
|
||||||
SIMPLE, HINT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<WebView
|
|
||||||
android:id="@+id/webView"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
|
|
||||||
</layout>
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<com.meloda.fast.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.google.android.material.appbar.MaterialToolbar xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
@@ -63,4 +63,4 @@
|
|||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
</com.meloda.fast.widget.Toolbar>
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
@@ -17,24 +17,6 @@
|
|||||||
app:popUpTo="@id/loginFragment"
|
app:popUpTo="@id/loginFragment"
|
||||||
app:popUpToInclusive="true" />
|
app:popUpToInclusive="true" />
|
||||||
|
|
||||||
<action
|
|
||||||
android:id="@+id/toValidation"
|
|
||||||
app:destination="@id/validationFragment" />
|
|
||||||
|
|
||||||
</fragment>
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/validationFragment"
|
|
||||||
android:name="com.meloda.fast.screens.login.ValidationFragment"
|
|
||||||
android:label="ValidationFragment"
|
|
||||||
tools:layout="@layout/fragment_validation">
|
|
||||||
|
|
||||||
<action
|
|
||||||
android:id="@+id/toLogin"
|
|
||||||
app:destination="@id/loginFragment"
|
|
||||||
app:popUpTo="@id/validationFragment"
|
|
||||||
app:popUpToInclusive="true" />
|
|
||||||
|
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,24 +29,6 @@
|
|||||||
app:popUpTo="@id/loginFragment"
|
app:popUpTo="@id/loginFragment"
|
||||||
app:popUpToInclusive="true" />
|
app:popUpToInclusive="true" />
|
||||||
|
|
||||||
<action
|
|
||||||
android:id="@+id/toValidation"
|
|
||||||
app:destination="@id/validationFragment" />
|
|
||||||
|
|
||||||
</fragment>
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/validationFragment"
|
|
||||||
android:name="com.meloda.fast.screens.login.ValidationFragment"
|
|
||||||
android:label="ValidationFragment"
|
|
||||||
tools:layout="@layout/fragment_validation">
|
|
||||||
|
|
||||||
<action
|
|
||||||
android:id="@+id/toLogin"
|
|
||||||
app:destination="@id/loginFragment"
|
|
||||||
app:popUpTo="@id/validationFragment"
|
|
||||||
app:popUpToInclusive="true" />
|
|
||||||
|
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
</navigation>
|
</navigation>
|
||||||
Reference in New Issue
Block a user