forked from melod1n/fast-messenger
code saving
This commit is contained in:
@@ -1,81 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'com.android.application'
|
|
||||||
id 'kotlin-android'
|
|
||||||
id 'kotlin-kapt'
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion 30
|
|
||||||
buildToolsVersion "30.0.3"
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
applicationId "com.meloda.fast"
|
|
||||||
minSdkVersion 23
|
|
||||||
targetSdkVersion 30
|
|
||||||
versionCode 1
|
|
||||||
versionName "1.0"
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled false
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
coreLibraryDesugaringEnabled true
|
|
||||||
|
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = JavaVersion.VERSION_1_8.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation project(":mvp")
|
|
||||||
implementation project(":vksdk")
|
|
||||||
implementation project(":arrayutils")
|
|
||||||
implementation project(":netservices")
|
|
||||||
implementation project(":concurrent")
|
|
||||||
implementation project(":extensions")
|
|
||||||
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
|
||||||
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
|
|
||||||
|
|
||||||
implementation 'androidx.core:core-ktx:1.5.0-beta02'
|
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.3.0-beta01'
|
|
||||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
|
||||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01'
|
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.2.0-beta02'
|
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
|
||||||
implementation 'androidx.fragment:fragment-ktx:1.3.0'
|
|
||||||
implementation 'com.google.android.material:material:1.3.0'
|
|
||||||
|
|
||||||
implementation 'androidx.room:room-runtime:2.3.0-beta02'
|
|
||||||
kapt 'androidx.room:room-compiler:2.3.0-beta02'
|
|
||||||
|
|
||||||
implementation 'com.facebook.fresco:fresco:2.3.0'
|
|
||||||
|
|
||||||
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
|
||||||
|
|
||||||
implementation 'com.squareup.picasso:picasso:2.71828'
|
|
||||||
|
|
||||||
implementation 'com.github.rahatarmanahmed:circularprogressview:2.5.0'
|
|
||||||
|
|
||||||
implementation 'com.google.code.gson:gson:2.8.6'
|
|
||||||
|
|
||||||
implementation 'org.jsoup:jsoup:1.13.1'
|
|
||||||
|
|
||||||
implementation 'ch.acra:acra:4.11.1'
|
|
||||||
|
|
||||||
def appCenterSdkVersion = '4.1.0'
|
|
||||||
implementation "com.microsoft.appcenter:appcenter-analytics:${appCenterSdkVersion}"
|
|
||||||
implementation "com.microsoft.appcenter:appcenter-crashes:${appCenterSdkVersion}"
|
|
||||||
implementation "com.microsoft.appcenter:appcenter-distribute:${appCenterSdkVersion}"
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
plugins {
|
||||||
|
id("com.android.application")
|
||||||
|
id("kotlin-android")
|
||||||
|
id("kotlin-kapt")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion(ConfigData.compileSdkVersion)
|
||||||
|
buildToolsVersion(ConfigData.buildToolsVersion)
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId = "com.meloda.fast"
|
||||||
|
minSdkVersion(ConfigData.minSdkVersion)
|
||||||
|
targetSdkVersion(ConfigData.targetSdkVersion)
|
||||||
|
versionCode = ConfigData.versionCode
|
||||||
|
versionName = ConfigData.versionName
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
getByName("release") {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
isCoreLibraryDesugaringEnabled = true
|
||||||
|
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
dataBinding = true
|
||||||
|
viewBinding = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
val kotlinSrcDir = "src/main/kotlin"
|
||||||
|
println(sourceSets.names)
|
||||||
|
// val mainJavaSourceSet: SourceDirectorySet = sourceSets.getByName("main").java
|
||||||
|
// mainJavaSourceSet.srcDir(kotlinSrcDir)
|
||||||
|
// println(mainJavaSourceSet.srcDirs)
|
||||||
|
}
|
||||||
|
|
||||||
|
//java.sourceSets.create("src/main/kotlin")
|
||||||
|
|
||||||
|
//sourceSets {
|
||||||
|
// main.java.srcDirs += "src/main/kotlin"
|
||||||
|
//}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(Deps.kotlin)
|
||||||
|
|
||||||
|
coreLibraryDesugaring(Deps.desugaring)
|
||||||
|
|
||||||
|
implementation(Deps.appCompat)
|
||||||
|
implementation(Deps.material)
|
||||||
|
implementation(Deps.core)
|
||||||
|
implementation(Deps.preferences)
|
||||||
|
implementation(Deps.swipeRefreshLayout)
|
||||||
|
implementation(Deps.recyclerView)
|
||||||
|
implementation(Deps.cardView)
|
||||||
|
implementation(Deps.fragment)
|
||||||
|
|
||||||
|
implementation(Deps.coroutineCore)
|
||||||
|
implementation(Deps.coroutineAndroid)
|
||||||
|
|
||||||
|
implementation(Deps.roomRuntime)
|
||||||
|
kapt(Deps.roomCompiler)
|
||||||
|
|
||||||
|
implementation(Deps.gson)
|
||||||
|
implementation(Deps.jsoup)
|
||||||
|
implementation(Deps.acra)
|
||||||
|
implementation("com.github.yogacp:android-viewbinding:1.0.2")
|
||||||
|
|
||||||
|
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.lifecycle}")
|
||||||
|
implementation("androidx.lifecycle:lifecycle-livedata-ktx:${Versions.lifecycle}")
|
||||||
|
implementation("androidx.lifecycle:lifecycle-runtime-ktx:${Versions.lifecycle}")
|
||||||
|
implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:${Versions.lifecycle}")
|
||||||
|
implementation("androidx.lifecycle:lifecycle-common-java8:${Versions.lifecycle}")
|
||||||
|
|
||||||
|
implementation("com.squareup.retrofit2:retrofit:${Versions.retrofit}")
|
||||||
|
implementation("com.squareup.retrofit2:converter-gson:${Versions.retrofit}")
|
||||||
|
}
|
||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
# Add project specific ProGuard rules here.
|
# Add project specific ProGuard rules here.
|
||||||
# You can control the set of applied configuration files using the
|
# You can control the set of applied configuration files using the
|
||||||
# proguardFiles setting in build.gradle.
|
# proguardFiles setting in build.gradle.kts.
|
||||||
#
|
#
|
||||||
# For more details, see
|
# For more details, see
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|||||||
@@ -26,20 +26,6 @@
|
|||||||
android:name=".service.LongPollService"
|
android:name=".service.LongPollService"
|
||||||
android:enabled="true" />
|
android:enabled="true" />
|
||||||
|
|
||||||
<activity android:name=".activity.MessagesActivityDeprecated" />
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".activity.LoginActivityDeprecated"
|
|
||||||
android:label="@string/activity_login" />
|
|
||||||
|
|
||||||
<activity android:name=".activity.DropUserDataActivity" />
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".activity.SettingsActivityDeprecated"
|
|
||||||
android:label="@string/navigation_settings" />
|
|
||||||
|
|
||||||
<activity android:name=".activity.UpdateActivityDeprecated" />
|
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".receiver.MinuteReceiver"
|
android:name=".receiver.MinuteReceiver"
|
||||||
android:enabled="true">
|
android:enabled="true">
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package com.meloda.fast
|
|||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import com.meloda.concurrent.EventInfo
|
import com.meloda.fast.concurrent.EventInfo
|
||||||
import com.meloda.concurrent.TaskManager
|
import com.meloda.fast.concurrent.TaskManager
|
||||||
import com.meloda.vksdk.VKApiKeys
|
import com.meloda.fast.api.VKApiKeys
|
||||||
import com.meloda.vksdk.model.VKMessage
|
import com.meloda.fast.api.model.VKMessage
|
||||||
import com.meloda.vksdk.util.VKUtil
|
import com.meloda.fast.api.util.VKUtil
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.meloda.fast.activity
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import com.meloda.fast.UserConfig
|
|
||||||
import com.meloda.fast.base.BaseActivity
|
|
||||||
|
|
||||||
class DropUserDataActivity : BaseActivity() {
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
UserConfig.clear()
|
|
||||||
|
|
||||||
// TaskManager.execute { AppGlobal.database.clearAllTables() }
|
|
||||||
|
|
||||||
startActivity(Intent(this, MainActivity::class.java))
|
|
||||||
finishAffinity()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
package com.meloda.fast.activity
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.webkit.*
|
|
||||||
import android.widget.ProgressBar
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
import com.meloda.extensions.ContextExtensions.color
|
|
||||||
import com.meloda.extensions.ContextExtensions.drawable
|
|
||||||
import com.meloda.extensions.DrawableExtensions.tint
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.UserConfig
|
|
||||||
import com.meloda.fast.base.BaseActivity
|
|
||||||
import com.meloda.fast.widget.Toolbar
|
|
||||||
import com.meloda.vksdk.VKAuth
|
|
||||||
|
|
||||||
class LoginActivityDeprecated : BaseActivity() {
|
|
||||||
|
|
||||||
private lateinit var toolbar: Toolbar
|
|
||||||
private lateinit var progressBar: ProgressBar
|
|
||||||
private lateinit var webView: WebView
|
|
||||||
private lateinit var refreshLayout: SwipeRefreshLayout
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_login)
|
|
||||||
|
|
||||||
initViews()
|
|
||||||
|
|
||||||
prepareToolbar()
|
|
||||||
prepareRefreshLayout()
|
|
||||||
|
|
||||||
prepareSettings()
|
|
||||||
|
|
||||||
val url = VKAuth.getUrl(UserConfig.API_ID, VKAuth.settings)
|
|
||||||
|
|
||||||
webView.loadUrl(url)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initViews() {
|
|
||||||
toolbar = findViewById(R.id.toolbar)
|
|
||||||
progressBar = findViewById(R.id.progressBar)
|
|
||||||
webView = findViewById(R.id.webView)
|
|
||||||
refreshLayout = findViewById(R.id.refreshLayout)
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
|
||||||
private fun prepareSettings() {
|
|
||||||
webView.settings.javaScriptEnabled = true
|
|
||||||
webView.clearCache(true)
|
|
||||||
webView.webViewClient = VKWebClient()
|
|
||||||
|
|
||||||
val cookieManager = CookieManager.getInstance()
|
|
||||||
cookieManager.setAcceptCookie(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareToolbar() {
|
|
||||||
setSupportActionBar(toolbar)
|
|
||||||
|
|
||||||
toolbar.navigationIcon = drawable(R.drawable.ic_close).tint(color(R.color.accent))
|
|
||||||
toolbar.setNavigationClickListener { onBackPressed() }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
if (item.itemId == android.R.id.home) onBackPressed()
|
|
||||||
return super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareRefreshLayout() {
|
|
||||||
refreshLayout.apply {
|
|
||||||
setColorSchemeColors(color(R.color.accent))
|
|
||||||
setOnRefreshListener {
|
|
||||||
webView.reload()
|
|
||||||
isRefreshing = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class VKWebClient : WebViewClient() {
|
|
||||||
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
|
|
||||||
view.loadUrl(url)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
|
|
||||||
super.onPageStarted(view, url, favicon)
|
|
||||||
|
|
||||||
progressBar.isVisible = true
|
|
||||||
view.isVisible = false
|
|
||||||
|
|
||||||
parseUrl(url)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPageFinished(view: WebView, url: String) {
|
|
||||||
super.onPageFinished(view, url)
|
|
||||||
|
|
||||||
progressBar.isVisible = false
|
|
||||||
view.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onReceivedError(
|
|
||||||
view: WebView,
|
|
||||||
request: WebResourceRequest?,
|
|
||||||
error: WebResourceError?
|
|
||||||
) {
|
|
||||||
super.onReceivedError(view, request, error)
|
|
||||||
Log.e("VKM WebView", error.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseUrl(url: String) {
|
|
||||||
try {
|
|
||||||
if (url.startsWith(VKAuth.redirectUrl) && !url.contains("error=")) {
|
|
||||||
val auth = VKAuth.parseRedirectUrl(url)
|
|
||||||
val token = auth[0]
|
|
||||||
val id = auth[1].toInt()
|
|
||||||
|
|
||||||
UserConfig.token = token
|
|
||||||
UserConfig.userId = id
|
|
||||||
UserConfig.save()
|
|
||||||
|
|
||||||
finishAffinity()
|
|
||||||
startActivity(Intent(this, MainActivity::class.java))
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,254 +1,23 @@
|
|||||||
package com.meloda.fast.activity
|
package com.meloda.fast.activity
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.viewbinding.library.activity.viewBinding
|
||||||
import android.view.MenuItem
|
|
||||||
import androidx.core.view.GravityCompat
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.drawerlayout.widget.DrawerLayout
|
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
|
||||||
import com.google.android.material.navigation.NavigationView
|
|
||||||
import com.meloda.extensions.ContextExtensions.color
|
|
||||||
import com.meloda.extensions.ContextExtensions.drawable
|
|
||||||
import com.meloda.extensions.DrawableExtensions.tint
|
|
||||||
import com.meloda.fast.R
|
import com.meloda.fast.R
|
||||||
import com.meloda.fast.UserConfig
|
|
||||||
import com.meloda.fast.base.BaseActivity
|
import com.meloda.fast.base.BaseActivity
|
||||||
import com.meloda.fast.common.AppGlobal
|
import com.meloda.fast.databinding.ActivityMainBinding
|
||||||
import com.meloda.fast.common.FragmentSwitcher
|
import com.meloda.fast.fragment.LoginFragment
|
||||||
import com.meloda.fast.common.TimeManager
|
|
||||||
import com.meloda.fast.dialog.AccountDialog
|
|
||||||
import com.meloda.fast.fragment.*
|
|
||||||
import com.meloda.fast.service.LongPollService
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
|
||||||
import com.meloda.fast.util.ViewUtils
|
|
||||||
import com.meloda.fast.widget.Toolbar
|
|
||||||
import com.meloda.vksdk.VKApi
|
|
||||||
import com.meloda.vksdk.model.VKUser
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : BaseActivity(),
|
class MainActivity : BaseActivity(R.layout.activity_main) {
|
||||||
NavigationView.OnNavigationItemSelectedListener,
|
|
||||||
BottomNavigationView.OnNavigationItemSelectedListener {
|
|
||||||
|
|
||||||
private lateinit var fragmentConversationsDeprecated: FragmentConversationsDeprecated
|
private val binding: ActivityMainBinding by viewBinding()
|
||||||
private lateinit var fragmentFriendsDeprecated: FragmentFriendsDeprecated
|
|
||||||
private lateinit var settingsFragment: SettingsFragment
|
|
||||||
|
|
||||||
private var selectedId = 0
|
|
||||||
|
|
||||||
private lateinit var drawerLayout: DrawerLayout
|
|
||||||
lateinit var bottomBar: BottomNavigationView
|
|
||||||
private lateinit var navigationView: NavigationView
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
|
||||||
|
|
||||||
initViews()
|
|
||||||
|
|
||||||
// checkLogin()
|
|
||||||
|
|
||||||
if (UserConfig.isLoggedIn()) {
|
|
||||||
VKApi.init(Locale.getDefault().language, UserConfig.token, AppGlobal.handler)
|
|
||||||
|
|
||||||
supportFragmentManager.beginTransaction()
|
|
||||||
.replace(R.id.fragmentContainer, ChatsFragment())
|
|
||||||
.commit()
|
|
||||||
} else {
|
|
||||||
bottomBar.isVisible = false
|
|
||||||
|
|
||||||
supportFragmentManager.beginTransaction()
|
supportFragmentManager.beginTransaction()
|
||||||
.replace(R.id.fragmentContainer, LoginFragment())
|
.replace(R.id.fragmentContainer, LoginFragment())
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TimeManager.init(this)
|
|
||||||
|
|
||||||
// prepareFragments()
|
|
||||||
|
|
||||||
// prepareNavigationView()
|
|
||||||
// prepareBottomBar()
|
|
||||||
// checkLogin()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initViews() {
|
|
||||||
drawerLayout = findViewById(R.id.drawerLayout)
|
|
||||||
bottomBar = findViewById(R.id.bottomBar)
|
|
||||||
navigationView = findViewById(R.id.navigationView)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
TimeManager.destroy()
|
|
||||||
super.onDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareFragments() {
|
|
||||||
fragmentConversationsDeprecated = FragmentConversationsDeprecated()
|
|
||||||
fragmentFriendsDeprecated = FragmentFriendsDeprecated(UserConfig.userId)
|
|
||||||
settingsFragment = SettingsFragment()
|
|
||||||
|
|
||||||
val containerId = R.id.fragmentContainer
|
|
||||||
|
|
||||||
FragmentSwitcher.addFragments(
|
|
||||||
supportFragmentManager,
|
|
||||||
containerId,
|
|
||||||
listOf(fragmentConversationsDeprecated)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun initToolbar(toolbar: Toolbar) {
|
|
||||||
toolbar.navigationIcon =
|
|
||||||
drawable(R.drawable.ic_search).tint(color(R.color.text_secondary_60_alpha))
|
|
||||||
|
|
||||||
toolbar.setTitleMode(Toolbar.TitleMode.HINT)
|
|
||||||
toolbar.setTitle(R.string.action_search)
|
|
||||||
toolbar.setAvatarClickListener { openAccountDialog() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openAccountDialog() {
|
|
||||||
AccountDialog().show(supportFragmentManager, AccountDialog.TAG)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareNavigationView() {
|
|
||||||
navigationView.layoutParams?.width = AppGlobal.screenWidth - AppGlobal.screenWidth / 6
|
|
||||||
|
|
||||||
navigationView.setNavigationItemSelectedListener(this)
|
|
||||||
|
|
||||||
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareBottomBar() {
|
|
||||||
// val menu = bottomBar.menu
|
|
||||||
//
|
|
||||||
// val navigationFriends = menu.add(R.string.navigation_friends)
|
|
||||||
// navigationFriends.icon = drawable(R.drawable.ic_people_outline)
|
|
||||||
//
|
|
||||||
// val navigationConversations = menu.add(R.string.navigation_conversations)
|
|
||||||
// navigationConversations.icon = drawable(R.drawable.ic_message_outline)
|
|
||||||
//
|
|
||||||
// val navigationImportant = menu.add(R.string.navigation_important)
|
|
||||||
// navigationImportant.icon = drawable(R.drawable.ic_star_border)
|
|
||||||
|
|
||||||
bottomBar.setOnNavigationItemSelectedListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createMenuItem(menu: Menu, tag: String): MenuItem {
|
|
||||||
return when (tag) {
|
|
||||||
"friends" ->
|
|
||||||
menu.add("Friends").apply { icon = drawable(R.drawable.ic_people_outline) }
|
|
||||||
"conversations" ->
|
|
||||||
menu.add("Conversations").apply { icon = drawable(R.drawable.ic_message_outline) }
|
|
||||||
"important" ->
|
|
||||||
menu.add("Important").apply { icon = drawable(R.drawable.ic_star_border) }
|
|
||||||
|
|
||||||
else -> menu.add("")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkLogin() {
|
|
||||||
if (UserConfig.isLoggedIn()) {
|
|
||||||
startLongPoll()
|
|
||||||
loadProfileInfo()
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openMainScreen() {
|
|
||||||
selectedId = R.id.navigationConversations
|
|
||||||
bottomBar.selectedItemId = selectedId
|
|
||||||
openConversationsScreen()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startLongPoll() {
|
|
||||||
startService(Intent(this, LongPollService::class.java))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openConversationsScreen() {
|
|
||||||
FragmentSwitcher.showFragment(
|
|
||||||
supportFragmentManager,
|
|
||||||
fragmentConversationsDeprecated.javaClass.simpleName,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openFriendsScreen() {
|
|
||||||
FragmentSwitcher.showFragment(
|
|
||||||
supportFragmentManager,
|
|
||||||
fragmentFriendsDeprecated.javaClass.simpleName,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openSettingsScreen() {
|
|
||||||
startActivity(Intent(this, SettingsActivityDeprecated::class.java))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadProfileInfo() {
|
|
||||||
if (AndroidUtils.hasConnection()) {
|
|
||||||
// TaskManager.loadUser(
|
|
||||||
// VKApiKeys.UPDATE_USER, UserConfig.userId,
|
|
||||||
// object : OnResponseListener<VKUser> {
|
|
||||||
// override fun onResponse(response: VKUser) {
|
|
||||||
// prepareNavigationHeader(response)
|
|
||||||
// openMainScreen()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onError(t: Throwable) {
|
|
||||||
// openMainScreen()
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareNavigationHeader(user: VKUser) {
|
|
||||||
ViewUtils.prepareNavigationHeader(navigationView.getHeaderView(0), user)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNavigationItemSelected(item: MenuItem): Boolean {
|
|
||||||
switchFragment(item.itemId)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun switchFragment(itemId: Int) {
|
|
||||||
var valid = true
|
|
||||||
|
|
||||||
when (itemId) {
|
|
||||||
R.id.navigationConversations -> {
|
|
||||||
openConversationsScreen()
|
|
||||||
}
|
|
||||||
R.id.navigationFriends -> {
|
|
||||||
openFriendsScreen()
|
|
||||||
}
|
|
||||||
R.id.navigationSettings -> {
|
|
||||||
openSettingsScreen()
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
valid = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) return
|
|
||||||
|
|
||||||
if (selectedId != itemId) {
|
|
||||||
selectedId = itemId
|
|
||||||
navigationView.setCheckedItem(selectedId)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
|
|
||||||
drawerLayout.closeDrawer(GravityCompat.START)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
if (drawerLayout.isDrawerOpen(navigationView)) {
|
|
||||||
drawerLayout.closeDrawer(navigationView)
|
|
||||||
} else {
|
|
||||||
super.onBackPressed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,402 +0,0 @@
|
|||||||
package com.meloda.fast.activity
|
|
||||||
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.widget.*
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.core.widget.addTextChangedListener
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
import com.amulyakhare.textdrawable.TextDrawable
|
|
||||||
import com.meloda.extensions.ContextExtensions.color
|
|
||||||
import com.meloda.extensions.DrawableExtensions.tint
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.activity.ui.presenter.MessagesPresenterDeprecated
|
|
||||||
import com.meloda.fast.activity.ui.view.MessagesViewDeprecated
|
|
||||||
import com.meloda.fast.base.BaseActivity
|
|
||||||
import com.meloda.fast.common.AppGlobal
|
|
||||||
import com.meloda.fast.dialog.ProfileDialog
|
|
||||||
import com.meloda.fast.fragment.SettingsFragment
|
|
||||||
import com.meloda.fast.util.KeyboardUtils
|
|
||||||
import com.meloda.fast.util.TextUtils
|
|
||||||
import com.meloda.fast.util.ViewUtils
|
|
||||||
import com.meloda.fast.widget.CircleImageView
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
import com.meloda.vksdk.model.VKGroup
|
|
||||||
import com.meloda.vksdk.model.VKModel
|
|
||||||
import com.meloda.vksdk.model.VKUser
|
|
||||||
|
|
||||||
|
|
||||||
class MessagesActivityDeprecated : BaseActivity(), MessagesViewDeprecated {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val TAG = "MessagesActivity"
|
|
||||||
|
|
||||||
const val MESSAGES_COUNT = 30
|
|
||||||
|
|
||||||
const val TAG_EXTRA_TITLE = "title"
|
|
||||||
const val TAG_EXTRA_AVATAR = "avatar"
|
|
||||||
const val TAG_EXTRA_ID = "id"
|
|
||||||
const val TAG_EXTRA_USER = "user"
|
|
||||||
const val TAG_EXTRA_GROUP = "group"
|
|
||||||
}
|
|
||||||
|
|
||||||
private var isEdit = false
|
|
||||||
|
|
||||||
private var fabState = FabState.VOICE
|
|
||||||
|
|
||||||
private enum class FabState {
|
|
||||||
VOICE, SEND, EDIT, DELETE, BLOCKED
|
|
||||||
}
|
|
||||||
|
|
||||||
private var title = ""
|
|
||||||
private var avatar = ""
|
|
||||||
|
|
||||||
private var lastMessageText = ""
|
|
||||||
private var attachments = arrayListOf<VKModel>()
|
|
||||||
|
|
||||||
private var peerId = 0
|
|
||||||
|
|
||||||
private var dialogUser: VKUser? = null
|
|
||||||
private var dialogGroup: VKGroup? = null
|
|
||||||
|
|
||||||
private lateinit var presenterDeprecated: MessagesPresenterDeprecated
|
|
||||||
|
|
||||||
lateinit var recyclerView: RecyclerView
|
|
||||||
private lateinit var refreshLayout: SwipeRefreshLayout
|
|
||||||
private lateinit var toolbar: Toolbar
|
|
||||||
private lateinit var chatAvatar: CircleImageView
|
|
||||||
private lateinit var chatTitle: TextView
|
|
||||||
private lateinit var chatInfo: TextView
|
|
||||||
private lateinit var chatPanel: LinearLayout
|
|
||||||
private lateinit var chatMessage: EditText
|
|
||||||
private lateinit var chatSend: ImageButton
|
|
||||||
private lateinit var progressBar: ProgressBar
|
|
||||||
|
|
||||||
private lateinit var noItemsView: LinearLayout
|
|
||||||
private lateinit var noInternetView: LinearLayout
|
|
||||||
private lateinit var errorView: LinearLayout
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
presenterDeprecated.destroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_messages)
|
|
||||||
initViews()
|
|
||||||
|
|
||||||
initExtraData()
|
|
||||||
|
|
||||||
prepareToolbar()
|
|
||||||
prepareRefreshLayout()
|
|
||||||
prepareRecyclerView()
|
|
||||||
prepareEditText()
|
|
||||||
|
|
||||||
presenterDeprecated = MessagesPresenterDeprecated(this)
|
|
||||||
presenterDeprecated.setup(peerId, recyclerView)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initViews() {
|
|
||||||
toolbar = findViewById(R.id.toolbar)
|
|
||||||
recyclerView = findViewById(R.id.recyclerView)
|
|
||||||
refreshLayout = findViewById(R.id.refreshLayout)
|
|
||||||
chatAvatar = findViewById(R.id.chatAvatar)
|
|
||||||
chatTitle = findViewById(R.id.chatTitle)
|
|
||||||
chatInfo = findViewById(R.id.chatInfo)
|
|
||||||
chatPanel = findViewById(R.id.chatPanel)
|
|
||||||
chatMessage = findViewById(R.id.chatMessage)
|
|
||||||
chatSend = findViewById(R.id.chatSend)
|
|
||||||
progressBar = findViewById(R.id.progressBar)
|
|
||||||
|
|
||||||
noItemsView = findViewById(R.id.noItemsView)
|
|
||||||
noInternetView = findViewById(R.id.noInternetView)
|
|
||||||
errorView = findViewById(R.id.errorView)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initExtraData() {
|
|
||||||
peerId = intent.getIntExtra(TAG_EXTRA_ID, -1)
|
|
||||||
title = intent.getStringExtra(TAG_EXTRA_TITLE) ?: ""
|
|
||||||
avatar = intent.getStringExtra(TAG_EXTRA_AVATAR) ?: ""
|
|
||||||
|
|
||||||
dialogUser = intent.getSerializableExtra(TAG_EXTRA_USER) as VKUser?
|
|
||||||
dialogGroup = intent.getSerializableExtra(TAG_EXTRA_GROUP) as VKGroup?
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareToolbar() {
|
|
||||||
setSupportActionBar(toolbar)
|
|
||||||
|
|
||||||
val placeholder = TextDrawable
|
|
||||||
.builder()
|
|
||||||
.buildRound(TextUtils.getFirstLetterFromString(title), color(R.color.accent))
|
|
||||||
|
|
||||||
chatAvatar.setImageDrawable(placeholder)
|
|
||||||
|
|
||||||
// chatAvatar.loadImage(avatar, placeholder)
|
|
||||||
|
|
||||||
toolbar.setOnClickListener { presenterDeprecated.openProfile() }
|
|
||||||
|
|
||||||
chatAvatar.setOnClickListener { presenterDeprecated.openProfile() }
|
|
||||||
|
|
||||||
chatTitle.text = title
|
|
||||||
|
|
||||||
supportActionBar?.setDisplayShowTitleEnabled(false)
|
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
|
||||||
|
|
||||||
toolbar.navigationIcon.tint(color(R.color.accent))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareRefreshLayout() {
|
|
||||||
refreshLayout.isEnabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareRecyclerView() {
|
|
||||||
recyclerView.layoutManager =
|
|
||||||
LinearLayoutManager(this, RecyclerView.VERTICAL, false).also {
|
|
||||||
it.stackFromEnd = true
|
|
||||||
}
|
|
||||||
|
|
||||||
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
|
||||||
super.onScrolled(recyclerView, dx, dy)
|
|
||||||
|
|
||||||
if (dy < 0 && AppGlobal.inputMethodManager.isAcceptingText && AppGlobal.preferences.getBoolean(
|
|
||||||
SettingsFragment.KEY_HIDE_KEYBOARD_ON_SCROLL_UP,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
KeyboardUtils.hideKeyboardFrom(chatMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareEditText() {
|
|
||||||
chatMessage.addTextChangedListener {
|
|
||||||
fabState = if (it.toString().trim().isEmpty()) {
|
|
||||||
if (isEdit) {
|
|
||||||
FabState.DELETE
|
|
||||||
} else {
|
|
||||||
FabState.VOICE
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isEdit) {
|
|
||||||
FabState.EDIT
|
|
||||||
} else {
|
|
||||||
FabState.SEND
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshFabStyle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
|
||||||
menuInflater.inflate(R.menu.activity_messages, menu)
|
|
||||||
return super.onCreateOptionsMenu(menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
when (item.itemId) {
|
|
||||||
android.R.id.home -> onBackPressed()
|
|
||||||
|
|
||||||
R.id.messagesRefresh -> {
|
|
||||||
presenterDeprecated.updateData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun refreshFabStyle() {
|
|
||||||
chatSend.isClickable = true
|
|
||||||
|
|
||||||
when (fabState) {
|
|
||||||
FabState.VOICE -> {
|
|
||||||
chatSend.apply {
|
|
||||||
setImageResource(R.drawable.ic_mic)
|
|
||||||
|
|
||||||
setOnClickListener {
|
|
||||||
showVoiceRecordingTip()
|
|
||||||
}
|
|
||||||
setOnLongClickListener {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FabState.SEND -> {
|
|
||||||
chatSend.apply {
|
|
||||||
setImageResource(R.drawable.ic_send)
|
|
||||||
|
|
||||||
setOnClickListener {
|
|
||||||
presenterDeprecated.sendMessage(chatMessage.text.toString(), attachments)
|
|
||||||
}
|
|
||||||
|
|
||||||
setOnLongClickListener {
|
|
||||||
presenterDeprecated.sendMessage(chatMessage.text.toString(), attachments, false)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FabState.EDIT -> {
|
|
||||||
chatSend.apply {
|
|
||||||
setImageResource(R.drawable.ic_done)
|
|
||||||
|
|
||||||
setOnClickListener {
|
|
||||||
//editMessage()
|
|
||||||
}
|
|
||||||
|
|
||||||
setOnLongClickListener {
|
|
||||||
performClick()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
FabState.DELETE -> {
|
|
||||||
chatSend.apply {
|
|
||||||
setImageResource(R.drawable.ic_trash_outline)
|
|
||||||
|
|
||||||
chatSend.setOnClickListener {
|
|
||||||
//deleteMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
chatSend.setOnLongClickListener {
|
|
||||||
performClick()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FabState.BLOCKED -> {
|
|
||||||
chatSend.apply {
|
|
||||||
isClickable = false
|
|
||||||
setImageResource(R.drawable.ic_lock)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showChatPanel() {
|
|
||||||
chatPanel.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideChatPanel() {
|
|
||||||
chatPanel.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setWritingAllowed(allowed: Boolean) {
|
|
||||||
if (allowed) {
|
|
||||||
fabState = FabState.VOICE
|
|
||||||
|
|
||||||
chatSend.imageTintList = ColorStateList.valueOf(color(R.color.accent))
|
|
||||||
|
|
||||||
chatMessage.isEnabled = true
|
|
||||||
|
|
||||||
chatPanel.setBackgroundResource(R.drawable.chat_panel_background)
|
|
||||||
} else {
|
|
||||||
fabState = FabState.BLOCKED
|
|
||||||
|
|
||||||
chatSend.imageTintList = ColorStateList.valueOf(Color.WHITE)
|
|
||||||
|
|
||||||
chatMessage.isEnabled = false
|
|
||||||
chatMessage.setHintTextColor(Color.WHITE)
|
|
||||||
chatMessage.setHint(R.string.no_access)
|
|
||||||
|
|
||||||
chatPanel.setBackgroundResource(R.drawable.chat_panel_background_blocked)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setChatInfo(info: String) {
|
|
||||||
chatInfo.text = info
|
|
||||||
chatInfo.isVisible = info.isNotEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openProfile(conversation: VKConversation) {
|
|
||||||
conversation.let {
|
|
||||||
val profileDialog = ProfileDialog(it, title)
|
|
||||||
profileDialog.show(supportFragmentManager, ProfileDialog.TAG)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showErrorLoadConversationAlert() {
|
|
||||||
val builder = AlertDialog.Builder(this)
|
|
||||||
builder.setTitle(R.string.error_occurred)
|
|
||||||
builder.setMessage(R.string.error_loading_message)
|
|
||||||
builder.setPositiveButton(R.string.retry) { _, _ ->
|
|
||||||
presenterDeprecated.loadConversation(peerId)
|
|
||||||
}
|
|
||||||
builder.setNegativeButton(R.string.no) { _, _ -> onBackPressed() }
|
|
||||||
builder.setCancelable(false)
|
|
||||||
builder.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showVoiceRecordingTip() {
|
|
||||||
Toast.makeText(this, R.string.voice_record_tip, Toast.LENGTH_LONG).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setMessageText(text: String) {
|
|
||||||
chatMessage.setText(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showErrorSnackbar(t: Throwable) {
|
|
||||||
ViewUtils.showErrorSnackbar(getRootView(), t)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareNoItemsView() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showNoItemsView() {
|
|
||||||
noItemsView.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideNoItemsView() {
|
|
||||||
noItemsView.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareNoInternetView() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showNoInternetView() {
|
|
||||||
noInternetView.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideNoInternetView() {
|
|
||||||
noInternetView.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareErrorView() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showErrorView() {
|
|
||||||
errorView.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideErrorView() {
|
|
||||||
errorView.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showProgressBar() {
|
|
||||||
progressBar.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideProgressBar() {
|
|
||||||
progressBar.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showRefreshLayout() {
|
|
||||||
refreshLayout.isRefreshing = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideRefreshLayout() {
|
|
||||||
refreshLayout.isRefreshing = false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package com.meloda.fast.activity
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import com.meloda.extensions.ContextExtensions.drawable
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.base.BaseActivity
|
|
||||||
import com.meloda.fast.common.FragmentSwitcher
|
|
||||||
import com.meloda.fast.fragment.SettingsFragment
|
|
||||||
import com.meloda.fast.util.ColorUtils
|
|
||||||
import com.meloda.fast.widget.Toolbar
|
|
||||||
|
|
||||||
class SettingsActivityDeprecated : BaseActivity() {
|
|
||||||
|
|
||||||
private lateinit var toolbar: Toolbar
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_settings)
|
|
||||||
initViews()
|
|
||||||
|
|
||||||
setSupportActionBar(toolbar)
|
|
||||||
|
|
||||||
toolbar.setNavigationClickListener { onBackPressed() }
|
|
||||||
|
|
||||||
toolbar.navigationIcon = drawable(R.drawable.ic_arrow_back)
|
|
||||||
toolbar.tintNavigationIcon(ColorUtils.getColorAccent(this))
|
|
||||||
|
|
||||||
supportFragmentManager.beginTransaction()
|
|
||||||
.replace(R.id.fragmentContainer, SettingsFragment())
|
|
||||||
.commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initViews() {
|
|
||||||
toolbar = findViewById(R.id.toolbar)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
val currentFragment = FragmentSwitcher.getCurrentFragment(supportFragmentManager) ?: return
|
|
||||||
|
|
||||||
if (currentFragment.javaClass == SettingsFragment::class.java && (currentFragment as SettingsFragment).onBackPressed()) {
|
|
||||||
super.onBackPressed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,350 +0,0 @@
|
|||||||
package com.meloda.fast.activity
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.app.DownloadManager
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Environment
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.core.content.FileProvider
|
|
||||||
import androidx.core.text.HtmlCompat
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import com.github.rahatarmanahmed.cpv.CircularProgressView
|
|
||||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
|
||||||
import com.meloda.concurrent.TaskManager
|
|
||||||
import com.meloda.extensions.ContextExtensions.drawable
|
|
||||||
import com.meloda.extensions.FloatExtensions.int
|
|
||||||
import com.meloda.fast.BuildConfig
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.base.BaseActivity
|
|
||||||
import com.meloda.fast.common.AppGlobal
|
|
||||||
import com.meloda.fast.common.UpdateManager
|
|
||||||
import com.meloda.fast.model.NewUpdateInfo
|
|
||||||
import com.meloda.fast.receiver.DownloadUpdateReceiver
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
|
||||||
import com.meloda.fast.util.TimeUtils
|
|
||||||
import com.meloda.vksdk.OnResponseListener
|
|
||||||
import java.io.File
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
class UpdateActivityDeprecated : BaseActivity() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val FILE_BASE_PATH = "file://"
|
|
||||||
private const val MIME_TYPE = "application/vnd.android.package-archive"
|
|
||||||
private const val PROVIDER_PATH = ".provider"
|
|
||||||
}
|
|
||||||
|
|
||||||
private var isChecking = false
|
|
||||||
private var isNewUpdate = false
|
|
||||||
private var isDownloading = false
|
|
||||||
|
|
||||||
private var downloadId = 0L
|
|
||||||
|
|
||||||
private var lastCheckTime = 0L
|
|
||||||
|
|
||||||
private var newUpdate = NewUpdateInfo()
|
|
||||||
|
|
||||||
private lateinit var updateCheckUpdates: ExtendedFloatingActionButton
|
|
||||||
private lateinit var updateState: TextView
|
|
||||||
private lateinit var updateVersion: TextView
|
|
||||||
private lateinit var updateInfo: TextView
|
|
||||||
private lateinit var updateInfoLayout: LinearLayout
|
|
||||||
private lateinit var updateProgress: LinearLayout
|
|
||||||
private lateinit var updateProgressBar: CircularProgressView
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
setContentView(R.layout.activity_update)
|
|
||||||
initViews()
|
|
||||||
|
|
||||||
updateProgressBar.maxProgress = 100F
|
|
||||||
|
|
||||||
lastCheckTime = AppGlobal.preferences.getLong("updateCheckTime", 0)
|
|
||||||
|
|
||||||
refreshState()
|
|
||||||
|
|
||||||
checkUpdates()
|
|
||||||
|
|
||||||
updateCheckUpdates.setOnClickListener {
|
|
||||||
lastCheckTime = System.currentTimeMillis()
|
|
||||||
AppGlobal.preferences.edit().putLong("updateCheckTime", lastCheckTime).apply()
|
|
||||||
|
|
||||||
checkUpdates()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initViews() {
|
|
||||||
updateCheckUpdates = findViewById(R.id.updateCheckUpdates)
|
|
||||||
updateInfo = findViewById(R.id.updateInfo)
|
|
||||||
updateVersion = findViewById(R.id.updateVersion)
|
|
||||||
updateState = findViewById(R.id.updateState)
|
|
||||||
updateInfoLayout = findViewById(R.id.updateInfoLayout)
|
|
||||||
updateProgress = findViewById(R.id.updateProgress)
|
|
||||||
updateProgressBar = updateProgress.getChildAt(0) as CircularProgressView
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun installUpdate(context: Activity, file: File) {
|
|
||||||
val install = Intent(Intent.ACTION_VIEW)
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
||||||
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
install.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
|
|
||||||
install.data = FileProvider.getUriForFile(
|
|
||||||
this,
|
|
||||||
BuildConfig.APPLICATION_ID + PROVIDER_PATH,
|
|
||||||
file
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
install.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
|
|
||||||
install.setDataAndType(Uri.fromFile(file), MIME_TYPE)
|
|
||||||
}
|
|
||||||
|
|
||||||
context.startActivity(install)
|
|
||||||
// context.finishAffinity()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun downloadUpdate() {
|
|
||||||
checkIsInstallingAllowed()
|
|
||||||
|
|
||||||
val timer = Timer()
|
|
||||||
|
|
||||||
updateCheckUpdates.shrink()
|
|
||||||
updateCheckUpdates.isClickable = false
|
|
||||||
|
|
||||||
isDownloading = true
|
|
||||||
refreshState()
|
|
||||||
|
|
||||||
TaskManager.execute {
|
|
||||||
val apkName = newUpdate.version
|
|
||||||
|
|
||||||
val destination =
|
|
||||||
getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/$apkName.apk"
|
|
||||||
|
|
||||||
val uri = Uri.parse("$FILE_BASE_PATH$destination")
|
|
||||||
|
|
||||||
val file = File(destination)
|
|
||||||
if (file.exists()) file.delete()
|
|
||||||
|
|
||||||
val request = DownloadManager.Request(Uri.parse(newUpdate.downloadLink))
|
|
||||||
|
|
||||||
request.setTitle("${getString(R.string.app_name)} ${apkName}.apk")
|
|
||||||
request.setMimeType(MIME_TYPE)
|
|
||||||
request.setDestinationUri(uri)
|
|
||||||
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
|
|
||||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
|
|
||||||
|
|
||||||
val receiver = DownloadUpdateReceiver()
|
|
||||||
receiver.listener = object : OnResponseListener<Any?> {
|
|
||||||
override fun onResponse(response: Any?) {
|
|
||||||
timer.cancel()
|
|
||||||
|
|
||||||
installUpdate(this@UpdateActivityDeprecated, file)
|
|
||||||
|
|
||||||
unregisterReceiver(receiver)
|
|
||||||
|
|
||||||
runOnUiThread {
|
|
||||||
updateProgressBar.isIndeterminate = true
|
|
||||||
|
|
||||||
updateCheckUpdates.extend()
|
|
||||||
updateCheckUpdates.isClickable = true
|
|
||||||
|
|
||||||
isDownloading = false
|
|
||||||
refreshState()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registerReceiver(receiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
|
|
||||||
|
|
||||||
downloadId = AppGlobal.downloadManager.enqueue(request)
|
|
||||||
|
|
||||||
timer.schedule(object : TimerTask() {
|
|
||||||
override fun run() {
|
|
||||||
val query = DownloadManager.Query()
|
|
||||||
query.setFilterById(downloadId)
|
|
||||||
|
|
||||||
val cursor = AppGlobal.downloadManager.query(query)
|
|
||||||
if (cursor.moveToFirst()) {
|
|
||||||
val sizeIndex =
|
|
||||||
cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
|
|
||||||
val downloadedIndex =
|
|
||||||
cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
|
|
||||||
val size = cursor.getInt(sizeIndex)
|
|
||||||
val downloaded = cursor.getInt(downloadedIndex)
|
|
||||||
|
|
||||||
val progress = if (size != -1) (downloaded * 100.0F / size) else 0.0F
|
|
||||||
|
|
||||||
Log.d("Downloading update", "progress $progress%")
|
|
||||||
|
|
||||||
if (progress.int() > 0) {
|
|
||||||
runOnUiThread {
|
|
||||||
if (updateProgressBar.isIndeterminate) {
|
|
||||||
updateProgressBar.isIndeterminate = false
|
|
||||||
updateProgressBar.stopAnimation()
|
|
||||||
}
|
|
||||||
|
|
||||||
updateProgressBar.progress = progress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 0, 1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkUpdates() {
|
|
||||||
if (isChecking) return
|
|
||||||
|
|
||||||
isChecking = true
|
|
||||||
refreshState()
|
|
||||||
|
|
||||||
UpdateManager.checkUpdates(object : UpdateManager.OnUpdateListener {
|
|
||||||
override fun onNewUpdate(updateInfo: NewUpdateInfo) {
|
|
||||||
isChecking = false
|
|
||||||
isNewUpdate = true
|
|
||||||
|
|
||||||
this@UpdateActivityDeprecated.newUpdate = updateInfo
|
|
||||||
|
|
||||||
refreshState()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNoUpdates() {
|
|
||||||
isNewUpdate = false
|
|
||||||
isChecking = false
|
|
||||||
|
|
||||||
this@UpdateActivityDeprecated.newUpdate = NewUpdateInfo()
|
|
||||||
|
|
||||||
refreshState()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkIsInstallingAllowed() {
|
|
||||||
if (!AndroidUtils.isCanInstallUnknownApps(this)) {
|
|
||||||
val builder = AlertDialog.Builder(this)
|
|
||||||
builder.setTitle(R.string.warning)
|
|
||||||
builder.setMessage(R.string.update_unknown_sources_disabled_message)
|
|
||||||
builder.setPositiveButton(R.string.yes) { _, _ ->
|
|
||||||
AndroidUtils.openInstallUnknownAppsScreen(this)
|
|
||||||
}
|
|
||||||
builder.setNegativeButton(R.string.no, null)
|
|
||||||
builder.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun refreshState() {
|
|
||||||
when {
|
|
||||||
isChecking -> {
|
|
||||||
updateState.text = getString(R.string.update_state_checking)
|
|
||||||
|
|
||||||
setAlpha(updateInfoLayout, true)
|
|
||||||
setAlpha(updateProgress, false)
|
|
||||||
setAlpha(updateCheckUpdates, true)
|
|
||||||
}
|
|
||||||
isDownloading -> {
|
|
||||||
updateState.text = getString(R.string.update_state_downloading)
|
|
||||||
|
|
||||||
setAlpha(updateInfoLayout, true)
|
|
||||||
setAlpha(updateProgress, false)
|
|
||||||
setAlpha(updateCheckUpdates, true)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
if (isNewUpdate) {
|
|
||||||
updateCheckUpdates.text = getString(R.string.update_download)
|
|
||||||
updateCheckUpdates.icon = drawable(R.drawable.ic_file_download)
|
|
||||||
} else {
|
|
||||||
updateCheckUpdates.text = getString(R.string.update_check_updates)
|
|
||||||
updateCheckUpdates.icon = drawable(R.drawable.ic_refresh)
|
|
||||||
}
|
|
||||||
|
|
||||||
updateCheckUpdates.setOnClickListener {
|
|
||||||
if (isNewUpdate) {
|
|
||||||
downloadUpdate()
|
|
||||||
} else {
|
|
||||||
checkUpdates()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateState.text =
|
|
||||||
getString(if (isNewUpdate) R.string.update_state_update_available else R.string.update_state_no_updates)
|
|
||||||
|
|
||||||
updateVersion.text =
|
|
||||||
if (isNewUpdate)
|
|
||||||
getString(
|
|
||||||
R.string.update_new_version,
|
|
||||||
newUpdate.version,
|
|
||||||
newUpdate.code
|
|
||||||
)
|
|
||||||
else getString(
|
|
||||||
R.string.update_current_version,
|
|
||||||
AppGlobal.versionName,
|
|
||||||
AppGlobal.versionCode
|
|
||||||
)
|
|
||||||
|
|
||||||
updateInfo.text =
|
|
||||||
when {
|
|
||||||
isNewUpdate -> if (newUpdate.changelog.isEmpty()) "" else getString(
|
|
||||||
R.string.update_changelog,
|
|
||||||
HtmlCompat.fromHtml(
|
|
||||||
newUpdate.changelog,
|
|
||||||
HtmlCompat.FROM_HTML_MODE_LEGACY
|
|
||||||
)
|
|
||||||
)
|
|
||||||
lastCheckTime.toString().isEmpty() || lastCheckTime == 0L -> ""
|
|
||||||
else -> getString(R.string.update_last_check_time, getCheckTime())
|
|
||||||
}
|
|
||||||
|
|
||||||
setAlpha(updateInfoLayout, false)
|
|
||||||
setAlpha(updateProgress, true)
|
|
||||||
setAlpha(updateCheckUpdates, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCheckTime(): String {
|
|
||||||
val time = lastCheckTime
|
|
||||||
|
|
||||||
val lastTime = TimeUtils.removeTime(Date(time))
|
|
||||||
val currentTime = TimeUtils.removeTime(Date(System.currentTimeMillis()))
|
|
||||||
|
|
||||||
val format = if (currentTime > lastTime) {
|
|
||||||
"dd.MM.yyyy HH:mm"
|
|
||||||
} else {
|
|
||||||
"HH:mm"
|
|
||||||
}
|
|
||||||
|
|
||||||
return SimpleDateFormat(format, Locale.getDefault()).format(time)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setAlpha(view: View, toZero: Boolean) {
|
|
||||||
if (toZero) {
|
|
||||||
view.animate()
|
|
||||||
.alpha(0F)
|
|
||||||
.setDuration(250)
|
|
||||||
.withEndAction { view.isVisible = false }
|
|
||||||
.start()
|
|
||||||
} else {
|
|
||||||
view.animate()
|
|
||||||
.alpha(1F)
|
|
||||||
.setDuration(250)
|
|
||||||
.withStartAction { view.isVisible = true }
|
|
||||||
.start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-254
@@ -1,254 +0,0 @@
|
|||||||
package com.meloda.fast.activity.ui.presenter
|
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.meloda.concurrent.EventInfo
|
|
||||||
import com.meloda.concurrent.TaskManager
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.UserConfig
|
|
||||||
import com.meloda.fast.activity.ui.repository.MessagesRepositoryDeprecated
|
|
||||||
import com.meloda.fast.activity.ui.view.MessagesViewDeprecated
|
|
||||||
import com.meloda.fast.adapter.MessagesAdapterDeprecated
|
|
||||||
import com.meloda.fast.common.AppGlobal
|
|
||||||
import com.meloda.fast.listener.ItemClickListener
|
|
||||||
import com.meloda.fast.listener.ItemLongClickListener
|
|
||||||
import com.meloda.mvp.MvpOnResponseListener
|
|
||||||
import com.meloda.mvp.MvpPresenter
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
import com.meloda.vksdk.model.VKMessage
|
|
||||||
import com.meloda.vksdk.model.VKModel
|
|
||||||
import kotlin.random.Random
|
|
||||||
|
|
||||||
class MessagesPresenterDeprecated(viewState: MessagesViewDeprecated) :
|
|
||||||
MvpPresenter<VKMessage, MessagesRepositoryDeprecated, MessagesViewDeprecated>(
|
|
||||||
viewState,
|
|
||||||
MessagesRepositoryDeprecated::class.java.name
|
|
||||||
),
|
|
||||||
ItemClickListener,
|
|
||||||
ItemLongClickListener,
|
|
||||||
TaskManager.OnEventListener {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val DEFAULT_MESSAGES_COUNT = 30
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var adapter: MessagesAdapterDeprecated
|
|
||||||
private lateinit var conversation: VKConversation
|
|
||||||
|
|
||||||
private var peerId: Int = -1
|
|
||||||
|
|
||||||
private var lastMessageText: String = ""
|
|
||||||
|
|
||||||
private lateinit var recyclerView: RecyclerView
|
|
||||||
|
|
||||||
override fun destroy() {
|
|
||||||
adapter.destroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setup(peerId: Int, recyclerView: RecyclerView) {
|
|
||||||
this.peerId = peerId
|
|
||||||
this.recyclerView = recyclerView
|
|
||||||
this.context = recyclerView.context
|
|
||||||
|
|
||||||
viewState.showProgressBar()
|
|
||||||
getCachedConversation(peerId)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateData() {
|
|
||||||
adapter.clear()
|
|
||||||
loadMessages(peerId)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun openProfile() {
|
|
||||||
viewState.openProfile(conversation)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createAdapter() {
|
|
||||||
adapter = MessagesAdapterDeprecated(context!!, arrayListOf(), conversation).also {
|
|
||||||
it.itemClickListener = this
|
|
||||||
it.itemLongClickListener = this
|
|
||||||
}
|
|
||||||
|
|
||||||
recyclerView.adapter = adapter
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCachedConversation(peerId: Int) {
|
|
||||||
repository.getCachedConversation(peerId, object : MvpOnResponseListener<VKConversation> {
|
|
||||||
override fun onResponse(response: VKConversation) {
|
|
||||||
conversation = response
|
|
||||||
|
|
||||||
createAdapter()
|
|
||||||
refreshConversation(response)
|
|
||||||
|
|
||||||
getCachedMessages(peerId, 0, DEFAULT_MESSAGES_COUNT,
|
|
||||||
object : MvpOnResponseListener<Any?> {
|
|
||||||
override fun onResponse(response: Any?) {
|
|
||||||
loadConversation(peerId)
|
|
||||||
loadMessages(peerId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
loadConversation(peerId)
|
|
||||||
loadMessages(peerId)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
loadConversation(peerId)
|
|
||||||
loadMessages(peerId)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadConversation(peerId: Int) {
|
|
||||||
if (adapter.isNotEmpty()) {
|
|
||||||
viewState.hideProgressBar()
|
|
||||||
}
|
|
||||||
|
|
||||||
repository.loadConversation(peerId, object : MvpOnResponseListener<VKConversation> {
|
|
||||||
|
|
||||||
override fun onResponse(response: VKConversation) {
|
|
||||||
conversation = response
|
|
||||||
|
|
||||||
createAdapter()
|
|
||||||
refreshConversation(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
viewState.hideProgressBar()
|
|
||||||
viewState.showErrorLoadConversationAlert()
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun refreshConversation(conversation: VKConversation) {
|
|
||||||
checkIsWritingAllowed(conversation)
|
|
||||||
|
|
||||||
repository.getChatInfo(
|
|
||||||
conversation,
|
|
||||||
object : MvpOnResponseListener<String> {
|
|
||||||
override fun onResponse(response: String) {
|
|
||||||
viewState.setChatInfo(response)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
viewState.setChatInfo(AppGlobal.resources.getString(R.string.error_obtain_chat_info))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkIsWritingAllowed(conversation: VKConversation) {
|
|
||||||
if (conversation.isGroupChannel) {
|
|
||||||
viewState.hideChatPanel()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
viewState.showChatPanel()
|
|
||||||
viewState.setWritingAllowed(conversation.isAllowed)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCachedMessages(
|
|
||||||
peerId: Int,
|
|
||||||
offset: Int = 0,
|
|
||||||
count: Int = DEFAULT_MESSAGES_COUNT,
|
|
||||||
listener: MvpOnResponseListener<Any?>? = null
|
|
||||||
) {
|
|
||||||
repository.getCachedMessages(peerId, offset, count,
|
|
||||||
object : MvpOnResponseListener<ArrayList<VKMessage>> {
|
|
||||||
override fun onResponse(response: ArrayList<VKMessage>) {
|
|
||||||
viewState.hideProgressBar()
|
|
||||||
fillAdapter(response, offset)
|
|
||||||
|
|
||||||
listener?.onResponse(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
if (adapter.isEmpty()) {
|
|
||||||
viewState.showProgressBar()
|
|
||||||
}
|
|
||||||
|
|
||||||
listener?.onError(t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadMessages(peerId: Int, offset: Int = 0, count: Int = DEFAULT_MESSAGES_COUNT) {
|
|
||||||
repository.loadMessages(peerId, offset, count,
|
|
||||||
object : MvpOnResponseListener<ArrayList<VKMessage>> {
|
|
||||||
override fun onResponse(response: ArrayList<VKMessage>) {
|
|
||||||
fillAdapter(response, offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fillAdapter(
|
|
||||||
messages: ArrayList<VKMessage>,
|
|
||||||
offset: Int
|
|
||||||
) {
|
|
||||||
if (adapter.isEmpty()) adapter.isNotCachedValues = true
|
|
||||||
if (offset == 0) {
|
|
||||||
adapter.updateValues(messages)
|
|
||||||
} else {
|
|
||||||
adapter.addAll(messages)
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.notifyDataSetChanged()
|
|
||||||
|
|
||||||
if (offset == 0) recyclerView.scrollToPosition(adapter.itemCount - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemClick(position: Int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemLongClick(position: Int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNewEvent(info: EventInfo<*>) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendMessage(
|
|
||||||
text: String = "",
|
|
||||||
attachments: ArrayList<VKModel> = arrayListOf(),
|
|
||||||
scrollToBottom: Boolean = true
|
|
||||||
) {
|
|
||||||
lastMessageText = text
|
|
||||||
|
|
||||||
val message = VKMessage().also {
|
|
||||||
it.date = (System.currentTimeMillis() / 1000).toInt()
|
|
||||||
it.text = text
|
|
||||||
it.isOut = true
|
|
||||||
it.peerId = peerId
|
|
||||||
it.fromId = UserConfig.userId
|
|
||||||
it.randomId = Random.nextInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
viewState.setMessageText("")
|
|
||||||
|
|
||||||
adapter.addMessage(message, true, scrollToBottom)
|
|
||||||
|
|
||||||
repository.sendMessage(peerId, text, message.randomId, object : MvpOnResponseListener<Int> {
|
|
||||||
override fun onResponse(response: Int) {
|
|
||||||
message.id = response
|
|
||||||
|
|
||||||
// TaskManager.execute { MemoryCache.put(message) }
|
|
||||||
// TaskManager.loadMessage(VKApiKeys.UPDATE_MESSAGE, response)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
viewState.showErrorSnackbar(t)
|
|
||||||
|
|
||||||
viewState.setMessageText(lastMessageText)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-170
@@ -1,170 +0,0 @@
|
|||||||
package com.meloda.fast.activity.ui.repository
|
|
||||||
|
|
||||||
import com.meloda.concurrent.TaskManager
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.common.AppGlobal
|
|
||||||
import com.meloda.mvp.MvpOnResponseListener
|
|
||||||
import com.meloda.mvp.MvpRepository
|
|
||||||
import com.meloda.vksdk.OnResponseListener
|
|
||||||
import com.meloda.vksdk.VKApi
|
|
||||||
import com.meloda.vksdk.VKConstants
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
import com.meloda.vksdk.model.VKMessage
|
|
||||||
import com.meloda.vksdk.util.VKUtil
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class MessagesRepositoryDeprecated : MvpRepository<VKMessage>() {
|
|
||||||
|
|
||||||
fun loadMessages(
|
|
||||||
peerId: Int,
|
|
||||||
offset: Int,
|
|
||||||
count: Int,
|
|
||||||
listener: MvpOnResponseListener<ArrayList<VKMessage>>
|
|
||||||
) {
|
|
||||||
TaskManager.execute {
|
|
||||||
VKApi.messages()
|
|
||||||
.getHistory()
|
|
||||||
.peerId(peerId)
|
|
||||||
.reversed(false)
|
|
||||||
.extended(true)
|
|
||||||
.fields(VKConstants.USER_FIELDS + "," + VKConstants.GROUP_FIELDS)
|
|
||||||
.offset(offset)
|
|
||||||
.count(count)
|
|
||||||
.executeArray(
|
|
||||||
VKMessage::class.java,
|
|
||||||
object : OnResponseListener<ArrayList<VKMessage>> {
|
|
||||||
override fun onResponse(response: ArrayList<VKMessage>) {
|
|
||||||
TaskManager.execute {
|
|
||||||
cacheLoadedMessages(response)
|
|
||||||
|
|
||||||
// MemoryCache.putUsers(VKMessage.profiles)
|
|
||||||
// MemoryCache.putGroups(VKMessage.groups)
|
|
||||||
// MemoryCache.putConversations(VKMessage.conversations)
|
|
||||||
|
|
||||||
VKUtil.sortMessagesByDate(response, false)
|
|
||||||
|
|
||||||
sendResponse(listener, response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
sendError(listener, t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getCachedMessages(
|
|
||||||
peerId: Int, offset: Int, count: Int,
|
|
||||||
listener: MvpOnResponseListener<ArrayList<VKMessage>>
|
|
||||||
) {
|
|
||||||
TaskManager.execute {
|
|
||||||
// val messages = MemoryCache.getMessagesByPeerId(peerId).asArrayList()
|
|
||||||
//
|
|
||||||
// if (messages.isEmpty()) {
|
|
||||||
// sendError(listener, NullPointerException("Messages is empty"))
|
|
||||||
// return@execute
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// VKUtil.sortMessagesByDate(messages, false)
|
|
||||||
//
|
|
||||||
// val preparedMessages = ArrayUtils.cut(messages, offset, count)
|
|
||||||
//
|
|
||||||
// sendResponseArray(listener, preparedMessages)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getCachedConversation(peerId: Int, listener: MvpOnResponseListener<VKConversation>) {
|
|
||||||
TaskManager.execute {
|
|
||||||
// val conversation = MemoryCache.getConversationById(peerId)
|
|
||||||
//
|
|
||||||
// if (conversation == null) {
|
|
||||||
// sendError(
|
|
||||||
// listener,
|
|
||||||
// NullPointerException("Conversation is not cached at the moment")
|
|
||||||
// )
|
|
||||||
// } else {
|
|
||||||
// sendResponse(listener, conversation)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadConversation(peerId: Int, listener: MvpOnResponseListener<VKConversation>) {
|
|
||||||
// TaskManager.loadConversation(
|
|
||||||
// VKApiKeys.UPDATE_CONVERSATION,
|
|
||||||
// peerId,
|
|
||||||
// object : OnResponseListener<VKConversation> {
|
|
||||||
// override fun onResponse(response: VKConversation) {
|
|
||||||
// sendResponse(listener, response)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onError(t: Throwable) {
|
|
||||||
// sendError(listener, t)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getChatInfo(conversation: VKConversation, listener: MvpOnResponseListener<String>) {
|
|
||||||
when (conversation.type) {
|
|
||||||
VKConversation.Type.CHAT -> {
|
|
||||||
sendResponse(
|
|
||||||
listener,
|
|
||||||
AppGlobal.resources.getString(
|
|
||||||
if (conversation.isGroupChannel)
|
|
||||||
R.string.group_channel_members
|
|
||||||
else R.string.chat_members,
|
|
||||||
conversation.membersCount
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
VKConversation.Type.USER -> {
|
|
||||||
// val user = VKUtil.searchUser(conversation.conversationId,
|
|
||||||
// object : OnResponseListener<VKUser> {
|
|
||||||
// override fun onResponse(response: VKUser) {
|
|
||||||
// sendResponse(listener, VKUtil.getUserOnline(response))
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onError(t: Throwable) {
|
|
||||||
// sendError(listener, t)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// user?.let {
|
|
||||||
// sendResponse(listener, VKUtil.getUserOnline(it))
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
sendResponse(listener, "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendMessage(
|
|
||||||
peerId: Int,
|
|
||||||
message: String,
|
|
||||||
randomId: Int,
|
|
||||||
listener: MvpOnResponseListener<Int>
|
|
||||||
) {
|
|
||||||
TaskManager.execute {
|
|
||||||
VKApi.messages()
|
|
||||||
.send()
|
|
||||||
.peerId(peerId)
|
|
||||||
.message(message)
|
|
||||||
.randomId(randomId)
|
|
||||||
.executeArray(Int::class.java, object : OnResponseListener<ArrayList<Int>> {
|
|
||||||
override fun onResponse(response: ArrayList<Int>) {
|
|
||||||
val messageId = response[0]
|
|
||||||
sendResponse(listener, messageId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
sendError(listener, t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun cacheLoadedMessages(messages: ArrayList<VKMessage>) {
|
|
||||||
// MemoryCache.putMessages(messages)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.meloda.fast.activity.ui.view
|
|
||||||
|
|
||||||
import com.meloda.mvp.MvpView
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
|
|
||||||
interface MessagesViewDeprecated : MvpView {
|
|
||||||
|
|
||||||
fun showChatPanel()
|
|
||||||
|
|
||||||
fun hideChatPanel()
|
|
||||||
|
|
||||||
fun setWritingAllowed(allowed: Boolean)
|
|
||||||
|
|
||||||
fun setChatInfo(info: String)
|
|
||||||
|
|
||||||
fun openProfile(conversation: VKConversation)
|
|
||||||
|
|
||||||
fun showErrorLoadConversationAlert()
|
|
||||||
|
|
||||||
fun showVoiceRecordingTip()
|
|
||||||
|
|
||||||
fun setMessageText(text: String)
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
package com.meloda.fast.adapter
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
|
||||||
import com.meloda.concurrent.EventInfo
|
|
||||||
import com.meloda.concurrent.TaskManager
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.VKLongPollParser
|
|
||||||
import com.meloda.fast.adapter.diffutil.ConversationsCallback
|
|
||||||
import com.meloda.fast.base.BaseAdapter
|
|
||||||
import com.meloda.fast.base.BaseHolder
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
import com.meloda.vksdk.model.VKMessage
|
|
||||||
|
|
||||||
class ChatsAdapter(context: Context, values: ArrayList<VKConversation>) :
|
|
||||||
BaseAdapter<VKConversation, ChatsAdapter.ViewHolder>(
|
|
||||||
context, values
|
|
||||||
),
|
|
||||||
TaskManager.OnEventListener,
|
|
||||||
VKLongPollParser.OnMessagesListener {
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
|
||||||
return ViewHolder(view(R.layout.item_conversation, parent))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun notifyChanges(oldList: List<VKConversation>, newList: List<VKConversation>) {
|
|
||||||
val callback = ConversationsCallback(oldList, newList)
|
|
||||||
val diff = DiffUtil.calculateDiff(callback)
|
|
||||||
|
|
||||||
diff.dispatchUpdatesTo(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNewEvent(info: EventInfo<*>) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ViewHolder(v: View) : BaseHolder(v) {
|
|
||||||
|
|
||||||
override fun bind(position: Int, payloads: MutableList<Any>?) {
|
|
||||||
val conversation = getItem(position)
|
|
||||||
val lastMessage = conversation.lastMessage
|
|
||||||
|
|
||||||
TaskManager.execute {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNewMessage(message: VKMessage) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onEditMessage(message: VKMessage) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRestoredMessage(message: VKMessage) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDeleteMessage(peerId: Int, messageId: Int) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onReadMessage(peerId: Int, messageId: Int) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,696 +0,0 @@
|
|||||||
package com.meloda.fast.adapter
|
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.drawable.ColorDrawable
|
|
||||||
import android.net.Uri
|
|
||||||
import android.text.SpannableString
|
|
||||||
import android.text.TextUtils
|
|
||||||
import android.text.style.ForegroundColorSpan
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.FrameLayout
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.meloda.concurrent.EventInfo
|
|
||||||
import com.meloda.concurrent.TaskManager
|
|
||||||
import com.meloda.extensions.ContextExtensions.color
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.UserConfig
|
|
||||||
import com.meloda.fast.adapter.diffutil.ConversationsCallbackDeprecated
|
|
||||||
import com.meloda.fast.base.BaseAdapter
|
|
||||||
import com.meloda.fast.base.BaseHolder
|
|
||||||
import com.meloda.fast.common.AppGlobal
|
|
||||||
import com.meloda.fast.database.CacheStorage
|
|
||||||
import com.meloda.fast.util.VKUtils
|
|
||||||
import com.meloda.fast.widget.CircleImageView
|
|
||||||
import com.meloda.vksdk.OnResponseListener
|
|
||||||
import com.meloda.vksdk.VKApiKeys
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
import com.meloda.vksdk.model.VKGroup
|
|
||||||
import com.meloda.vksdk.model.VKMessage
|
|
||||||
import com.meloda.vksdk.model.VKUser
|
|
||||||
import com.meloda.vksdk.util.VKUtil
|
|
||||||
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
class ConversationsAdapterDeprecated(
|
|
||||||
val recyclerView: RecyclerView,
|
|
||||||
values: ArrayList<VKConversation>
|
|
||||||
) : BaseAdapter<VKConversation, ConversationsAdapterDeprecated.ConversationHolder>(
|
|
||||||
recyclerView.context,
|
|
||||||
values
|
|
||||||
), TaskManager.OnEventListener {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "ConversationsAdapter"
|
|
||||||
}
|
|
||||||
|
|
||||||
var isLoading: Boolean = false
|
|
||||||
private var currentPosition: Int = -1
|
|
||||||
|
|
||||||
init {
|
|
||||||
TaskManager.addOnEventListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun destroy() {
|
|
||||||
TaskManager.removeOnEventListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNewEvent(info: EventInfo<*>) {
|
|
||||||
when (info.key) {
|
|
||||||
VKApiKeys.NEW_MESSAGE.name -> addMessage(info.data as VKMessage)
|
|
||||||
VKApiKeys.EDIT_MESSAGE.name -> editMessage(info.data as VKMessage)
|
|
||||||
VKApiKeys.RESTORE_MESSAGE.name -> restoreMessage(info.data as VKMessage)
|
|
||||||
VKApiKeys.READ_MESSAGE.name -> readMessage(
|
|
||||||
(info.data as Array<Int>)[0],
|
|
||||||
(info.data as Array<Int>)[1]
|
|
||||||
)
|
|
||||||
VKApiKeys.DELETE_MESSAGE.name -> deleteMessage(
|
|
||||||
(info.data as Array<Int>)[0],
|
|
||||||
(info.data as Array<Int>)[1]
|
|
||||||
)
|
|
||||||
|
|
||||||
VKApiKeys.UPDATE_CONVERSATION.name -> updateConversation(info.data as Int)
|
|
||||||
VKApiKeys.UPDATE_MESSAGE.name -> updateMessage(info.data as Int)
|
|
||||||
VKApiKeys.UPDATE_USER.name -> updateUsers(info.data as ArrayList<Int>)
|
|
||||||
VKApiKeys.UPDATE_GROUP.name -> updateGroups(info.data as ArrayList<Int>)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ConversationHolder {
|
|
||||||
return ConversationHolder(view(R.layout.item_conversation, parent))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(
|
|
||||||
holder: ConversationHolder,
|
|
||||||
position: Int,
|
|
||||||
payloads: MutableList<Any>
|
|
||||||
) {
|
|
||||||
currentPosition = position
|
|
||||||
initListeners(holder.itemView, position)
|
|
||||||
holder.bind(position, payloads)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isLastItem() = currentPosition >= itemCount - 1
|
|
||||||
|
|
||||||
inner class ConversationHolder(v: View) : BaseHolder(v) {
|
|
||||||
|
|
||||||
private var attachments: ImageView = v.findViewById(R.id.conversationTextAttachment)
|
|
||||||
private var text: TextView = v.findViewById(R.id.conversationText)
|
|
||||||
private var title: TextView = v.findViewById(R.id.conversationTitle)
|
|
||||||
private var avatar: ImageView = v.findViewById(R.id.conversationAvatar)
|
|
||||||
private var online: ImageView = v.findViewById(R.id.conversationUserOnline)
|
|
||||||
private var out: CircleImageView = v.findViewById(R.id.conversationOut)
|
|
||||||
private var counter: TextView = v.findViewById(R.id.conversationCounter)
|
|
||||||
private var date: TextView = v.findViewById(R.id.conversationDate)
|
|
||||||
private var type: ImageView = v.findViewById(R.id.conversationType)
|
|
||||||
private var userAvatar: ImageView = v.findViewById(R.id.conversationUserAvatar)
|
|
||||||
private var root: FrameLayout = v.findViewById(R.id.conversationRoot)
|
|
||||||
|
|
||||||
private val colorHighlight = context.color(R.color.accent)
|
|
||||||
|
|
||||||
override fun bind(position: Int) {
|
|
||||||
bind(position, mutableListOf())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun bind(position: Int, payloads: MutableList<Any>?) {
|
|
||||||
Log.d(TAG, "bind position: $position")
|
|
||||||
|
|
||||||
val conversation = getItem(position)
|
|
||||||
val lastMessage = conversation.lastMessage
|
|
||||||
|
|
||||||
TaskManager.execute {
|
|
||||||
val peerUser: VKUser? =
|
|
||||||
if (conversation.isUser()) CacheStorage.usersStorage.getUser(conversation.id) else null
|
|
||||||
|
|
||||||
val peerGroup: VKGroup? =
|
|
||||||
if (conversation.isGroup()) CacheStorage.groupsStorage.getGroup(conversation.id) else null
|
|
||||||
|
|
||||||
val fromUser: VKUser? =
|
|
||||||
if (lastMessage.isFromUser()) CacheStorage.usersStorage.getUser(lastMessage.fromId) else null
|
|
||||||
|
|
||||||
val fromGroup: VKGroup? =
|
|
||||||
if (lastMessage.isFromGroup()) CacheStorage.groupsStorage.getGroup(lastMessage.fromId) else null
|
|
||||||
|
|
||||||
conversation.peerUser = peerUser
|
|
||||||
conversation.peerGroup = peerGroup
|
|
||||||
|
|
||||||
lastMessage.fromUser = fromUser
|
|
||||||
lastMessage.fromGroup = fromGroup
|
|
||||||
|
|
||||||
post {
|
|
||||||
val dialogTitle = setTitle(conversation, peerUser, peerGroup)
|
|
||||||
|
|
||||||
if (payloads != null && payloads.isNotEmpty()) {
|
|
||||||
for (payload in payloads) {
|
|
||||||
when (payload) {
|
|
||||||
ConversationsCallbackDeprecated.CONVERSATION -> {
|
|
||||||
setUserOnline(conversation, peerUser)
|
|
||||||
prepareUserAvatar(
|
|
||||||
conversation,
|
|
||||||
lastMessage,
|
|
||||||
fromUser,
|
|
||||||
fromGroup
|
|
||||||
)
|
|
||||||
prepareAvatar(dialogTitle, conversation, peerUser, peerGroup)
|
|
||||||
setDialogType(conversation)
|
|
||||||
setIsRead(lastMessage, conversation)
|
|
||||||
setCounterBackground(conversation)
|
|
||||||
}
|
|
||||||
ConversationsCallbackDeprecated.MESSAGE -> {
|
|
||||||
prepareUserAvatar(
|
|
||||||
conversation,
|
|
||||||
lastMessage,
|
|
||||||
fromUser,
|
|
||||||
fromGroup
|
|
||||||
)
|
|
||||||
prepareAttachments(lastMessage)
|
|
||||||
setIsRead(lastMessage, conversation)
|
|
||||||
setDate(lastMessage)
|
|
||||||
}
|
|
||||||
ConversationsCallbackDeprecated.GROUP -> {
|
|
||||||
prepareAvatar(dialogTitle, conversation, peerUser, peerGroup)
|
|
||||||
}
|
|
||||||
ConversationsCallbackDeprecated.USER -> {
|
|
||||||
setUserOnline(conversation, peerUser)
|
|
||||||
prepareAvatar(dialogTitle, conversation, peerUser, peerGroup)
|
|
||||||
}
|
|
||||||
ConversationsCallbackDeprecated.EDIT_MESSAGE -> {
|
|
||||||
prepareUserAvatar(
|
|
||||||
conversation,
|
|
||||||
lastMessage,
|
|
||||||
fromUser,
|
|
||||||
fromGroup
|
|
||||||
)
|
|
||||||
prepareAttachments(lastMessage)
|
|
||||||
setIsRead(lastMessage, conversation)
|
|
||||||
setDate(lastMessage)
|
|
||||||
}
|
|
||||||
ConversationsCallbackDeprecated.DATE -> {
|
|
||||||
setDate(lastMessage)
|
|
||||||
}
|
|
||||||
ConversationsCallbackDeprecated.ONLINE -> {
|
|
||||||
setUserOnline(conversation, peerUser)
|
|
||||||
}
|
|
||||||
ConversationsCallbackDeprecated.ATTACHMENTS -> {
|
|
||||||
prepareAttachments(lastMessage)
|
|
||||||
}
|
|
||||||
ConversationsCallbackDeprecated.AVATAR -> {
|
|
||||||
prepareAvatar(dialogTitle, conversation, peerUser, peerGroup)
|
|
||||||
}
|
|
||||||
ConversationsCallbackDeprecated.USER_AVATAR -> {
|
|
||||||
prepareUserAvatar(
|
|
||||||
conversation,
|
|
||||||
lastMessage,
|
|
||||||
fromUser,
|
|
||||||
fromGroup
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ConversationsCallbackDeprecated.READ -> {
|
|
||||||
setIsRead(lastMessage, conversation)
|
|
||||||
}
|
|
||||||
ConversationsCallbackDeprecated.NOTIFICATIONS -> {
|
|
||||||
setCounterBackground(conversation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return@post
|
|
||||||
}
|
|
||||||
|
|
||||||
setUserOnline(conversation, peerUser)
|
|
||||||
|
|
||||||
prepareUserAvatar(conversation, lastMessage, fromUser, fromGroup)
|
|
||||||
|
|
||||||
prepareAvatar(dialogTitle, conversation, peerUser, peerGroup)
|
|
||||||
|
|
||||||
setDialogType(conversation)
|
|
||||||
|
|
||||||
prepareAttachments(lastMessage)
|
|
||||||
|
|
||||||
setIsRead(lastMessage, conversation)
|
|
||||||
|
|
||||||
setDate(lastMessage)
|
|
||||||
|
|
||||||
setCounterBackground(conversation)
|
|
||||||
|
|
||||||
root.isVisible = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setTitle(
|
|
||||||
conversation: VKConversation,
|
|
||||||
peerUser: VKUser?,
|
|
||||||
peerGroup: VKGroup?
|
|
||||||
): String {
|
|
||||||
val dialogTitle = VKUtil.getTitle(conversation, peerUser, peerGroup)
|
|
||||||
title.text = dialogTitle
|
|
||||||
|
|
||||||
return dialogTitle
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setUserOnline(conversation: VKConversation, peerUser: VKUser?) {
|
|
||||||
val onlineIcon = VKUtils.getUserOnlineIcon(context, conversation, peerUser)
|
|
||||||
|
|
||||||
online.setImageDrawable(onlineIcon)
|
|
||||||
online.isVisible = onlineIcon != null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareUserAvatar(
|
|
||||||
conversation: VKConversation,
|
|
||||||
lastMessage: VKMessage,
|
|
||||||
fromUser: VKUser?,
|
|
||||||
fromGroup: VKGroup?
|
|
||||||
) {
|
|
||||||
if ((conversation.isChat() || lastMessage.isOut) && !conversation.isGroupChannel) {
|
|
||||||
userAvatar.isVisible = true
|
|
||||||
|
|
||||||
val avatar = VKUtil.getUserAvatar(lastMessage, fromUser, fromGroup)
|
|
||||||
|
|
||||||
if (avatar.isEmpty()) {
|
|
||||||
userAvatar.setImageDrawable(ColorDrawable(Color.TRANSPARENT))
|
|
||||||
} else {
|
|
||||||
userAvatar.setImageURI(Uri.parse(avatar))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
userAvatar.isVisible = false
|
|
||||||
userAvatar.setImageDrawable(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareAvatar(
|
|
||||||
dialogTitle: String,
|
|
||||||
conversation: VKConversation,
|
|
||||||
peerUser: VKUser?,
|
|
||||||
peerGroup: VKGroup?
|
|
||||||
) {
|
|
||||||
val dialogAvatarPlaceholder = VKUtils.getAvatarPlaceholder(context, dialogTitle)
|
|
||||||
|
|
||||||
avatar.setImageDrawable(dialogAvatarPlaceholder)
|
|
||||||
|
|
||||||
val avatarLink = VKUtil.getAvatar(conversation, peerUser, peerGroup)
|
|
||||||
|
|
||||||
if (avatarLink.isNotEmpty()) {
|
|
||||||
avatar.setImageURI(Uri.parse(avatarLink))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setDialogType(conversation: VKConversation) {
|
|
||||||
// val dDialogType = VKUtil.getDialogType(context, conversation)
|
|
||||||
//
|
|
||||||
// type.setImageDrawable(dDialogType)
|
|
||||||
// type.isVisible = dDialogType != null
|
|
||||||
// type.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareAttachments(lastMessage: VKMessage) {
|
|
||||||
// text.apply {
|
|
||||||
// compoundDrawablePadding = 0
|
|
||||||
// setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, null, null)
|
|
||||||
// }
|
|
||||||
attachments.isVisible = false
|
|
||||||
|
|
||||||
if (lastMessage.action == null) {
|
|
||||||
when {
|
|
||||||
lastMessage.attachments.isNotEmpty() -> {
|
|
||||||
val attachmentString =
|
|
||||||
VKUtils.getAttachmentText(context, lastMessage.attachments)
|
|
||||||
|
|
||||||
val attachmentText =
|
|
||||||
if (lastMessage.text.isEmpty()) attachmentString else lastMessage.text
|
|
||||||
|
|
||||||
val startIndex =
|
|
||||||
if (lastMessage.text.isEmpty()) 0 else lastMessage.text.length
|
|
||||||
|
|
||||||
val span = SpannableString(attachmentText).apply {
|
|
||||||
setSpan(
|
|
||||||
ForegroundColorSpan(colorHighlight),
|
|
||||||
startIndex,
|
|
||||||
attachmentText.length,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val attachmentDrawable =
|
|
||||||
VKUtils.getAttachmentDrawable(context, lastMessage.attachments)
|
|
||||||
text.text = span
|
|
||||||
|
|
||||||
attachments.isVisible = true
|
|
||||||
attachments.setImageDrawable(attachmentDrawable)
|
|
||||||
|
|
||||||
// text.apply {
|
|
||||||
// text = span
|
|
||||||
// setCompoundDrawablesRelativeWithIntrinsicBounds(
|
|
||||||
// attachmentDrawable,
|
|
||||||
// null,
|
|
||||||
// null,
|
|
||||||
// null
|
|
||||||
// )
|
|
||||||
// compoundDrawablePadding = 8
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
lastMessage.fwdMessages.isNotEmpty() -> {
|
|
||||||
val fwdText =
|
|
||||||
VKUtils.getFwdText(context, lastMessage.getForwardedMessages())
|
|
||||||
val span = SpannableString(fwdText).apply {
|
|
||||||
setSpan(ForegroundColorSpan(colorHighlight), 0, fwdText.length, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
text.text = span
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
text.text = if (text.maxLines == 1) lastMessage.text.replace(
|
|
||||||
"\n",
|
|
||||||
" "
|
|
||||||
) else lastMessage.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
VKUtils.getActionText(context, lastMessage,
|
|
||||||
object : OnResponseListener<String> {
|
|
||||||
override fun onResponse(response: String) {
|
|
||||||
val span = SpannableString(response).apply {
|
|
||||||
setSpan(
|
|
||||||
ForegroundColorSpan(colorHighlight),
|
|
||||||
0,
|
|
||||||
response.length,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
text.text = span
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastMessage.attachments.isEmpty() && lastMessage.fwdMessages.isEmpty() && lastMessage.action == null && TextUtils.isEmpty(
|
|
||||||
lastMessage.text
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
val unknown = "..."
|
|
||||||
val span = SpannableString(unknown).apply {
|
|
||||||
setSpan(ForegroundColorSpan(colorHighlight), 0, unknown.length, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
text.text = span
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setIsRead(lastMessage: VKMessage, conversation: VKConversation) {
|
|
||||||
val isRead =
|
|
||||||
((lastMessage.isOut && conversation.outReadMessageId == conversation.lastMessageId ||
|
|
||||||
!lastMessage.isOut && conversation.inReadMessageId == conversation.lastMessageId) && conversation.lastMessageId == lastMessage.id) && conversation.unreadCount == 0
|
|
||||||
|
|
||||||
if (isRead) {
|
|
||||||
counter.visibility = View.GONE
|
|
||||||
out.visibility = View.GONE
|
|
||||||
} else {
|
|
||||||
if (lastMessage.isOut) {
|
|
||||||
out.visibility = View.VISIBLE
|
|
||||||
counter.visibility = View.GONE
|
|
||||||
counter.text = ""
|
|
||||||
} else {
|
|
||||||
out.visibility = View.GONE
|
|
||||||
counter.visibility = View.VISIBLE
|
|
||||||
counter.text = conversation.unreadCount.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setDate(lastMessage: VKMessage) {
|
|
||||||
val dateText = VKUtils.getTime(context, lastMessage)
|
|
||||||
date.text = dateText
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setCounterBackground(conversation: VKConversation) {
|
|
||||||
counter.background.setTint(if (conversation.isNotificationsDisabled()) Color.GRAY else colorHighlight)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Message is bad")
|
|
||||||
private fun addMessage(message: VKMessage) {
|
|
||||||
val index = searchConversationIndex(message.peerId)
|
|
||||||
|
|
||||||
val oldList = ArrayList(values)
|
|
||||||
|
|
||||||
if (index >= 0) {
|
|
||||||
val currentConversation = this[index]
|
|
||||||
|
|
||||||
val conversation = prepareConversation(currentConversation, message)
|
|
||||||
|
|
||||||
removeAt(index)
|
|
||||||
add(0, conversation)
|
|
||||||
notifyChanges(oldList)
|
|
||||||
} else {
|
|
||||||
// TaskManager.loadConversation(
|
|
||||||
// VKApiKeys.UPDATE_CONVERSATION,
|
|
||||||
// message.peerId,
|
|
||||||
// null
|
|
||||||
// )
|
|
||||||
|
|
||||||
TaskManager.execute {
|
|
||||||
// val cachedConversation = MemoryCache.getConversationById(message.peerId)
|
|
||||||
// if (cachedConversation != null) {
|
|
||||||
// add(0, prepareConversation(cachedConversation, message))
|
|
||||||
// post { notifyChanges(oldList) }
|
|
||||||
// return@execute
|
|
||||||
// }
|
|
||||||
|
|
||||||
val tempConversations = VKConversation().apply {
|
|
||||||
id = message.peerId
|
|
||||||
|
|
||||||
localId =
|
|
||||||
if (VKUtil.isChatId(id)) id - 2000000000 else id
|
|
||||||
type =
|
|
||||||
if (id < 0) VKConversation.Type.GROUP else if (id > 2000000000) VKConversation.Type.CHAT else VKConversation.Type.USER
|
|
||||||
|
|
||||||
lastMessage = message
|
|
||||||
lastMessageId = message.id
|
|
||||||
}
|
|
||||||
|
|
||||||
add(0, tempConversations)
|
|
||||||
|
|
||||||
post { notifyChanges(oldList) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val firstVisiblePosition =
|
|
||||||
(recyclerView.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
|
|
||||||
|
|
||||||
if (firstVisiblePosition <= 1) recyclerView.scrollToPosition(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun editMessage(message: VKMessage) {
|
|
||||||
val index = searchConversationIndex(message.peerId)
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
val conversation = getItem(index)
|
|
||||||
|
|
||||||
if (conversation.lastMessageId != message.id) return
|
|
||||||
|
|
||||||
conversation.lastMessage = message
|
|
||||||
|
|
||||||
notifyItemChanged(index, ConversationsCallbackDeprecated.EDIT_MESSAGE)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun readMessage(peerId: Int, messageId: Int) {
|
|
||||||
val index = searchConversationIndex(peerId)
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
val conversation = getItem(index)
|
|
||||||
val message = conversation.lastMessage
|
|
||||||
|
|
||||||
if (message.isInbox()) {
|
|
||||||
conversation.inReadMessageId = messageId
|
|
||||||
} else {
|
|
||||||
conversation.outReadMessageId = messageId
|
|
||||||
}
|
|
||||||
|
|
||||||
conversation.unreadCount = if (conversation.lastMessageId == messageId) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
conversation.lastMessageId - messageId
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyItemChanged(index, ConversationsCallbackDeprecated.READ)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Need to rewrite")
|
|
||||||
private fun deleteMessage(peerId: Int, messageId: Int) {
|
|
||||||
return
|
|
||||||
val index = searchConversationIndex(peerId)
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
val oldList = ArrayList(values)
|
|
||||||
|
|
||||||
val oldDialog = values[index]
|
|
||||||
|
|
||||||
val dialog = oldDialog.clone()
|
|
||||||
|
|
||||||
// TaskManager.execute {
|
|
||||||
// val cachedMessages = MemoryCache.getMessagesByPeerId(dialog.conversationId)
|
|
||||||
// val messages = VKUtil.sortMessagesByDate(ArrayList(cachedMessages), true)
|
|
||||||
//
|
|
||||||
// if (messages.isEmpty()) {
|
|
||||||
// MemoryCache.deleteConversation(dialog.conversationId)
|
|
||||||
//
|
|
||||||
// AppGlobal.post {
|
|
||||||
// removeAt(index)
|
|
||||||
// notifyChanges(oldList)
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// val lastMessage = messages[0]
|
|
||||||
//
|
|
||||||
// dialog.lastMessageId = lastMessage.messageId
|
|
||||||
// dialog.lastMessage = lastMessage
|
|
||||||
//
|
|
||||||
// set(index, dialog)
|
|
||||||
//
|
|
||||||
// VKUtil.sortConversationsByDate(values, true)
|
|
||||||
//
|
|
||||||
// AppGlobal.post {
|
|
||||||
// notifyChanges(oldList)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Message is bad")
|
|
||||||
private fun restoreMessage(message: VKMessage) {
|
|
||||||
val index = searchConversationIndex(message.peerId)
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
val oldList = ArrayList<VKConversation>().apply { addAll(values) }
|
|
||||||
val oldDialog = values[index]
|
|
||||||
|
|
||||||
val dialog = oldDialog.clone()
|
|
||||||
|
|
||||||
// TaskManager.execute {
|
|
||||||
// val messages =
|
|
||||||
// MemoryCache.getMessagesByPeerId(dialog.conversationId).apply { addMessage(message) }
|
|
||||||
//
|
|
||||||
// VKUtil.sortMessagesByDate(ArrayList(messages), true)
|
|
||||||
//
|
|
||||||
// val lastMessage = messages[0]
|
|
||||||
//
|
|
||||||
// dialog.lastMessageId = lastMessage.messageId
|
|
||||||
// dialog.lastMessage = lastMessage
|
|
||||||
//
|
|
||||||
// set(index, dialog)
|
|
||||||
//
|
|
||||||
// VKUtil.sortConversationsByDate(values, true)
|
|
||||||
//
|
|
||||||
// AppGlobal.handler.post {
|
|
||||||
// notifyChanges(oldList)
|
|
||||||
//
|
|
||||||
// fragmentConversations.presenter.checkListIsEmpty(values)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareConversation(
|
|
||||||
conversation: VKConversation,
|
|
||||||
newMessage: VKMessage
|
|
||||||
): VKConversation {
|
|
||||||
conversation.lastMessage = newMessage
|
|
||||||
conversation.lastMessageId = newMessage.id
|
|
||||||
|
|
||||||
if (newMessage.isOut) {
|
|
||||||
conversation.unreadCount = 0
|
|
||||||
newMessage.isRead = false
|
|
||||||
} else {
|
|
||||||
conversation.unreadCount++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newMessage.peerId == newMessage.fromId && newMessage.fromId == UserConfig.userId) { //для лс
|
|
||||||
conversation.outReadMessageId = newMessage.id
|
|
||||||
}
|
|
||||||
|
|
||||||
return conversation
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun searchConversationIndex(peerId: Int): Int {
|
|
||||||
for (i in values.indices) {
|
|
||||||
if (getItem(i).id == peerId) return i
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun searchMessageIndex(messageId: Int): Int {
|
|
||||||
for (i in values.indices) {
|
|
||||||
if (getItem(i).lastMessageId == messageId) return i
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateConversation(peerId: Int) {
|
|
||||||
val index = searchConversationIndex(peerId)
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
// TaskManager.execute {
|
|
||||||
// val conversation = MemoryCache.getConversationById(peerId) ?: return@execute
|
|
||||||
//
|
|
||||||
// set(index, conversation)
|
|
||||||
//
|
|
||||||
// AppGlobal.post {
|
|
||||||
// notifyItemChanged(
|
|
||||||
// index,
|
|
||||||
// ConversationsCallbackDeprecated.CONVERSATION
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateGroups(groupIds: ArrayList<Int>) {
|
|
||||||
for (groupId in groupIds) {
|
|
||||||
val index = searchConversationIndex(groupId)
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
notifyItemChanged(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateUsers(userIds: ArrayList<Int>) {
|
|
||||||
for (userId in userIds) {
|
|
||||||
val index = searchConversationIndex(userId)
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
notifyItemChanged(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateMessage(messageId: Int) {
|
|
||||||
val index = searchMessageIndex(messageId)
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
|
|
||||||
TaskManager.execute {
|
|
||||||
val conversation = getItem(index).clone()
|
|
||||||
|
|
||||||
// conversation.apply {
|
|
||||||
// lastMessageId = messageId
|
|
||||||
// lastMessage = MemoryCache.getMessageById(messageId) ?: return@execute
|
|
||||||
// }
|
|
||||||
|
|
||||||
AppGlobal.handler.post {
|
|
||||||
notifyItemChanged(
|
|
||||||
index,
|
|
||||||
ConversationsCallbackDeprecated.MESSAGE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,584 +0,0 @@
|
|||||||
package com.meloda.fast.adapter
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import com.meloda.concurrent.EventInfo
|
|
||||||
import com.meloda.concurrent.TaskManager
|
|
||||||
import com.meloda.extensions.FloatExtensions.int
|
|
||||||
import com.meloda.fast.BuildConfig
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.activity.MessagesActivityDeprecated
|
|
||||||
import com.meloda.fast.base.BaseAdapter
|
|
||||||
import com.meloda.fast.base.BaseHolder
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
|
||||||
import com.meloda.fast.widget.BoundedLinearLayout
|
|
||||||
import com.meloda.fast.widget.CircleImageView
|
|
||||||
import com.meloda.vksdk.VKApiKeys
|
|
||||||
import com.meloda.vksdk.model.*
|
|
||||||
import com.meloda.vksdk.util.VKUtil
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.math.abs
|
|
||||||
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
class MessagesAdapterDeprecated(
|
|
||||||
context: Context,
|
|
||||||
values: ArrayList<VKMessage>,
|
|
||||||
var conversation: VKConversation
|
|
||||||
|
|
||||||
) : BaseAdapter<VKMessage, MessagesAdapterDeprecated.Holder>(context, values),
|
|
||||||
TaskManager.OnEventListener {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val TYPE_FOOTER = 10101
|
|
||||||
|
|
||||||
private const val TYPE_NORMAL_IN = 7910
|
|
||||||
private const val TYPE_NORMAL_OUT = 7911
|
|
||||||
|
|
||||||
private const val TYPE_ATTACHMENT_IN = 7920
|
|
||||||
private const val TYPE_ATTACHMENT_OUT = 7921
|
|
||||||
|
|
||||||
private const val TYPE_ACTION = 7930
|
|
||||||
|
|
||||||
private const val TYPE_NORMAL_CHANNEL = 7940
|
|
||||||
|
|
||||||
const val TAG = "MessagesAdapter"
|
|
||||||
}
|
|
||||||
|
|
||||||
private var recyclerView = (context as MessagesActivityDeprecated).recyclerView
|
|
||||||
private var layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
|
||||||
|
|
||||||
var isNotCachedValues = false
|
|
||||||
|
|
||||||
init {
|
|
||||||
TaskManager.addOnEventListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun destroy() {
|
|
||||||
TaskManager.removeOnEventListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNewEvent(info: EventInfo<*>) {
|
|
||||||
when (info.key) {
|
|
||||||
VKApiKeys.NEW_MESSAGE.name -> addMessage(info.data as VKMessage)
|
|
||||||
|
|
||||||
VKApiKeys.READ_MESSAGE.name -> readMessage(
|
|
||||||
(info.data as Array<Int>)[0],
|
|
||||||
(info.data as Array<Int>)[1]
|
|
||||||
)
|
|
||||||
|
|
||||||
VKApiKeys.RESTORE_MESSAGE.name -> restoreMessage(info.data as VKMessage)
|
|
||||||
VKApiKeys.EDIT_MESSAGE.name -> editMessage(info.data as VKMessage)
|
|
||||||
VKApiKeys.DELETE_MESSAGE.name -> deleteMessage(
|
|
||||||
(info.data as Array<Int>)[0],
|
|
||||||
(info.data as Array<Int>)[1]
|
|
||||||
)
|
|
||||||
|
|
||||||
VKApiKeys.UPDATE_MESSAGE.name -> updateMessage(info.data as Int)
|
|
||||||
VKApiKeys.UPDATE_USER.name -> updateUser(info.data as ArrayList<Int>)
|
|
||||||
VKApiKeys.UPDATE_GROUP.name -> updateGroup(info.data as ArrayList<Int>)
|
|
||||||
|
|
||||||
else -> return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
|
||||||
return values.size + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int {
|
|
||||||
if (position == values.size) return TYPE_FOOTER
|
|
||||||
|
|
||||||
val message = getItem(position)
|
|
||||||
|
|
||||||
return when {
|
|
||||||
message.action != null -> TYPE_ACTION
|
|
||||||
conversation.isGroupChannel -> TYPE_NORMAL_CHANNEL
|
|
||||||
message.isOut && message.attachments.isEmpty() && message.fwdMessages.isEmpty() -> TYPE_NORMAL_OUT
|
|
||||||
!message.isOut && message.attachments.isEmpty() && message.fwdMessages.isEmpty() -> TYPE_NORMAL_IN
|
|
||||||
message.isOut && (message.attachments.isNotEmpty() || message.fwdMessages.isNotEmpty()) -> TYPE_ATTACHMENT_OUT
|
|
||||||
!message.isOut && (message.attachments.isNotEmpty() || message.fwdMessages.isNotEmpty()) -> TYPE_ATTACHMENT_IN
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, type: Int): Holder {
|
|
||||||
return when (type) {
|
|
||||||
TYPE_FOOTER -> FooterHolder(generateEmptyView())
|
|
||||||
|
|
||||||
TYPE_NORMAL_IN -> ItemNormalIn(view(R.layout.item_message_normal_in, viewGroup))
|
|
||||||
TYPE_NORMAL_OUT -> ItemNormalOut(view(R.layout.item_message_normal_out, viewGroup))
|
|
||||||
|
|
||||||
TYPE_ATTACHMENT_IN -> ItemAttachmentIn(
|
|
||||||
view(
|
|
||||||
R.layout.item_message_attachment_in,
|
|
||||||
viewGroup
|
|
||||||
)
|
|
||||||
)
|
|
||||||
TYPE_ATTACHMENT_OUT -> ItemAttachmentOut(
|
|
||||||
view(
|
|
||||||
R.layout.item_message_attachment_out,
|
|
||||||
viewGroup
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
TYPE_ACTION -> ItemAction(view(R.layout.item_message_action, viewGroup))
|
|
||||||
|
|
||||||
TYPE_NORMAL_CHANNEL -> ItemChannel(view(R.layout.item_message_channel, viewGroup))
|
|
||||||
|
|
||||||
else -> PlaceHolder(view(R.layout.item_message, viewGroup))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: Holder, position: Int) {
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Log.d(TAG, "bind position: $position")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (holder is FooterHolder) return
|
|
||||||
|
|
||||||
super.onBindViewHolder(holder, position)
|
|
||||||
if (!isNotCachedValues) return
|
|
||||||
|
|
||||||
val message = this[position]
|
|
||||||
|
|
||||||
if (message.isRead.not()) {
|
|
||||||
// TaskManager.readMessage(
|
|
||||||
// VKApiKeys.READ_MESSAGE,
|
|
||||||
// conversation.conversationId,
|
|
||||||
// message.messageId
|
|
||||||
// )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateEmptyView(): View {
|
|
||||||
return View(context).also {
|
|
||||||
it.isFocusable = false
|
|
||||||
it.isClickable = false
|
|
||||||
it.isEnabled = false
|
|
||||||
it.layoutParams = ViewGroup.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
if (conversation.isGroupChannel) 0 else AndroidUtils.px(74f).int()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class FooterHolder(v: View) : Holder(v) {
|
|
||||||
override fun bind(position: Int) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ItemChannel(v: View) : ItemNormalIn(v) {
|
|
||||||
private val title: TextView = v.findViewById(R.id.channelTitle)
|
|
||||||
|
|
||||||
override fun bind(position: Int) {
|
|
||||||
val message = getItem(position)
|
|
||||||
|
|
||||||
ViewController().prepareDate(message, date)
|
|
||||||
|
|
||||||
val avatarString = conversation.photo100
|
|
||||||
|
|
||||||
// val placeHolder = VKUtil.getAvatarPlaceholder(context, conversation.title)
|
|
||||||
|
|
||||||
// avatar.setImageDrawable(placeHolder)
|
|
||||||
// ImageUtils.loadImage(avatarString, avatar, placeHolder)
|
|
||||||
|
|
||||||
title.text = conversation.title
|
|
||||||
|
|
||||||
text.text = message.text
|
|
||||||
|
|
||||||
root.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ItemAction(v: View) : Holder(v) {
|
|
||||||
private val text: TextView = v.findViewById(R.id.messageAction)
|
|
||||||
|
|
||||||
override fun bind(position: Int) {
|
|
||||||
val message = getItem(position)
|
|
||||||
|
|
||||||
TaskManager.execute {
|
|
||||||
val user = searchUser(message)
|
|
||||||
val group = searchGroup(message)
|
|
||||||
|
|
||||||
val name =
|
|
||||||
(if (group == null && !VKUtil.isGroupId(message.fromId)) user?.firstName else group?.name)
|
|
||||||
?: "null"
|
|
||||||
|
|
||||||
// VKUtil.getActionText(context, message, object : OnResponseListener<String> {
|
|
||||||
//
|
|
||||||
// override fun onResponse(response: String) {
|
|
||||||
// val actionText = "$name $response"
|
|
||||||
//
|
|
||||||
// val spannable = SpannableString(actionText)
|
|
||||||
// spannable.setSpan(StyleSpan(Typeface.BOLD), 0, name.length, 0)
|
|
||||||
//
|
|
||||||
// text.text = spannable
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onError(t: Throwable) {
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
post { text.isVisible = true }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open inner class ItemNormalIn(v: View) : NormalViewHolder(v) {
|
|
||||||
|
|
||||||
override fun bind(position: Int) {
|
|
||||||
val message = getItem(position)
|
|
||||||
|
|
||||||
TaskManager.execute {
|
|
||||||
val user = searchUser(message)
|
|
||||||
val group = searchGroup(message)
|
|
||||||
|
|
||||||
post {
|
|
||||||
ViewController().apply {
|
|
||||||
prepareText(message, bubble, text)
|
|
||||||
prepareDate(message, date)
|
|
||||||
prepareAvatar(message, avatar)
|
|
||||||
loadAvatarImage(message, user, group, avatar)
|
|
||||||
}
|
|
||||||
|
|
||||||
root.isVisible = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ItemAttachmentIn(v: View) : ItemNormalIn(v) {
|
|
||||||
val attachments: LinearLayout = v.findViewById(R.id.messageAttachments)
|
|
||||||
|
|
||||||
override fun bind(position: Int) {
|
|
||||||
super.bind(position)
|
|
||||||
|
|
||||||
val message = getItem(position)
|
|
||||||
|
|
||||||
AttachmentInflater.showAttachments(message, this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open inner class ItemNormalOut(v: View) : NormalViewHolder(v) {
|
|
||||||
|
|
||||||
override fun bind(position: Int) {
|
|
||||||
val message = getItem(position)
|
|
||||||
|
|
||||||
TaskManager.execute {
|
|
||||||
val user = searchUser(message)
|
|
||||||
val group = searchGroup(message)
|
|
||||||
|
|
||||||
post {
|
|
||||||
ViewController().apply {
|
|
||||||
prepareText(message, bubble, text)
|
|
||||||
prepareDate(message, date)
|
|
||||||
prepareAvatar(message, avatar)
|
|
||||||
loadAvatarImage(message, user, group, avatar)
|
|
||||||
}
|
|
||||||
|
|
||||||
root.isVisible = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ItemAttachmentOut(v: View) : ItemNormalOut(v) {
|
|
||||||
|
|
||||||
val attachments: LinearLayout = v.findViewById(R.id.messageAttachments)
|
|
||||||
|
|
||||||
override fun bind(position: Int) {
|
|
||||||
super.bind(position)
|
|
||||||
|
|
||||||
val message = getItem(position)
|
|
||||||
|
|
||||||
AttachmentInflater.showAttachments(message, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract inner class NormalViewHolder(v: View) : Holder(v) {
|
|
||||||
protected val date: TextView = v.findViewById(R.id.messageDate)
|
|
||||||
protected val text: TextView = v.findViewById(R.id.messageText)
|
|
||||||
protected val root: LinearLayout = v.findViewById(R.id.messageRoot)
|
|
||||||
protected val bubble: BoundedLinearLayout = v.findViewById(R.id.messageBubble)
|
|
||||||
protected val avatar: CircleImageView = v.findViewById(R.id.messageAvatar)
|
|
||||||
}
|
|
||||||
|
|
||||||
object AttachmentInflater {
|
|
||||||
fun showAttachments(message: VKMessage, holder: NormalViewHolder) {
|
|
||||||
val attachments =
|
|
||||||
(if (holder is ItemAttachmentOut) holder.attachments else if (holder is ItemAttachmentIn) holder.attachments else null)
|
|
||||||
?: return
|
|
||||||
|
|
||||||
if (message.fwdMessages.isNotEmpty() || message.attachments.isNotEmpty()) {
|
|
||||||
attachments.visibility = View.VISIBLE
|
|
||||||
attachments.removeAllViews()
|
|
||||||
} else {
|
|
||||||
attachments.visibility = View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.attachments.isNotEmpty()) {
|
|
||||||
prepareAttachments(message, attachments)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.fwdMessages.isNotEmpty()) {
|
|
||||||
prepareForwardedMessages(message, attachments)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareAttachments(message: VKMessage, attachments: LinearLayout) {
|
|
||||||
for (attachment in message.attachments) {
|
|
||||||
when (attachment) {
|
|
||||||
is VKPhoto -> photo(message, attachments)
|
|
||||||
is VKVideo -> video(message, attachments)
|
|
||||||
is VKLink -> link(message, attachments)
|
|
||||||
is VKAudio -> audio(message, attachments)
|
|
||||||
is VKDocument -> doc(message, attachments)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareForwardedMessages(message: VKMessage, attachments: LinearLayout) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun link(message: VKMessage, attachments: LinearLayout) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun video(message: VKMessage, attachments: LinearLayout) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun photo(message: VKMessage, attachments: LinearLayout) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fun audio(message: VKMessage, attachments: LinearLayout) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun doc(message: VKMessage, attachments: LinearLayout) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ViewController {
|
|
||||||
|
|
||||||
fun prepareText(message: VKMessage, bubble: BoundedLinearLayout, text: TextView) {
|
|
||||||
val screenWidth = context.resources.displayMetrics.widthPixels
|
|
||||||
val boundedWidth = screenWidth - screenWidth / 5
|
|
||||||
bubble.maxWidth = boundedWidth
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
text.setTextColor(
|
|
||||||
AndroidUtils.getThemeAttrColor(
|
|
||||||
context,
|
|
||||||
if (message.isOutbox()) R.attr.messageOutTextColor else R.attr.messageInTextColor
|
|
||||||
)
|
|
||||||
)
|
|
||||||
text.text = message.text
|
|
||||||
}
|
|
||||||
|
|
||||||
fun prepareDate(message: VKMessage, date: TextView) {
|
|
||||||
var dateText =
|
|
||||||
SimpleDateFormat("HH:mm", Locale.getDefault()).format(message.date * 1000L)
|
|
||||||
|
|
||||||
if (message.editTime > 0) {
|
|
||||||
dateText += ", ${
|
|
||||||
context.getString(R.string.edited)
|
|
||||||
.toLowerCase(Locale.getDefault())
|
|
||||||
}"
|
|
||||||
}
|
|
||||||
|
|
||||||
date.text = dateText
|
|
||||||
}
|
|
||||||
|
|
||||||
fun prepareAvatar(message: VKMessage, avatar: ImageView) {
|
|
||||||
avatar.isVisible = !message.isOut
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadAvatarImage(message: VKMessage, user: VKUser?, group: VKGroup?, avatar: ImageView) {
|
|
||||||
// val dialogTitle = VKUtil.getMessageTitle(message, user, group)
|
|
||||||
// val avatarPlaceholder = VKUtil.getAvatarPlaceholder(context, dialogTitle)
|
|
||||||
//
|
|
||||||
// avatar.setImageDrawable(avatarPlaceholder)
|
|
||||||
//
|
|
||||||
// val avatarString = VKUtil.getUserAvatar(message, user, group)
|
|
||||||
//
|
|
||||||
// ImageUtils.loadImage(avatarString, avatar, avatarPlaceholder)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
open inner class Holder(v: View) : BaseHolder(v) {
|
|
||||||
override fun bind(position: Int) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class PlaceHolder(v: View) : NormalViewHolder(v)
|
|
||||||
|
|
||||||
private fun searchUser(message: VKMessage): VKUser? {
|
|
||||||
if (!message.isFromUser()) return null
|
|
||||||
|
|
||||||
// return VKUtil.searchUser(message.fromId)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun searchGroup(message: VKMessage): VKGroup? {
|
|
||||||
if (!message.isFromGroup()) return null
|
|
||||||
|
|
||||||
// return VKUtil.searchGroup(message.fromId)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateGroup(groupIds: ArrayList<Int>) {
|
|
||||||
for (groupId in groupIds) {
|
|
||||||
var index = -1
|
|
||||||
|
|
||||||
for (i in values.indices) {
|
|
||||||
val item = getItem(i)
|
|
||||||
|
|
||||||
if (abs(item.fromId) == groupId) {
|
|
||||||
index = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
notifyItemChanged(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateUser(userIds: ArrayList<Int>) {
|
|
||||||
for (userId in userIds) {
|
|
||||||
var index = -1
|
|
||||||
|
|
||||||
for (i in values.indices) {
|
|
||||||
val item = getItem(i)
|
|
||||||
|
|
||||||
if (item.fromId == userId) {
|
|
||||||
index = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == -1) return
|
|
||||||
notifyItemChanged(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateMessage(messageId: Int) {
|
|
||||||
var index = -1
|
|
||||||
|
|
||||||
for (i in values.indices) {
|
|
||||||
val item = getItem(i)
|
|
||||||
|
|
||||||
if (item.id == messageId) {
|
|
||||||
index = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
// TaskManager.execute {
|
|
||||||
// AppGlobal.database.messages.getById(messageId)?.let {
|
|
||||||
// values[index] = it
|
|
||||||
//
|
|
||||||
// post { notifyItemChanged(index) }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun searchMessagePosition(messageId: Int): Int {
|
|
||||||
for (i in values.indices) {
|
|
||||||
if (getItem(i).id == messageId) return i
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun containsRandomId(randomId: Int): Boolean {
|
|
||||||
for (message in values) {
|
|
||||||
if (message.randomId == randomId) return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addMessage(message: VKMessage, fromApp: Boolean = false, withScroll: Boolean = false) {
|
|
||||||
val randomId = message.randomId
|
|
||||||
if (randomId > 0 && containsRandomId(message.randomId) || message.peerId != conversation.id) return
|
|
||||||
|
|
||||||
add(message)
|
|
||||||
|
|
||||||
notifyDataSetChanged()
|
|
||||||
|
|
||||||
val lastVisiblePosition = layoutManager.findLastVisibleItemPosition()
|
|
||||||
|
|
||||||
if ((message.isInbox() && lastVisiblePosition >= itemCount - 2) || !fromApp || withScroll) {
|
|
||||||
recyclerView.scrollToPosition(itemCount - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun readMessage(peerId: Int, messageId: Int) {
|
|
||||||
if (peerId != conversation.id) return
|
|
||||||
|
|
||||||
val index = searchMessagePosition(messageId)
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
val message = this[index]
|
|
||||||
message.isRead = true
|
|
||||||
|
|
||||||
notifyDataSetChanged()
|
|
||||||
|
|
||||||
if (message.isInbox()) {
|
|
||||||
conversation.inReadMessageId = messageId
|
|
||||||
} else {
|
|
||||||
conversation.outReadMessageId = messageId
|
|
||||||
}
|
|
||||||
|
|
||||||
conversation.unreadCount--
|
|
||||||
|
|
||||||
// TaskManager.execute {
|
|
||||||
// MemoryCache.put(message)
|
|
||||||
// MemoryCache.put(conversation)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun editMessage(message: VKMessage) {
|
|
||||||
val index = searchMessagePosition(message.id)
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
set(index, message)
|
|
||||||
notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteMessage(messageId: Int, peerId: Int) {
|
|
||||||
if (peerId != conversation.id) return
|
|
||||||
|
|
||||||
val index = searchMessagePosition(messageId)
|
|
||||||
if (index == -1) return
|
|
||||||
|
|
||||||
removeAt(index)
|
|
||||||
notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: кривое сообщение
|
|
||||||
fun restoreMessage(message: VKMessage) {
|
|
||||||
if (message.peerId != conversation.id) return
|
|
||||||
|
|
||||||
updateValues(VKUtil.sortMessagesByDate(values.apply { add(message) }, false))
|
|
||||||
notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package com.meloda.fast.adapter
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.base.BaseAdapter
|
|
||||||
import com.meloda.fast.base.BaseHolder
|
|
||||||
import com.meloda.fast.item.SimpleMenuItem
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class SimpleItemAdapter(context: Context, values: ArrayList<SimpleMenuItem>) :
|
|
||||||
BaseAdapter<SimpleMenuItem, SimpleItemAdapter.ViewHolder>(context, values) {
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
|
||||||
return ViewHolder(view(R.layout.item_simple_menu, parent))
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class ViewHolder(v: View) : BaseHolder(v) {
|
|
||||||
|
|
||||||
private val title: TextView = v.findViewById(R.id.profileItemTitle)
|
|
||||||
private val icon: ImageView = v.findViewById(R.id.profileItemIcon)
|
|
||||||
|
|
||||||
override fun bind(position: Int) {
|
|
||||||
val item = getItem(position)
|
|
||||||
|
|
||||||
title.text = item.title
|
|
||||||
|
|
||||||
icon.setImageDrawable(item.icon)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
package com.meloda.fast.adapter
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.adapter.diffutil.UsersCallbackDeprecated
|
|
||||||
import com.meloda.fast.base.BaseAdapter
|
|
||||||
import com.meloda.fast.base.BaseHolder
|
|
||||||
import com.meloda.fast.util.ImageUtils
|
|
||||||
import com.meloda.fast.widget.CircleImageView
|
|
||||||
import com.meloda.vksdk.model.VKUser
|
|
||||||
import com.meloda.vksdk.util.VKUtil
|
|
||||||
|
|
||||||
class UsersAdapterDeprecated(context: Context, values: ArrayList<VKUser>) :
|
|
||||||
BaseAdapter<VKUser, UsersAdapterDeprecated.ViewHolder>(context, values) {
|
|
||||||
|
|
||||||
var isLoading: Boolean = false
|
|
||||||
var currentPosition: Int = 0
|
|
||||||
|
|
||||||
fun isLastItem() = currentPosition >= itemCount - 1
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
|
||||||
return ViewHolder(view(R.layout.item_user, parent))
|
|
||||||
}
|
|
||||||
|
|
||||||
open inner class ViewHolder(v: View) : BaseHolder(v) {
|
|
||||||
private val avatar: CircleImageView = v.findViewById(R.id.userAvatar)
|
|
||||||
private val name: TextView = v.findViewById(R.id.userName)
|
|
||||||
private val online: ImageView = v.findViewById(R.id.userOnline)
|
|
||||||
private val onlineText: TextView = v.findViewById(R.id.userOnlineText)
|
|
||||||
|
|
||||||
override fun bind(position: Int) {
|
|
||||||
currentPosition = position
|
|
||||||
|
|
||||||
val user = getItem(position)
|
|
||||||
|
|
||||||
name.text = user.toString()
|
|
||||||
|
|
||||||
// val avatarPlaceholder = VKUtil.getAvatarPlaceholder(context, user.toString())
|
|
||||||
// avatar.setImageDrawable(avatarPlaceholder)
|
|
||||||
|
|
||||||
// ImageUtils.loadImage(user.photo200, avatar, avatarPlaceholder)
|
|
||||||
|
|
||||||
online.isVisible = false
|
|
||||||
|
|
||||||
// VKUtil.getUserOnlineIcon(context, user)?.let {
|
|
||||||
// online.setImageDrawable(it)
|
|
||||||
// online.isVisible = true
|
|
||||||
// }
|
|
||||||
|
|
||||||
// onlineText.text = VKUtil.getUserOnline(user)
|
|
||||||
|
|
||||||
//TODO: отладить открытие чата
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun notifyChanges(oldList: List<VKUser>, newList: List<VKUser>) {
|
|
||||||
val callback = UsersCallbackDeprecated(oldList, newList)
|
|
||||||
val diff = DiffUtil.calculateDiff(callback, false)
|
|
||||||
|
|
||||||
diff.dispatchUpdatesTo(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.meloda.fast.adapter.diffutil
|
|
||||||
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
|
|
||||||
class ConversationsCallback(
|
|
||||||
private val oldList: List<VKConversation>,
|
|
||||||
private val newList: List<VKConversation>
|
|
||||||
) : DiffUtil.Callback() {
|
|
||||||
|
|
||||||
override fun getOldListSize() = oldList.size
|
|
||||||
|
|
||||||
override fun getNewListSize() = newList.size
|
|
||||||
|
|
||||||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
|
||||||
//TODO: rewrite
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
|
||||||
//TODO: rewrite
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
|
|
||||||
//TODO: rewrite
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
package com.meloda.fast.adapter.diffutil
|
|
||||||
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
|
|
||||||
class ConversationsCallbackDeprecated(
|
|
||||||
private val oldList: List<VKConversation>,
|
|
||||||
private val newList: List<VKConversation>
|
|
||||||
) : DiffUtil.Callback() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val DATE = "date"
|
|
||||||
const val ONLINE = "online"
|
|
||||||
const val AVATAR = "avatar"
|
|
||||||
const val USER_AVATAR = "user_avatar"
|
|
||||||
const val ATTACHMENTS = "attachments"
|
|
||||||
const val READ = "read"
|
|
||||||
const val NOTIFICATIONS = "notifications"
|
|
||||||
const val EDIT_MESSAGE = "edit_message"
|
|
||||||
const val MESSAGE = "message"
|
|
||||||
const val USER = "user"
|
|
||||||
const val GROUP = "group"
|
|
||||||
const val CONVERSATION = "conversation"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getOldListSize() = oldList.size
|
|
||||||
|
|
||||||
override fun getNewListSize() = newList.size
|
|
||||||
|
|
||||||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
|
||||||
val old = oldList[oldItemPosition]
|
|
||||||
val new = newList[newItemPosition]
|
|
||||||
|
|
||||||
if (true) return false
|
|
||||||
return old.id == new.id
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
|
||||||
val old = oldList[oldItemPosition]
|
|
||||||
val new = newList[newItemPosition]
|
|
||||||
|
|
||||||
val oldMessage = old.lastMessage
|
|
||||||
val newMessage = new.lastMessage
|
|
||||||
|
|
||||||
if (true) return false else
|
|
||||||
|
|
||||||
return old.title == new.title &&
|
|
||||||
old.lastMessageId == new.lastMessageId &&
|
|
||||||
old.photo50 == new.photo50 &&
|
|
||||||
old.unreadCount == new.unreadCount &&
|
|
||||||
|
|
||||||
old.isNoSound == new.isNoSound &&
|
|
||||||
old.isDisabledForever == new.isDisabledForever &&
|
|
||||||
old.disabledUntil == new.disabledUntil &&
|
|
||||||
|
|
||||||
old.inReadMessageId == new.inReadMessageId &&
|
|
||||||
old.outReadMessageId == new.outReadMessageId &&
|
|
||||||
|
|
||||||
old.peerUser == new.peerUser &&
|
|
||||||
old.peerGroup == new.peerGroup &&
|
|
||||||
|
|
||||||
oldMessage == newMessage
|
|
||||||
|
|
||||||
// oldMessage.messageId == newMessage.messageId &&
|
|
||||||
// oldMessage.isOut == newMessage.isOut &&
|
|
||||||
// oldMessage.fromId == newMessage.fromId &&
|
|
||||||
// oldMessage.date == newMessage.date &&
|
|
||||||
// oldMessage.action == newMessage.action &&
|
|
||||||
// oldMessage.text == newMessage.text &&
|
|
||||||
// oldMessage.attachments == newMessage.attachments &&
|
|
||||||
// oldMessage.fwdMessages == newMessage.fwdMessages &&
|
|
||||||
// oldMessage.messageId == newMessage.messageId &&
|
|
||||||
//
|
|
||||||
// oldMessage.fromUser == newMessage.fromUser &&
|
|
||||||
// oldMessage.fromGroup == newMessage.fromGroup
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
|
|
||||||
val oldConversation = oldList[oldItemPosition]
|
|
||||||
val newConversation = newList[newItemPosition]
|
|
||||||
|
|
||||||
val oldMessage = oldConversation.lastMessage
|
|
||||||
val newMessage = newConversation.lastMessage
|
|
||||||
|
|
||||||
val oldDate = oldMessage.date
|
|
||||||
val newDate = newMessage.date
|
|
||||||
|
|
||||||
// if (oldDate != newDate) return DATE
|
|
||||||
|
|
||||||
// if (oldMessage != newMessage) return MESSAGE
|
|
||||||
|
|
||||||
return super.getChangePayload(oldItemPosition, newItemPosition)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package com.meloda.fast.adapter.diffutil
|
|
||||||
|
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
|
||||||
import com.meloda.vksdk.model.VKUser
|
|
||||||
|
|
||||||
class UsersCallbackDeprecated(private val oldList: List<VKUser>, private val newList: List<VKUser>) :
|
|
||||||
DiffUtil.Callback() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val ONLINE = "online"
|
|
||||||
const val ONLINE_MOBILE = "online_mobile"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
|
||||||
val old = oldList[oldItemPosition]
|
|
||||||
val new = newList[newItemPosition]
|
|
||||||
|
|
||||||
return old.userId == new.userId
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getOldListSize() = oldList.size
|
|
||||||
|
|
||||||
override fun getNewListSize() = newList.size
|
|
||||||
|
|
||||||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
|
||||||
val old = oldList[oldItemPosition]
|
|
||||||
val new = newList[newItemPosition]
|
|
||||||
|
|
||||||
return old.firstName == new.firstName &&
|
|
||||||
old.lastName == new.lastName &&
|
|
||||||
old.isOnline == new.isOnline &&
|
|
||||||
old.isOnlineMobile == new.isOnlineMobile &&
|
|
||||||
old.lastSeen == new.lastSeen &&
|
|
||||||
old.lastSeenPlatform == new.lastSeenPlatform &&
|
|
||||||
old.deactivated == new.deactivated
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
|
|
||||||
val old = oldList[oldItemPosition]
|
|
||||||
val new = newList[newItemPosition]
|
|
||||||
|
|
||||||
if (old.isOnlineMobile != new.isOnlineMobile) {
|
|
||||||
if (old.isOnline != new.isOnline) return ONLINE
|
|
||||||
|
|
||||||
return ONLINE_MOBILE
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.getChangePayload(oldItemPosition, newItemPosition)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk
|
package com.meloda.fast.api
|
||||||
|
|
||||||
object ErrorCodes {
|
object ErrorCodes {
|
||||||
const val UNKNOWN_ERROR = 1
|
const val UNKNOWN_ERROR = 1
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk
|
package com.meloda.fast.api
|
||||||
|
|
||||||
interface OnResponseListener<T> {
|
interface OnResponseListener<T> {
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.meloda.fast.api
|
||||||
|
|
||||||
|
data class Resource<out T> constructor(
|
||||||
|
val status: Status,
|
||||||
|
val responseData: T?,
|
||||||
|
val message: String?
|
||||||
|
) {
|
||||||
|
|
||||||
|
enum class Status {
|
||||||
|
SUCCESS,
|
||||||
|
ERROR,
|
||||||
|
LOADING
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun <T> success(responseData: T?): Resource<T> =
|
||||||
|
Resource(Status.SUCCESS, responseData, null)
|
||||||
|
|
||||||
|
fun <T> error(message: String?, responseBody: T? = null): Resource<T> =
|
||||||
|
Resource(Status.ERROR, responseBody, message)
|
||||||
|
|
||||||
|
fun <T> loading(responseData: T? = null): Resource<T> =
|
||||||
|
Resource(Status.LOADING, responseData, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
+69
-45
@@ -1,18 +1,21 @@
|
|||||||
package com.meloda.vksdk
|
package com.meloda.fast.api
|
||||||
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import com.meloda.concurrent.TaskManager
|
import com.meloda.fast.BuildConfig
|
||||||
import com.meloda.netservices.HttpRequest
|
import com.meloda.fast.api.method.MessageMethodSetter
|
||||||
import com.meloda.vksdk.method.MessageMethodSetter
|
import com.meloda.fast.api.method.MethodSetter
|
||||||
import com.meloda.vksdk.method.MethodSetter
|
import com.meloda.fast.api.method.UserMethodSetter
|
||||||
import com.meloda.vksdk.method.UserMethodSetter
|
import kotlinx.coroutines.flow.Flow
|
||||||
import com.meloda.vksdk.model.*
|
import kotlinx.coroutines.flow.asFlow
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
import kotlin.coroutines.resumeWithException
|
||||||
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
object VKApi {
|
object VKApi {
|
||||||
@@ -41,7 +44,8 @@ object VKApi {
|
|||||||
Log.w(TAG, "url: $url")
|
Log.w(TAG, "url: $url")
|
||||||
}
|
}
|
||||||
|
|
||||||
val buffer = HttpRequest[url].asString()
|
val buffer = com.meloda.fast.net.HttpRequest[url].asString()
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
Log.i(TAG, "response: $buffer")
|
Log.i(TAG, "response: $buffer")
|
||||||
}
|
}
|
||||||
@@ -63,9 +67,9 @@ object VKApi {
|
|||||||
when (cls) {
|
when (cls) {
|
||||||
null -> return null
|
null -> return null
|
||||||
|
|
||||||
VKLongPollServer::class.java -> {
|
com.meloda.fast.api.model.VKLongPollServer::class.java -> {
|
||||||
json.optJSONObject("response")?.let {
|
json.optJSONObject("response")?.let {
|
||||||
return arrayListOf(VKLongPollServer(it)) as ArrayList<T>?
|
return arrayListOf(com.meloda.fast.api.model.VKLongPollServer(it)) as ArrayList<T>?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,50 +95,56 @@ object VKApi {
|
|||||||
val models = ArrayList<T>(array.length())
|
val models = ArrayList<T>(array.length())
|
||||||
|
|
||||||
when (cls) {
|
when (cls) {
|
||||||
VKUser::class.java -> {
|
com.meloda.fast.api.model.VKUser::class.java -> {
|
||||||
json.optJSONObject("response")?.let { r ->
|
json.optJSONObject("response")?.let { r ->
|
||||||
VKUser.friendsCount = r.optInt("count")
|
com.meloda.fast.api.model.VKUser.friendsCount = r.optInt("count")
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i in 0 until array.length()) {
|
for (i in 0 until array.length()) {
|
||||||
models.add(VKUser(array.optJSONObject(i)) as T)
|
models.add(com.meloda.fast.api.model.VKUser(array.optJSONObject(i)) as T)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VKMessage::class.java -> {
|
com.meloda.fast.api.model.VKMessage::class.java -> {
|
||||||
response as JSONObject
|
response as JSONObject
|
||||||
|
|
||||||
if (url.contains("messages.getHistory")) {
|
if (url.contains("messages.getHistory")) {
|
||||||
VKMessage.lastHistoryCount = response.optInt("count")
|
com.meloda.fast.api.model.VKMessage.lastHistoryCount = response.optInt("count")
|
||||||
|
|
||||||
response.optJSONArray("profiles")?.let {
|
response.optJSONArray("profiles")?.let {
|
||||||
val profiles = arrayListOf<VKUser>()
|
val profiles = arrayListOf<com.meloda.fast.api.model.VKUser>()
|
||||||
|
|
||||||
for (j in 0 until it.length()) {
|
for (j in 0 until it.length()) {
|
||||||
profiles.add(VKUser(it.optJSONObject(j)))
|
profiles.add(com.meloda.fast.api.model.VKUser(it.optJSONObject(j)))
|
||||||
}
|
}
|
||||||
|
|
||||||
VKMessage.profiles = profiles
|
com.meloda.fast.api.model.VKMessage.profiles = profiles
|
||||||
}
|
}
|
||||||
|
|
||||||
response.optJSONArray("groups")?.let {
|
response.optJSONArray("groups")?.let {
|
||||||
val groups = arrayListOf<VKGroup>()
|
val groups = arrayListOf<com.meloda.fast.api.model.VKGroup>()
|
||||||
|
|
||||||
for (j in 0 until it.length()) {
|
for (j in 0 until it.length()) {
|
||||||
groups.add(VKGroup(it.optJSONObject(j)))
|
groups.add(com.meloda.fast.api.model.VKGroup(it.optJSONObject(j)))
|
||||||
}
|
}
|
||||||
|
|
||||||
VKMessage.groups = groups
|
com.meloda.fast.api.model.VKMessage.groups = groups
|
||||||
}
|
}
|
||||||
|
|
||||||
response.optJSONArray("conversations")?.let {
|
response.optJSONArray("conversations")?.let {
|
||||||
val conversations = arrayListOf<VKConversation>()
|
val conversations = arrayListOf<com.meloda.fast.api.model.VKConversation>()
|
||||||
|
|
||||||
for (j in 0 until it.length()) {
|
for (j in 0 until it.length()) {
|
||||||
conversations.add(VKConversation(it.optJSONObject(j)))
|
conversations.add(
|
||||||
|
com.meloda.fast.api.model.VKConversation(
|
||||||
|
it.optJSONObject(
|
||||||
|
j
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
VKMessage.conversations = conversations
|
com.meloda.fast.api.model.VKMessage.conversations = conversations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,35 +154,35 @@ object VKApi {
|
|||||||
source = source.optJSONObject("message")
|
source = source.optJSONObject("message")
|
||||||
}
|
}
|
||||||
|
|
||||||
val message = VKMessage(source)
|
val message = com.meloda.fast.api.model.VKMessage(source)
|
||||||
models.add(message as T)
|
models.add(message as T)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VKGroup::class.java -> {
|
com.meloda.fast.api.model.VKGroup::class.java -> {
|
||||||
for (i in 0 until array.length()) {
|
for (i in 0 until array.length()) {
|
||||||
models.add(VKGroup(array.optJSONObject(i)) as T)
|
models.add(com.meloda.fast.api.model.VKGroup(array.optJSONObject(i)) as T)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VKModel::class.java -> {
|
com.meloda.fast.api.model.VKModel::class.java -> {
|
||||||
if (url.contains("messages.getHistoryAttachments")) {
|
if (url.contains("messages.getHistoryAttachments")) {
|
||||||
return VKAttachments.parse(array) as ArrayList<T>
|
return com.meloda.fast.api.model.VKAttachments.parse(array) as ArrayList<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VKConversation::class.java -> {
|
com.meloda.fast.api.model.VKConversation::class.java -> {
|
||||||
if (url.contains("getConversationsById")) {
|
if (url.contains("getConversationsById")) {
|
||||||
for (i in 0 until array.length()) {
|
for (i in 0 until array.length()) {
|
||||||
val source = array.optJSONObject(i)
|
val source = array.optJSONObject(i)
|
||||||
models.add(VKConversation(source) as T)
|
models.add(com.meloda.fast.api.model.VKConversation(source) as T)
|
||||||
}
|
}
|
||||||
|
|
||||||
return models
|
return models
|
||||||
}
|
}
|
||||||
|
|
||||||
json.optJSONObject("response")?.let { r ->
|
json.optJSONObject("response")?.let { r ->
|
||||||
VKConversation.conversationsCount = r.optInt("count")
|
com.meloda.fast.api.model.VKConversation.conversationsCount = r.optInt("count")
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i in 0 until array.length()) {
|
for (i in 0 until array.length()) {
|
||||||
@@ -182,28 +192,28 @@ object VKApi {
|
|||||||
val oConversation = source.optJSONObject("conversation") ?: return null
|
val oConversation = source.optJSONObject("conversation") ?: return null
|
||||||
val oLastMessage = source.optJSONObject("last_message") ?: return null
|
val oLastMessage = source.optJSONObject("last_message") ?: return null
|
||||||
|
|
||||||
val conversation = VKConversation(oConversation).also {
|
val conversation = com.meloda.fast.api.model.VKConversation(oConversation).also {
|
||||||
it.lastMessage = VKMessage(oLastMessage)
|
it.lastMessage = com.meloda.fast.api.model.VKMessage(oLastMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
response.optJSONArray("profiles")?.let {
|
response.optJSONArray("profiles")?.let {
|
||||||
val profiles = arrayListOf<VKUser>()
|
val profiles = arrayListOf<com.meloda.fast.api.model.VKUser>()
|
||||||
|
|
||||||
for (j in 0 until it.length()) {
|
for (j in 0 until it.length()) {
|
||||||
profiles.add(VKUser(it.optJSONObject(j)))
|
profiles.add(com.meloda.fast.api.model.VKUser(it.optJSONObject(j)))
|
||||||
}
|
}
|
||||||
|
|
||||||
VKConversation.profiles = profiles
|
com.meloda.fast.api.model.VKConversation.profiles = profiles
|
||||||
}
|
}
|
||||||
|
|
||||||
response.optJSONArray("groups")?.let {
|
response.optJSONArray("groups")?.let {
|
||||||
val groups = arrayListOf<VKGroup>()
|
val groups = arrayListOf<com.meloda.fast.api.model.VKGroup>()
|
||||||
|
|
||||||
for (j in 0 until it.length()) {
|
for (j in 0 until it.length()) {
|
||||||
groups.add(VKGroup(it.optJSONObject(j)))
|
groups.add(com.meloda.fast.api.model.VKGroup(it.optJSONObject(j)))
|
||||||
}
|
}
|
||||||
|
|
||||||
VKConversation.groups = groups
|
com.meloda.fast.api.model.VKConversation.groups = groups
|
||||||
}
|
}
|
||||||
|
|
||||||
models.add(conversation as T)
|
models.add(conversation as T)
|
||||||
@@ -215,21 +225,35 @@ object VKApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <E> execute(url: String, cls: Class<E>, listener: OnResponseListener<E>?) {
|
fun <E> execute(url: String, cls: Class<E>, listener: OnResponseListener<E>?) {
|
||||||
TaskManager.execute {
|
com.meloda.fast.concurrent.TaskManager.execute {
|
||||||
try {
|
try {
|
||||||
val models = execute(url, cls)
|
val models = execute(url, cls) ?: return@execute
|
||||||
|
|
||||||
listener?.let { SuccessCallback(listener, models as E) }
|
// listener?.onResponse(models)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
listener?.onError(e)
|
||||||
|
// it.resumeWithException(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
listener?.let { ErrorCallback(listener, 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>>) {
|
fun <E> executeArray(url: String, cls: Class<E>, listener: OnResponseListener<ArrayList<E>>) {
|
||||||
TaskManager.execute {
|
com.meloda.fast.concurrent.TaskManager.execute {
|
||||||
try {
|
try {
|
||||||
val models = execute(url, cls)
|
val models = execute(url, cls)
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk
|
package com.meloda.fast.api
|
||||||
|
|
||||||
enum class VKApiKeys(val value: String) {
|
enum class VKApiKeys(val value: String) {
|
||||||
READ_MESSAGE("_read_message"),
|
READ_MESSAGE("_read_message"),
|
||||||
+3
-2
@@ -1,7 +1,8 @@
|
|||||||
package com.meloda.vksdk
|
package com.meloda.fast.api
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.meloda.vksdk.util.VKUtil
|
import com.meloda.fast.BuildConfig
|
||||||
|
import com.meloda.fast.api.util.VKUtil
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
|
|
||||||
object VKAuth {
|
object VKAuth {
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk
|
package com.meloda.fast.api
|
||||||
|
|
||||||
object VKConstants {
|
object VKConstants {
|
||||||
|
|
||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
package com.meloda.vksdk
|
package com.meloda.fast.api
|
||||||
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
class VKException(var url: String, override var message: String, var code: Int) :
|
class VKException(var url: String = "", override var message: String = "", var code: Int) :
|
||||||
IOException(message) {
|
IOException(message) {
|
||||||
var captchaSid: String? = null
|
var captchaSid: String? = null
|
||||||
var captchaImg: String? = null
|
var captchaImg: String? = null
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package com.meloda.fast.api.datasource
|
||||||
|
|
||||||
|
class MessagesDataSource constructor() {
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package com.meloda.fast.api.datasource.base
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import com.google.gson.JsonParser
|
||||||
|
import com.google.gson.JsonSyntaxException
|
||||||
|
import com.meloda.fast.api.Resource
|
||||||
|
import com.meloda.fast.api.model.ApiResponse
|
||||||
|
import com.meloda.fast.api.ErrorCodes
|
||||||
|
import com.meloda.fast.api.VKException
|
||||||
|
import okhttp3.ResponseBody
|
||||||
|
import retrofit2.HttpException
|
||||||
|
|
||||||
|
class BaseDataSource {
|
||||||
|
|
||||||
|
private val TAG = BaseDataSource::class.simpleName
|
||||||
|
|
||||||
|
//TODO: move to resources
|
||||||
|
private val DEFAULT_ERROR = "Internal server error"
|
||||||
|
|
||||||
|
protected suspend fun <T> getResult(apiCall: suspend () -> ApiResponse<T>): Resource<T> {
|
||||||
|
try {
|
||||||
|
val response = apiCall()
|
||||||
|
return if (response.isSuccessful) {
|
||||||
|
Resource.success(response.response)
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Server response unsuccessful")
|
||||||
|
if (response.error != null) {
|
||||||
|
Log.w(TAG, "Unsuccessful response with code 2XX")
|
||||||
|
Resource.error(response.error.message, response.response)
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Unsuccessful result without error!")
|
||||||
|
Resource.error(DEFAULT_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: HttpException) {
|
||||||
|
Log.e(TAG, "Error while executing request ${e.message}")
|
||||||
|
val errorBody = e.response()?.errorBody() ?: return Resource.error(DEFAULT_ERROR)
|
||||||
|
val errorResponse = parseErrorBody<T>(errorBody) ?: return Resource.error(DEFAULT_ERROR)
|
||||||
|
|
||||||
|
return Resource.error(errorResponse.message)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Error while executing request ${e.message}")
|
||||||
|
|
||||||
|
return Resource.error(DEFAULT_ERROR)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> parseErrorBody(responseBody: ResponseBody?): Exception? {
|
||||||
|
if (responseBody == null) return null
|
||||||
|
|
||||||
|
val jsonResponse: JsonObject?
|
||||||
|
try {
|
||||||
|
jsonResponse = JsonParser.parseString(responseBody.string()) as? JsonObject
|
||||||
|
if (jsonResponse == null) {
|
||||||
|
Log.d(TAG, "Response body is empty while parsing error body.")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
} catch (e: JsonSyntaxException) {
|
||||||
|
Log.e(TAG, "Error while parsing json ${e.message}")
|
||||||
|
return null
|
||||||
|
} catch (e: java.lang.Exception) {
|
||||||
|
Log.e(TAG, "Unknown error ${e.message}")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jsonResponse.has("error")) {
|
||||||
|
val error = jsonResponse["error"].asJsonObject
|
||||||
|
|
||||||
|
val message = error["error_msg"].asString
|
||||||
|
val code = error["error_code"].asInt
|
||||||
|
|
||||||
|
val e = VKException("", 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["captcha_img"].asString
|
||||||
|
e.captchaSid = error["captcha_sid"].asString
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code == ErrorCodes.VALIDATION_REQUIRED) {
|
||||||
|
e.redirectUri = error["redirect_uri"].asString
|
||||||
|
}
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+9
-9
@@ -1,6 +1,6 @@
|
|||||||
package com.meloda.vksdk.method
|
package com.meloda.fast.api.method
|
||||||
|
|
||||||
import com.meloda.arrayutils.ArrayUtils
|
import com.meloda.fast.util.ArrayUtils
|
||||||
|
|
||||||
class MessageMethodSetter(name: String) : MethodSetter(name) {
|
class MessageMethodSetter(name: String) : MethodSetter(name) {
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ class MessageMethodSetter(name: String) : MethodSetter(name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun peerIds(vararg values: Int): MessageMethodSetter {
|
fun peerIds(vararg values: Int): MessageMethodSetter {
|
||||||
put("peer_ids", ArrayUtils.asString(values))
|
put("peer_ids", com.meloda.fast.util.ArrayUtils.asString(values))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,22 +100,22 @@ class MessageMethodSetter(name: String) : MethodSetter(name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun attachment(attachments: Collection<String>): MessageMethodSetter {
|
fun attachment(attachments: Collection<String>): MessageMethodSetter {
|
||||||
put("attachment", ArrayUtils.asString(attachments))
|
put("attachment", com.meloda.fast.util.ArrayUtils.asString(attachments))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun attachment(vararg attachments: String): MessageMethodSetter {
|
fun attachment(vararg attachments: String): MessageMethodSetter {
|
||||||
put("attachment", ArrayUtils.asString(*attachments))
|
put("attachment", com.meloda.fast.util.ArrayUtils.asString(*attachments))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun forwardMessages(ids: Collection<String>): MessageMethodSetter {
|
fun forwardMessages(ids: Collection<String>): MessageMethodSetter {
|
||||||
put("forward_messages", ArrayUtils.asString(ids))
|
put("forward_messages", com.meloda.fast.util.ArrayUtils.asString(ids))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun forwardMessages(vararg ids: Int): MessageMethodSetter {
|
fun forwardMessages(vararg ids: Int): MessageMethodSetter {
|
||||||
put("forward_messages", ArrayUtils.asString(ids))
|
put("forward_messages", com.meloda.fast.util.ArrayUtils.asString(ids))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,12 +160,12 @@ class MessageMethodSetter(name: String) : MethodSetter(name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun chatIds(vararg ids: Int): MessageMethodSetter {
|
fun chatIds(vararg ids: Int): MessageMethodSetter {
|
||||||
put("max_msg_id", ArrayUtils.asString(ids))
|
put("max_msg_id", com.meloda.fast.util.ArrayUtils.asString(ids))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun chatIds(ids: Collection<Int>): MessageMethodSetter {
|
fun chatIds(ids: Collection<Int>): MessageMethodSetter {
|
||||||
put("max_msg_id", ArrayUtils.asString(ids))
|
put("max_msg_id", com.meloda.fast.util.ArrayUtils.asString(ids))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
+13
-9
@@ -1,11 +1,11 @@
|
|||||||
package com.meloda.vksdk.method
|
package com.meloda.fast.api.method
|
||||||
|
|
||||||
import android.util.ArrayMap
|
import android.util.ArrayMap
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.meloda.arrayutils.ArrayUtils
|
import com.meloda.fast.BuildConfig
|
||||||
import com.meloda.vksdk.BuildConfig
|
import com.meloda.fast.api.OnResponseListener
|
||||||
import com.meloda.vksdk.OnResponseListener
|
import com.meloda.fast.api.VKApi
|
||||||
import com.meloda.vksdk.VKApi
|
import kotlinx.coroutines.flow.Flow
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@@ -79,6 +79,10 @@ open class MethodSetter(private val name: String) {
|
|||||||
return 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>? {
|
fun <E> execute(cls: Class<E>): ArrayList<E>? {
|
||||||
return VKApi.execute(getSignedUrl(), cls)
|
return VKApi.execute(getSignedUrl(), cls)
|
||||||
}
|
}
|
||||||
@@ -96,11 +100,11 @@ open class MethodSetter(private val name: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun userIds(vararg ids: Int): MethodSetter {
|
fun userIds(vararg ids: Int): MethodSetter {
|
||||||
return put("user_ids", ArrayUtils.asString(ids))
|
return put("user_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun userIds(ids: ArrayList<Int>): MethodSetter {
|
fun userIds(ids: ArrayList<Int>): MethodSetter {
|
||||||
return put("user_ids", ArrayUtils.asString(ids))
|
return put("user_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ownerId(value: Int): MethodSetter {
|
fun ownerId(value: Int): MethodSetter {
|
||||||
@@ -112,11 +116,11 @@ open class MethodSetter(private val name: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun groupIds(vararg ids: Int): MethodSetter {
|
fun groupIds(vararg ids: Int): MethodSetter {
|
||||||
return put("group_ids", ArrayUtils.asString(ids))
|
return put("group_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun groupIds(ids: ArrayList<Int>): MethodSetter {
|
fun groupIds(ids: ArrayList<Int>): MethodSetter {
|
||||||
return put("group_ids", ArrayUtils.asString(ids))
|
return put("group_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fields(values: String): MethodSetter {
|
fun fields(values: String): MethodSetter {
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.method
|
package com.meloda.fast.api.method
|
||||||
|
|
||||||
class UserMethodSetter(name: String) : MethodSetter(name) {
|
class UserMethodSetter(name: String) : MethodSetter(name) {
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
|
data class ApiResponse<T> constructor(
|
||||||
|
val isSuccessful: Boolean,
|
||||||
|
val error: Error?,
|
||||||
|
val response: T?
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Error constructor(
|
||||||
|
val code: Long,
|
||||||
|
val message: String
|
||||||
|
)
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import java.util.*
|
import java.util.*
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import android.util.ArrayMap
|
import android.util.ArrayMap
|
||||||
import com.meloda.vksdk.util.VKUtil
|
import com.meloda.fast.api.util.VKUtil
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
open class VKMessage() : VKModel() {
|
open class VKMessage() : VKModel() {
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.vksdk.model
|
package com.meloda.fast.api.model
|
||||||
|
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
package com.meloda.fast.api.model.request
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
class RequestMessagesGetConversations(
|
||||||
|
@SerializedName("offset")
|
||||||
|
private val offset: Int = 0,
|
||||||
|
|
||||||
|
@SerializedName("count")
|
||||||
|
private val count: Int = 0,
|
||||||
|
|
||||||
|
//values = all, unread
|
||||||
|
@SerializedName("filter")
|
||||||
|
private val filter: String = "",
|
||||||
|
|
||||||
|
@SerializedName("extended")
|
||||||
|
private val extended: Boolean = false,
|
||||||
|
|
||||||
|
@SerializedName("fields")
|
||||||
|
private var fields: String = ""
|
||||||
|
)
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package com.meloda.fast.api.model.response
|
||||||
|
|
||||||
|
class ResponseMessagesGetConversations(
|
||||||
|
val count: Int
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.meloda.fast.api.service
|
||||||
|
|
||||||
|
import com.meloda.fast.api.model.ApiResponse
|
||||||
|
import com.meloda.fast.api.model.request.RequestMessagesGetConversations
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.QueryMap
|
||||||
|
|
||||||
|
interface MessagesService {
|
||||||
|
|
||||||
|
@GET("messages.getConversations")
|
||||||
|
suspend fun getConversations(@QueryMap params: RequestMessagesGetConversations): ApiResponse<Map<String, Any>>
|
||||||
|
|
||||||
|
}
|
||||||
+31
-32
@@ -1,7 +1,6 @@
|
|||||||
package com.meloda.vksdk.util
|
package com.meloda.fast.api.util
|
||||||
|
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import com.meloda.vksdk.model.*
|
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
@@ -28,9 +27,9 @@ object VKUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sortMessagesByDate(
|
fun sortMessagesByDate(
|
||||||
values: ArrayList<VKMessage>,
|
values: ArrayList<com.meloda.fast.api.model.VKMessage>,
|
||||||
firstOnTop: Boolean
|
firstOnTop: Boolean
|
||||||
): ArrayList<VKMessage> {
|
): ArrayList<com.meloda.fast.api.model.VKMessage> {
|
||||||
values.sortWith { m1, m2 ->
|
values.sortWith { m1, m2 ->
|
||||||
val d1 = m1.date
|
val d1 = m1.date
|
||||||
val d2 = m2.date
|
val d2 = m2.date
|
||||||
@@ -46,9 +45,9 @@ object VKUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sortConversationsByDate(
|
fun sortConversationsByDate(
|
||||||
values: ArrayList<VKConversation>,
|
values: ArrayList<com.meloda.fast.api.model.VKConversation>,
|
||||||
firstOnTop: Boolean
|
firstOnTop: Boolean
|
||||||
): ArrayList<VKConversation> {
|
): ArrayList<com.meloda.fast.api.model.VKConversation> {
|
||||||
values.sortWith { c1, c2 ->
|
values.sortWith { c1, c2 ->
|
||||||
val d1 = c1.lastMessage.date
|
val d1 = c1.lastMessage.date
|
||||||
val d2 = c2.lastMessage.date
|
val d2 = c2.lastMessage.date
|
||||||
@@ -122,7 +121,7 @@ object VKUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getTitle(conversation: VKConversation, peerUser: VKUser?, peerGroup: VKGroup?): String {
|
fun getTitle(conversation: com.meloda.fast.api.model.VKConversation, peerUser: com.meloda.fast.api.model.VKUser?, peerGroup: com.meloda.fast.api.model.VKGroup?): String {
|
||||||
return when {
|
return when {
|
||||||
conversation.isUser() -> {
|
conversation.isUser() -> {
|
||||||
peerUser?.let { return it.toString() } ?: ""
|
peerUser?.let { return it.toString() } ?: ""
|
||||||
@@ -140,7 +139,7 @@ object VKUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMessageTitle(message: VKMessage, fromUser: VKUser?, fromGroup: VKGroup?): String {
|
fun getMessageTitle(message: com.meloda.fast.api.model.VKMessage, fromUser: com.meloda.fast.api.model.VKUser?, fromGroup: com.meloda.fast.api.model.VKGroup?): String {
|
||||||
return when {
|
return when {
|
||||||
message.isFromUser() -> {
|
message.isFromUser() -> {
|
||||||
fromUser?.let { return it.toString() } ?: ""
|
fromUser?.let { return it.toString() } ?: ""
|
||||||
@@ -154,7 +153,7 @@ object VKUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAvatar(conversation: VKConversation, peerUser: VKUser?, peerGroup: VKGroup?): String {
|
fun getAvatar(conversation: com.meloda.fast.api.model.VKConversation, peerUser: com.meloda.fast.api.model.VKUser?, peerGroup: com.meloda.fast.api.model.VKGroup?): String {
|
||||||
return when {
|
return when {
|
||||||
conversation.isUser() -> {
|
conversation.isUser() -> {
|
||||||
peerUser?.let { return it.photo200 } ?: ""
|
peerUser?.let { return it.photo200 } ?: ""
|
||||||
@@ -172,7 +171,7 @@ object VKUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUserAvatar(message: VKMessage, fromUser: VKUser?, fromGroup: VKGroup?): String {
|
fun getUserAvatar(message: com.meloda.fast.api.model.VKMessage, fromUser: com.meloda.fast.api.model.VKUser?, fromGroup: com.meloda.fast.api.model.VKGroup?): String {
|
||||||
return when {
|
return when {
|
||||||
message.isFromUser() -> {
|
message.isFromUser() -> {
|
||||||
fromUser?.let { return it.photo100 } ?: ""
|
fromUser?.let { return it.photo100 } ?: ""
|
||||||
@@ -186,7 +185,7 @@ object VKUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUserPhoto(user: VKUser): String {
|
fun getUserPhoto(user: com.meloda.fast.api.model.VKUser): String {
|
||||||
if (user.photo200.isEmpty()) {
|
if (user.photo200.isEmpty()) {
|
||||||
if (user.photo100.isEmpty()) {
|
if (user.photo100.isEmpty()) {
|
||||||
if (user.photo50.isEmpty()) {
|
if (user.photo50.isEmpty()) {
|
||||||
@@ -202,7 +201,7 @@ object VKUtil {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGroupPhoto(group: VKGroup): String {
|
fun getGroupPhoto(group: com.meloda.fast.api.model.VKGroup): String {
|
||||||
if (group.photo200.isEmpty()) {
|
if (group.photo200.isEmpty()) {
|
||||||
if (group.photo100.isEmpty()) {
|
if (group.photo100.isEmpty()) {
|
||||||
if (group.photo50.isEmpty()) {
|
if (group.photo50.isEmpty()) {
|
||||||
@@ -219,26 +218,26 @@ object VKUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun parseConversations(array: JSONArray): ArrayList<VKConversation> {
|
fun parseConversations(array: JSONArray): ArrayList<com.meloda.fast.api.model.VKConversation> {
|
||||||
val conversations = arrayListOf<VKConversation>()
|
val conversations = arrayListOf<com.meloda.fast.api.model.VKConversation>()
|
||||||
for (i in 0 until array.length()) {
|
for (i in 0 until array.length()) {
|
||||||
conversations.add(VKConversation(array.optJSONObject(i)))
|
conversations.add(com.meloda.fast.api.model.VKConversation(array.optJSONObject(i)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return conversations
|
return conversations
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseMessages(array: JSONArray): ArrayList<VKMessage> {
|
fun parseMessages(array: JSONArray): ArrayList<com.meloda.fast.api.model.VKMessage> {
|
||||||
val messages = arrayListOf<VKMessage>()
|
val messages = arrayListOf<com.meloda.fast.api.model.VKMessage>()
|
||||||
for (i in 0 until array.length()) {
|
for (i in 0 until array.length()) {
|
||||||
messages.add(VKMessage(array.optJSONObject(i)))
|
messages.add(com.meloda.fast.api.model.VKMessage(array.optJSONObject(i)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return messages
|
return messages
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isMessageHasFlag(mask: Int, flagName: String): Boolean {
|
fun isMessageHasFlag(mask: Int, flagName: String): Boolean {
|
||||||
val o: Any? = VKMessage.flags[flagName]
|
val o: Any? = com.meloda.fast.api.model.VKMessage.flags[flagName]
|
||||||
return if (o != null) { //has flag
|
return if (o != null) { //has flag
|
||||||
val flag = o as Int
|
val flag = o as Int
|
||||||
flag and mask > 0
|
flag and mask > 0
|
||||||
@@ -249,8 +248,8 @@ object VKUtil {
|
|||||||
//fromUser and fromGroup are null
|
//fromUser and fromGroup are null
|
||||||
@Deprecated("need to rewrite")
|
@Deprecated("need to rewrite")
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
fun parseLongPollMessage(array: JSONArray): VKMessage {
|
fun parseLongPollMessage(array: JSONArray): com.meloda.fast.api.model.VKMessage {
|
||||||
val message = VKMessage()
|
val message = com.meloda.fast.api.model.VKMessage()
|
||||||
|
|
||||||
val id = array.optInt(1)
|
val id = array.optInt(1)
|
||||||
val flags = array.optInt(2)
|
val flags = array.optInt(2)
|
||||||
@@ -277,33 +276,33 @@ object VKUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (it.has("source_act")) {
|
if (it.has("source_act")) {
|
||||||
message.action = VKMessageAction().also { action ->
|
message.action = com.meloda.fast.api.model.VKMessageAction().also { action ->
|
||||||
action.type = VKMessageAction.Type.fromString(it.optString("source_act"))
|
action.type = com.meloda.fast.api.model.VKMessageAction.Type.fromString(it.optString("source_act"))
|
||||||
|
|
||||||
when (action.type) {
|
when (action.type) {
|
||||||
VKMessageAction.Type.CHAT_CREATE -> {
|
com.meloda.fast.api.model.VKMessageAction.Type.CHAT_CREATE -> {
|
||||||
action.text = it.optString("source_text")
|
action.text = it.optString("source_text")
|
||||||
}
|
}
|
||||||
VKMessageAction.Type.TITLE_UPDATE -> {
|
com.meloda.fast.api.model.VKMessageAction.Type.TITLE_UPDATE -> {
|
||||||
action.oldText = it.optString("source_old_text")
|
action.oldText = it.optString("source_old_text")
|
||||||
action.text = it.optString("source_text")
|
action.text = it.optString("source_text")
|
||||||
}
|
}
|
||||||
VKMessageAction.Type.PIN_MESSAGE -> {
|
com.meloda.fast.api.model.VKMessageAction.Type.PIN_MESSAGE -> {
|
||||||
action.memberId = it.optInt("source_mid")
|
action.memberId = it.optInt("source_mid")
|
||||||
action.conversationMessageId = it.optInt("source_chat_local_id")
|
action.conversationMessageId = it.optInt("source_chat_local_id")
|
||||||
|
|
||||||
it.optJSONObject("source_message")?.let { message ->
|
it.optJSONObject("source_message")?.let { message ->
|
||||||
action.message = VKMessage(message)
|
action.message = com.meloda.fast.api.model.VKMessage(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VKMessageAction.Type.UNPIN_MESSAGE -> {
|
com.meloda.fast.api.model.VKMessageAction.Type.UNPIN_MESSAGE -> {
|
||||||
action.memberId = it.optInt("source_mid")
|
action.memberId = it.optInt("source_mid")
|
||||||
action.conversationMessageId = it.optInt("source_chat_local_id")
|
action.conversationMessageId = it.optInt("source_chat_local_id")
|
||||||
}
|
}
|
||||||
VKMessageAction.Type.INVITE_USER,
|
com.meloda.fast.api.model.VKMessageAction.Type.INVITE_USER,
|
||||||
VKMessageAction.Type.KICK_USER,
|
com.meloda.fast.api.model.VKMessageAction.Type.KICK_USER,
|
||||||
VKMessageAction.Type.SCREENSHOT,
|
com.meloda.fast.api.model.VKMessageAction.Type.SCREENSHOT,
|
||||||
VKMessageAction.Type.INVITE_USER_BY_CALL -> {
|
com.meloda.fast.api.model.VKMessageAction.Type.INVITE_USER_BY_CALL -> {
|
||||||
action.memberId = it.optInt("source_mid")
|
action.memberId = it.optInt("source_mid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,33 +1,48 @@
|
|||||||
package com.meloda.fast.base
|
package com.meloda.fast.base
|
||||||
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.annotation.LayoutRes
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.meloda.extensions.ContextExtensions.color
|
import androidx.lifecycle.Lifecycle
|
||||||
import com.meloda.fast.R
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import com.meloda.fast.util.AndroidUtils
|
import androidx.lifecycle.LifecycleRegistry
|
||||||
import com.meloda.fast.util.ColorUtils
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
|
||||||
abstract class BaseActivity : AppCompatActivity() {
|
abstract class BaseActivity : AppCompatActivity, LifecycleOwner {
|
||||||
|
|
||||||
|
constructor() : super()
|
||||||
|
|
||||||
|
constructor(@LayoutRes resId: Int) : super(resId)
|
||||||
|
|
||||||
|
protected lateinit var lifecycleRegistry: LifecycleRegistry
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
|
lifecycleRegistry = LifecycleRegistry(this)
|
||||||
val navigationBarColor =
|
lifecycleRegistry.currentState = Lifecycle.State.CREATED
|
||||||
if (AndroidUtils.isDarkTheme()) {
|
|
||||||
color(R.color.dark_primaryDark)
|
|
||||||
} else {
|
|
||||||
ColorUtils.darkenColor(color(R.color.primaryDark))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.navigationBarColor = navigationBarColor
|
override fun onStart() {
|
||||||
}
|
super.onStart()
|
||||||
|
lifecycleRegistry.currentState = Lifecycle.State.STARTED
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRootView(): View {
|
override fun onResume() {
|
||||||
return findViewById(android.R.id.content)
|
super.onResume()
|
||||||
|
lifecycleRegistry.currentState = Lifecycle.State.RESUMED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
|
||||||
|
}
|
||||||
|
|
||||||
|
val rootView: View? get() = findViewById(android.R.id.content)
|
||||||
|
|
||||||
|
fun requireRootView() = rootView!!
|
||||||
|
|
||||||
|
var errorSnackbar: Snackbar? = null
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
package com.meloda.fast.base
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Parcelable
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.AdapterView
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.meloda.arrayutils.ArrayUtils.asArrayList
|
|
||||||
import com.meloda.fast.common.AppGlobal
|
|
||||||
import com.meloda.fast.listener.ItemClickListener
|
|
||||||
import com.meloda.fast.listener.ItemLongClickListener
|
|
||||||
import java.io.Serializable
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
abstract class BaseAdapter<Item, VH : BaseHolder>(
|
|
||||||
var context: Context,
|
|
||||||
var values: ArrayList<Item> = arrayListOf()
|
|
||||||
) : RecyclerView.Adapter<VH>() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val P_ITEMS = "BaseAdapter.values"
|
|
||||||
}
|
|
||||||
|
|
||||||
private var cleanValues: ArrayList<Item>? = null
|
|
||||||
|
|
||||||
private var inflater: LayoutInflater = LayoutInflater.from(context)
|
|
||||||
|
|
||||||
var itemClickListener: ItemClickListener? = null
|
|
||||||
var itemLongClickListener: ItemLongClickListener? = null
|
|
||||||
|
|
||||||
open fun destroy() {}
|
|
||||||
|
|
||||||
open fun getItem(position: Int): Item {
|
|
||||||
return values[position]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun add(position: Int, item: Item) {
|
|
||||||
values.add(position, item)
|
|
||||||
cleanValues?.add(position, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun add(item: Item) {
|
|
||||||
values.add(item)
|
|
||||||
cleanValues?.add(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addAll(items: List<Item>) {
|
|
||||||
values.addAll(items)
|
|
||||||
cleanValues?.addAll(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addAll(position: Int, items: List<Item>) {
|
|
||||||
values.addAll(position, items)
|
|
||||||
cleanValues?.addAll(position, items)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun set(position: Int, item: Item) {
|
|
||||||
values[position] = item
|
|
||||||
cleanValues?.set(position, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun indexOf(item: Item): Int {
|
|
||||||
return values.indexOf(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun removeAt(index: Int) {
|
|
||||||
values.removeAt(index)
|
|
||||||
cleanValues?.removeAt(index)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun remove(item: Item) {
|
|
||||||
values.remove(item)
|
|
||||||
cleanValues?.remove(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun notifyChanges(oldList: List<Item>, newList: List<Item> = values) {}
|
|
||||||
|
|
||||||
fun isEmpty() = values.isNullOrEmpty()
|
|
||||||
|
|
||||||
fun isNotEmpty() = !isEmpty()
|
|
||||||
|
|
||||||
fun view(resId: Int, viewGroup: ViewGroup): View {
|
|
||||||
return inflater.inflate(resId, viewGroup, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateValues(arrayList: ArrayList<Item>) {
|
|
||||||
values.clear()
|
|
||||||
values.addAll(arrayList)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateValues(list: List<Item>) = updateValues(list.asArrayList())
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: VH, position: Int) {
|
|
||||||
onBindItemViewHolder(holder, position)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun initListeners(itemView: View, position: Int) {
|
|
||||||
if (itemView is AdapterView<*>) return
|
|
||||||
|
|
||||||
itemView.setOnClickListener {
|
|
||||||
if (itemClickListener != null) itemClickListener!!.onItemClick(
|
|
||||||
position
|
|
||||||
)
|
|
||||||
}
|
|
||||||
itemView.setOnLongClickListener {
|
|
||||||
if (itemLongClickListener != null) itemLongClickListener!!.onItemLongClick(position)
|
|
||||||
itemClickListener == null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
|
||||||
return values.size
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onBindItemViewHolder(holder: VH, position: Int) {
|
|
||||||
initListeners(holder.itemView, position)
|
|
||||||
holder.bind(position)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onSaveInstanceState(): Parcelable {
|
|
||||||
val bundle = Bundle()
|
|
||||||
if (values.size > 0 && (values[0] is Parcelable || values[0] is Serializable)) {
|
|
||||||
bundle.putSerializable(P_ITEMS, values)
|
|
||||||
}
|
|
||||||
return bundle
|
|
||||||
}
|
|
||||||
|
|
||||||
fun post(runnable: Runnable) {
|
|
||||||
AppGlobal.handler.post(runnable)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onRestoreInstanceState(state: Parcelable?) {
|
|
||||||
if (state is Bundle) {
|
|
||||||
if (state.containsKey(P_ITEMS)) {
|
|
||||||
values = state.getSerializable(P_ITEMS) as ArrayList<Item>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear() {
|
|
||||||
values.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun filter(query: String) {
|
|
||||||
if (cleanValues == null) {
|
|
||||||
cleanValues = ArrayList(values)
|
|
||||||
}
|
|
||||||
|
|
||||||
values.clear()
|
|
||||||
|
|
||||||
if (query.isEmpty()) {
|
|
||||||
values.addAll(cleanValues!!)
|
|
||||||
} else {
|
|
||||||
for (item in cleanValues!!) {
|
|
||||||
if (onQueryItem(item, query)) {
|
|
||||||
values.add(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun onQueryItem(item: Item, query: String): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun get(index: Int): Item {
|
|
||||||
return values[index]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,23 +1,12 @@
|
|||||||
package com.meloda.fast.base
|
package com.meloda.fast.base
|
||||||
|
|
||||||
import androidx.annotation.IdRes
|
import androidx.annotation.LayoutRes
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.meloda.fast.activity.MainActivity
|
|
||||||
|
|
||||||
abstract class BaseFragment : Fragment() {
|
abstract class BaseFragment : Fragment {
|
||||||
|
|
||||||
protected open fun initToolbar(@IdRes resId: Int) {
|
constructor() : super()
|
||||||
val toolbar: Toolbar = requireView().findViewById(resId)
|
|
||||||
|
|
||||||
activity?.let {
|
constructor(@LayoutRes resId: Int) : super(resId)
|
||||||
if (it is MainActivity && toolbar is com.meloda.fast.widget.Toolbar) it.initToolbar(
|
|
||||||
toolbar
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun runOnUiThread(runnable: Runnable) {
|
|
||||||
activity?.runOnUiThread(runnable)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
package com.meloda.fast.base.adapter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.meloda.fast.base.BaseHolder
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.add
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.addAll
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.clear
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.get
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.isEmpty
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.isNotEmpty
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.plusAssign
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.remove
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.removeAll
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.removeAt
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.set
|
||||||
|
import com.meloda.fast.extensions.LiveDataExtensions.size
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST", "unused", "MemberVisibilityCanBePrivate", "CanBeParameter")
|
||||||
|
abstract class BaseAdapter<Item, VH : BaseHolder>(
|
||||||
|
var context: Context,
|
||||||
|
values: ArrayList<Item>
|
||||||
|
) : RecyclerView.Adapter<VH>() {
|
||||||
|
|
||||||
|
val cleanValues = MutableLiveData<MutableList<Item>>(arrayListOf())
|
||||||
|
val values = MutableLiveData<MutableList<Item>>(arrayListOf())
|
||||||
|
|
||||||
|
protected var inflater: LayoutInflater = LayoutInflater.from(context)
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.values.value = values
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemClickListener: OnItemClickListener? = null
|
||||||
|
var itemLongClickListener: OnItemLongClickListener? = null
|
||||||
|
|
||||||
|
open fun destroy() {
|
||||||
|
itemClickListener = null
|
||||||
|
itemLongClickListener = null
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun getItem(position: Int): Item {
|
||||||
|
return values[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(position: Int, item: Item) {
|
||||||
|
values.add(item, position)
|
||||||
|
cleanValues.add(item, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(item: Item) {
|
||||||
|
values += item
|
||||||
|
cleanValues.add(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addAll(items: List<Item>) {
|
||||||
|
values += items
|
||||||
|
cleanValues.addAll(items)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addAll(position: Int, items: List<Item>) {
|
||||||
|
values.addAll(items, position)
|
||||||
|
cleanValues.addAll(items, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeAll(items: List<Item>) {
|
||||||
|
values.removeAll(items)
|
||||||
|
cleanValues.removeAll(items)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeAt(index: Int) {
|
||||||
|
values.removeAt(index)
|
||||||
|
cleanValues.removeAt(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove(item: Item) {
|
||||||
|
values.remove(item)
|
||||||
|
cleanValues.remove(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clear() {
|
||||||
|
values.clear()
|
||||||
|
cleanValues.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun get(position: Int): Item {
|
||||||
|
return values[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(position: Int, item: Item) {
|
||||||
|
values[position] = item
|
||||||
|
cleanValues[position] = item
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun notifyChanges(oldList: List<Item>, newList: List<Item>) {}
|
||||||
|
|
||||||
|
fun isEmpty() = values.isEmpty()
|
||||||
|
fun isNotEmpty() = values.isNotEmpty()
|
||||||
|
|
||||||
|
fun view(resId: Int, viewGroup: ViewGroup, attachToRoot: Boolean = false): View {
|
||||||
|
return inflater.inflate(resId, viewGroup, attachToRoot)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateValues(arrayList: ArrayList<Item>) {
|
||||||
|
values.clear()
|
||||||
|
values += arrayList
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateValues(list: List<Item>) = updateValues(ArrayList(list))
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: VH, position: Int) {
|
||||||
|
onBindItemViewHolder(holder, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun initListeners(itemView: View, position: Int) {
|
||||||
|
if (itemView is AdapterView<*>) return
|
||||||
|
|
||||||
|
itemView.setOnClickListener {
|
||||||
|
itemClickListener?.onItemClick(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
itemView.setOnLongClickListener {
|
||||||
|
itemLongClickListener?.onItemLongClick(position)
|
||||||
|
return@setOnLongClickListener itemClickListener == null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return values.size
|
||||||
|
}
|
||||||
|
|
||||||
|
val size get() = itemCount
|
||||||
|
|
||||||
|
private fun onBindItemViewHolder(holder: VH, position: Int) {
|
||||||
|
initListeners(holder.itemView, position)
|
||||||
|
holder.bind(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.meloda.fast.base.adapter
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onItemClick(position: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnItemLongClickListener {
|
||||||
|
fun onItemLongClick(position: Int)
|
||||||
|
}
|
||||||
@@ -2,32 +2,18 @@ package com.meloda.fast.common
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.app.DownloadManager
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.database.sqlite.SQLiteDatabase
|
import android.database.sqlite.SQLiteDatabase
|
||||||
import android.net.ConnectivityManager
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.view.WindowManager
|
|
||||||
import android.view.inputmethod.InputMethodManager
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
|
||||||
import androidx.core.content.pm.PackageInfoCompat
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.meloda.fast.BuildConfig
|
import com.meloda.fast.BuildConfig
|
||||||
import com.meloda.fast.R
|
import com.meloda.fast.R
|
||||||
import com.meloda.fast.UserConfig
|
import com.meloda.fast.UserConfig
|
||||||
import com.meloda.fast.database.CacheStorage
|
|
||||||
import com.meloda.fast.database.DatabaseHelper
|
import com.meloda.fast.database.DatabaseHelper
|
||||||
import com.meloda.fast.fragment.SettingsFragment
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
import com.meloda.fast.util.AndroidUtils
|
||||||
import com.meloda.mvp.MvpBase
|
|
||||||
import com.microsoft.appcenter.AppCenter
|
|
||||||
import com.microsoft.appcenter.analytics.Analytics
|
|
||||||
import com.microsoft.appcenter.crashes.Crashes
|
|
||||||
import org.acra.ACRA
|
import org.acra.ACRA
|
||||||
import org.acra.ReportingInteractionMode
|
import org.acra.ReportingInteractionMode
|
||||||
import org.acra.annotation.ReportsCrashes
|
import org.acra.annotation.ReportsCrashes
|
||||||
@@ -46,13 +32,6 @@ import java.util.*
|
|||||||
class AppGlobal : Application() {
|
class AppGlobal : Application() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val APP_CENTER_TOKEN = "c87e410a-d622-4c52-ad7e-7388ab511704"
|
|
||||||
|
|
||||||
lateinit var windowManager: WindowManager
|
|
||||||
lateinit var connectivityManager: ConnectivityManager
|
|
||||||
lateinit var inputMethodManager: InputMethodManager
|
|
||||||
lateinit var clipboardManager: ClipboardManager
|
|
||||||
lateinit var downloadManager: DownloadManager
|
|
||||||
|
|
||||||
lateinit var preferences: SharedPreferences
|
lateinit var preferences: SharedPreferences
|
||||||
lateinit var locale: Locale
|
lateinit var locale: Locale
|
||||||
@@ -82,15 +61,9 @@ class AppGlobal : Application() {
|
|||||||
instance = this
|
instance = this
|
||||||
|
|
||||||
if (!BuildConfig.DEBUG) {
|
if (!BuildConfig.DEBUG) {
|
||||||
AppCenter.start(
|
|
||||||
this, APP_CENTER_TOKEN, Analytics::class.java, Crashes::class.java
|
|
||||||
)
|
|
||||||
|
|
||||||
ACRA.init(this)
|
ACRA.init(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
Fresco.initialize(this)
|
|
||||||
|
|
||||||
preferences = PreferenceManager.getDefaultSharedPreferences(this)
|
preferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
handler = Handler(mainLooper)
|
handler = Handler(mainLooper)
|
||||||
locale = Locale.getDefault()
|
locale = Locale.getDefault()
|
||||||
@@ -106,62 +79,10 @@ class AppGlobal : Application() {
|
|||||||
Companion.packageName = packageName
|
Companion.packageName = packageName
|
||||||
Companion.packageManager = packageManager
|
Companion.packageManager = packageManager
|
||||||
|
|
||||||
inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
|
||||||
windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
|
||||||
connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
|
||||||
clipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
||||||
downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
|
||||||
|
|
||||||
screenWidth = AndroidUtils.getDisplayWidth()
|
screenWidth = AndroidUtils.getDisplayWidth()
|
||||||
screenHeight = AndroidUtils.getDisplayHeight()
|
screenHeight = AndroidUtils.getDisplayHeight()
|
||||||
|
|
||||||
UserConfig.restore()
|
UserConfig.restore()
|
||||||
|
|
||||||
MvpBase.init(handler)
|
|
||||||
|
|
||||||
logDatabase()
|
|
||||||
fillMemoryCache()
|
|
||||||
|
|
||||||
applyNightMode()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun logDatabase() {
|
|
||||||
val users = CacheStorage.usersStorage.getAllValues()
|
|
||||||
val groups = CacheStorage.groupsStorage.getAllValues()
|
|
||||||
val chats = CacheStorage.chatsStorage.getAllValues()
|
|
||||||
val messages = CacheStorage.messagesStorage.getAllValues()
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fillMemoryCache() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun applyNightMode(value: String? = null): Int {
|
|
||||||
val mode = value ?: preferences.getString(SettingsFragment.KEY_THEME, "-1")!!
|
|
||||||
|
|
||||||
val nightMode = getNightMode(mode.toInt())
|
|
||||||
|
|
||||||
val oldNightMode = AppCompatDelegate.getDefaultNightMode()
|
|
||||||
|
|
||||||
AppCompatDelegate.setDefaultNightMode(nightMode)
|
|
||||||
|
|
||||||
return nightMode
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getNightMode(nightMode: Int = -1): Int {
|
|
||||||
val mode = if (nightMode != -1) nightMode else preferences.getString(
|
|
||||||
SettingsFragment.KEY_THEME,
|
|
||||||
"-1"
|
|
||||||
)!!.toInt()
|
|
||||||
|
|
||||||
return when (mode) {
|
|
||||||
1 -> AppCompatDelegate.MODE_NIGHT_YES
|
|
||||||
2 -> AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY
|
|
||||||
3 -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
|
||||||
else -> AppCompatDelegate.MODE_NIGHT_NO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,8 +3,6 @@ package com.meloda.fast.common
|
|||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import com.meloda.fast.R
|
import com.meloda.fast.R
|
||||||
import com.meloda.fast.fragment.FragmentConversationsDeprecated
|
|
||||||
import com.meloda.fast.fragment.FragmentFriendsDeprecated
|
|
||||||
|
|
||||||
object FragmentSwitcher {
|
object FragmentSwitcher {
|
||||||
|
|
||||||
@@ -62,8 +60,7 @@ object FragmentSwitcher {
|
|||||||
val transaction = fragmentManager.beginTransaction()
|
val transaction = fragmentManager.beginTransaction()
|
||||||
|
|
||||||
if (fragmentToShow == null) {
|
if (fragmentToShow == null) {
|
||||||
fragmentToShow = createFragmentByTag(tag)
|
throw NullPointerException("Required fragment is null")
|
||||||
transaction.add(containerId, fragmentToShow, tag)
|
|
||||||
} else {
|
} else {
|
||||||
transaction.show(fragmentToShow)
|
transaction.show(fragmentToShow)
|
||||||
}
|
}
|
||||||
@@ -105,12 +102,4 @@ object FragmentSwitcher {
|
|||||||
|
|
||||||
transaction.commitNow()
|
transaction.commitNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createFragmentByTag(tag: String): Fragment {
|
|
||||||
return when (tag) {
|
|
||||||
"FragmentFriends" -> FragmentFriendsDeprecated()
|
|
||||||
"FragmentConversations" -> FragmentConversationsDeprecated()
|
|
||||||
else -> Fragment()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ package com.meloda.fast.common
|
|||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.collection.arrayMapOf
|
import androidx.collection.arrayMapOf
|
||||||
import com.meloda.concurrent.TaskManager
|
import com.meloda.fast.concurrent.TaskManager
|
||||||
import com.meloda.fast.BuildConfig
|
import com.meloda.fast.BuildConfig
|
||||||
import com.meloda.fast.model.NewUpdateInfo
|
import com.meloda.fast.model.NewUpdateInfo
|
||||||
import com.meloda.netservices.HttpRequest
|
import com.meloda.fast.net.HttpRequest
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
package com.meloda.concurrent
|
package com.meloda.fast.concurrent
|
||||||
|
|
||||||
class EventInfo<T> constructor(var key: String, var data: T? = null)
|
class EventInfo<T> constructor(var key: String, var data: T? = null)
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.concurrent
|
package com.meloda.fast.concurrent
|
||||||
|
|
||||||
import android.os.Process
|
import android.os.Process
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.concurrent
|
package com.meloda.fast.concurrent
|
||||||
|
|
||||||
object TaskManager {
|
object TaskManager {
|
||||||
|
|
||||||
@@ -12,9 +12,9 @@ import com.meloda.fast.database.storage.ChatsStorage
|
|||||||
import com.meloda.fast.database.storage.GroupsStorage
|
import com.meloda.fast.database.storage.GroupsStorage
|
||||||
import com.meloda.fast.database.storage.MessagesStorage
|
import com.meloda.fast.database.storage.MessagesStorage
|
||||||
import com.meloda.fast.database.storage.UsersStorage
|
import com.meloda.fast.database.storage.UsersStorage
|
||||||
import com.meloda.vksdk.model.VKConversation
|
import com.meloda.fast.api.model.VKConversation
|
||||||
import com.meloda.vksdk.model.VKMessage
|
import com.meloda.fast.api.model.VKMessage
|
||||||
import com.meloda.vksdk.model.VKUser
|
import com.meloda.fast.api.model.VKUser
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
object CacheStorage {
|
object CacheStorage {
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ import com.meloda.fast.database.DatabaseKeys.TYPE
|
|||||||
import com.meloda.fast.database.DatabaseKeys.UNREAD_COUNT
|
import com.meloda.fast.database.DatabaseKeys.UNREAD_COUNT
|
||||||
import com.meloda.fast.database.DatabaseUtils.TABLE_CHATS
|
import com.meloda.fast.database.DatabaseUtils.TABLE_CHATS
|
||||||
import com.meloda.fast.database.base.Storage
|
import com.meloda.fast.database.base.Storage
|
||||||
import com.meloda.vksdk.model.VKConversation
|
import com.meloda.fast.api.model.VKConversation
|
||||||
import com.meloda.vksdk.util.VKUtil
|
import com.meloda.fast.api.util.VKUtil
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ import com.meloda.fast.database.DatabaseKeys.SCREEN_NAME
|
|||||||
import com.meloda.fast.database.DatabaseKeys.TYPE
|
import com.meloda.fast.database.DatabaseKeys.TYPE
|
||||||
import com.meloda.fast.database.DatabaseUtils.TABLE_GROUPS
|
import com.meloda.fast.database.DatabaseUtils.TABLE_GROUPS
|
||||||
import com.meloda.fast.database.base.Storage
|
import com.meloda.fast.database.base.Storage
|
||||||
import com.meloda.vksdk.model.VKGroup
|
import com.meloda.fast.api.model.VKGroup
|
||||||
import com.meloda.vksdk.util.VKUtil
|
import com.meloda.fast.api.util.VKUtil
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
class GroupsStorage : Storage<VKGroup>() {
|
class GroupsStorage : Storage<VKGroup>() {
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ import com.meloda.fast.database.DatabaseKeys.TEXT
|
|||||||
import com.meloda.fast.database.DatabaseUtils.TABLE_MESSAGES
|
import com.meloda.fast.database.DatabaseUtils.TABLE_MESSAGES
|
||||||
import com.meloda.fast.database.base.Storage
|
import com.meloda.fast.database.base.Storage
|
||||||
import com.meloda.fast.util.Utils
|
import com.meloda.fast.util.Utils
|
||||||
import com.meloda.vksdk.model.VKMessage
|
import com.meloda.fast.api.model.VKMessage
|
||||||
import com.meloda.vksdk.model.VKMessageAction
|
import com.meloda.fast.api.model.VKMessageAction
|
||||||
import com.meloda.vksdk.model.VKModel
|
import com.meloda.fast.api.model.VKModel
|
||||||
import java.util.stream.Collectors
|
import java.util.stream.Collectors
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ 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.vksdk.model.VKUser
|
import com.meloda.fast.api.model.VKUser
|
||||||
import com.meloda.vksdk.util.VKUtil
|
import com.meloda.fast.api.util.VKUtil
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
|
|||||||
@@ -1,113 +0,0 @@
|
|||||||
package com.meloda.fast.dialog
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.RelativeLayout
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
import com.facebook.imagepipeline.cache.MemoryCache
|
|
||||||
import com.meloda.extensions.ContextExtensions.drawable
|
|
||||||
import com.meloda.extensions.DrawableExtensions.tint
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.UserConfig
|
|
||||||
import com.meloda.fast.activity.SettingsActivityDeprecated
|
|
||||||
import com.meloda.fast.adapter.SimpleItemAdapter
|
|
||||||
import com.meloda.fast.base.BaseFullscreenDialog
|
|
||||||
import com.meloda.fast.common.AppGlobal
|
|
||||||
import com.meloda.fast.item.SimpleMenuItem
|
|
||||||
import com.meloda.fast.listener.ItemClickListener
|
|
||||||
import com.meloda.fast.util.ColorUtils
|
|
||||||
import com.meloda.fast.util.ViewUtils
|
|
||||||
import com.meloda.fast.widget.Toolbar
|
|
||||||
|
|
||||||
class AccountDialog : BaseFullscreenDialog(), ItemClickListener {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val TAG = "account_fullscreen_dialog"
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var adapter: SimpleItemAdapter
|
|
||||||
|
|
||||||
private lateinit var toolbar: Toolbar
|
|
||||||
private lateinit var recyclerView: RecyclerView
|
|
||||||
private lateinit var refreshLayout: SwipeRefreshLayout
|
|
||||||
private lateinit var headerRoot: RelativeLayout
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
return inflater.inflate(R.layout.dialog_account, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
initViews()
|
|
||||||
prepareToolbar()
|
|
||||||
prepareRecyclerView()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initViews() {
|
|
||||||
toolbar = requireView().findViewById(R.id.toolbar)
|
|
||||||
recyclerView = requireView().findViewById(R.id.recyclerView)
|
|
||||||
refreshLayout = requireView().findViewById(R.id.refreshLayout)
|
|
||||||
headerRoot = requireView().findViewById(R.id.headerRoot)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareToolbar() {
|
|
||||||
toolbar.navigationIcon = requireContext().drawable(R.drawable.ic_close)
|
|
||||||
toolbar.tintNavigationIcon(ColorUtils.getColorAccent(requireContext()))
|
|
||||||
|
|
||||||
toolbar.setTitle(R.string.account_dialog_title)
|
|
||||||
toolbar.setTitleMode(Toolbar.TitleMode.SIMPLE)
|
|
||||||
toolbar.setNavigationClickListener { dismiss() }
|
|
||||||
|
|
||||||
// MemoryCache.getUserById(UserConfig.userId)?.let {
|
|
||||||
// AppGlobal.handler.post { ViewUtils.prepareNavigationHeader(headerRoot, it) }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareRecyclerView() {
|
|
||||||
refreshLayout.isEnabled = false
|
|
||||||
|
|
||||||
recyclerView.layoutManager =
|
|
||||||
LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false)
|
|
||||||
recyclerView.setHasFixedSize(true)
|
|
||||||
|
|
||||||
createItemsAndAdapter()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createItemsAndAdapter() {
|
|
||||||
val items = arrayListOf<SimpleMenuItem>()
|
|
||||||
|
|
||||||
SimpleMenuItem(
|
|
||||||
requireContext().drawable(R.drawable.ic_settings_outline)
|
|
||||||
.tint(ColorUtils.getColorAccent(requireContext())),
|
|
||||||
requireContext().getString(R.string.navigation_settings)
|
|
||||||
) { openSettingsScreen() }.let { items.add(it) }
|
|
||||||
|
|
||||||
adapter = SimpleItemAdapter(requireContext(), items).also {
|
|
||||||
it.itemClickListener = this
|
|
||||||
}
|
|
||||||
|
|
||||||
recyclerView.adapter = adapter
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openSettingsScreen() {
|
|
||||||
startActivity(Intent(requireContext(), SettingsActivityDeprecated::class.java))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemClick(position: Int) {
|
|
||||||
val item = adapter.getItem(position)
|
|
||||||
|
|
||||||
item.clickListener?.let {
|
|
||||||
it.onClick(requireView().findViewById(android.R.id.content))
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
package com.meloda.fast.dialog
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.adapter.SimpleItemAdapter
|
|
||||||
import com.meloda.fast.item.SimpleMenuItem
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
import com.meloda.vksdk.model.VKUser
|
|
||||||
|
|
||||||
open class ProfileDialog(
|
|
||||||
private val conversation: VKConversation,
|
|
||||||
private val chatTitle: String
|
|
||||||
) : BottomSheetDialogFragment() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val TAG = "profile_bottom_sheet_dialog"
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var title: TextView
|
|
||||||
private lateinit var subtitle: TextView
|
|
||||||
private lateinit var recyclerView: RecyclerView
|
|
||||||
private lateinit var root: LinearLayout
|
|
||||||
|
|
||||||
private var adapter: SimpleItemAdapter? = null
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
setStyle(STYLE_NO_TITLE, R.style.AppTheme_ProfileDialog)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
return inflater.inflate(R.layout.dialog_profile_bottom, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
title = view.findViewById(R.id.profileTitle)
|
|
||||||
subtitle = view.findViewById(R.id.profileSubtitle)
|
|
||||||
recyclerView = view.findViewById(R.id.profileItemMenu)
|
|
||||||
root = view.findViewById(R.id.profileRoot)
|
|
||||||
|
|
||||||
val layoutManager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false)
|
|
||||||
|
|
||||||
recyclerView.layoutManager = layoutManager
|
|
||||||
|
|
||||||
title.text = chatTitle
|
|
||||||
|
|
||||||
subtitle.text = getSubtitle()
|
|
||||||
|
|
||||||
val items = ArrayList<SimpleMenuItem>()
|
|
||||||
|
|
||||||
items.add(
|
|
||||||
SimpleMenuItem(
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
requireContext(),
|
|
||||||
R.drawable.ic_search
|
|
||||||
)!!, "Search"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
createAdapter(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createAdapter(items: ArrayList<SimpleMenuItem>) {
|
|
||||||
adapter = SimpleItemAdapter(requireContext(), items)
|
|
||||||
recyclerView.adapter = adapter
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getSubtitle(): String {
|
|
||||||
return when (conversation.type) {
|
|
||||||
VKConversation.Type.CHAT -> getString(
|
|
||||||
R.string.chat_members,
|
|
||||||
conversation.membersCount
|
|
||||||
)
|
|
||||||
VKConversation.Type.GROUP -> {
|
|
||||||
// val group = MemoryCache.getGroupById(conversation.conversationId) ?: return ""
|
|
||||||
//
|
|
||||||
// "@${group.screenName}"
|
|
||||||
""
|
|
||||||
}
|
|
||||||
VKConversation.Type.USER -> {
|
|
||||||
// val user = MemoryCache.getUserById(conversation.id) ?: return ""
|
|
||||||
|
|
||||||
//TODO: придумать чо делать
|
|
||||||
val user: VKUser = null ?: return ""
|
|
||||||
|
|
||||||
var str =
|
|
||||||
if (user.screenName.contains("id${user.userId}")) "" else "@${user.screenName}"
|
|
||||||
|
|
||||||
val online =
|
|
||||||
getString(if (user.isOnlineMobile) R.string.user_online_mobile else if (user.isOnline) R.string.user_online else R.string.user_offline)
|
|
||||||
|
|
||||||
str += if (str.isEmpty()) online else " · $online"
|
|
||||||
|
|
||||||
str
|
|
||||||
}
|
|
||||||
else -> ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.extensions
|
package com.meloda.fast.extensions
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.extensions
|
package com.meloda.fast.extensions
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.extensions
|
package com.meloda.fast.extensions
|
||||||
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
package com.meloda.fast.extensions
|
||||||
|
|
||||||
|
import androidx.annotation.UiThread
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
|
||||||
|
object LiveDataExtensions {
|
||||||
|
|
||||||
|
operator fun <T> MutableLiveData<MutableList<T>>.set(position: Int, v: T) {
|
||||||
|
val value = (this.value ?: arrayListOf()).apply { this[position] = v }
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun <T> MutableLiveData<MutableList<T>>.get(position: Int): T {
|
||||||
|
return (value as MutableList<T>)[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
fun <T> MutableLiveData<MutableList<T>>.add(v: T, position: Int = -1) {
|
||||||
|
val value = (this.value ?: arrayListOf()).apply {
|
||||||
|
if (position == -1) this.add(v) else this.add(position, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
fun <T> MutableLiveData<MutableList<T>>.addAll(values: List<T>, position: Int = -1) {
|
||||||
|
val value = (this.value ?: arrayListOf()).apply {
|
||||||
|
if (position == -1) this.addAll(values)
|
||||||
|
else this.addAll(position, values)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("TYPE_INFERENCE_ONLY_INPUT_TYPES_WARNING")
|
||||||
|
fun <T> MutableLiveData<MutableList<T>>.removeAll(values: List<T>) {
|
||||||
|
val value = (this.value ?: arrayListOf()).apply {
|
||||||
|
this.removeAll(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> MutableLiveData<MutableList<T>>.removeAt(index: Int) {
|
||||||
|
val value = (this.value ?: arrayListOf()).apply {
|
||||||
|
this.removeAt(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> MutableLiveData<MutableList<T>>.remove(item: T) {
|
||||||
|
val value = (this.value ?: arrayListOf()).apply {
|
||||||
|
this.remove(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun <T> MutableLiveData<MutableList<T>>.iterator(): Iterator<T> {
|
||||||
|
return (value as MutableList<T>).iterator()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> MutableLiveData<MutableList<T>>.clear() {
|
||||||
|
value = arrayListOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
val <T> MutableLiveData<MutableList<T>>.indices get() = (value as MutableList<T>).indices
|
||||||
|
|
||||||
|
val <T> MutableLiveData<MutableList<T>>.size get() = (value as MutableList<T>).size
|
||||||
|
|
||||||
|
fun <T> MutableLiveData<MutableList<T>>.isEmpty(): Boolean {
|
||||||
|
return (value as MutableList<T>).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> MutableLiveData<MutableList<T>>.isNotEmpty(): Boolean {
|
||||||
|
return !isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> MutableLiveData<MutableList<T>>.requireValue() = value!!
|
||||||
|
|
||||||
|
@UiThread
|
||||||
|
operator fun <T> MutableLiveData<MutableList<T>>.plusAssign(values: List<T>) {
|
||||||
|
val value = (this.value ?: arrayListOf()).apply {
|
||||||
|
this.addAll(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun <T> MutableLiveData<MutableList<T>>.plusAssign(v: T) {
|
||||||
|
val value = (this.value ?: arrayListOf()).apply {
|
||||||
|
this.add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun <T> MutableLiveData<MutableList<T>>.minusAssign(values: List<T>) {
|
||||||
|
val value = (this.value ?: arrayListOf()).apply {
|
||||||
|
this.removeAll(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun <T> MutableLiveData<MutableList<T>>.minusAssign(v: T) {
|
||||||
|
val value = (this.value ?: arrayListOf()).apply {
|
||||||
|
this.remove(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.extensions
|
package com.meloda.fast.extensions
|
||||||
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.meloda.extensions
|
package com.meloda.fast.extensions
|
||||||
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
package com.meloda.fast.fragment
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.ProgressBar
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
import com.meloda.concurrent.TaskManager
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.adapter.ConversationsAdapterDeprecated
|
|
||||||
import com.meloda.fast.base.BaseFragment
|
|
||||||
import com.meloda.fast.database.CacheStorage
|
|
||||||
import com.meloda.fast.widget.Toolbar
|
|
||||||
import com.meloda.vksdk.OnResponseListener
|
|
||||||
import com.meloda.vksdk.VKApi
|
|
||||||
import com.meloda.vksdk.VKConstants
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
import com.meloda.vksdk.model.VKMessage
|
|
||||||
|
|
||||||
class ChatsFragment : BaseFragment() {
|
|
||||||
|
|
||||||
private lateinit var toolbar: Toolbar
|
|
||||||
private lateinit var progressBar: ProgressBar
|
|
||||||
private lateinit var recyclerView: RecyclerView
|
|
||||||
private lateinit var refreshLayout: SwipeRefreshLayout
|
|
||||||
|
|
||||||
private lateinit var noItemsView: LinearLayout
|
|
||||||
private lateinit var noInternetView: LinearLayout
|
|
||||||
private lateinit var errorView: LinearLayout
|
|
||||||
|
|
||||||
private lateinit var adapter: ConversationsAdapterDeprecated
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
return inflater.inflate(R.layout.fragment_conversations, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
initViews()
|
|
||||||
prepareViews()
|
|
||||||
|
|
||||||
createAdapter()
|
|
||||||
|
|
||||||
loadConversations()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initViews() {
|
|
||||||
toolbar = requireView().findViewById(R.id.toolbar)
|
|
||||||
progressBar = requireView().findViewById(R.id.progressBar)
|
|
||||||
recyclerView = requireView().findViewById(R.id.recyclerView)
|
|
||||||
refreshLayout = requireView().findViewById(R.id.refreshLayout)
|
|
||||||
|
|
||||||
noItemsView = requireView().findViewById(R.id.noItemsView)
|
|
||||||
noInternetView = requireView().findViewById(R.id.noInternetView)
|
|
||||||
errorView = requireView().findViewById(R.id.errorView)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareViews() {
|
|
||||||
prepareRecyclerView()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareRecyclerView() {
|
|
||||||
val manager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false)
|
|
||||||
|
|
||||||
recyclerView.layoutManager = manager
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createAdapter() {
|
|
||||||
adapter = ConversationsAdapterDeprecated(recyclerView, arrayListOf())
|
|
||||||
recyclerView.adapter = adapter
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadConversations() {
|
|
||||||
TaskManager.execute {
|
|
||||||
VKApi.messages()
|
|
||||||
.getConversations()
|
|
||||||
.filter("all")
|
|
||||||
.extended(true)
|
|
||||||
.fields(VKConstants.USER_FIELDS)
|
|
||||||
.offset(0)
|
|
||||||
.count(30)
|
|
||||||
.executeArray(
|
|
||||||
VKConversation::class.java,
|
|
||||||
object : OnResponseListener<ArrayList<VKConversation>> {
|
|
||||||
override fun onResponse(response: ArrayList<VKConversation>) {
|
|
||||||
TaskManager.execute {
|
|
||||||
CacheStorage.chatsStorage.insertValues(response)
|
|
||||||
|
|
||||||
val lastMessages = arrayListOf<VKMessage>()
|
|
||||||
response.forEach { lastMessages.add(it.lastMessage) }
|
|
||||||
|
|
||||||
CacheStorage.messagesStorage.insertValues(lastMessages)
|
|
||||||
CacheStorage.usersStorage.insertValues(VKConversation.profiles)
|
|
||||||
CacheStorage.groupsStorage.insertValues(VKConversation.groups)
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.updateValues(response)
|
|
||||||
adapter.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
package com.meloda.fast.fragment
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.drawable.ColorDrawable
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.ProgressBar
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
import com.meloda.concurrent.EventInfo
|
|
||||||
import com.meloda.concurrent.TaskManager
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.UserConfig
|
|
||||||
import com.meloda.fast.activity.MessagesActivityDeprecated
|
|
||||||
import com.meloda.fast.base.BaseFragment
|
|
||||||
import com.meloda.fast.fragment.ui.presenter.ConversationsPresenterDeprecated
|
|
||||||
import com.meloda.fast.fragment.ui.view.ConversationsViewDeprecated
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
|
||||||
import com.meloda.fast.util.ViewUtils
|
|
||||||
import com.meloda.fast.widget.Toolbar
|
|
||||||
import com.meloda.vksdk.VKApiKeys
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
class FragmentConversationsDeprecated : BaseFragment(), ConversationsViewDeprecated {
|
|
||||||
|
|
||||||
private lateinit var presenterDeprecated: ConversationsPresenterDeprecated
|
|
||||||
|
|
||||||
private lateinit var toolbar: Toolbar
|
|
||||||
private lateinit var refreshLayout: SwipeRefreshLayout
|
|
||||||
private lateinit var recyclerView: RecyclerView
|
|
||||||
private lateinit var progressBar: ProgressBar
|
|
||||||
|
|
||||||
private lateinit var noItemsView: LinearLayout
|
|
||||||
private lateinit var noInternetView: LinearLayout
|
|
||||||
private lateinit var errorView: LinearLayout
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? = inflater.inflate(R.layout.fragment_conversations, container, false)
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
initViews()
|
|
||||||
|
|
||||||
prepareToolbar()
|
|
||||||
prepareRecyclerView()
|
|
||||||
prepareRefreshLayout()
|
|
||||||
|
|
||||||
presenterDeprecated = ConversationsPresenterDeprecated(this)
|
|
||||||
presenterDeprecated.setup(recyclerView, refreshLayout)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initViews() {
|
|
||||||
toolbar = requireView().findViewById(R.id.toolbar)
|
|
||||||
recyclerView = requireView().findViewById(R.id.recyclerView)
|
|
||||||
refreshLayout = requireView().findViewById(R.id.refreshLayout)
|
|
||||||
progressBar = requireView().findViewById(R.id.progressBar)
|
|
||||||
|
|
||||||
noItemsView = requireView().findViewById(R.id.noItemsView)
|
|
||||||
noInternetView = requireView().findViewById(R.id.noInternetView)
|
|
||||||
errorView = requireView().findViewById(R.id.errorView)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareToolbar() {
|
|
||||||
initToolbar(R.id.toolbar)
|
|
||||||
toolbar.title = getString(R.string.navigation_chats)
|
|
||||||
setProfileAvatar()
|
|
||||||
|
|
||||||
TaskManager.addOnEventListener(object : TaskManager.OnEventListener {
|
|
||||||
override fun onNewEvent(info: EventInfo<*>) {
|
|
||||||
if (info.key == VKApiKeys.UPDATE_USER.name) {
|
|
||||||
val userIds = info.data as ArrayList<Int>
|
|
||||||
|
|
||||||
if (userIds.contains(UserConfig.userId)) {
|
|
||||||
setProfileAvatar()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareRefreshLayout() {
|
|
||||||
refreshLayout.setColorSchemeResources(R.color.accent)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareRecyclerView() {
|
|
||||||
val manager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false)
|
|
||||||
|
|
||||||
val decoration = DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)
|
|
||||||
|
|
||||||
decoration.setDrawable(
|
|
||||||
ColorDrawable(
|
|
||||||
AndroidUtils.getThemeAttrColor(
|
|
||||||
requireContext(),
|
|
||||||
R.attr.dividerHorizontal
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
recyclerView.itemAnimator = null
|
|
||||||
recyclerView.addItemDecoration(decoration)
|
|
||||||
|
|
||||||
recyclerView.layoutManager = manager
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setProfileAvatar() {
|
|
||||||
TaskManager.execute {
|
|
||||||
// AppGlobal.database.users.getById(UserConfig.userId)?.let {
|
|
||||||
// if (it.photo100.isNotEmpty()) {
|
|
||||||
// runOnUiThread {
|
|
||||||
// toolbar.getAvatar().setImageURI(it.photo100)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openChat(extras: Bundle) {
|
|
||||||
startActivity(
|
|
||||||
Intent(requireContext(), MessagesActivityDeprecated::class.java).putExtras(
|
|
||||||
extras
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showErrorSnackbar(t: Throwable) {
|
|
||||||
ViewUtils.showErrorSnackbar(requireView(), t)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareNoItemsView() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showNoItemsView() {
|
|
||||||
noItemsView.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideNoItemsView() {
|
|
||||||
noItemsView.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareNoInternetView() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showNoInternetView() {
|
|
||||||
noInternetView.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideNoInternetView() {
|
|
||||||
noInternetView.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareErrorView() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showErrorView() {
|
|
||||||
errorView.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideErrorView() {
|
|
||||||
errorView.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showProgressBar() {
|
|
||||||
progressBar.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideProgressBar() {
|
|
||||||
progressBar.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showRefreshLayout() {
|
|
||||||
refreshLayout.isRefreshing = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideRefreshLayout() {
|
|
||||||
refreshLayout.isRefreshing = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
package com.meloda.fast.fragment
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.drawable.ColorDrawable
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.ProgressBar
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
import com.meloda.concurrent.EventInfo
|
|
||||||
import com.meloda.concurrent.TaskManager
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.UserConfig
|
|
||||||
import com.meloda.fast.activity.MessagesActivityDeprecated
|
|
||||||
import com.meloda.fast.base.BaseFragment
|
|
||||||
import com.meloda.fast.fragment.ui.presenter.FriendsPresenterDeprecated
|
|
||||||
import com.meloda.fast.fragment.ui.view.FriendsViewDeprecated
|
|
||||||
import com.meloda.fast.util.ViewUtils
|
|
||||||
import com.meloda.fast.widget.Toolbar
|
|
||||||
import com.meloda.vksdk.VKApiKeys
|
|
||||||
|
|
||||||
class FragmentFriendsDeprecated(private val userId: Int = 0) : BaseFragment(),
|
|
||||||
FriendsViewDeprecated {
|
|
||||||
|
|
||||||
private lateinit var presenterDeprecated: FriendsPresenterDeprecated
|
|
||||||
|
|
||||||
private lateinit var toolbar: Toolbar
|
|
||||||
private lateinit var recyclerView: RecyclerView
|
|
||||||
private lateinit var refreshLayout: SwipeRefreshLayout
|
|
||||||
private lateinit var progressBar: ProgressBar
|
|
||||||
|
|
||||||
private lateinit var noItemsView: LinearLayout
|
|
||||||
private lateinit var noInternetView: LinearLayout
|
|
||||||
private lateinit var errorView: LinearLayout
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
return inflater.inflate(R.layout.fragment_friends, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
initViews()
|
|
||||||
|
|
||||||
prepareToolbar()
|
|
||||||
prepareRecyclerView()
|
|
||||||
prepareRefreshLayout()
|
|
||||||
|
|
||||||
presenterDeprecated = FriendsPresenterDeprecated(this)
|
|
||||||
presenterDeprecated.setup(userId, recyclerView, refreshLayout)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initViews() {
|
|
||||||
toolbar = requireView().findViewById(R.id.toolbar)
|
|
||||||
recyclerView = requireView().findViewById(R.id.recyclerView)
|
|
||||||
refreshLayout = requireView().findViewById(R.id.refreshLayout)
|
|
||||||
progressBar = requireView().findViewById(R.id.progressBar)
|
|
||||||
|
|
||||||
noItemsView = requireView().findViewById(R.id.noItemsView)
|
|
||||||
noInternetView = requireView().findViewById(R.id.noInternetView)
|
|
||||||
errorView = requireView().findViewById(R.id.errorView)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareToolbar() {
|
|
||||||
initToolbar(R.id.toolbar)
|
|
||||||
toolbar.title = getString(R.string.navigation_friends)
|
|
||||||
setProfileAvatar()
|
|
||||||
|
|
||||||
toolbar.inflateMenu(R.menu.fragment_friends)
|
|
||||||
|
|
||||||
TaskManager.addOnEventListener(object : TaskManager.OnEventListener {
|
|
||||||
override fun onNewEvent(info: EventInfo<*>) {
|
|
||||||
if (info.key == VKApiKeys.UPDATE_USER.name) {
|
|
||||||
val userId = info.data as ArrayList<Int>
|
|
||||||
|
|
||||||
if (userId[0] == UserConfig.userId) {
|
|
||||||
setProfileAvatar()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setProfileAvatar() {
|
|
||||||
TaskManager.execute {
|
|
||||||
// AppGlobal.database.users.getById(UserConfig.userId)?.let {
|
|
||||||
// if (it.photo100.isNotEmpty()) {
|
|
||||||
// runOnUi {
|
|
||||||
// toolbar.getAvatar().setImageURI(it.photo100)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDetach() {
|
|
||||||
presenterDeprecated.destroy()
|
|
||||||
super.onDetach()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareRefreshLayout() {
|
|
||||||
refreshLayout.setColorSchemeResources(R.color.accent)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareRecyclerView() {
|
|
||||||
val manager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false)
|
|
||||||
|
|
||||||
val decoration = DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)
|
|
||||||
|
|
||||||
decoration.setDrawable(
|
|
||||||
ColorDrawable(
|
|
||||||
ContextCompat.getColor(
|
|
||||||
requireContext(),
|
|
||||||
R.color.divider
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
recyclerView.addItemDecoration(decoration)
|
|
||||||
recyclerView.layoutManager = manager
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openChat(extras: Bundle) {
|
|
||||||
startActivity(
|
|
||||||
Intent(requireContext(), MessagesActivityDeprecated::class.java).putExtras(
|
|
||||||
extras
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showErrorSnackbar(t: Throwable) {
|
|
||||||
ViewUtils.showErrorSnackbar(requireView(), t)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareNoItemsView() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showNoItemsView() {
|
|
||||||
noItemsView.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideNoItemsView() {
|
|
||||||
noItemsView.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareNoInternetView() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showNoInternetView() {
|
|
||||||
noInternetView.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideNoInternetView() {
|
|
||||||
noInternetView.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareErrorView() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showErrorView() {
|
|
||||||
errorView.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideErrorView() {
|
|
||||||
errorView.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun showProgressBar() {
|
|
||||||
progressBar.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideProgressBar() {
|
|
||||||
progressBar.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showRefreshLayout() {
|
|
||||||
refreshLayout.isRefreshing = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideRefreshLayout() {
|
|
||||||
refreshLayout.isRefreshing = false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,171 +1,22 @@
|
|||||||
package com.meloda.fast.fragment
|
package com.meloda.fast.fragment
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
|
||||||
import android.text.TextWatcher
|
|
||||||
import android.view.KeyEvent
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.viewbinding.library.fragment.viewBinding
|
||||||
import android.view.inputmethod.EditorInfo
|
|
||||||
import android.widget.EditText
|
|
||||||
import com.google.android.material.button.MaterialButton
|
|
||||||
import com.google.android.material.card.MaterialCardView
|
|
||||||
import com.meloda.fast.R
|
import com.meloda.fast.R
|
||||||
import com.meloda.fast.base.BaseFragment
|
import com.meloda.fast.base.BaseFragment
|
||||||
import com.meloda.fast.fragment.ui.presenter.LoginPresenter
|
import com.meloda.fast.databinding.FragmentLoginBinding
|
||||||
import com.meloda.fast.fragment.ui.view.LoginView
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
|
||||||
import com.meloda.fast.util.KeyboardUtils
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
class LoginFragment : BaseFragment(), LoginView {
|
class LoginFragment : BaseFragment(R.layout.fragment_login) {
|
||||||
|
|
||||||
private lateinit var presenter: LoginPresenter
|
private val binding: FragmentLoginBinding by viewBinding()
|
||||||
|
|
||||||
private lateinit var email: EditText
|
|
||||||
private lateinit var password: EditText
|
|
||||||
private lateinit var authorize: MaterialButton
|
|
||||||
private lateinit var card: MaterialCardView
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
presenter = LoginPresenter(this)
|
|
||||||
presenter.onCreate(requireContext(), this, savedInstanceState)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
presenter.onCreateView(savedInstanceState)
|
|
||||||
return inflater.inflate(R.layout.fragment_login, container, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
presenter.onViewCreated(savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initViews() {
|
|
||||||
email = requireView().findViewById(R.id.loginEmailEditText)
|
|
||||||
password = requireView().findViewById(R.id.loginPasswordEditText)
|
|
||||||
authorize = requireView().findViewById(R.id.loginAuthorize)
|
|
||||||
card = requireView().findViewById(R.id.loginCard)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareViews() {
|
|
||||||
prepareEmailEditText()
|
|
||||||
preparePasswordEditText()
|
|
||||||
prepareAuthorizeButton()
|
|
||||||
prepareCardView()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareEmailEditText() {
|
|
||||||
email.addTextChangedListener(onTextChangedListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun preparePasswordEditText() {
|
|
||||||
password.addTextChangedListener(onTextChangedListener)
|
|
||||||
|
|
||||||
password.setOnEditorActionListener { _, _, event ->
|
|
||||||
if (event == null) return@setOnEditorActionListener false
|
|
||||||
return@setOnEditorActionListener if (event.action == EditorInfo.IME_ACTION_GO ||
|
|
||||||
(event.action == KeyEvent.ACTION_DOWN && (event.keyCode == KeyEvent.KEYCODE_ENTER || event.keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER))
|
|
||||||
) {
|
|
||||||
KeyboardUtils.hideKeyboardFrom(password)
|
|
||||||
authorize.performClick()
|
|
||||||
true
|
|
||||||
} else false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareAuthorizeButton() {
|
|
||||||
authorize.isEnabled = false
|
|
||||||
authorize.setOnClickListener {
|
|
||||||
val emailString = email.text.toString().trim()
|
|
||||||
val passwordString = password.text.toString().trim()
|
|
||||||
|
|
||||||
presenter.login(emailString, passwordString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prepareCardView() {
|
|
||||||
val width = AndroidUtils.dp(resources.displayMetrics.widthPixels).roundToInt()
|
|
||||||
|
|
||||||
if (width < 380) {
|
|
||||||
card.strokeWidth = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showErrorSnackbar(t: Throwable) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareNoItemsView() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showNoItemsView() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideNoItemsView() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareNoInternetView() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showNoInternetView() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideNoInternetView() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun prepareErrorView() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showErrorView() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideErrorView() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showProgressBar() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideProgressBar() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showRefreshLayout() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideRefreshLayout() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
private val onTextChangedListener = object : TextWatcher {
|
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
|
||||||
authorize.isEnabled =
|
|
||||||
email.text.toString().trim().isNotEmpty() &&
|
|
||||||
password.text.toString().trim().isNotEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun afterTextChanged(s: Editable?) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
package com.meloda.fast.fragment
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.preference.Preference
|
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
|
||||||
import androidx.preference.PreferenceScreen
|
|
||||||
import com.meloda.concurrent.TaskManager
|
|
||||||
import com.meloda.extensions.ContextExtensions.color
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.activity.DropUserDataActivity
|
|
||||||
import com.meloda.fast.activity.UpdateActivityDeprecated
|
|
||||||
import com.meloda.fast.common.AppGlobal
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
|
||||||
|
|
||||||
class SettingsFragment : PreferenceFragmentCompat(),
|
|
||||||
Preference.OnPreferenceClickListener,
|
|
||||||
Preference.OnPreferenceChangeListener {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
const val CATEGORY_GENERAL = "general"
|
|
||||||
const val KEY_HIDE_KEYBOARD_ON_SCROLL_UP = "hide_keyboard_on_scroll_up"
|
|
||||||
|
|
||||||
const val CATEGORY_APPEARANCE = "appearance"
|
|
||||||
const val KEY_EXTENDED_CONVERSATIONS = "appearance_extended_conversations"
|
|
||||||
const val KEY_THEME = "appearance_theme"
|
|
||||||
|
|
||||||
const val CATEGORY_ABOUT = "about"
|
|
||||||
const val KEY_APP_VERSION = "app_version"
|
|
||||||
|
|
||||||
const val CATEGORY_ACCOUNT = "account"
|
|
||||||
const val KEY_ACCOUNT_LOGOUT = "account_logout"
|
|
||||||
|
|
||||||
const val CATEGORY_DEBUG = "debug"
|
|
||||||
const val KEY_CLEAR_USERS_GROUPS_CACHE = "clear_users_groups_cache"
|
|
||||||
}
|
|
||||||
|
|
||||||
private var currentPreferenceLayout = 0
|
|
||||||
private var isRestoringState = false
|
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
||||||
setPreferencesFromResource(R.xml.fragment_settings, rootKey)
|
|
||||||
currentPreferenceLayout = R.xml.fragment_settings
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun init() {
|
|
||||||
setTitle()
|
|
||||||
setPreferencesFromResource(currentPreferenceLayout, null)
|
|
||||||
|
|
||||||
val general = findPreference<Preference>(CATEGORY_GENERAL)
|
|
||||||
general?.onPreferenceClickListener = rootLayoutClickListener
|
|
||||||
|
|
||||||
val account = findPreference<Preference>(CATEGORY_ACCOUNT)
|
|
||||||
account?.onPreferenceClickListener = rootLayoutClickListener
|
|
||||||
|
|
||||||
val logout = findPreference<Preference>(KEY_ACCOUNT_LOGOUT)
|
|
||||||
logout?.onPreferenceClickListener = this
|
|
||||||
|
|
||||||
val about = findPreference<Preference>(CATEGORY_ABOUT)
|
|
||||||
about?.onPreferenceClickListener = rootLayoutClickListener
|
|
||||||
|
|
||||||
val appVersion = findPreference<Preference>(KEY_APP_VERSION)
|
|
||||||
appVersion?.onPreferenceClickListener = this
|
|
||||||
|
|
||||||
val appearance = findPreference<Preference>(CATEGORY_APPEARANCE)
|
|
||||||
appearance?.onPreferenceClickListener = rootLayoutClickListener
|
|
||||||
|
|
||||||
val extendedConversations = findPreference<Preference>(KEY_EXTENDED_CONVERSATIONS)
|
|
||||||
extendedConversations?.onPreferenceChangeListener = this
|
|
||||||
|
|
||||||
val theme = findPreference<Preference>(KEY_THEME)
|
|
||||||
theme?.onPreferenceChangeListener = this
|
|
||||||
|
|
||||||
val debug = findPreference<Preference>(CATEGORY_DEBUG)
|
|
||||||
debug?.onPreferenceClickListener = rootLayoutClickListener
|
|
||||||
updateDebugCategoryVisibility()
|
|
||||||
|
|
||||||
val clearUsersGroupsCache = findPreference<Preference>(KEY_CLEAR_USERS_GROUPS_CACHE)
|
|
||||||
clearUsersGroupsCache?.onPreferenceClickListener = this
|
|
||||||
|
|
||||||
applyTintInPreferenceScreen(preferenceScreen)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
|
|
||||||
updateDebugCategoryVisibility()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateDebugCategoryVisibility() {
|
|
||||||
findPreference<Preference>(CATEGORY_DEBUG)?.isVisible =
|
|
||||||
AndroidUtils.isDeveloperSettingsEnabled(requireContext())
|
|
||||||
}
|
|
||||||
|
|
||||||
private val rootLayoutClickListener =
|
|
||||||
Preference.OnPreferenceClickListener { changeRootLayout(it) }
|
|
||||||
|
|
||||||
private fun setTitle() {
|
|
||||||
var title = R.string.navigation_settings
|
|
||||||
when (currentPreferenceLayout) {
|
|
||||||
R.xml.fragment_settings_general -> title = R.string.prefs_general
|
|
||||||
R.xml.fragment_settings_appearance -> title = R.string.prefs_appearance
|
|
||||||
R.xml.fragment_settings_about -> title = R.string.prefs_about
|
|
||||||
R.xml.fragment_settings_account -> title = R.string.prefs_account
|
|
||||||
}
|
|
||||||
requireActivity().setTitle(title)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun changeRootLayout(preference: Preference): Boolean {
|
|
||||||
currentPreferenceLayout = when (preference.key) {
|
|
||||||
CATEGORY_GENERAL -> R.xml.fragment_settings_general
|
|
||||||
CATEGORY_ABOUT -> R.xml.fragment_settings_about
|
|
||||||
CATEGORY_ACCOUNT -> R.xml.fragment_settings_account
|
|
||||||
CATEGORY_APPEARANCE -> R.xml.fragment_settings_appearance
|
|
||||||
CATEGORY_DEBUG -> R.xml.fragment_settings_debug
|
|
||||||
else -> R.xml.fragment_settings
|
|
||||||
}
|
|
||||||
|
|
||||||
init()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun applyTintInPreferenceScreen(rootScreen: PreferenceScreen) {
|
|
||||||
if (rootScreen.preferenceCount > 0) {
|
|
||||||
for (i in 0 until rootScreen.preferenceCount) {
|
|
||||||
val preference = rootScreen.getPreference(i)
|
|
||||||
tintPreference(preference)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun tintPreference(preference: Preference) {
|
|
||||||
if (preference.icon != null && context != null) {
|
|
||||||
preference.icon.setTint(requireContext().color(R.color.accent))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPreferenceClick(preference: Preference): Boolean {
|
|
||||||
when (preference.key) {
|
|
||||||
KEY_ACCOUNT_LOGOUT -> {
|
|
||||||
logout()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
KEY_APP_VERSION -> {
|
|
||||||
openUpdateScreen()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
KEY_CLEAR_USERS_GROUPS_CACHE -> {
|
|
||||||
showClearCacheConfirmation()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showClearCacheConfirmation() {
|
|
||||||
val builder = AlertDialog.Builder(requireContext())
|
|
||||||
|
|
||||||
builder.setMessage("Clear cache?")
|
|
||||||
builder.setPositiveButton("Yes") { _, _ ->
|
|
||||||
TaskManager.execute {
|
|
||||||
// AppGlobal.database.users.clear()
|
|
||||||
// AppGlobal.database.groups.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
builder.setNegativeButton("No", null)
|
|
||||||
builder.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openUpdateScreen() {
|
|
||||||
startActivity(Intent(requireContext(), UpdateActivityDeprecated::class.java))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
|
|
||||||
when (preference.key) {
|
|
||||||
KEY_EXTENDED_CONVERSATIONS -> {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
KEY_THEME -> {
|
|
||||||
val nightMode = AppGlobal.instance.applyNightMode(newValue as String)
|
|
||||||
(requireActivity() as AppCompatActivity).delegate.localNightMode = nightMode
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onBackPressed() = if (currentPreferenceLayout == R.xml.fragment_settings) {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
currentPreferenceLayout = R.xml.fragment_settings
|
|
||||||
init()
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun logout() {
|
|
||||||
startActivity(Intent(requireContext(), DropUserDataActivity::class.java))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
package com.meloda.fast.fragment
|
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.webkit.CookieManager
|
|
||||||
import android.webkit.WebView
|
|
||||||
import android.webkit.WebViewClient
|
|
||||||
import androidx.core.os.bundleOf
|
|
||||||
import com.meloda.fast.base.BaseFragment
|
|
||||||
import com.meloda.vksdk.VKAuth
|
|
||||||
|
|
||||||
|
|
||||||
class ValidationFragment : BaseFragment() {
|
|
||||||
|
|
||||||
private var url: String = ""
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
if (arguments != null && requireArguments().isEmpty.not()) {
|
|
||||||
url = requireArguments().getString("url") ?: ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View {
|
|
||||||
val webView = WebView(requireContext())
|
|
||||||
webView.webViewClient = object : WebViewClient() {
|
|
||||||
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
|
||||||
parseUrl(url ?: "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
webView.settings.domStorageEnabled = true
|
|
||||||
webView.clearCache(true)
|
|
||||||
webView.layoutParams = ViewGroup.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
|
||||||
)
|
|
||||||
|
|
||||||
val manager = CookieManager.getInstance()
|
|
||||||
manager.removeAllCookies(null)
|
|
||||||
manager.flush()
|
|
||||||
manager.setAcceptCookie(true)
|
|
||||||
|
|
||||||
return webView
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
(requireView() as WebView).loadUrl(url)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseUrl(url: String) {
|
|
||||||
Log.d("WebView url", url)
|
|
||||||
try {
|
|
||||||
if (url.startsWith("https://oauth.vk.com/blank.html#success=1")) {
|
|
||||||
Log.d("Success WebView", "")
|
|
||||||
if (!url.contains("error=")) {
|
|
||||||
val auth = VKAuth.parseRedirectUrl(url)
|
|
||||||
|
|
||||||
val token = auth[0]
|
|
||||||
val userId = auth[1].toInt()
|
|
||||||
|
|
||||||
parentFragmentManager.setFragmentResult(
|
|
||||||
"validation",
|
|
||||||
bundleOf(
|
|
||||||
Pair("token", token),
|
|
||||||
Pair("userId", userId)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
parentFragmentManager.popBackStack()
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
package com.meloda.fast.fragment.ui.presenter
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
import com.meloda.fast.adapter.ChatsAdapter
|
|
||||||
import com.meloda.fast.common.TimeManager
|
|
||||||
import com.meloda.fast.fragment.ui.repository.ChatsRepository
|
|
||||||
import com.meloda.fast.fragment.ui.view.ChatsView
|
|
||||||
import com.meloda.fast.listener.ItemClickListener
|
|
||||||
import com.meloda.fast.listener.ItemLongClickListener
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
|
||||||
import com.meloda.mvp.MvpOnLoadListener
|
|
||||||
import com.meloda.mvp.MvpPresenter
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
|
|
||||||
class ChatsPresenter(viewState: ChatsView) :
|
|
||||||
MvpPresenter<VKConversation, ChatsRepository, ChatsView>(
|
|
||||||
viewState, ChatsRepository::class.java.name
|
|
||||||
),
|
|
||||||
ItemClickListener,
|
|
||||||
ItemLongClickListener,
|
|
||||||
TimeManager.OnMinuteChangeListener {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val DEFAULT_CONVERSATIONS_COUNT = 30
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var adapter: ChatsAdapter
|
|
||||||
|
|
||||||
override fun onViewCreated(bundle: Bundle?) {
|
|
||||||
viewState.initViews()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setup(recyclerView: RecyclerView, refreshLayout: SwipeRefreshLayout) {
|
|
||||||
viewState.prepareViews()
|
|
||||||
|
|
||||||
createAdapter()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createAdapter() {
|
|
||||||
adapter = ChatsAdapter(requireContext(), arrayListOf()).also {
|
|
||||||
it.itemClickListener = this
|
|
||||||
it.itemLongClickListener = this
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fillAdapter(conversations: ArrayList<VKConversation>, offset: Int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCachedConversations(
|
|
||||||
offset: Int = 0,
|
|
||||||
count: Int = DEFAULT_CONVERSATIONS_COUNT,
|
|
||||||
listener: MvpOnLoadListener? = null
|
|
||||||
) {
|
|
||||||
listener?.onSuccess()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadConversations(
|
|
||||||
offset: Int = 0,
|
|
||||||
count: Int = DEFAULT_CONVERSATIONS_COUNT,
|
|
||||||
listener: MvpOnLoadListener? = null
|
|
||||||
) {
|
|
||||||
if (AndroidUtils.hasConnection()) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemClick(position: Int) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemLongClick(position: Int) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMinuteChange(currentMinute: Int) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-256
@@ -1,256 +0,0 @@
|
|||||||
package com.meloda.fast.fragment.ui.presenter
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
import com.meloda.arrayutils.ArrayUtils
|
|
||||||
import com.meloda.fast.BuildConfig
|
|
||||||
import com.meloda.fast.adapter.ConversationsAdapterDeprecated
|
|
||||||
import com.meloda.fast.adapter.diffutil.ConversationsCallbackDeprecated
|
|
||||||
import com.meloda.fast.common.TimeManager
|
|
||||||
import com.meloda.fast.fragment.ui.repository.ConversationsRepositoryDeprecated
|
|
||||||
import com.meloda.fast.fragment.ui.view.ConversationsViewDeprecated
|
|
||||||
import com.meloda.fast.listener.ItemClickListener
|
|
||||||
import com.meloda.fast.listener.ItemLongClickListener
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
|
||||||
import com.meloda.mvp.MvpOnResponseListener
|
|
||||||
import com.meloda.mvp.MvpPresenter
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class ConversationsPresenterDeprecated(viewState: ConversationsViewDeprecated) :
|
|
||||||
MvpPresenter<VKConversation, ConversationsRepositoryDeprecated, ConversationsViewDeprecated>(
|
|
||||||
viewState,
|
|
||||||
ConversationsRepositoryDeprecated::class.java.name
|
|
||||||
),
|
|
||||||
ItemClickListener,
|
|
||||||
ItemLongClickListener,
|
|
||||||
TimeManager.OnMinuteChangeListener {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val DEFAULT_CONVERSATIONS_COUNT = 30
|
|
||||||
}
|
|
||||||
|
|
||||||
private var conversationsCount: Int = 0
|
|
||||||
|
|
||||||
private lateinit var adapter: ConversationsAdapterDeprecated
|
|
||||||
|
|
||||||
private lateinit var recyclerView: RecyclerView
|
|
||||||
private lateinit var layoutManager: LinearLayoutManager
|
|
||||||
|
|
||||||
fun setup(recyclerView: RecyclerView, refreshLayout: SwipeRefreshLayout) {
|
|
||||||
this.recyclerView = recyclerView
|
|
||||||
this.context = recyclerView.context
|
|
||||||
this.layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
|
||||||
|
|
||||||
prepareViews()
|
|
||||||
|
|
||||||
// setRecyclerViewScrollListener(recyclerView)
|
|
||||||
setRefreshLayoutListener(refreshLayout)
|
|
||||||
|
|
||||||
createAdapter()
|
|
||||||
|
|
||||||
TimeManager.addOnMinuteChangeListener(this)
|
|
||||||
|
|
||||||
loadConversations(0, DEFAULT_CONVERSATIONS_COUNT)
|
|
||||||
|
|
||||||
// getCachedConversations(0, DEFAULT_CONVERSATIONS_COUNT, object : MvpOnLoadListener<Any?> {
|
|
||||||
// override fun onResponse(response: Any?) {
|
|
||||||
// setState(if (adapter.isEmpty()) ListState.EMPTY_LOADING else ListState.FILLED_LOADING)
|
|
||||||
// loadConversations(0, DEFAULT_CONVERSATIONS_COUNT)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onError(t: Throwable) {
|
|
||||||
// setState(if (adapter.isEmpty()) ListState.EMPTY_LOADING else ListState.FILLED_LOADING)
|
|
||||||
// loadConversations(0, DEFAULT_CONVERSATIONS_COUNT)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setRecyclerViewScrollListener(recyclerView: RecyclerView) {
|
|
||||||
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
|
||||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
|
||||||
if (dy > 0) {
|
|
||||||
if (adapter.isLastItem() && !adapter.isLoading && adapter.itemCount < conversationsCount) {
|
|
||||||
adapter.isLoading = true
|
|
||||||
|
|
||||||
val position = adapter.itemCount - 1
|
|
||||||
// adapter.itemCount - 1 - (layoutManager.findLastCompletelyVisibleItemPosition() - layoutManager.findFirstCompletelyVisibleItemPosition())
|
|
||||||
|
|
||||||
setState(ListState.FILLED_LOADING)
|
|
||||||
if (AndroidUtils.hasConnection()) {
|
|
||||||
loadConversations(adapter.itemCount, DEFAULT_CONVERSATIONS_COUNT,
|
|
||||||
object : MvpOnResponseListener<Any?> {
|
|
||||||
override fun onResponse(response: Any?) {
|
|
||||||
recyclerView.scrollToPosition(position)
|
|
||||||
|
|
||||||
adapter.isLoading = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
viewState.showErrorSnackbar(t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
getCachedConversations(adapter.itemCount, DEFAULT_CONVERSATIONS_COUNT,
|
|
||||||
object : MvpOnResponseListener<Any?> {
|
|
||||||
override fun onResponse(response: Any?) {
|
|
||||||
recyclerView.scrollToPosition(position)
|
|
||||||
|
|
||||||
adapter.isLoading = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
viewState.showErrorSnackbar(t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BuildConfig.DEBUG)
|
|
||||||
Log.d("RecyclerView", "Bottom reached")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setRefreshLayoutListener(refreshLayout: SwipeRefreshLayout) {
|
|
||||||
refreshLayout.setOnRefreshListener { loadConversations() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCachedConversations(
|
|
||||||
offset: Int = 0,
|
|
||||||
count: Int = DEFAULT_CONVERSATIONS_COUNT,
|
|
||||||
listener: MvpOnResponseListener<Any?>? = null
|
|
||||||
) {
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY_LOADING else ListState.FILLED_LOADING)
|
|
||||||
|
|
||||||
repository.getCachedConversations(offset, count,
|
|
||||||
object : MvpOnResponseListener<ArrayList<VKConversation>> {
|
|
||||||
override fun onResponse(response: ArrayList<VKConversation>) {
|
|
||||||
conversationsCount = response.size
|
|
||||||
|
|
||||||
val conversations = ArrayUtils.cut(response, offset, count)
|
|
||||||
|
|
||||||
fillAdapter(conversations, offset)
|
|
||||||
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY else ListState.FILLED)
|
|
||||||
|
|
||||||
listener?.onResponse(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY_ERROR else ListState.FILLED)
|
|
||||||
|
|
||||||
listener?.onError(t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadConversations(
|
|
||||||
offset: Int = 0,
|
|
||||||
count: Int = DEFAULT_CONVERSATIONS_COUNT,
|
|
||||||
listener: MvpOnResponseListener<Any?>? = null
|
|
||||||
) {
|
|
||||||
if (!AndroidUtils.hasConnection()) {
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY_NO_INTERNET else ListState.FILLED)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY_LOADING else ListState.FILLED_LOADING)
|
|
||||||
}
|
|
||||||
|
|
||||||
repository.loadConversations(offset, count,
|
|
||||||
object : MvpOnResponseListener<ArrayList<VKConversation>> {
|
|
||||||
override fun onResponse(response: ArrayList<VKConversation>) {
|
|
||||||
conversationsCount = VKConversation.conversationsCount
|
|
||||||
|
|
||||||
fillAdapter(response, offset)
|
|
||||||
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY else ListState.FILLED)
|
|
||||||
|
|
||||||
listener?.onResponse(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY_ERROR else ListState.FILLED)
|
|
||||||
|
|
||||||
listener?.onError(t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun destroy() {
|
|
||||||
adapter.destroy()
|
|
||||||
TimeManager.removeOnMinuteChangeListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createAdapter() {
|
|
||||||
adapter = ConversationsAdapterDeprecated(recyclerView, arrayListOf()).also {
|
|
||||||
it.itemClickListener = this
|
|
||||||
it.itemLongClickListener = this
|
|
||||||
}
|
|
||||||
|
|
||||||
recyclerView.adapter = adapter
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fillAdapter(conversations: ArrayList<VKConversation>, offset: Int) {
|
|
||||||
val oldItems = ArrayList(adapter.values)
|
|
||||||
|
|
||||||
if (offset > 0) {
|
|
||||||
adapter.addAll(conversations)
|
|
||||||
} else {
|
|
||||||
adapter.updateValues(conversations)
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.notifyChanges(oldItems)
|
|
||||||
|
|
||||||
if (offset == 0) recyclerView.scrollToPosition(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemClick(position: Int) {
|
|
||||||
openChat(adapter[position])
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemLongClick(position: Int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMinuteChange(currentMinute: Int) {
|
|
||||||
post {
|
|
||||||
adapter.notifyItemRangeChanged(
|
|
||||||
0,
|
|
||||||
adapter.itemCount,
|
|
||||||
ConversationsCallbackDeprecated.DATE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openChat(conversation: VKConversation) {
|
|
||||||
// TaskManager.execute {
|
|
||||||
// val peerUser = MemoryCache.getUserById(conversation.conversationId)
|
|
||||||
// val peerGroup = MemoryCache.getGroupById(conversation.conversationId)
|
|
||||||
//
|
|
||||||
// val extras = Bundle().also {
|
|
||||||
// it.putInt(MessagesActivityDeprecated.TAG_EXTRA_ID, conversation.conversationId)
|
|
||||||
// it.putString(
|
|
||||||
// MessagesActivityDeprecated.TAG_EXTRA_TITLE,
|
|
||||||
// VKUtil.getTitle(conversation, peerUser, peerGroup)
|
|
||||||
// )
|
|
||||||
// it.putString(
|
|
||||||
// MessagesActivityDeprecated.TAG_EXTRA_AVATAR,
|
|
||||||
// VKUtil.getAvatar(conversation, peerUser, peerGroup)
|
|
||||||
// )
|
|
||||||
// it.putSerializable(MessagesActivityDeprecated.TAG_EXTRA_USER, peerUser)
|
|
||||||
// it.putSerializable(MessagesActivityDeprecated.TAG_EXTRA_GROUP, peerGroup)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// post { viewState.openChat(extras) }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-232
@@ -1,232 +0,0 @@
|
|||||||
package com.meloda.fast.fragment.ui.presenter
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
import com.meloda.arrayutils.ArrayUtils
|
|
||||||
import com.meloda.fast.activity.MessagesActivityDeprecated
|
|
||||||
import com.meloda.fast.adapter.UsersAdapterDeprecated
|
|
||||||
import com.meloda.fast.fragment.ui.repository.FriendsRepositoryDeprecated
|
|
||||||
import com.meloda.fast.fragment.ui.view.FriendsViewDeprecated
|
|
||||||
import com.meloda.fast.listener.ItemClickListener
|
|
||||||
import com.meloda.fast.util.AndroidUtils
|
|
||||||
import com.meloda.mvp.MvpOnResponseListener
|
|
||||||
import com.meloda.mvp.MvpPresenter
|
|
||||||
import com.meloda.vksdk.model.VKUser
|
|
||||||
|
|
||||||
class FriendsPresenterDeprecated(viewState: FriendsViewDeprecated) :
|
|
||||||
MvpPresenter<VKUser, FriendsRepositoryDeprecated, FriendsViewDeprecated>(
|
|
||||||
viewState,
|
|
||||||
FriendsRepositoryDeprecated::class.java.name
|
|
||||||
),
|
|
||||||
ItemClickListener {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val ONLY_ONLINE = "_only_online"
|
|
||||||
|
|
||||||
const val DEFAULT_FRIENDS_COUNT = 30
|
|
||||||
}
|
|
||||||
|
|
||||||
private var userId: Int = 0
|
|
||||||
private var friendsCount: Int = 0
|
|
||||||
|
|
||||||
private lateinit var adapter: UsersAdapterDeprecated
|
|
||||||
|
|
||||||
private lateinit var recyclerView: RecyclerView
|
|
||||||
private lateinit var layoutManager: LinearLayoutManager
|
|
||||||
|
|
||||||
fun setup(userId: Int, recyclerView: RecyclerView, refreshLayout: SwipeRefreshLayout) {
|
|
||||||
this.userId = userId
|
|
||||||
this.recyclerView = recyclerView
|
|
||||||
this.context = recyclerView.context
|
|
||||||
this.layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
|
||||||
|
|
||||||
setRecyclerViewScrollListener(recyclerView)
|
|
||||||
setRefreshListener(refreshLayout)
|
|
||||||
|
|
||||||
createAdapter()
|
|
||||||
|
|
||||||
getCachedFriends(userId, 0, DEFAULT_FRIENDS_COUNT, false, object : MvpOnResponseListener<Any?> {
|
|
||||||
override fun onResponse(response: Any?) {
|
|
||||||
setState(if (adapter.isEmpty()) MvpPresenter.ListState.EMPTY_LOADING else ListState.FILLED_LOADING)
|
|
||||||
loadFriends(userId, 0, DEFAULT_FRIENDS_COUNT)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY_LOADING else ListState.FILLED_LOADING)
|
|
||||||
loadFriends(userId, 0, DEFAULT_FRIENDS_COUNT)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCachedFriends(
|
|
||||||
userId: Int,
|
|
||||||
offset: Int = 0,
|
|
||||||
count: Int = DEFAULT_FRIENDS_COUNT,
|
|
||||||
onlyOnline: Boolean = false,
|
|
||||||
listener: MvpOnResponseListener<Any?>? = null
|
|
||||||
) {
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY_LOADING else ListState.FILLED_LOADING)
|
|
||||||
|
|
||||||
repository.getCachedFriends(
|
|
||||||
userId,
|
|
||||||
offset,
|
|
||||||
count,
|
|
||||||
onlyOnline,
|
|
||||||
object : MvpOnResponseListener<ArrayList<VKUser>> {
|
|
||||||
override fun onResponse(response: ArrayList<VKUser>) {
|
|
||||||
val friends = ArrayUtils.cut(response, offset, count)
|
|
||||||
|
|
||||||
fillAdapter(friends, offset)
|
|
||||||
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY else ListState.FILLED)
|
|
||||||
|
|
||||||
listener?.onResponse(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY_ERROR else ListState.FILLED)
|
|
||||||
|
|
||||||
listener?.onError(t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadFriends(
|
|
||||||
userId: Int,
|
|
||||||
offset: Int = 0,
|
|
||||||
count: Int = DEFAULT_FRIENDS_COUNT,
|
|
||||||
onlyOnline: Boolean = false,
|
|
||||||
listener: MvpOnResponseListener<Any?>? = null
|
|
||||||
) {
|
|
||||||
if (!AndroidUtils.hasConnection()) {
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY_NO_INTERNET else ListState.FILLED)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY_LOADING else ListState.FILLED_LOADING)
|
|
||||||
}
|
|
||||||
|
|
||||||
repository.loadFriends(
|
|
||||||
userId,
|
|
||||||
offset,
|
|
||||||
count,
|
|
||||||
object : MvpOnResponseListener<ArrayList<VKUser>> {
|
|
||||||
override fun onResponse(response: ArrayList<VKUser>) {
|
|
||||||
friendsCount = VKUser.friendsCount
|
|
||||||
|
|
||||||
fillAdapter(response, offset)
|
|
||||||
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY else ListState.FILLED)
|
|
||||||
|
|
||||||
listener?.onResponse(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
setState(if (adapter.isEmpty()) ListState.EMPTY_ERROR else ListState.FILLED)
|
|
||||||
|
|
||||||
listener?.onError(t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setRecyclerViewScrollListener(recyclerView: RecyclerView) {
|
|
||||||
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
|
||||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
|
||||||
if (dy > 0) {
|
|
||||||
if (adapter.isLastItem() && !adapter.isLoading && adapter.itemCount < friendsCount) {
|
|
||||||
adapter.isLoading = true
|
|
||||||
|
|
||||||
val position = adapter.itemCount - 1
|
|
||||||
// adapter.itemCount - 1 - (layoutManager.findLastCompletelyVisibleItemPosition() - layoutManager.findFirstCompletelyVisibleItemPosition())
|
|
||||||
|
|
||||||
setState(ListState.FILLED_LOADING)
|
|
||||||
if (AndroidUtils.hasConnection()) {
|
|
||||||
loadFriends(
|
|
||||||
userId,
|
|
||||||
adapter.itemCount,
|
|
||||||
DEFAULT_FRIENDS_COUNT,
|
|
||||||
false,
|
|
||||||
object : MvpOnResponseListener<Any?> {
|
|
||||||
override fun onResponse(response: Any?) {
|
|
||||||
recyclerView.scrollToPosition(position)
|
|
||||||
|
|
||||||
adapter.isLoading = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
viewState.showErrorSnackbar(t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
getCachedFriends(
|
|
||||||
userId,
|
|
||||||
adapter.itemCount,
|
|
||||||
DEFAULT_FRIENDS_COUNT,
|
|
||||||
false,
|
|
||||||
object : MvpOnResponseListener<Any?> {
|
|
||||||
override fun onResponse(response: Any?) {
|
|
||||||
recyclerView.scrollToPosition(position)
|
|
||||||
|
|
||||||
adapter.isLoading = false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
viewState.showErrorSnackbar(t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d("RecyclerView", "Bottom reached")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setRefreshListener(refreshLayout: SwipeRefreshLayout) {
|
|
||||||
refreshLayout.setOnRefreshListener { loadFriends(userId) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createAdapter() {
|
|
||||||
adapter = UsersAdapterDeprecated(context!!, arrayListOf()).also {
|
|
||||||
it.itemClickListener = this
|
|
||||||
}
|
|
||||||
|
|
||||||
recyclerView.adapter = adapter
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fillAdapter(values: ArrayList<VKUser>, offset: Int) {
|
|
||||||
val oldItems = ArrayList(adapter.values)
|
|
||||||
|
|
||||||
if (offset > 0) {
|
|
||||||
adapter.addAll(values)
|
|
||||||
} else {
|
|
||||||
adapter.updateValues(values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// adapter.notifyDataSetChanged()
|
|
||||||
adapter.notifyChanges(oldItems)
|
|
||||||
|
|
||||||
if (offset == 0) recyclerView.scrollToPosition(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openChat(position: Int) {
|
|
||||||
val user = adapter[position]
|
|
||||||
|
|
||||||
val data = Bundle().apply {
|
|
||||||
putInt(MessagesActivityDeprecated.TAG_EXTRA_ID, user.userId)
|
|
||||||
putString(MessagesActivityDeprecated.TAG_EXTRA_TITLE, user.toString())
|
|
||||||
putString(MessagesActivityDeprecated.TAG_EXTRA_AVATAR, user.photo200)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemClick(position: Int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
package com.meloda.fast.fragment.ui.presenter
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.Gravity
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.fragment.app.setFragmentResultListener
|
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
|
||||||
import com.meloda.fast.R
|
|
||||||
import com.meloda.fast.UserConfig
|
|
||||||
import com.meloda.fast.activity.MainActivity
|
|
||||||
import com.meloda.fast.common.AppGlobal
|
|
||||||
import com.meloda.fast.fragment.ChatsFragment
|
|
||||||
import com.meloda.fast.fragment.LoginFragment
|
|
||||||
import com.meloda.fast.fragment.ValidationFragment
|
|
||||||
import com.meloda.fast.fragment.ui.repository.LoginRepository
|
|
||||||
import com.meloda.fast.fragment.ui.view.LoginView
|
|
||||||
import com.meloda.mvp.MvpOnResponseListener
|
|
||||||
import com.meloda.mvp.MvpPresenter
|
|
||||||
import com.meloda.vksdk.VKApi
|
|
||||||
import com.squareup.picasso.Picasso
|
|
||||||
import org.json.JSONObject
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
class LoginPresenter(
|
|
||||||
viewState: LoginView
|
|
||||||
) : MvpPresenter<Any, LoginRepository, LoginView>(
|
|
||||||
viewState,
|
|
||||||
LoginRepository::class.java.name
|
|
||||||
) {
|
|
||||||
|
|
||||||
private var lastEmail: String = ""
|
|
||||||
private var lastPassword: String = ""
|
|
||||||
|
|
||||||
private lateinit var fragment: LoginFragment
|
|
||||||
|
|
||||||
fun onCreate(context: Context, fragment: LoginFragment, bundle: Bundle?) {
|
|
||||||
super.onCreate(context, bundle)
|
|
||||||
this.fragment = fragment
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(bundle: Bundle?) {
|
|
||||||
viewState.initViews()
|
|
||||||
viewState.prepareViews()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun login(
|
|
||||||
email: String,
|
|
||||||
password: String,
|
|
||||||
captcha: String = "",
|
|
||||||
onResponseListener: MvpOnResponseListener<Any?>? = null
|
|
||||||
) {
|
|
||||||
lastEmail = email
|
|
||||||
lastPassword = password
|
|
||||||
|
|
||||||
repository.login(requireContext(), email, password, captcha,
|
|
||||||
object : MvpOnResponseListener<JSONObject> {
|
|
||||||
override fun onResponse(response: JSONObject) {
|
|
||||||
checkResponse(response, onResponseListener)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(t: Throwable) {
|
|
||||||
onResponseListener?.onError(t)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("MoveVariableDeclarationIntoWhen")
|
|
||||||
private fun checkResponse(
|
|
||||||
response: JSONObject,
|
|
||||||
onResponseListener: MvpOnResponseListener<Any?>? = null
|
|
||||||
) {
|
|
||||||
if (response.has("error")) {
|
|
||||||
val errorString = response.optString("error")
|
|
||||||
when (errorString) {
|
|
||||||
"need_validation" -> {
|
|
||||||
val redirectUrl = response.optString("redirect_uri")
|
|
||||||
|
|
||||||
val bundle = Bundle()
|
|
||||||
bundle.putString("url", redirectUrl)
|
|
||||||
|
|
||||||
fragment.runOnUiThread {
|
|
||||||
fragment.setFragmentResultListener("validation") { _, bundle ->
|
|
||||||
val userId = bundle.getInt("userId")
|
|
||||||
val token = bundle.getString("token") ?: ""
|
|
||||||
saveUserData(userId, token)
|
|
||||||
|
|
||||||
openMainScreen()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fragment.parentFragmentManager.beginTransaction()
|
|
||||||
.replace(
|
|
||||||
R.id.fragmentContainer,
|
|
||||||
ValidationFragment().apply { arguments = bundle })
|
|
||||||
.addToBackStack("")
|
|
||||||
.commit()
|
|
||||||
|
|
||||||
}
|
|
||||||
"need_captcha" -> {
|
|
||||||
val captchaImage = response.optString("captcha_img")
|
|
||||||
val captchaSid = response.optString("captcha_sid")
|
|
||||||
showCaptchaDialog(captchaImage, captchaSid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val userId = response.optInt("user_id", -1)
|
|
||||||
val token = response.optString("access_token")
|
|
||||||
saveUserData(userId, token)
|
|
||||||
|
|
||||||
openMainScreen()
|
|
||||||
|
|
||||||
onResponseListener?.onResponse(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun openMainScreen() {
|
|
||||||
fragment.runOnUiThread {
|
|
||||||
VKApi.init(Locale.getDefault().language, UserConfig.token, AppGlobal.handler)
|
|
||||||
|
|
||||||
(fragment.requireActivity() as MainActivity).bottomBar.isVisible = true
|
|
||||||
|
|
||||||
fragment.parentFragmentManager.beginTransaction()
|
|
||||||
.replace(
|
|
||||||
R.id.fragmentContainer,
|
|
||||||
ChatsFragment()
|
|
||||||
).commit()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun saveUserData(userId: Int, token: String) {
|
|
||||||
UserConfig.userId = userId
|
|
||||||
UserConfig.token = token
|
|
||||||
UserConfig.save()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showCaptchaDialog(captchaImage: String, captchaSid: String) {
|
|
||||||
val resources = fragment.resources
|
|
||||||
val metrics = resources.displayMetrics
|
|
||||||
|
|
||||||
fragment.runOnUiThread {
|
|
||||||
val image = ImageView(requireContext())
|
|
||||||
image.layoutParams = ViewGroup.LayoutParams(
|
|
||||||
(metrics.widthPixels / 3.5).toInt(), metrics.heightPixels / 7
|
|
||||||
)
|
|
||||||
|
|
||||||
Picasso.get().load(captchaImage).priority(Picasso.Priority.HIGH).into(image)
|
|
||||||
|
|
||||||
val captchaCodeEditText = TextInputEditText(requireContext())
|
|
||||||
captchaCodeEditText.setHint(R.string.captcha_hint)
|
|
||||||
|
|
||||||
captchaCodeEditText.layoutParams =
|
|
||||||
LinearLayout.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
||||||
)
|
|
||||||
|
|
||||||
val builder = AlertDialog.Builder(requireContext())
|
|
||||||
|
|
||||||
val layout = LinearLayout(requireContext())
|
|
||||||
|
|
||||||
layout.orientation = LinearLayout.VERTICAL
|
|
||||||
layout.gravity = Gravity.CENTER
|
|
||||||
layout.addView(image)
|
|
||||||
layout.addView(captchaCodeEditText)
|
|
||||||
|
|
||||||
builder.setView(layout)
|
|
||||||
builder.setNegativeButton(android.R.string.cancel, null)
|
|
||||||
builder.setPositiveButton(android.R.string.ok) { _, _ ->
|
|
||||||
val captchaCode = captchaCodeEditText.text.toString().trim()
|
|
||||||
|
|
||||||
login(
|
|
||||||
lastEmail,
|
|
||||||
lastPassword,
|
|
||||||
"&captcha_sid=$captchaSid&captcha_key=$captchaCode"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.setTitle(R.string.input_captcha)
|
|
||||||
builder.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package com.meloda.fast.fragment.ui.repository
|
|
||||||
|
|
||||||
import com.meloda.mvp.MvpRepository
|
|
||||||
import com.meloda.vksdk.model.VKConversation
|
|
||||||
|
|
||||||
class ChatsRepository : MvpRepository<VKConversation>() {
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user