mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-13 15:54:59 +01:00
Implement empty presenter & Lots of other nice improvements
This commit is contained in:
parent
5a473faba9
commit
c18623de8e
@ -154,9 +154,9 @@ android {
|
||||
}
|
||||
|
||||
ext {
|
||||
work_version = "2.3.0-alpha02"
|
||||
work_version = '2.3.0-beta02'
|
||||
koin_version = "2.1.0-alpha-1"
|
||||
lifecycle_version = "2.2.0-rc01"
|
||||
lifecycle_version = '2.2.0-rc03'
|
||||
coil_version = "0.9.1"
|
||||
room_version = "2.2.3"
|
||||
}
|
||||
@ -257,12 +257,12 @@ dependencies {
|
||||
implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.14.3'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.14.3'
|
||||
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.6.2'
|
||||
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.2'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.7.1'
|
||||
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.7.1'
|
||||
implementation 'com.github.aurae.retrofit2:converter-logansquare:1.4.1'
|
||||
implementation group: 'joda-time', name: 'joda-time', version: '2.10.3'
|
||||
implementation 'com.bluelinelabs:logansquare:1.3.7'
|
||||
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.10.0.pr1'
|
||||
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.10.1'
|
||||
kapt 'com.bluelinelabs:logansquare-compiler:1.3.7'
|
||||
|
||||
compileOnly 'javax.annotation:jsr250-api:1.0'
|
||||
@ -277,8 +277,8 @@ dependencies {
|
||||
annotationProcessor "org.projectlombok:lombok:1.18.10"
|
||||
kapt "org.projectlombok:lombok:1.18.10"
|
||||
|
||||
implementation 'com.jakewharton:butterknife:10.2.0'
|
||||
kapt 'com.jakewharton:butterknife-compiler:10.2.0'
|
||||
implementation 'com.jakewharton:butterknife:10.2.1'
|
||||
kapt 'com.jakewharton:butterknife-compiler:10.2.1'
|
||||
implementation 'com.github.HITGIF:TextFieldBoxes:1.4.5'
|
||||
implementation 'eu.davidea:flexible-adapter:5.1.0'
|
||||
implementation 'eu.davidea:flexible-adapter-ui:1.0.0'
|
||||
@ -315,13 +315,13 @@ dependencies {
|
||||
implementation 'org.parceler:parceler-api:1.1.12'
|
||||
kapt 'org.parceler:parceler:1.1.12'
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation 'junit:junit:4.13'
|
||||
testImplementation 'org.mockito:mockito-core:3.0.0'
|
||||
testImplementation 'org.powermock:powermock-core:2.0.2'
|
||||
testImplementation 'org.powermock:powermock-module-junit4:2.0.2'
|
||||
testImplementation 'org.powermock:powermock-api-mockito2:2.0.2'
|
||||
|
||||
androidTestImplementation('androidx.test.espresso:espresso-core:3.3.0-alpha02', {
|
||||
androidTestImplementation('androidx.test.espresso:espresso-core:3.3.0-alpha03', {
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
})
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'
|
||||
|
@ -39,9 +39,11 @@ import java.util.*
|
||||
@Data
|
||||
@JsonObject(serializeNullCollectionElements = true, serializeNullObjects = true)
|
||||
class Conversation {
|
||||
@JsonIgnore
|
||||
var databaseId: String? = null
|
||||
@JsonIgnore
|
||||
@NonNull
|
||||
var internalUserId: Long? = null
|
||||
var databaseUserId: Long? = null
|
||||
@JsonField(name = ["id"])
|
||||
var conversationId: String? = null
|
||||
@JsonField(name = ["token"])
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
*
|
||||
* * Nextcloud Talk application
|
||||
* *
|
||||
* * @author Mario Danic
|
||||
* * Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
|
||||
* *
|
||||
* * 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.newarch.data.presenters
|
||||
|
||||
import android.content.Context
|
||||
import com.otaliastudios.elements.Element
|
||||
import com.otaliastudios.elements.Page
|
||||
import com.otaliastudios.elements.extensions.EmptyPresenter
|
||||
|
||||
class AdvancedEmptyPresenter(context: Context, layout: Int, private val onViewClick: (() -> Unit)? = null) : EmptyPresenter(context, layout) {
|
||||
override fun onBind(page: Page, holder: Holder, element: Element<Void>, payloads: List<Any>) {
|
||||
super.onBind(page, holder, element, payloads)
|
||||
holder.itemView.setOnClickListener {
|
||||
onViewClick?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.adapters
|
||||
package com.nextcloud.talk.newarch.features.conversationsList
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
*
|
||||
* * Nextcloud Talk application
|
||||
* *
|
||||
* * @author Mario Danic
|
||||
* * Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
|
||||
* *
|
||||
* * 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.newarch.features.conversationsList
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.otaliastudios.elements.Element
|
||||
import com.otaliastudios.elements.Page
|
||||
import com.otaliastudios.elements.Source
|
||||
import com.otaliastudios.elements.extensions.MainSource
|
||||
|
||||
class ConversationsListSource<T: Conversation>(private val data: LiveData<List<T>>, private val elementType: Int = 0, loadingIndicatorsEnabled: Boolean = true, errorIndicatorEnabled: Boolean = true, emptyIndicatorEnabled: Boolean = true) : MainSource<T>(loadingIndicatorsEnabled, errorIndicatorEnabled, emptyIndicatorEnabled) {
|
||||
|
||||
override fun onPageOpened(page: Page, dependencies: List<Element<*>>) {
|
||||
super.onPageOpened(page, dependencies)
|
||||
if (page.previous() == null) {
|
||||
postResult(page, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun dependsOn(source: Source<*>): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(first: T, second: T): Boolean {
|
||||
return first.databaseId == second.databaseId
|
||||
}
|
||||
|
||||
}
|
@ -22,7 +22,6 @@ package com.nextcloud.talk.newarch.features.conversationsList
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.lifecycle.observe
|
||||
import butterknife.OnClick
|
||||
@ -36,13 +35,13 @@ import com.bluelinelabs.conductor.changehandler.TransitionChangeHandlerCompat
|
||||
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.R.drawable
|
||||
import com.nextcloud.talk.adapters.ConversationsPresenter
|
||||
import com.nextcloud.talk.controllers.ContactsController
|
||||
import com.nextcloud.talk.controllers.SettingsController
|
||||
import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage
|
||||
import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseView
|
||||
import com.nextcloud.talk.newarch.data.presenters.AdvancedEmptyPresenter
|
||||
import com.nextcloud.talk.newarch.mvvm.ext.initRecyclerView
|
||||
import com.nextcloud.talk.utils.ConductorRemapping
|
||||
import com.nextcloud.talk.utils.DisplayUtils
|
||||
@ -147,19 +146,19 @@ class ConversationsListView : BaseView() {
|
||||
val view = super.onCreateView(inflater, container)
|
||||
|
||||
val adapter = Adapter.builder(this)
|
||||
.addSource(Source.fromLiveData(viewModel.conversationsLiveData))
|
||||
.addSource(ConversationsListSource(viewModel.conversationsLiveData))
|
||||
.addPresenter(ConversationsPresenter(context, ::onElementClick, ::onElementLongClick))
|
||||
.addPresenter(Presenter.forLoadingIndicator(context, R.layout.loading_state))
|
||||
.addPresenter(Presenter.forEmptyIndicator(context, R.layout.message_state))
|
||||
.addPresenter(AdvancedEmptyPresenter(context, R.layout.message_state, ::openNewConversationScreen))
|
||||
.addPresenter(Presenter.forErrorIndicator(context, R.layout.message_state) { view, throwable ->
|
||||
view.messageStateTextView.setText(R.string.nc_oops)
|
||||
view.messageStateImageView.setImageDrawable(context.getDrawable(drawable.ic_announcement_white_24dp))
|
||||
})
|
||||
.into(view.recyclerView)
|
||||
|
||||
|
||||
view.apply {
|
||||
recyclerView.initRecyclerView(SmoothScrollLinearLayoutManager(activity), adapter, false)
|
||||
|
||||
swipeRefreshLayoutView.setOnRefreshListener {
|
||||
view.swipeRefreshLayoutView.isRefreshing = false
|
||||
viewModel.loadConversations()
|
||||
|
@ -182,7 +182,7 @@ class ConversationsListViewModel constructor(
|
||||
val mutableList = result.toMutableList()
|
||||
val internalUserId = globalService.currentUserLiveData.value!!.id
|
||||
mutableList.forEach {
|
||||
it.internalUserId = internalUserId
|
||||
it.databaseUserId = internalUserId
|
||||
}
|
||||
|
||||
conversationsRepository.saveConversationsForUser(
|
||||
|
@ -42,7 +42,7 @@ class ParticipantMapConverter {
|
||||
return null
|
||||
}
|
||||
|
||||
return LoganSquare.parse(value, HashMap::class.java) as java.util.HashMap<String, Participant>?
|
||||
return LoganSquare.parseMap(value, Participant::class.java) as HashMap<String, Participant>?
|
||||
}
|
||||
|
||||
}
|
@ -118,7 +118,8 @@ data class ConversationEntity(
|
||||
|
||||
fun ConversationEntity.toConversation(): Conversation {
|
||||
val conversation = Conversation()
|
||||
conversation.internalUserId = this.userId
|
||||
conversation.databaseId = this.id
|
||||
conversation.databaseUserId = this.userId
|
||||
conversation.conversationId = this.conversationId
|
||||
conversation.type = this.type
|
||||
conversation.token = this.token
|
||||
@ -148,8 +149,8 @@ fun ConversationEntity.toConversation(): Conversation {
|
||||
}
|
||||
|
||||
fun Conversation.toConversationEntity(): ConversationEntity {
|
||||
val conversationEntity = ConversationEntity(this.internalUserId.toString() + "@" + this.token)
|
||||
conversationEntity.userId = this.internalUserId
|
||||
val conversationEntity = ConversationEntity(this.databaseUserId.toString() + "@" + this.token)
|
||||
conversationEntity.userId = this.databaseUserId
|
||||
conversationEntity.conversationId = this.conversationId
|
||||
conversationEntity.token = this.token
|
||||
conversationEntity.name = this.name
|
||||
|
@ -25,6 +25,7 @@ package com.nextcloud.talk.newarch.services.shortcuts
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.core.app.Person
|
||||
import androidx.core.content.pm.ShortcutInfoCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
@ -38,6 +39,7 @@ import coil.transform.CircleCropTransformation
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.activities.MainActivity
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.models.json.participants.Participant
|
||||
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||
import com.nextcloud.talk.newarch.local.models.getCredentials
|
||||
@ -47,6 +49,7 @@ import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.lang.Exception
|
||||
import kotlin.math.abs
|
||||
|
||||
|
||||
@ -91,6 +94,7 @@ class ShortcutService constructor(private var context: Context,
|
||||
.setAlwaysBadged()
|
||||
.build())
|
||||
|
||||
var iconImage: Drawable? = null
|
||||
for ((index, conversation) in conversations.withIndex()) {
|
||||
val intent = Intent(context, MainActivity::class.java)
|
||||
intent.action = BundleKeys.KEY_OPEN_CONVERSATION
|
||||
@ -99,28 +103,31 @@ class ShortcutService constructor(private var context: Context,
|
||||
|
||||
val persons = mutableListOf<Person>()
|
||||
conversation.participants?.forEach {
|
||||
val hashMap = it.value as HashMap<*, *>
|
||||
val key = it.key
|
||||
val participant = it.value
|
||||
val personBuilder = Person.Builder()
|
||||
personBuilder.setName(hashMap["name"].toString())
|
||||
personBuilder.setName(participant.name.toString())
|
||||
personBuilder.setBot(false)
|
||||
// we need a key for each of the users
|
||||
|
||||
/*val isGuest = hashMap["type"]?.equals(Participant.ParticipantType.GUEST) == true
|
||||
|| hashMap["type"]?.equals(Participant.ParticipantType.GUEST_AS_MODERATOR) == true
|
||||
|| hashMap["type"]?.equals(Participant.ParticipantType.USER_FOLLOWING_LINK) == true
|
||||
val isGuest = participant.type == Participant.ParticipantType.GUEST || participant.type == Participant.ParticipantType.GUEST_AS_MODERATOR || participant.type == Participant.ParticipantType.USER_FOLLOWING_LINK
|
||||
|
||||
val avatarUrl = if (isGuest) ApiUtils.getUrlForAvatarWithNameForGuests(user.baseUrl, hashMap["name"].toString(), R.dimen.avatar_size_big)
|
||||
else ApiUtils.getUrlForAvatarWithName(user.baseUrl, hashMap["userId"].toString(), R.dimen.avatar_size_big)
|
||||
val avatarUrl = if (isGuest) ApiUtils.getUrlForAvatarWithNameForGuests(user.baseUrl, participant.name, R.dimen.avatar_size_big)
|
||||
else ApiUtils.getUrlForAvatarWithName(user.baseUrl, it.key, R.dimen.avatar_size_big)
|
||||
|
||||
iconImage = Coil.get(avatarUrl) {
|
||||
addHeader("Authorization", user.getCredentials())
|
||||
transformations(CircleCropTransformation())
|
||||
try {
|
||||
iconImage = Coil.get(avatarUrl) {
|
||||
addHeader("Authorization", user.getCredentials())
|
||||
transformations(CircleCropTransformation())
|
||||
}
|
||||
personBuilder.setIcon(IconCompat.createWithBitmap((iconImage as BitmapDrawable).bitmap))
|
||||
} catch (e: Exception) {
|
||||
// No icon, that's fine for now
|
||||
}
|
||||
personBuilder.setIcon(IconCompat.createWithBitmap((iconImage as BitmapDrawable).bitmap))*/
|
||||
persons.add(personBuilder.build())
|
||||
}
|
||||
|
||||
var iconImage = images.getImageForConversation(context, conversation)
|
||||
iconImage = images.getImageForConversation(context, conversation)
|
||||
|
||||
if (iconImage == null) {
|
||||
iconImage = Coil.get(ApiUtils.getUrlForAvatarWithName(user.baseUrl, conversation.name, R.dimen.avatar_size_big)) {
|
||||
|
@ -49,8 +49,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"
|
||||
app:layout_anchor="@id/recyclerView"
|
||||
app:layout_anchorGravity="bottom|end"
|
||||
app:backgroundTint="@color/colorPrimary"
|
||||
app:srcCompat="@drawable/ic_add_white_24px"
|
||||
app:tint="@color/white" />
|
||||
|
@ -33,8 +33,7 @@
|
||||
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:icon="@drawable/ic_settings_white_24dp"
|
||||
android:title="@string/nc_settings"
|
||||
android:visible="@bool/value_true"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user