New cache system
Refactoring Separation into libraries
This commit is contained in:
@@ -1,20 +0,0 @@
|
||||
package com.meloda.fast.database
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import com.meloda.fast.api.model.*
|
||||
import com.meloda.fast.database.dao.*
|
||||
|
||||
@Database(
|
||||
entities = [VKConversation::class, VKMessage::class, VKUser::class, VKGroup::class, VKFriend::class],
|
||||
version = 1,
|
||||
exportSchema = false
|
||||
)
|
||||
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract val conversations: ConversationsDao
|
||||
abstract val messages: MessagesDao
|
||||
abstract val users: UsersDao
|
||||
abstract val groups: GroupsDao
|
||||
abstract val friends: FriendsDao
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.meloda.fast.database
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import android.os.Bundle
|
||||
import com.meloda.fast.common.AppGlobal.Companion.database
|
||||
import com.meloda.fast.database.DatabaseUtils.TABLE_CHATS
|
||||
import com.meloda.fast.database.DatabaseUtils.TABLE_FRIENDS
|
||||
import com.meloda.fast.database.DatabaseUtils.TABLE_MESSAGES
|
||||
import com.meloda.fast.database.DatabaseUtils.TABLE_USERS
|
||||
import com.meloda.fast.database.storage.ChatsStorage
|
||||
import com.meloda.fast.database.storage.GroupsStorage
|
||||
import com.meloda.fast.database.storage.MessagesStorage
|
||||
import com.meloda.fast.database.storage.UsersStorage
|
||||
import com.meloda.vksdk.model.VKConversation
|
||||
import com.meloda.vksdk.model.VKMessage
|
||||
import com.meloda.vksdk.model.VKUser
|
||||
import java.util.*
|
||||
|
||||
object CacheStorage {
|
||||
|
||||
val usersStorage = UsersStorage()
|
||||
val messagesStorage = MessagesStorage()
|
||||
val chatsStorage = ChatsStorage()
|
||||
val groupsStorage = GroupsStorage()
|
||||
|
||||
fun selectCursor(tableName: String): Cursor {
|
||||
return QueryBuilder.query()
|
||||
.select("*").from(tableName)
|
||||
.asCursor(database)
|
||||
}
|
||||
|
||||
fun selectCursor(tableName: String, where: String): Cursor {
|
||||
return QueryBuilder.query()
|
||||
.select("*").from(tableName)
|
||||
.where(where)
|
||||
.asCursor(database)
|
||||
}
|
||||
|
||||
fun selectCursor(tableName: String, columnName: String, value: Any): Cursor {
|
||||
return QueryBuilder.query()
|
||||
.select("*").from(tableName)
|
||||
.where("$columnName=$value")
|
||||
.asCursor(database)
|
||||
}
|
||||
|
||||
fun selectCursor(tableName: String, columnName: String, ids: IntArray): Cursor {
|
||||
val where = StringBuilder(5 * ids.size)
|
||||
|
||||
where.append("$columnName=${ids[0]}")
|
||||
|
||||
for (i in 1 until ids.size) {
|
||||
where.append(" OR ")
|
||||
where.append("$columnName=${ids[i]}")
|
||||
}
|
||||
|
||||
return selectCursor(tableName, where.toString())
|
||||
}
|
||||
|
||||
fun getInt(cursor: Cursor, columnName: String) =
|
||||
cursor.getInt(cursor.getColumnIndexOrThrow(columnName))
|
||||
|
||||
fun getString(cursor: Cursor, columnName: String) =
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(columnName))
|
||||
|
||||
fun getBlob(cursor: Cursor, columnName: String) =
|
||||
cursor.getBlob(cursor.getColumnIndexOrThrow(columnName))
|
||||
|
||||
fun <T> insert(tableName: String, values: ArrayList<T>) {
|
||||
database.beginTransaction()
|
||||
|
||||
val contentValues = ContentValues()
|
||||
|
||||
for (value in values) {
|
||||
when (tableName) {
|
||||
TABLE_USERS -> {
|
||||
usersStorage.cacheValue(contentValues, value as VKUser)
|
||||
break
|
||||
}
|
||||
TABLE_FRIENDS -> {
|
||||
usersStorage.cacheValue(
|
||||
contentValues,
|
||||
value as VKUser,
|
||||
Bundle().apply { putBoolean("toFriends", true) })
|
||||
break
|
||||
}
|
||||
TABLE_MESSAGES -> {
|
||||
messagesStorage.cacheValue(contentValues, value as VKMessage)
|
||||
break
|
||||
}
|
||||
TABLE_CHATS -> {
|
||||
chatsStorage.cacheValue(contentValues, value as VKConversation)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
database.insert(tableName, null, contentValues)
|
||||
contentValues.clear()
|
||||
}
|
||||
|
||||
database.setTransactionSuccessful()
|
||||
database.endTransaction()
|
||||
}
|
||||
|
||||
fun delete(tableName: String, whereClause: String, vararg whereArgs: String) {
|
||||
database.delete(tableName, whereClause, whereArgs)
|
||||
}
|
||||
|
||||
fun delete(tableName: String) {
|
||||
database.delete(tableName, null, null)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.meloda.fast.database
|
||||
|
||||
import android.content.Context
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
|
||||
class DatabaseHelper constructor(context: Context) : SQLiteOpenHelper(
|
||||
context,
|
||||
DB_NAME,
|
||||
null,
|
||||
DB_VERSION
|
||||
) {
|
||||
companion object {
|
||||
private const val DB_NAME = "cache.db"
|
||||
private const val DB_VERSION = 1
|
||||
}
|
||||
|
||||
override fun onCreate(db: SQLiteDatabase) {
|
||||
db.execSQL(DatabaseUtils.createUsersTable())
|
||||
db.execSQL(DatabaseUtils.createGroupsTable())
|
||||
db.execSQL(DatabaseUtils.createFriendsTable())
|
||||
db.execSQL(DatabaseUtils.createMessagesTable())
|
||||
db.execSQL(DatabaseUtils.createChatsTable())
|
||||
}
|
||||
|
||||
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.meloda.fast.database
|
||||
|
||||
object DatabaseKeys {
|
||||
|
||||
const val ID = "_id"
|
||||
|
||||
const val SORT_ID = "_sort_id"
|
||||
|
||||
const val USER_ID = "_user_id"
|
||||
|
||||
const val FIRST_NAME = "_first_name"
|
||||
|
||||
const val LAST_NAME = "_last_name"
|
||||
|
||||
const val DEACTIVATED = "_deactivated"
|
||||
|
||||
const val GENDER = "_gender"
|
||||
|
||||
const val SCREEN_NAME = "_screen_name"
|
||||
|
||||
const val PHOTOS = "_photos"
|
||||
|
||||
const val IS_ONLINE = "_is_online"
|
||||
|
||||
const val IS_ONLINE_MOBILE = "_is_online_mobile"
|
||||
|
||||
const val STATUS = "_status"
|
||||
|
||||
const val LAST_SEEN = "_last_seen"
|
||||
|
||||
const val MESSAGE_ID = "_message_id"
|
||||
|
||||
const val DATE = "_date"
|
||||
|
||||
const val PEER_ID = "_peer_id"
|
||||
|
||||
const val FROM_ID = "_from_id"
|
||||
|
||||
const val EDIT_TIME = "_edit_time"
|
||||
|
||||
const val IS_OUT = "_is_out"
|
||||
|
||||
const val TEXT = "_text"
|
||||
|
||||
const val RANDOM_ID = "_random_id"
|
||||
|
||||
const val CONVERSATION_MESSAGE_ID = "_conversation_message_id"
|
||||
|
||||
const val ATTACHMENTS = "_attachments"
|
||||
|
||||
const val FWD_MESSAGES = "_fwd_messages"
|
||||
|
||||
const val REPLY_MESSAGE_ID = "_reply_message_id"
|
||||
|
||||
const val ACTION = "_action"
|
||||
|
||||
const val IS_ALLOWED = "_is_allowed"
|
||||
|
||||
const val NOT_ALLOWED_REASON = "_not_allowed_reason"
|
||||
|
||||
const val IN_READ_MESSAGE_ID = "_in_read_message_id"
|
||||
|
||||
const val OUT_READ_MESSAGE_ID = "_out_read_message_id"
|
||||
|
||||
const val LAST_MESSAGE_ID = "_last_message_id"
|
||||
|
||||
const val UNREAD_COUNT = "_unread_count"
|
||||
|
||||
const val CONVERSATION_ID = "_conversation_id"
|
||||
|
||||
const val TYPE = "_type"
|
||||
|
||||
const val LOCAL_ID = "_local_id"
|
||||
|
||||
const val IS_NOTIFICATIONS_DISABLED = "_is_notifications_disabled"
|
||||
|
||||
const val MEMBERS_COUNT = "_members_count"
|
||||
|
||||
const val TITLE = "_title"
|
||||
|
||||
const val PINNED_MESSAGE_ID = "_pinned_message_id"
|
||||
|
||||
const val CHAT_STATE = "_chat_state"
|
||||
|
||||
const val IS_GROUP_CHANNEL = "_is_group_channel"
|
||||
|
||||
const val FRIEND_ID = "_friend_id"
|
||||
|
||||
const val GROUP_ID = "_group_id"
|
||||
|
||||
const val NAME = "_name"
|
||||
|
||||
const val IS_CLOSED = "_is_closed"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package com.meloda.fast.database
|
||||
|
||||
import com.meloda.fast.database.DatabaseKeys.ACTION
|
||||
import com.meloda.fast.database.DatabaseKeys.ATTACHMENTS
|
||||
import com.meloda.fast.database.DatabaseKeys.CHAT_STATE
|
||||
import com.meloda.fast.database.DatabaseKeys.CONVERSATION_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.CONVERSATION_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.DATE
|
||||
import com.meloda.fast.database.DatabaseKeys.DEACTIVATED
|
||||
import com.meloda.fast.database.DatabaseKeys.EDIT_TIME
|
||||
import com.meloda.fast.database.DatabaseKeys.FIRST_NAME
|
||||
import com.meloda.fast.database.DatabaseKeys.FRIEND_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.FROM_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.FWD_MESSAGES
|
||||
import com.meloda.fast.database.DatabaseKeys.GENDER
|
||||
import com.meloda.fast.database.DatabaseKeys.GROUP_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.IN_READ_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_ALLOWED
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_CLOSED
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_GROUP_CHANNEL
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_NOTIFICATIONS_DISABLED
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_ONLINE
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_ONLINE_MOBILE
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_OUT
|
||||
import com.meloda.fast.database.DatabaseKeys.LAST_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.LAST_NAME
|
||||
import com.meloda.fast.database.DatabaseKeys.LAST_SEEN
|
||||
import com.meloda.fast.database.DatabaseKeys.LOCAL_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.MEMBERS_COUNT
|
||||
import com.meloda.fast.database.DatabaseKeys.MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.NAME
|
||||
import com.meloda.fast.database.DatabaseKeys.NOT_ALLOWED_REASON
|
||||
import com.meloda.fast.database.DatabaseKeys.OUT_READ_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.PEER_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.PHOTOS
|
||||
import com.meloda.fast.database.DatabaseKeys.PINNED_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.RANDOM_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.REPLY_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.SCREEN_NAME
|
||||
import com.meloda.fast.database.DatabaseKeys.SORT_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.STATUS
|
||||
import com.meloda.fast.database.DatabaseKeys.TEXT
|
||||
import com.meloda.fast.database.DatabaseKeys.TITLE
|
||||
import com.meloda.fast.database.DatabaseKeys.TYPE
|
||||
import com.meloda.fast.database.DatabaseKeys.UNREAD_COUNT
|
||||
import com.meloda.fast.database.DatabaseKeys.USER_ID
|
||||
|
||||
object DatabaseUtils {
|
||||
|
||||
const val TABLE_USERS = "users"
|
||||
const val TABLE_MESSAGES = "messages"
|
||||
const val TABLE_CHATS = "chats"
|
||||
const val TABLE_FRIENDS = "friends"
|
||||
const val TABLE_GROUPS = "groups"
|
||||
|
||||
private val usersTableMap = HashMap<String, String>().apply {
|
||||
this[USER_ID] = "integer primary key on conflict replace"
|
||||
this[FIRST_NAME] = "varchar(255)"
|
||||
this[LAST_NAME] = "varchar(255)"
|
||||
this[DEACTIVATED] = "varchar(255)"
|
||||
this[GENDER] = "integer default 0"
|
||||
this[SCREEN_NAME] = "varchar(255)"
|
||||
this[PHOTOS] = "text"
|
||||
this[IS_ONLINE] = "integer default 0"
|
||||
this[IS_ONLINE_MOBILE] = "integer default 0"
|
||||
this[STATUS] = "varchar(255)"
|
||||
this[LAST_SEEN] = "integer"
|
||||
}
|
||||
|
||||
private val groupsTableMap = HashMap<String, String>().apply {
|
||||
this[GROUP_ID] = "integer primary key on conflict replace"
|
||||
this[NAME] = "varchar(255)"
|
||||
this[SCREEN_NAME] = "varchar(255)"
|
||||
this[IS_CLOSED] = "integer default 0"
|
||||
this[DEACTIVATED] = "varchar(255)"
|
||||
this[TYPE] = "varchar(255)"
|
||||
this[PHOTOS] = "text"
|
||||
}
|
||||
|
||||
private val messagesTableMap = HashMap<String, String>().apply {
|
||||
this[MESSAGE_ID] = "integer primary key on conflict replace"
|
||||
this[DATE] = "integer"
|
||||
this[PEER_ID] = "integer"
|
||||
this[FROM_ID] = "integer"
|
||||
this[EDIT_TIME] = "integer"
|
||||
this[IS_OUT] = "integer default 0"
|
||||
this[TEXT] = "text"
|
||||
this[RANDOM_ID] = "integer"
|
||||
this[CONVERSATION_MESSAGE_ID] = "integer"
|
||||
this[ATTACHMENTS] = "blob"
|
||||
this[REPLY_MESSAGE_ID] = "integer"
|
||||
this[ACTION] = "blob"
|
||||
|
||||
//2,3,4,5 - message_ids
|
||||
this[FWD_MESSAGES] = "text"
|
||||
}
|
||||
|
||||
private val chatsTableMap = HashMap<String, String>().apply {
|
||||
this[CONVERSATION_ID] = "integer primary key on conflict replace"
|
||||
this[IS_ALLOWED] = "integer default 1"
|
||||
this[NOT_ALLOWED_REASON] = "integer"
|
||||
this[IN_READ_MESSAGE_ID] = "integer"
|
||||
this[OUT_READ_MESSAGE_ID] = "integer"
|
||||
this[LAST_MESSAGE_ID] = "integer"
|
||||
this[UNREAD_COUNT] = "integer"
|
||||
this[LOCAL_ID] = "integer"
|
||||
this[IS_NOTIFICATIONS_DISABLED] = "integer default 0"
|
||||
this[MEMBERS_COUNT] = "integer"
|
||||
this[TITLE] = "varchar(255)"
|
||||
this[IS_GROUP_CHANNEL] = "integer default 0"
|
||||
this[TYPE] = "integer"
|
||||
this[CHAT_STATE] = "integer"
|
||||
this[PHOTOS] = "text"
|
||||
|
||||
this[PINNED_MESSAGE_ID] = "integer"
|
||||
}
|
||||
|
||||
private val friendsTableMap = HashMap<String, String>().apply {
|
||||
this[FRIEND_ID] = "integer primary key on conflict replace"
|
||||
this[SORT_ID] = "integer"
|
||||
|
||||
//id which user friend
|
||||
this[USER_ID] = "integer"
|
||||
}
|
||||
|
||||
fun createUsersTable() = createTableQuery(TABLE_USERS, usersTableMap)
|
||||
fun createGroupsTable() = createTableQuery(TABLE_GROUPS, groupsTableMap)
|
||||
fun createMessagesTable() = createTableQuery(TABLE_MESSAGES, messagesTableMap)
|
||||
fun createChatsTable() = createTableQuery(TABLE_CHATS, chatsTableMap)
|
||||
fun createFriendsTable() = createTableQuery(TABLE_FRIENDS, friendsTableMap)
|
||||
|
||||
private fun createTableQuery(tableName: String, tableData: HashMap<String, String>): String {
|
||||
val builder = StringBuilder("create table $tableName (")
|
||||
|
||||
val entry: Map.Entry<String, String> = tableData.entries.first()
|
||||
builder.append(entry.key)
|
||||
builder.append(" ")
|
||||
builder.append(entry.value)
|
||||
|
||||
tableData.forEach {
|
||||
if (it == entry) return@forEach
|
||||
builder.append(", ")
|
||||
builder.append(it.key)
|
||||
builder.append(" ")
|
||||
builder.append(it.value)
|
||||
}
|
||||
|
||||
builder.append(");")
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
package com.meloda.fast.database
|
||||
|
||||
import android.util.SparseArray
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.meloda.fast.api.model.*
|
||||
import com.meloda.fast.common.AppGlobal
|
||||
|
||||
object MemoryCache {
|
||||
|
||||
private val users = SparseArray<VKUser>()
|
||||
private val groups = SparseArray<VKGroup>()
|
||||
|
||||
@WorkerThread
|
||||
fun getUserById(id: Int): VKUser? {
|
||||
var user = users[id]
|
||||
if (user == null) {
|
||||
user = AppGlobal.database.users.getById(id)
|
||||
|
||||
user?.let { append(it) }
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getGroupById(positiveId: Int): VKGroup? {
|
||||
var group = groups[positiveId]
|
||||
if (group == null) {
|
||||
group = AppGlobal.database.groups.getById(positiveId)
|
||||
|
||||
group?.let { append(it) }
|
||||
}
|
||||
return group
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getMessageById(id: Int): VKMessage? {
|
||||
return AppGlobal.database.messages.getById(id)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getMessagesByPeerId(peerId: Int): List<VKMessage> {
|
||||
return AppGlobal.database.messages.getByPeerId(peerId)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getMessages(): List<VKMessage> {
|
||||
return AppGlobal.database.messages.getAll()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getConversationById(id: Int): VKConversation? {
|
||||
return AppGlobal.database.conversations.getById(id)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getConversations(): List<VKConversation> {
|
||||
return AppGlobal.database.conversations.getAll()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getFriends(userId: Int): List<VKFriend> {
|
||||
return AppGlobal.database.friends.getByUserId(userId)
|
||||
}
|
||||
|
||||
fun appendUsers(users: Collection<VKUser>) {
|
||||
for (user in users) {
|
||||
append(user)
|
||||
}
|
||||
}
|
||||
|
||||
fun appendGroups(groups: Collection<VKGroup>) {
|
||||
for (group in groups) {
|
||||
append(group)
|
||||
}
|
||||
}
|
||||
|
||||
fun append(value: VKGroup) {
|
||||
groups.append(value.groupId, value)
|
||||
}
|
||||
|
||||
fun append(value: VKUser) {
|
||||
users.append(value.userId, value)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun put(value: VKUser) {
|
||||
append(value)
|
||||
|
||||
AppGlobal.database.users.insert(value)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun putUsers(users: List<VKUser>) {
|
||||
appendUsers(users)
|
||||
|
||||
AppGlobal.database.users.insert(users)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun put(value: VKFriend) {
|
||||
AppGlobal.database.friends.insert(value)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun putFriends(friends: List<VKFriend>) {
|
||||
AppGlobal.database.friends.insert(friends)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun put(value: VKMessage) {
|
||||
AppGlobal.database.messages.insert(value)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun putMessages(messages: List<VKMessage>) {
|
||||
AppGlobal.database.messages.insert(messages)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun put(value: VKGroup) {
|
||||
append(value)
|
||||
|
||||
AppGlobal.database.groups.insert(value)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun putGroups(groups: List<VKGroup>) {
|
||||
appendGroups(groups)
|
||||
|
||||
AppGlobal.database.groups.insert(groups)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun put(value: VKConversation) {
|
||||
AppGlobal.database.conversations.insert(value)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun putConversations(conversations: List<VKConversation>) {
|
||||
AppGlobal.database.conversations.insert(conversations)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun deleteMessage(messageId: Int, safe: Boolean = true) {
|
||||
if (safe) {
|
||||
AppGlobal.database.messages.getById(messageId) ?: return
|
||||
}
|
||||
|
||||
AppGlobal.database.messages.deleteById(messageId)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun deleteConversation(conversationId: Int, safe: Boolean = true) {
|
||||
if (safe) {
|
||||
AppGlobal.database.conversations.getById(conversationId) ?: return
|
||||
}
|
||||
|
||||
AppGlobal.database.conversations.deleteById(conversationId)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun edit(message: VKMessage?, safe: Boolean = true) {
|
||||
message ?: return
|
||||
|
||||
if (safe) {
|
||||
AppGlobal.database.messages.getById(message.messageId) ?: return
|
||||
}
|
||||
|
||||
AppGlobal.database.messages.update(message)
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
users.clear()
|
||||
groups.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.meloda.fast.database
|
||||
|
||||
import android.database.Cursor
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
|
||||
|
||||
class QueryBuilder private constructor() {
|
||||
|
||||
companion object {
|
||||
fun query(): QueryBuilder {
|
||||
return QueryBuilder()
|
||||
}
|
||||
}
|
||||
|
||||
private val builder: StringBuilder = StringBuilder()
|
||||
|
||||
fun select(column: String): QueryBuilder {
|
||||
builder.append("SELECT ")
|
||||
.append(column)
|
||||
.append(" ")
|
||||
return this
|
||||
}
|
||||
|
||||
fun from(table: String): QueryBuilder {
|
||||
builder.append("FROM ")
|
||||
.append(table)
|
||||
.append(" ")
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
fun where(clause: String): QueryBuilder {
|
||||
builder.append("WHERE ")
|
||||
.append(clause)
|
||||
.append(" ")
|
||||
return this
|
||||
}
|
||||
|
||||
fun leftJoin(table: String): QueryBuilder {
|
||||
builder.append("LEFT JOIN ")
|
||||
.append(table)
|
||||
.append(" ")
|
||||
return this
|
||||
}
|
||||
|
||||
fun on(where: String): QueryBuilder {
|
||||
builder.append("ON ")
|
||||
.append(where)
|
||||
.append(" ")
|
||||
return this
|
||||
}
|
||||
|
||||
fun and(): QueryBuilder {
|
||||
builder.append("AND ")
|
||||
return this
|
||||
}
|
||||
|
||||
fun or(): QueryBuilder {
|
||||
builder.append("OR ")
|
||||
return this
|
||||
}
|
||||
|
||||
fun asCursor(db: SQLiteDatabase): Cursor {
|
||||
return db.rawQuery(toString(), null)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return builder.toString().trim()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.meloda.fast.database.base
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.meloda.fast.common.AppGlobal
|
||||
|
||||
abstract class Storage<T> {
|
||||
|
||||
abstract val tag: String
|
||||
|
||||
protected var database = AppGlobal.database
|
||||
|
||||
@WorkerThread
|
||||
abstract fun getAllValues(): ArrayList<T>
|
||||
|
||||
@WorkerThread
|
||||
abstract fun insertValues(values: ArrayList<T>, params: Bundle? = null)
|
||||
|
||||
@WorkerThread
|
||||
fun insertValue(value: T, params: Bundle? = null) {
|
||||
insertValues(arrayListOf(value), params)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
abstract fun cacheValue(values: ContentValues, value: T, params: Bundle? = null)
|
||||
|
||||
@WorkerThread
|
||||
abstract fun parseValue(cursor: Cursor): T
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.meloda.fast.database.dao
|
||||
|
||||
import androidx.room.*
|
||||
import com.meloda.fast.api.model.VKConversation
|
||||
|
||||
@Dao
|
||||
interface ConversationsDao {
|
||||
|
||||
@Query("SELECT * FROM conversations")
|
||||
fun getAll(): List<VKConversation>
|
||||
|
||||
@Query("SELECT * FROM conversations WHERE conversationId = :id")
|
||||
fun getById(id: Int): VKConversation?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(item: VKConversation)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(items: List<VKConversation>)
|
||||
|
||||
@Update
|
||||
fun update(item: VKConversation)
|
||||
|
||||
@Update
|
||||
fun update(items: List<VKConversation>)
|
||||
|
||||
@Delete
|
||||
fun delete(item: VKConversation)
|
||||
|
||||
@Delete
|
||||
fun delete(items: List<VKConversation>)
|
||||
|
||||
@Query("DELETE FROM conversations WHERE conversationId = :id")
|
||||
fun deleteById(id: Int)
|
||||
|
||||
@Query("DELETE FROM conversations")
|
||||
fun clear()
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package com.meloda.fast.database.dao
|
||||
|
||||
import androidx.room.*
|
||||
import com.meloda.fast.api.model.VKFriend
|
||||
|
||||
@Dao
|
||||
interface FriendsDao {
|
||||
|
||||
@Query("SELECT * FROM friends")
|
||||
fun getAll(): List<VKFriend>
|
||||
|
||||
@Query("SELECT * FROM friends WHERE userId = :id")
|
||||
fun getById(id: Int): VKFriend?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(item: VKFriend)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(items: List<VKFriend>)
|
||||
|
||||
@Update
|
||||
fun update(item: VKFriend)
|
||||
|
||||
@Update
|
||||
fun update(items: List<VKFriend>)
|
||||
|
||||
@Delete
|
||||
fun delete(item: VKFriend)
|
||||
|
||||
@Delete
|
||||
fun delete(items: List<VKFriend>)
|
||||
|
||||
@Query("DELETE FROM friends WHERE userId = :id")
|
||||
fun deleteById(id: Int)
|
||||
|
||||
@Query("DELETE FROM friends")
|
||||
fun clear()
|
||||
|
||||
@Query("SELECT * FROM friends WHERE userId = :id")
|
||||
fun getByUserId(id: Int): List<VKFriend>
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.meloda.fast.database.dao
|
||||
|
||||
import androidx.room.*
|
||||
import com.meloda.fast.api.model.VKGroup
|
||||
|
||||
@Dao
|
||||
interface GroupsDao {
|
||||
@Query("SELECT * FROM groups")
|
||||
fun getAll(): List<VKGroup>
|
||||
|
||||
@Query("SELECT * FROM groups WHERE groupId = :id")
|
||||
fun getById(id: Int): VKGroup?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(item: VKGroup)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(items: List<VKGroup>)
|
||||
|
||||
@Update
|
||||
fun update(item: VKGroup)
|
||||
|
||||
@Update
|
||||
fun update(items: List<VKGroup>)
|
||||
|
||||
@Delete
|
||||
fun delete(item: VKGroup)
|
||||
|
||||
@Delete
|
||||
fun delete(items: List<VKGroup>)
|
||||
|
||||
@Query("DELETE FROM groups WHERE groupId = :id")
|
||||
fun deleteById(id: Int)
|
||||
|
||||
@Query("DELETE FROM groups")
|
||||
fun clear()
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package com.meloda.fast.database.dao
|
||||
|
||||
import androidx.room.*
|
||||
import com.meloda.fast.api.model.VKMessage
|
||||
|
||||
@Dao
|
||||
interface MessagesDao {
|
||||
|
||||
@Query("SELECT * FROM messages")
|
||||
fun getAll(): List<VKMessage>
|
||||
|
||||
@Query("SELECT * FROM messages WHERE messageId = :id")
|
||||
fun getById(id: Int): VKMessage?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(item: VKMessage)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(items: List<VKMessage>)
|
||||
|
||||
@Update
|
||||
fun update(item: VKMessage)
|
||||
|
||||
@Update
|
||||
fun update(items: List<VKMessage>)
|
||||
|
||||
@Delete
|
||||
fun delete(item: VKMessage)
|
||||
|
||||
@Delete
|
||||
fun delete(items: List<VKMessage>)
|
||||
|
||||
@Query("DELETE FROM messages WHERE messageId = :id")
|
||||
fun deleteById(id: Int)
|
||||
|
||||
@Query("DELETE FROM messages")
|
||||
fun clear()
|
||||
|
||||
@Query("SELECT * FROM messages WHERE peerId = :peerId")
|
||||
fun getByPeerId(peerId: Int): List<VKMessage>
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.meloda.fast.database.dao
|
||||
|
||||
import androidx.room.*
|
||||
import com.meloda.fast.api.model.VKUser
|
||||
|
||||
@Dao
|
||||
interface UsersDao {
|
||||
|
||||
@Query("SELECT * FROM users")
|
||||
fun getAll(): List<VKUser>
|
||||
|
||||
@Query("SELECT * FROM users WHERE userId = :id")
|
||||
fun getById(id: Int): VKUser?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(item: VKUser)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
fun insert(items: List<VKUser>)
|
||||
|
||||
@Update
|
||||
fun update(item: VKUser)
|
||||
|
||||
@Update
|
||||
fun update(items: List<VKUser>)
|
||||
|
||||
@Delete
|
||||
fun delete(item: VKUser)
|
||||
|
||||
@Delete
|
||||
fun delete(items: List<VKUser>)
|
||||
|
||||
@Query("DELETE FROM users WHERE userId = :id")
|
||||
fun deleteById(id: Int)
|
||||
|
||||
@Query("DELETE FROM users")
|
||||
fun clear()
|
||||
}
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
package com.meloda.fast.database.dao.converters
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.meloda.fast.api.model.VKModel
|
||||
import com.meloda.fast.extensions.ArrayExtensions.isNullOrEmpty
|
||||
import com.meloda.fast.util.Utils
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class ArrayListToByteArrayConverter {
|
||||
|
||||
@TypeConverter
|
||||
fun toForwarded(data: ByteArray?): ArrayList<VKModel> {
|
||||
return if (data.isNullOrEmpty()) arrayListOf() else {
|
||||
val deserializedData = Utils.deserialize(data)
|
||||
if (deserializedData == null) arrayListOf() else deserializedData as ArrayList<VKModel>
|
||||
}
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromForwarded(forwarded: List<VKModel>): ByteArray {
|
||||
return Utils.serialize(forwarded) ?: return byteArrayOf()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.meloda.fast.database.dao.converters
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.meloda.fast.api.model.VKMessage
|
||||
import com.meloda.fast.extensions.ArrayExtensions.isNullOrEmpty
|
||||
import com.meloda.fast.util.Utils
|
||||
import java.util.*
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class ForwardedConverter {
|
||||
|
||||
@TypeConverter
|
||||
fun toForwarded(data: ByteArray?): ArrayList<VKMessage> {
|
||||
return if (data.isNullOrEmpty()) arrayListOf() else {
|
||||
val deserializedData = Utils.deserialize(data)
|
||||
if (deserializedData == null) arrayListOf() else deserializedData as ArrayList<VKMessage>
|
||||
}
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromForwarded(forwarded: List<VKMessage>): ByteArray {
|
||||
return Utils.serialize(forwarded) ?: return byteArrayOf()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.meloda.fast.database.storage
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.meloda.fast.database.CacheStorage
|
||||
import com.meloda.fast.database.CacheStorage.messagesStorage
|
||||
import com.meloda.fast.database.DatabaseKeys.CHAT_STATE
|
||||
import com.meloda.fast.database.DatabaseKeys.CONVERSATION_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.IN_READ_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_ALLOWED
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_GROUP_CHANNEL
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_NOTIFICATIONS_DISABLED
|
||||
import com.meloda.fast.database.DatabaseKeys.LAST_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.LOCAL_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.MEMBERS_COUNT
|
||||
import com.meloda.fast.database.DatabaseKeys.NOT_ALLOWED_REASON
|
||||
import com.meloda.fast.database.DatabaseKeys.OUT_READ_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.PHOTOS
|
||||
import com.meloda.fast.database.DatabaseKeys.PINNED_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.TITLE
|
||||
import com.meloda.fast.database.DatabaseKeys.TYPE
|
||||
import com.meloda.fast.database.DatabaseKeys.UNREAD_COUNT
|
||||
import com.meloda.fast.database.DatabaseUtils.TABLE_CHATS
|
||||
import com.meloda.fast.database.base.Storage
|
||||
import com.meloda.vksdk.model.VKConversation
|
||||
import com.meloda.vksdk.util.VKUtil
|
||||
import org.json.JSONObject
|
||||
|
||||
@WorkerThread
|
||||
class ChatsStorage : Storage<VKConversation>() {
|
||||
|
||||
override val tag = "ChatsStorage"
|
||||
|
||||
override fun getAllValues(): ArrayList<VKConversation> {
|
||||
val cursor = CacheStorage.selectCursor(TABLE_CHATS)
|
||||
val conversations = ArrayList<VKConversation>()
|
||||
|
||||
while (cursor.moveToNext()) conversations.add(parseValue(cursor))
|
||||
|
||||
cursor.close()
|
||||
|
||||
return conversations
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun insertValues(values: ArrayList<VKConversation>, params: Bundle?) {
|
||||
if (values.isEmpty()) return
|
||||
|
||||
database.beginTransaction()
|
||||
|
||||
val contentValues = ContentValues()
|
||||
|
||||
for (value in values) {
|
||||
cacheValue(contentValues, value, params)
|
||||
|
||||
database.insert(TABLE_CHATS, null, contentValues)
|
||||
|
||||
contentValues.clear()
|
||||
}
|
||||
|
||||
database.setTransactionSuccessful()
|
||||
database.endTransaction()
|
||||
|
||||
Log.d(tag, "Successful cached chats")
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun cacheValue(values: ContentValues, value: VKConversation, params: Bundle?) {
|
||||
values.put(CONVERSATION_ID, value.id)
|
||||
values.put(IS_ALLOWED, value.isAllowed)
|
||||
values.put(NOT_ALLOWED_REASON, value.notAllowedReason.value)
|
||||
values.put(IN_READ_MESSAGE_ID, value.inReadMessageId)
|
||||
values.put(OUT_READ_MESSAGE_ID, value.outReadMessageId)
|
||||
values.put(LAST_MESSAGE_ID, value.lastMessageId)
|
||||
values.put(UNREAD_COUNT, value.unreadCount)
|
||||
values.put(LOCAL_ID, value.localId)
|
||||
values.put(IS_NOTIFICATIONS_DISABLED, value.notificationsEnabled)
|
||||
values.put(MEMBERS_COUNT, value.membersCount)
|
||||
values.put(TITLE, value.title)
|
||||
values.put(IS_GROUP_CHANNEL, value.isGroupChannel)
|
||||
values.put(TYPE, value.intType)
|
||||
values.put(CHAT_STATE, value.intState)
|
||||
|
||||
values.put(
|
||||
PHOTOS,
|
||||
VKUtil.putPhotosToJson(
|
||||
value.photo50,
|
||||
value.photo100,
|
||||
value.photo200
|
||||
).toString()
|
||||
)
|
||||
|
||||
value.pinnedMessage?.let {
|
||||
values.put(PINNED_MESSAGE_ID, it.id)
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun parseValue(cursor: Cursor): VKConversation {
|
||||
val conversation = VKConversation()
|
||||
|
||||
conversation.id = CacheStorage.getInt(cursor, CONVERSATION_ID)
|
||||
conversation.isAllowed = CacheStorage.getInt(cursor, IS_ALLOWED) == 1
|
||||
conversation.notAllowedReason = VKConversation.Reason.fromInt(
|
||||
CacheStorage.getInt(cursor, NOT_ALLOWED_REASON)
|
||||
)
|
||||
conversation.inReadMessageId = CacheStorage.getInt(cursor, IN_READ_MESSAGE_ID)
|
||||
conversation.outReadMessageId = CacheStorage.getInt(cursor, OUT_READ_MESSAGE_ID)
|
||||
conversation.unreadCount = CacheStorage.getInt(cursor, UNREAD_COUNT)
|
||||
conversation.localId = CacheStorage.getInt(cursor, LOCAL_ID)
|
||||
conversation.notificationsEnabled =
|
||||
CacheStorage.getInt(cursor, IS_NOTIFICATIONS_DISABLED) == 1
|
||||
conversation.membersCount = CacheStorage.getInt(cursor, MEMBERS_COUNT)
|
||||
conversation.title = CacheStorage.getString(cursor, TITLE)
|
||||
conversation.isGroupChannel = CacheStorage.getInt(cursor, IS_GROUP_CHANNEL) == 1
|
||||
|
||||
val pinnedMessageId = CacheStorage.getInt(cursor, PINNED_MESSAGE_ID)
|
||||
if (pinnedMessageId != -1) {
|
||||
val pinnedMessage = messagesStorage.getMessageById(pinnedMessageId)
|
||||
if (pinnedMessage != null) conversation.pinnedMessage = pinnedMessage
|
||||
}
|
||||
|
||||
conversation.intType = CacheStorage.getInt(cursor, TYPE)
|
||||
conversation.intState = CacheStorage.getInt(cursor, CHAT_STATE)
|
||||
|
||||
conversation.lastMessageId = CacheStorage.getInt(cursor, LAST_MESSAGE_ID)
|
||||
val lastMessage = messagesStorage.getMessageById(conversation.lastMessageId)
|
||||
if (lastMessage != null) conversation.lastMessage = lastMessage
|
||||
|
||||
val photos = VKUtil.parseJsonPhotos(JSONObject(CacheStorage.getString(cursor, PHOTOS)))
|
||||
conversation.photo50 = photos[0]
|
||||
conversation.photo100 = photos[1]
|
||||
conversation.photo200 = photos[2]
|
||||
|
||||
return conversation
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.meloda.fast.database.storage
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.meloda.fast.database.CacheStorage
|
||||
import com.meloda.fast.database.CacheStorage.getInt
|
||||
import com.meloda.fast.database.CacheStorage.getString
|
||||
import com.meloda.fast.database.DatabaseKeys.DEACTIVATED
|
||||
import com.meloda.fast.database.DatabaseKeys.GROUP_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_CLOSED
|
||||
import com.meloda.fast.database.DatabaseKeys.NAME
|
||||
import com.meloda.fast.database.DatabaseKeys.PHOTOS
|
||||
import com.meloda.fast.database.DatabaseKeys.SCREEN_NAME
|
||||
import com.meloda.fast.database.DatabaseKeys.TYPE
|
||||
import com.meloda.fast.database.DatabaseUtils.TABLE_GROUPS
|
||||
import com.meloda.fast.database.base.Storage
|
||||
import com.meloda.vksdk.model.VKGroup
|
||||
import com.meloda.vksdk.util.VKUtil
|
||||
import org.json.JSONObject
|
||||
|
||||
class GroupsStorage : Storage<VKGroup>() {
|
||||
|
||||
override val tag = "GroupsStorage"
|
||||
|
||||
@WorkerThread
|
||||
fun getGroups(ids: IntArray): ArrayList<VKGroup> {
|
||||
val cursor = CacheStorage.selectCursor(TABLE_GROUPS, GROUP_ID, ids)
|
||||
|
||||
val groups = ArrayList<VKGroup>(cursor.count)
|
||||
while (cursor.moveToNext()) groups.add(parseValue(cursor))
|
||||
|
||||
cursor.close()
|
||||
return groups
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getGroup(userId: Int): VKGroup? {
|
||||
val group = getGroups(intArrayOf(userId))
|
||||
|
||||
return if (group.isNotEmpty()) group[0] else null
|
||||
}
|
||||
|
||||
override fun getAllValues(): ArrayList<VKGroup> {
|
||||
val cursor = CacheStorage.selectCursor(TABLE_GROUPS)
|
||||
val groups = ArrayList<VKGroup>()
|
||||
|
||||
while (cursor.moveToNext()) groups.add(parseValue(cursor))
|
||||
|
||||
cursor.close()
|
||||
|
||||
return groups
|
||||
}
|
||||
|
||||
override fun insertValues(values: ArrayList<VKGroup>, params: Bundle?) {
|
||||
if (values.isEmpty()) return
|
||||
|
||||
database.beginTransaction()
|
||||
|
||||
val contentValues = ContentValues()
|
||||
|
||||
for (value in values) {
|
||||
cacheValue(contentValues, value, params)
|
||||
|
||||
database.insert(TABLE_GROUPS, null, contentValues)
|
||||
|
||||
contentValues.clear()
|
||||
}
|
||||
|
||||
database.setTransactionSuccessful()
|
||||
database.endTransaction()
|
||||
|
||||
Log.d(tag, "Successful cached groups")
|
||||
}
|
||||
|
||||
override fun cacheValue(values: ContentValues, value: VKGroup, params: Bundle?) {
|
||||
values.put(GROUP_ID, value.id)
|
||||
values.put(NAME, value.name)
|
||||
values.put(SCREEN_NAME, value.screenName)
|
||||
values.put(IS_CLOSED, value.isClosed)
|
||||
values.put(DEACTIVATED, value.deactivated)
|
||||
values.put(TYPE, value.type.value)
|
||||
|
||||
val photos =
|
||||
VKUtil.putPhotosToJson(value.photo50, value.photo100, value.photo200).toString()
|
||||
|
||||
values.put(PHOTOS, photos)
|
||||
}
|
||||
|
||||
override fun parseValue(cursor: Cursor): VKGroup {
|
||||
val group = VKGroup()
|
||||
|
||||
group.id = getInt(cursor, GROUP_ID)
|
||||
group.name = getString(cursor, NAME)
|
||||
group.screenName = getString(cursor, SCREEN_NAME)
|
||||
group.isClosed = getInt(cursor, IS_CLOSED) == 1
|
||||
group.deactivated = getString(cursor, DEACTIVATED)
|
||||
group.type = VKGroup.Type.fromString(getString(cursor, TYPE))
|
||||
|
||||
val photos = VKUtil.parseJsonPhotos(JSONObject(getString(cursor, PHOTOS)))
|
||||
|
||||
group.photo50 = photos[0]
|
||||
group.photo100 = photos[1]
|
||||
group.photo200 = photos[2]
|
||||
|
||||
return group
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package com.meloda.fast.database.storage
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.meloda.fast.database.CacheStorage
|
||||
import com.meloda.fast.database.CacheStorage.selectCursor
|
||||
import com.meloda.fast.database.DatabaseKeys.ACTION
|
||||
import com.meloda.fast.database.DatabaseKeys.ATTACHMENTS
|
||||
import com.meloda.fast.database.DatabaseKeys.CONVERSATION_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.DATE
|
||||
import com.meloda.fast.database.DatabaseKeys.EDIT_TIME
|
||||
import com.meloda.fast.database.DatabaseKeys.FROM_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.FWD_MESSAGES
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_OUT
|
||||
import com.meloda.fast.database.DatabaseKeys.MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.PEER_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.RANDOM_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.REPLY_MESSAGE_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.TEXT
|
||||
import com.meloda.fast.database.DatabaseUtils.TABLE_MESSAGES
|
||||
import com.meloda.fast.database.base.Storage
|
||||
import com.meloda.fast.util.Utils
|
||||
import com.meloda.vksdk.model.VKMessage
|
||||
import com.meloda.vksdk.model.VKMessageAction
|
||||
import com.meloda.vksdk.model.VKModel
|
||||
import java.util.stream.Collectors
|
||||
|
||||
@WorkerThread
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class MessagesStorage : Storage<VKMessage>() {
|
||||
|
||||
override val tag = "MessagesStorage"
|
||||
|
||||
@WorkerThread
|
||||
fun getMessagesHistory(peerId: Int): ArrayList<VKMessage> {
|
||||
val cursor = CacheStorage.selectCursor(TABLE_MESSAGES, PEER_ID, peerId)
|
||||
|
||||
val messages = ArrayList<VKMessage>(cursor.count)
|
||||
while (cursor.moveToNext()) messages.add(parseValue(cursor))
|
||||
|
||||
cursor.close()
|
||||
|
||||
return messages
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getMessageById(messageId: Int): VKMessage? {
|
||||
val cursor = CacheStorage.selectCursor(TABLE_MESSAGES, MESSAGE_ID, messageId)
|
||||
|
||||
if (cursor.moveToFirst()) {
|
||||
val message = parseValue(cursor)
|
||||
cursor.close()
|
||||
|
||||
return message
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getAllValues(): ArrayList<VKMessage> {
|
||||
val cursor = selectCursor(TABLE_MESSAGES)
|
||||
val messages = ArrayList<VKMessage>()
|
||||
|
||||
while (cursor.moveToNext()) messages.add(parseValue(cursor))
|
||||
|
||||
cursor.close()
|
||||
|
||||
return messages
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun insertValues(values: ArrayList<VKMessage>, params: Bundle?) {
|
||||
if (values.isEmpty()) return
|
||||
|
||||
database.beginTransaction()
|
||||
|
||||
val contentValues = ContentValues()
|
||||
|
||||
for (value in values) {
|
||||
cacheValue(contentValues, value)
|
||||
|
||||
database.insert(TABLE_MESSAGES, null, contentValues)
|
||||
|
||||
contentValues.clear()
|
||||
}
|
||||
|
||||
database.setTransactionSuccessful()
|
||||
database.endTransaction()
|
||||
|
||||
Log.d(tag, "Successful cached messages")
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun cacheValue(values: ContentValues, value: VKMessage, params: Bundle?) {
|
||||
values.put(MESSAGE_ID, value.id)
|
||||
values.put(DATE, value.date)
|
||||
values.put(PEER_ID, value.peerId)
|
||||
values.put(FROM_ID, value.fromId)
|
||||
values.put(EDIT_TIME, value.editTime)
|
||||
values.put(TEXT, value.text)
|
||||
values.put(RANDOM_ID, value.randomId)
|
||||
values.put(CONVERSATION_MESSAGE_ID, value.conversationMessageId)
|
||||
|
||||
value.replyMessage?.let {
|
||||
values.put(REPLY_MESSAGE_ID, it.id)
|
||||
}
|
||||
|
||||
value.action?.let {
|
||||
values.put(ACTION, Utils.serialize(it))
|
||||
}
|
||||
|
||||
value.attachments.let {
|
||||
if (it.isNotEmpty()) {
|
||||
values.put(ATTACHMENTS, Utils.serialize(it))
|
||||
}
|
||||
}
|
||||
|
||||
value.fwdMessages.let {
|
||||
if (it.isNotEmpty()) {
|
||||
val ids = arrayListOf<String>()
|
||||
it.forEach { message -> ids.add(message.id.toString()) }
|
||||
|
||||
ids.stream().collect(Collectors.joining(",")).let { str ->
|
||||
values.put(FWD_MESSAGES, str)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun parseValue(cursor: Cursor): VKMessage {
|
||||
val message = VKMessage()
|
||||
|
||||
message.id = CacheStorage.getInt(cursor, MESSAGE_ID)
|
||||
message.date = CacheStorage.getInt(cursor, DATE)
|
||||
message.peerId = CacheStorage.getInt(cursor, PEER_ID)
|
||||
message.fromId = CacheStorage.getInt(cursor, FROM_ID)
|
||||
message.editTime = CacheStorage.getInt(cursor, EDIT_TIME)
|
||||
message.isOut = CacheStorage.getInt(cursor, IS_OUT) == 1
|
||||
message.text = CacheStorage.getString(cursor, TEXT)
|
||||
message.randomId = CacheStorage.getInt(cursor, RANDOM_ID)
|
||||
message.conversationMessageId = CacheStorage.getInt(cursor, CONVERSATION_MESSAGE_ID)
|
||||
|
||||
val blobAttachments = Utils.deserialize(CacheStorage.getBlob(cursor, ATTACHMENTS))
|
||||
if (blobAttachments != null) message.attachments = blobAttachments as ArrayList<VKModel>
|
||||
else message.attachments = arrayListOf()
|
||||
|
||||
val replyMessageId = CacheStorage.getInt(cursor, REPLY_MESSAGE_ID)
|
||||
val replyMessage = getMessageById(replyMessageId)
|
||||
if (replyMessage != null) message.replyMessage = replyMessage
|
||||
|
||||
val blobAction = Utils.deserialize(CacheStorage.getBlob(cursor, ACTION))
|
||||
if (blobAction != null) message.action = blobAction as VKMessageAction
|
||||
|
||||
val stringFwdMessages = CacheStorage.getString(cursor, FWD_MESSAGES)
|
||||
if (stringFwdMessages != null) {
|
||||
val split = stringFwdMessages.split(',')
|
||||
|
||||
val ids = arrayListOf<Int>()
|
||||
for (s in split) ids.add(s.toInt())
|
||||
|
||||
val fwdMessages = arrayListOf<VKMessage>()
|
||||
|
||||
ids.forEach {
|
||||
val fwdMessage = getMessageById(it)
|
||||
if (fwdMessage != null) fwdMessages.add(fwdMessage)
|
||||
}
|
||||
|
||||
message.fwdMessages = fwdMessages
|
||||
} else message.fwdMessages = arrayListOf()
|
||||
|
||||
return message
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package com.meloda.fast.database.storage
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.meloda.fast.UserConfig
|
||||
import com.meloda.fast.database.CacheStorage
|
||||
import com.meloda.fast.database.CacheStorage.selectCursor
|
||||
import com.meloda.fast.database.DatabaseKeys.DEACTIVATED
|
||||
import com.meloda.fast.database.DatabaseKeys.FIRST_NAME
|
||||
import com.meloda.fast.database.DatabaseKeys.FRIEND_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.GENDER
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_ONLINE
|
||||
import com.meloda.fast.database.DatabaseKeys.IS_ONLINE_MOBILE
|
||||
import com.meloda.fast.database.DatabaseKeys.LAST_NAME
|
||||
import com.meloda.fast.database.DatabaseKeys.LAST_SEEN
|
||||
import com.meloda.fast.database.DatabaseKeys.PHOTOS
|
||||
import com.meloda.fast.database.DatabaseKeys.SCREEN_NAME
|
||||
import com.meloda.fast.database.DatabaseKeys.SORT_ID
|
||||
import com.meloda.fast.database.DatabaseKeys.STATUS
|
||||
import com.meloda.fast.database.DatabaseKeys.USER_ID
|
||||
import com.meloda.fast.database.DatabaseUtils.TABLE_FRIENDS
|
||||
import com.meloda.fast.database.DatabaseUtils.TABLE_USERS
|
||||
import com.meloda.fast.database.QueryBuilder
|
||||
import com.meloda.fast.database.base.Storage
|
||||
import com.meloda.vksdk.model.VKUser
|
||||
import com.meloda.vksdk.util.VKUtil
|
||||
import org.json.JSONObject
|
||||
|
||||
@WorkerThread
|
||||
class UsersStorage : Storage<VKUser>() {
|
||||
|
||||
override val tag = "UsersStorage"
|
||||
|
||||
@WorkerThread
|
||||
fun getUsers(ids: IntArray): ArrayList<VKUser> {
|
||||
val cursor = CacheStorage.selectCursor(TABLE_USERS, USER_ID, ids)
|
||||
|
||||
val users = ArrayList<VKUser>(cursor.count)
|
||||
while (cursor.moveToNext()) users.add(parseValue(cursor))
|
||||
|
||||
cursor.close()
|
||||
return users
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getUser(userId: Int): VKUser? {
|
||||
val user = getUsers(intArrayOf(userId))
|
||||
|
||||
return if (user.isNotEmpty()) user[0] else null
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getFriends(userId: Int, onlyOnline: Boolean = false): ArrayList<VKUser> {
|
||||
val cursor = QueryBuilder.query()
|
||||
.select("*")
|
||||
.from(TABLE_FRIENDS)
|
||||
.leftJoin(TABLE_USERS)
|
||||
.on("friends.${FRIEND_ID} = users.$USER_ID")
|
||||
.where("friends.${USER_ID} = $userId")
|
||||
.asCursor(database)
|
||||
|
||||
val users = ArrayList<VKUser>(cursor.count)
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
val userOnline = CacheStorage.getInt(cursor, IS_ONLINE) == 1
|
||||
if (onlyOnline && !userOnline) continue
|
||||
|
||||
val user = parseValue(cursor)
|
||||
users.add(user)
|
||||
}
|
||||
|
||||
cursor.close()
|
||||
|
||||
return users
|
||||
}
|
||||
|
||||
override fun getAllValues(): ArrayList<VKUser> {
|
||||
val cursor = selectCursor(TABLE_USERS)
|
||||
val users = ArrayList<VKUser>()
|
||||
|
||||
while (cursor.moveToNext()) users.add(parseValue(cursor))
|
||||
|
||||
cursor.close()
|
||||
|
||||
return users
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun insertValues(values: ArrayList<VKUser>, params: Bundle?) {
|
||||
if (values.isEmpty()) return
|
||||
|
||||
val toFriends = params?.getBoolean("toFriends") ?: false
|
||||
|
||||
database.beginTransaction()
|
||||
|
||||
val contentValues = ContentValues()
|
||||
|
||||
for (user in values) {
|
||||
cacheValue(contentValues, user, params)
|
||||
|
||||
database.insert(if (toFriends) TABLE_FRIENDS else TABLE_USERS, null, contentValues)
|
||||
|
||||
contentValues.clear()
|
||||
}
|
||||
|
||||
database.setTransactionSuccessful()
|
||||
database.endTransaction()
|
||||
|
||||
Log.d(tag, "Successful cached users. toFriends: $toFriends")
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun cacheValue(values: ContentValues, value: VKUser, params: Bundle?) {
|
||||
val toFriends = params?.getBoolean("toFriends") ?: false
|
||||
|
||||
if (toFriends) {
|
||||
values.put(USER_ID, UserConfig.userId)
|
||||
values.put(FRIEND_ID, value.userId)
|
||||
values.put(SORT_ID, value.sortId)
|
||||
return
|
||||
}
|
||||
|
||||
values.put(USER_ID, value.userId)
|
||||
values.put(FIRST_NAME, value.firstName)
|
||||
values.put(LAST_NAME, value.lastName)
|
||||
values.put(DEACTIVATED, value.deactivated)
|
||||
values.put(GENDER, value.sex)
|
||||
values.put(SCREEN_NAME, value.screenName)
|
||||
values.put(IS_ONLINE, value.isOnline)
|
||||
values.put(IS_ONLINE_MOBILE, value.isOnlineMobile)
|
||||
values.put(STATUS, value.status)
|
||||
values.put(LAST_SEEN, value.lastSeen)
|
||||
|
||||
values.put(
|
||||
PHOTOS,
|
||||
VKUtil.putPhotosToJson(
|
||||
value.photo50,
|
||||
value.photo100,
|
||||
value.photo200
|
||||
).toString()
|
||||
)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun parseValue(cursor: Cursor): VKUser {
|
||||
val user = VKUser()
|
||||
|
||||
user.userId = CacheStorage.getInt(cursor, USER_ID)
|
||||
user.firstName = CacheStorage.getString(cursor, FIRST_NAME)
|
||||
user.lastName = CacheStorage.getString(cursor, LAST_NAME)
|
||||
user.deactivated = CacheStorage.getString(cursor, DEACTIVATED)
|
||||
user.sex = CacheStorage.getInt(cursor, GENDER)
|
||||
user.screenName = CacheStorage.getString(cursor, SCREEN_NAME)
|
||||
user.isOnline = CacheStorage.getInt(cursor, IS_ONLINE) == 1
|
||||
user.isOnlineMobile = CacheStorage.getInt(cursor, IS_ONLINE_MOBILE) == 1
|
||||
user.status = CacheStorage.getString(cursor, STATUS)
|
||||
user.lastSeen = CacheStorage.getInt(cursor, LAST_SEEN)
|
||||
|
||||
val photos =
|
||||
VKUtil.parseJsonPhotos(JSONObject(CacheStorage.getString(cursor, PHOTOS)))
|
||||
|
||||
user.photo50 = photos[0]
|
||||
user.photo100 = photos[1]
|
||||
user.photo200 = photos[2]
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user