Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ abstract class BaseMessagesFragment<VM : BaseMessagesViewModel> : BaseFragment()
@Inject
lateinit var viewModelFactory: BaseMessagesViewModel.Factory
protected lateinit var viewModel: VM
var stopSearch:Boolean = false

protected val adapter by lazy {
MessagesAdapter(
Expand All @@ -67,6 +68,8 @@ abstract class BaseMessagesFragment<VM : BaseMessagesViewModel> : BaseFragment()

abstract fun getAdapterSettings(): MessagesAdapter.Settings

abstract fun getSearchMessageId(): Int

protected open fun prepareViewModel() {}

/**
Expand All @@ -85,6 +88,7 @@ abstract class BaseMessagesFragment<VM : BaseMessagesViewModel> : BaseFragment()
viewModel = ViewModelProviders.of(this, viewModelFactory)[getViewModelClass()]
prepareViewModel()
adapter.startLoading()
stopSearch = false

progressBar.show()
xviiToolbar.isLifted = true
Expand Down Expand Up @@ -112,26 +116,34 @@ abstract class BaseMessagesFragment<VM : BaseMessagesViewModel> : BaseFragment()
}
val interaction = data.data ?: return

val searchMsgId = getSearchMessageId()

try {
when (interaction.type) {
Interaction.Type.CLEAR -> {
adapter.clear()
}
Interaction.Type.ADD -> {
val firstLoad = adapter.isEmpty
val firstLoad = adapter.isEmpty || searchMsgId > 0
val isAtEnd = adapter.isAtBottom(rvChatList.layoutManager as? LinearLayoutManager)
adapter.addAll(interaction.messages.toMutableList(), interaction.position)
adapter.stopLoading(interaction.messages.isEmpty())
when {
firstLoad -> {
var unreadPos = adapter.itemCount - 1 // default last item
var unreadPos = if(searchMsgId>0) 0 else adapter.itemCount - 1 // default last item
for (index in interaction.messages.indices) {
val message = interaction.messages[index].message
if (!message.read && !message.isOut()) {
if (searchMsgId == 0 && !message.read && !message.isOut() ||
searchMsgId == message.id) {
unreadPos = index
stopSearch = true
break
}
}
if(searchMsgId > 0 && !stopSearch){
unreadPos = 0
loadMore(adapter.itemCount)
}
rvChatList.scrollToPosition(unreadPos)
}
isAtEnd -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import kotlinx.android.synthetic.main.view_chat_multiselect.*
abstract class BaseChatMessagesFragment<VM : BaseChatMessagesViewModel> : BaseMessagesFragment<VM>() {

protected val peerId by lazy { arguments?.getInt(ARG_PEER_ID) ?: 0 }
protected val messageId by lazy { arguments?.getInt(ARG_MESSAGE_ID) ?: 0 }
protected val title by lazy { arguments?.getString(ARG_TITLE) ?: "" }
protected val photo by lazy { arguments?.getString(ARG_PHOTO) ?: "" }
private val forwardedMessages by lazy { arguments?.getString(ARG_FORWARDED) }
Expand Down Expand Up @@ -423,6 +424,8 @@ abstract class BaseChatMessagesFragment<VM : BaseChatMessagesViewModel> : BaseMe
isImportant = false
)

override fun getSearchMessageId() = messageId

override fun getAdapterCallback() = MessageCallback()

override fun getAttachmentsCallback() = AttachmentsCallback(requireContext())
Expand All @@ -432,6 +435,7 @@ abstract class BaseChatMessagesFragment<VM : BaseChatMessagesViewModel> : BaseMe
const val MEMBERS_MAX = 5

const val ARG_PEER_ID = "peerId"
const val ARG_MESSAGE_ID = "messageId"
const val ARG_TITLE = "title"
const val ARG_FORWARDED = "forwarded"
const val ARG_PHOTO = "photo"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ class ChatActivity : ContentActivity() {
val shareImages = args?.getStringArrayList(SHARE_IMAGE) ?: emptyList<String>()
val dialog = args?.getParcelable(DIALOG) ?: Dialog(
peerId = args?.getInt(PEER_ID) ?: 0,
messageId = args?.getInt(MESSAGE_ID) ?: 0,
title = args?.getString(TITLE) ?: "",
photo = args?.getString(AVATAR)
)
return ChatMessagesFragment.newInstance(dialog, forwarded, shareText, shareImages)
val search = args?.getBoolean(SEARCH)?: false
return ChatMessagesFragment.newInstance(dialog, forwarded, shareText, shareImages, search)
}

override fun getDraggableBottomMargin(): Int = 200
Expand All @@ -55,8 +57,10 @@ class ChatActivity : ContentActivity() {
const val SHARE_TEXT = "shareText"
const val SHARE_IMAGE = "shareImage"
const val PEER_ID = "peerId"
const val MESSAGE_ID = "messageId"
const val TITLE = "title"
const val AVATAR = "avatar"
const val SEARCH = "search"

fun launch(context: Context?, chatOwner: ChatOwner) {
launch(context, Dialog(
Expand Down Expand Up @@ -102,5 +106,14 @@ class ChatActivity : ContentActivity() {
photo = user.photo100
))
}
fun launch(context: Context?, dialog: Dialog, search:Boolean = false) {
context ?: return

context.startActivity(Intent(context, ChatActivity::class.java).apply {
putExtra(DIALOG, dialog)
putExtra(SEARCH, search)
flags = flags or Intent.FLAG_ACTIVITY_CLEAR_TOP
})
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ class ChatMessagesFragment : BaseChatMessagesFragment<ChatMessagesViewModel>() {
companion object {

fun newInstance(dialog: Dialog, forwarded: String? = null,
shareText: String? = null, shareImages: List<String> = emptyList()): ChatMessagesFragment {
shareText: String? = null, shareImages: List<String> = emptyList(),
search:Boolean = false): ChatMessagesFragment {
val fragment = ChatMessagesFragment()
fragment.arguments = Bundle().apply {
putInt(ARG_PEER_ID, dialog.peerId)
Expand All @@ -116,6 +117,9 @@ class ChatMessagesFragment : BaseChatMessagesFragment<ChatMessagesViewModel>() {
if (shareImages.isNotEmpty()) {
putStringArrayList(ARG_SHARE_IMAGE, ArrayList(shareImages))
}
if (search){
putInt(ARG_MESSAGE_ID, dialog.messageId);
}
}
return fragment
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class StarredMessagesFragment : BaseMessagesFragment<StarredMessagesViewModel>()
isImportant = true
)

override fun getSearchMessageId() = 0

override fun getAdapterCallback() = object : MessagesAdapter.Callback {

override fun onClicked(message: Message) {
Expand Down
31 changes: 28 additions & 3 deletions app/src/main/java/com/twoeightnine/root/xvii/main/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package com.twoeightnine.root.xvii.main

import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
Expand All @@ -32,6 +33,7 @@ import com.twoeightnine.root.xvii.R
import com.twoeightnine.root.xvii.base.BaseActivity
import com.twoeightnine.root.xvii.base.FragmentPlacementActivity.Companion.startFragment
import com.twoeightnine.root.xvii.chatowner.ChatOwnerFactory
import com.twoeightnine.root.xvii.chats.attachments.base.BaseAttachmentsFragment
import com.twoeightnine.root.xvii.chats.messages.chat.usual.ChatActivity
import com.twoeightnine.root.xvii.dialogs.fragments.DialogsForwardFragment
import com.twoeightnine.root.xvii.dialogs.fragments.DialogsFragment
Expand Down Expand Up @@ -75,7 +77,10 @@ class MainActivity : BaseActivity() {
StatTool.get()?.incLaunch()

ivSearch.setOnClickListener {
startFragment<SearchFragment>()
var arguments = Bundle().apply {
putBoolean(SELECTED_FRIENDS, bottomNavView.selectedItemId==R.id.menu_friends)
}
startFragment<SearchFragment>(arguments)
}
ivSearch.paint(Munch.color.color)
ivSearch.applyTopInsetMargin()
Expand All @@ -88,6 +93,17 @@ class MainActivity : BaseActivity() {
}
insets
}

intent.extras?.let{
it.getString(SEARCH_TEXT)?.let{
val search = it;
var arguments = Bundle().apply {
putBoolean(SELECTED_FRIENDS, bottomNavView.selectedItemId==R.id.menu_friends)
putString(SEARCH_TEXT, search)
}
startFragment<SearchFragment>(arguments)
}
}
}

override fun onResume() {
Expand Down Expand Up @@ -135,8 +151,17 @@ class MainActivity : BaseActivity() {

companion object {

fun launch(context: Context?) {
launchActivity(context, MainActivity::class.java)
const val SEARCH_TEXT = "searchText"
const val SELECTED_FRIENDS = "selectedFriends"

fun launch(context: Context?, search:String?= null) {
if(search==null) {
launchActivity(context, MainActivity::class.java)
}else{
context?.startActivity(Intent(context, MainActivity::class.java).apply {
putExtra(MainActivity.SEARCH_TEXT, search)
})
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ data class Message(
@Expose
val attachments: ArrayList<Attachment>? = arrayListOf(),

@SerializedName("conversation_message_id")
@Expose
val conversationMessageId: Int = 0,

@SerializedName("reply_message")
@Expose
var replyMessage: Message? = null,
Expand Down Expand Up @@ -108,6 +112,7 @@ data class Message(
constructor(event: BaseMessageEvent, prepareText: (String) -> String = { it }) : this(
id = event.id,
peerId = event.peerId,
//conversationMessageId = event.peerId,
date = event.timeStamp,
fromId = event.info.from,
text = prepareText(event.text),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ interface ApiService {
@Query("start_from") startFrom: String?
): Flowable<BaseResponse<AttachmentsResponse>>

@GET("messages.search?extended=1")
fun search(
@Query("q") q: String,
@Query("count") count: Int,
@Query("offset") offset: Int,
@Query("fields") fields: String = User.FIELDS
): Flowable<BaseResponse<SearchResponse>>

@GET("messages.searchConversations?extended=1")
fun searchConversations(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* xvii - messenger for vk
* Copyright (C) 2021 TwoEightNine
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.twoeightnine.root.xvii.network.response

import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
import com.twoeightnine.root.xvii.model.Conversation
import com.twoeightnine.root.xvii.model.Group
import com.twoeightnine.root.xvii.model.User
import com.twoeightnine.root.xvii.model.messages.Message
import com.twoeightnine.root.xvii.utils.matchesChatId
import com.twoeightnine.root.xvii.utils.matchesGroupId
import com.twoeightnine.root.xvii.utils.matchesUserId

data class SearchResponse(

@SerializedName("items")
@Expose
val items: ArrayList<Message> = arrayListOf(),

@SerializedName("profiles")
@Expose
val profiles: ArrayList<User>,

@SerializedName("groups")
@Expose
val groups: ArrayList<Group>,

@SerializedName("conversations")
@Expose
val conversations: ArrayList<Conversation>
) {
fun getProfileById(id: Int) = profiles.find { it.id == id }

fun getGroupById(id: Int) = groups.find { it.id == id }

fun getConversationById(id: Int) = conversations.find { it.peer?.id == id }

fun getTitleFor(message: Message) = when {
message.peerId.matchesUserId() -> getProfileById(message.peerId)?.fullName
message.peerId.matchesGroupId() -> getGroupById(-message.peerId)?.name
message.peerId.matchesChatId() -> getConversationById(message.peerId)?.chatSettings?.title
else -> null
}

fun getPhotoFor(message: Message) = when {
message.peerId.matchesUserId() -> getProfileById(message.peerId)?.photo100
message.peerId.matchesGroupId() -> getGroupById(-message.peerId)?.photo100
message.peerId.matchesChatId() -> getConversationById(message.peerId)?.chatSettings?.photo?.photo100
else -> null
}


fun isOnline(message: Message): Boolean {
return when {
message.peerId.matchesUserId() -> getProfileById(message.fromId)?.isOnline == true
else -> false
}
}
}
Loading