Fix #703 and other improvements

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2020-01-14 16:35:54 +01:00
parent 7cf1cf6025
commit b1dcada075
No known key found for this signature in database
GPG Key ID: CDE0BBD2738C4CC0
19 changed files with 223 additions and 157 deletions

View File

@ -159,8 +159,8 @@ ext {
lifecycle_version = '2.2.0-rc03' lifecycle_version = '2.2.0-rc03'
coil_version = "0.9.1" coil_version = "0.9.1"
room_version = "2.2.3" room_version = "2.2.3"
geckoviewChannel = "stable" geckoviewChannel = "nightly"
geckoviewVersion = "72.0.20200107212822" geckoviewVersion = "71.0.20200108003105"
} }
configurations.all { configurations.all {

View File

@ -2,7 +2,7 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 1, "version": 1,
"identityHash": "2c4f372b48cd11e679b04c6d577f1cd8", "identityHash": "40ddfb9547f62f10e95450e4a5495115",
"entities": [ "entities": [
{ {
"tableName": "conversations", "tableName": "conversations",
@ -307,7 +307,7 @@
}, },
{ {
"tableName": "users", "tableName": "users",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `user_id` TEXT NOT NULL, `username` TEXT NOT NULL, `base_url` TEXT NOT NULL, `token` TEXT, `display_name` TEXT, `push_configuration` TEXT, `capabilities` TEXT, `client_auth_cert` TEXT, `external_signaling` TEXT, `status` INTEGER)", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `user_id` TEXT NOT NULL, `username` TEXT NOT NULL, `base_url` TEXT NOT NULL, `token` TEXT, `display_name` TEXT, `push_configuration` TEXT, `capabilities` TEXT, `client_auth_cert` TEXT, `signaling_settings` TEXT, `status` INTEGER)",
"fields": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
@ -364,8 +364,8 @@
"notNull": false "notNull": false
}, },
{ {
"fieldPath": "externalSignaling", "fieldPath": "signalingSettings",
"columnName": "external_signaling", "columnName": "signaling_settings",
"affinity": "TEXT", "affinity": "TEXT",
"notNull": false "notNull": false
}, },
@ -389,7 +389,7 @@
"views": [], "views": [],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2c4f372b48cd11e679b04c6d577f1cd8')" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '40ddfb9547f62f10e95450e4a5495115')"
] ]
} }
} }

View File

@ -83,10 +83,6 @@ class MagicIncomingTextMessageViewHolder(incomingView: View) : MessageHolders
@BindView(R.id.quotedMessage) @BindView(R.id.quotedMessage)
var quotedMessage: EmojiTextView? = null var quotedMessage: EmojiTextView? = null
@JvmField
@BindView(R.id.quotedMessageTime)
var quotedMessageTime: TextView? = null
@JvmField @JvmField
@BindView(R.id.quoteColoredView) @BindView(R.id.quoteColoredView)
var quoteColoredView: View? = null var quoteColoredView: View? = null
@ -227,8 +223,6 @@ class MagicIncomingTextMessageViewHolder(incomingView: View) : MessageHolders
quotedUserName?.setTextColor(context.resources.getColor(R.color.colorPrimary)) quotedUserName?.setTextColor(context.resources.getColor(R.color.colorPrimary))
quotedMessageTime?.text = DateFormatter.format(parentChatMessage.createdAt, DateFormatter.Template.TIME)
quotedMessageTime?.setTextColor(context.resources.getColor(R.color.warm_grey_four))
quoteColoredView?.setBackgroundResource(R.color.colorPrimary) quoteColoredView?.setBackgroundResource(R.color.colorPrimary)
quotedChatMessageView?.visibility = View.VISIBLE quotedChatMessageView?.visibility = View.VISIBLE
} ?: run { } ?: run {

View File

@ -70,10 +70,6 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
@BindView(R.id.quotedMessage) @BindView(R.id.quotedMessage)
var quotedMessage: EmojiTextView? = null var quotedMessage: EmojiTextView? = null
@JvmField
@BindView(R.id.quotedMessageTime)
var quotedMessageTime: TextView? = null
@JvmField @JvmField
@BindView(R.id.quoteColoredView) @BindView(R.id.quoteColoredView)
var quoteColoredView: View? = null var quoteColoredView: View? = null
@ -152,8 +148,6 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
quotedMessage?.setTextColor(context.resources.getColor(R.color.nc_outcoming_text_default)) quotedMessage?.setTextColor(context.resources.getColor(R.color.nc_outcoming_text_default))
quotedUserName?.setTextColor(context.resources.getColor(R.color.nc_grey)) quotedUserName?.setTextColor(context.resources.getColor(R.color.nc_grey))
quotedMessageTime?.text = DateFormatter.format(parentChatMessage.createdAt, DateFormatter.Template.TIME)
quotedMessageTime?.setTextColor(context.resources.getColor(R.color.white60))
quoteColoredView?.setBackgroundResource(R.color.white) quoteColoredView?.setBackgroundResource(R.color.white)
quotedChatMessageView?.visibility = View.VISIBLE quotedChatMessageView?.visibility = View.VISIBLE

View File

@ -29,10 +29,7 @@ import androidx.emoji.bundled.BundledEmojiCompatConfig
import androidx.emoji.text.EmojiCompat import androidx.emoji.text.EmojiCompat
import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.LifecycleObserver
import androidx.multidex.MultiDex import androidx.multidex.MultiDex
import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.*
import androidx.work.OneTimeWorkRequest
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkManager
import coil.Coil import coil.Coil
import coil.ImageLoader import coil.ImageLoader
import com.bluelinelabs.logansquare.LoganSquare import com.bluelinelabs.logansquare.LoganSquare
@ -46,7 +43,9 @@ import com.nextcloud.talk.models.ExternalSignalingServer
import com.nextcloud.talk.models.database.UserEntity import com.nextcloud.talk.models.database.UserEntity
import com.nextcloud.talk.models.json.capabilities.Capabilities import com.nextcloud.talk.models.json.capabilities.Capabilities
import com.nextcloud.talk.models.json.push.PushConfigurationState import com.nextcloud.talk.models.json.push.PushConfigurationState
import com.nextcloud.talk.models.json.signaling.settings.SignalingSettings
import com.nextcloud.talk.newarch.di.module.* import com.nextcloud.talk.newarch.di.module.*
import com.nextcloud.talk.newarch.domain.di.module.UseCasesModule
import com.nextcloud.talk.newarch.features.account.di.module.AccountModule import com.nextcloud.talk.newarch.features.account.di.module.AccountModule
import com.nextcloud.talk.newarch.features.conversationslist.di.module.ConversationsListModule import com.nextcloud.talk.newarch.features.conversationslist.di.module.ConversationsListModule
import com.nextcloud.talk.newarch.local.dao.UsersDao import com.nextcloud.talk.newarch.local.dao.UsersDao
@ -72,13 +71,14 @@ import org.koin.android.ext.android.inject
import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.startKoin import org.koin.core.context.startKoin
import org.mozilla.geckoview.GeckoRuntime
import org.webrtc.PeerConnectionFactory import org.webrtc.PeerConnectionFactory
import org.webrtc.voiceengine.WebRtcAudioManager import org.webrtc.voiceengine.WebRtcAudioManager
import org.webrtc.voiceengine.WebRtcAudioUtils import org.webrtc.voiceengine.WebRtcAudioUtils
import java.security.Security import java.security.Security
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class NextcloudTalkApplication : Application(), LifecycleObserver { class NextcloudTalkApplication : Application(), LifecycleObserver, Configuration.Provider {
//region Getters //region Getters
val userUtils: UserUtils by inject() val userUtils: UserUtils by inject()
@ -181,7 +181,7 @@ class NextcloudTalkApplication : Application(), LifecycleObserver {
startKoin { startKoin {
androidContext(this@NextcloudTalkApplication) androidContext(this@NextcloudTalkApplication)
androidLogger() androidLogger()
modules(listOf(CommunicationModule, StorageModule, NetworkModule, ConversationsListModule, ServiceModule, AccountModule, ServerModule)) modules(listOf(CommunicationModule, StorageModule, NetworkModule, ConversationsListModule, ServiceModule, AccountModule, UseCasesModule))
} }
} }
@ -211,8 +211,11 @@ class NextcloudTalkApplication : Application(), LifecycleObserver {
} }
userNg.clientCertificate = user.clientCertificate userNg.clientCertificate = user.clientCertificate
try { try {
userNg.externalSignaling = val external = LoganSquare.parse(user.externalSignalingServer, ExternalSignalingServer::class.java)
LoganSquare.parse(user.externalSignalingServer, ExternalSignalingServer::class.java) val signalingSettings = SignalingSettings()
signalingSettings.externalSignalingServer = external.externalSignalingServer
signalingSettings.externalSignalingTicket = external.externalSignalingTicket
userNg.signalingSettings = signalingSettings
} catch (e: Exception) { } catch (e: Exception) {
// no external signaling // no external signaling
} }
@ -259,5 +262,9 @@ class NextcloudTalkApplication : Application(), LifecycleObserver {
} }
} }
} }
override fun getWorkManagerConfiguration(): Configuration {
return Configuration.Builder().build()
}
//endregion //endregion
} }

View File

@ -1408,7 +1408,6 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.maxLines = 2 messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.maxLines = 2
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.ellipsize = TextUtils.TruncateAt.END messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.ellipsize = TextUtils.TruncateAt.END
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.text = it.text messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.text = it.text
messageInputView?.findViewById<TextView>(R.id.quotedMessageTime)?.text = DateFormatter.format(it.createdAt, DateFormatter.Template.TIME)
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessageAuthor)?.text = it.actorDisplayName messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessageAuthor)?.text = it.actorDisplayName
?: context.getText(R.string.nc_nick_guest) ?: context.getText(R.string.nc_nick_guest)

View File

@ -593,18 +593,7 @@ class SettingsController : BaseController() {
) )
.subscribe({ userProfileOverall -> .subscribe({ userProfileOverall ->
var displayName: String? = null var displayName: String? = userProfileOverall.ocs.data.displayName
if (!TextUtils.isEmpty(
userProfileOverall.ocs.data.displayName
)
) {
displayName = userProfileOverall.ocs.data.displayName
} else if (!TextUtils.isEmpty(
userProfileOverall.ocs.data.displayName
)
) {
displayName = userProfileOverall.ocs.data.displayNameAlt
}
if (!TextUtils.isEmpty(displayName) && displayName != currentUser!!.displayName) { if (!TextUtils.isEmpty(displayName) && displayName != currentUser!!.displayName) {
val user = usersRepository.getUserWithId(currentUser!!.id!!) val user = usersRepository.getUserWithId(currentUser!!.id!!)

View File

@ -71,7 +71,7 @@ class SignalingSettingsWorker(context: Context, workerParams: WorkerParameters)
externalSignalingServer.externalSignalingServer = signalingSettingsOverall.ocs.signalingSettings.externalSignalingServer externalSignalingServer.externalSignalingServer = signalingSettingsOverall.ocs.signalingSettings.externalSignalingServer
externalSignalingServer.externalSignalingTicket = signalingSettingsOverall.ocs.signalingSettings.externalSignalingTicket externalSignalingServer.externalSignalingTicket = signalingSettingsOverall.ocs.signalingSettings.externalSignalingTicket
val user = usersRepository.getUserWithId(userEntity.id!!) val user = usersRepository.getUserWithId(userEntity.id!!)
user.externalSignaling = externalSignalingServer //user.externalSignaling = externalSignalingServer
runBlocking { runBlocking {
val result = usersRepository.updateUser(user) val result = usersRepository.updateUser(user)
eventBus.post(EventStatus(user.id!!, eventBus.post(EventStatus(user.id!!,

View File

@ -41,7 +41,7 @@ class WebsocketConnectionsWorker(
var userEntity: UserNgEntity var userEntity: UserNgEntity
for (i in userEntityList.indices) { for (i in userEntityList.indices) {
userEntity = userEntityList[i] userEntity = userEntityList[i]
if (userEntity.externalSignaling != null) { /*if (userEntity.externalSignaling != null) {
if (!userEntity.externalSignaling!!.externalSignalingServer.isNullOrEmpty() && if (!userEntity.externalSignaling!!.externalSignalingServer.isNullOrEmpty() &&
!userEntity.externalSignaling!!.externalSignalingTicket.isNullOrEmpty()) { !userEntity.externalSignaling!!.externalSignalingTicket.isNullOrEmpty()) {
WebSocketConnectionHelper.getExternalSignalingInstanceForServer( WebSocketConnectionHelper.getExternalSignalingInstanceForServer(
@ -50,8 +50,7 @@ class WebsocketConnectionsWorker(
false false
) )
} }
}*/
}
} }
return Result.success() return Result.success()

View File

@ -57,6 +57,7 @@ import okhttp3.logging.HttpLoggingInterceptor.Logger
import org.koin.android.ext.koin.androidApplication import org.koin.android.ext.koin.androidApplication
import org.koin.android.ext.koin.androidContext import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module import org.koin.dsl.module
import org.mozilla.geckoview.GeckoRuntime
import retrofit2.Retrofit import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import java.io.IOException import java.io.IOException
@ -72,6 +73,7 @@ import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509KeyManager import javax.net.ssl.X509KeyManager
val NetworkModule = module { val NetworkModule = module {
single { createGeckoRuntime(androidContext()) }
single { createService(get()) } single { createService(get()) }
single { createLegacyNcApi(get()) } single { createLegacyNcApi(get()) }
single { createRetrofit(get()) } single { createRetrofit(get()) }
@ -89,6 +91,10 @@ val NetworkModule = module {
} }
fun createGeckoRuntime(context: Context): GeckoRuntime {
return GeckoRuntime.create(context)
}
fun createCookieManager(): CookieManager { fun createCookieManager(): CookieManager {
val cookieManager = CookieManager() val cookieManager = CookieManager()
cookieManager.setCookiePolicy(ACCEPT_ALL) cookieManager.setCookiePolicy(ACCEPT_ALL)

View File

@ -1,24 +0,0 @@
package com.nextcloud.talk.newarch.di.module
import com.nextcloud.talk.newarch.data.source.remote.ApiErrorHandler
import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkRepository
import com.nextcloud.talk.newarch.domain.usecases.GetCapabilitiesUseCase
import com.nextcloud.talk.newarch.domain.usecases.GetSignalingSettingsUseCase
import org.koin.dsl.module
val ServerModule = module {
single { createGetCapabilitiesUseCase(get(), get()) }
single { createGetSignalingSettingsUseCase(get(), get()) }
}
fun createGetCapabilitiesUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler
): GetCapabilitiesUseCase {
return GetCapabilitiesUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createGetSignalingSettingsUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler
): GetSignalingSettingsUseCase {
return GetSignalingSettingsUseCase(nextcloudTalkRepository, apiErrorHandler)
}

View File

@ -0,0 +1,118 @@
/*
*
* * 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.domain.di.module
import android.app.Application
import com.nextcloud.talk.newarch.data.source.remote.ApiErrorHandler
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
import com.nextcloud.talk.newarch.domain.repository.offline.MessagesRepository
import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkRepository
import com.nextcloud.talk.newarch.domain.usecases.*
import com.nextcloud.talk.newarch.features.chat.ChatViewModelFactory
import com.nextcloud.talk.newarch.services.GlobalService
import org.koin.dsl.module
val UseCasesModule = module {
single { createGetConversationUseCase(get(), get()) }
single { createGetConversationsUseCase(get(), get()) }
single { createSetConversationFavoriteValueUseCase(get(), get()) }
single { createLeaveConversationUseCase(get(), get()) }
single { createDeleteConversationUseCase(get(), get()) }
single { createJoinConversationUseCase(get(), get()) }
single { createExitConversationUseCase(get(), get()) }
single { createGetProfileUseCase(get(), get()) }
single { createGetSignalingUseCase(get(), get()) }
single { createGetCapabilitiesUseCase(get(), get()) }
factory { createChatViewModelFactory(get(), get(), get(), get(), get(), get()) }
}
fun createGetCapabilitiesUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler
): GetCapabilitiesUseCase {
return GetCapabilitiesUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createGetSignalingSettingsUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler
): GetSignalingSettingsUseCase {
return GetSignalingSettingsUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createGetSignalingUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler
): GetSignalingSettingsUseCase {
return GetSignalingSettingsUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createGetProfileUseCase(nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler
): GetProfileUseCase {
return GetProfileUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createSetConversationFavoriteValueUseCase(
nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler
): SetConversationFavoriteValueUseCase {
return SetConversationFavoriteValueUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createGetConversationUseCase(
nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler
): GetConversationUseCase {
return GetConversationUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createGetConversationsUseCase(
nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler
): GetConversationsUseCase {
return GetConversationsUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createLeaveConversationUseCase(
nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler
): LeaveConversationUseCase {
return LeaveConversationUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createDeleteConversationUseCase(
nextcloudTalkRepository: NextcloudTalkRepository,
apiErrorHandler: ApiErrorHandler
): DeleteConversationUseCase {
return DeleteConversationUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createJoinConversationUseCase(nextcloudTalkRepository: NextcloudTalkRepository, apiErrorHandler: ApiErrorHandler): JoinConversationUseCase {
return JoinConversationUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createExitConversationUseCase(nextcloudTalkRepository: NextcloudTalkRepository, apiErrorHandler: ApiErrorHandler): ExitConversationUseCase {
return ExitConversationUseCase(nextcloudTalkRepository, apiErrorHandler)
}
fun createChatViewModelFactory(application: Application, joinConversationUseCase: JoinConversationUseCase, exitConversationUseCase: ExitConversationUseCase, conversationsRepository: ConversationsRepository, messagesRepository: MessagesRepository, globalService: GlobalService): ChatViewModelFactory {
return ChatViewModelFactory(application, joinConversationUseCase, exitConversationUseCase, conversationsRepository, messagesRepository, globalService)
}

View File

@ -4,8 +4,10 @@ import android.app.Application
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
import com.nextcloud.talk.newarch.domain.usecases.GetCapabilitiesUseCase import com.nextcloud.talk.newarch.domain.usecases.GetCapabilitiesUseCase
import com.nextcloud.talk.newarch.domain.usecases.GetProfileUseCase import com.nextcloud.talk.newarch.domain.usecases.GetProfileUseCase
import com.nextcloud.talk.newarch.domain.usecases.GetSignalingSettingsUseCase
import com.nextcloud.talk.newarch.features.account.loginentry.LoginEntryViewModelFactory import com.nextcloud.talk.newarch.features.account.loginentry.LoginEntryViewModelFactory
import com.nextcloud.talk.newarch.features.account.serverentry.ServerEntryViewModelFactory import com.nextcloud.talk.newarch.features.account.serverentry.ServerEntryViewModelFactory
import com.nextcloud.talk.utils.preferences.AppPreferences
import org.koin.android.ext.koin.androidApplication import org.koin.android.ext.koin.androidApplication
import org.koin.dsl.module import org.koin.dsl.module
@ -16,7 +18,7 @@ val AccountModule = module {
) )
} }
factory { factory {
createLoginEntryViewModelFactory(androidApplication(), get(), get(), get()) createLoginEntryViewModelFactory(androidApplication(), get(), get(), get(), get(), get() )
} }
} }
@ -33,9 +35,11 @@ fun createLoginEntryViewModelFactory(
application: Application, application: Application,
getProfileUseCase: GetProfileUseCase, getProfileUseCase: GetProfileUseCase,
getCapabilitiesUseCase: GetCapabilitiesUseCase, getCapabilitiesUseCase: GetCapabilitiesUseCase,
getSignalingSettingsUseCase: GetSignalingSettingsUseCase,
appPreferences: AppPreferences,
usersRepository: UsersRepository usersRepository: UsersRepository
): LoginEntryViewModelFactory { ): LoginEntryViewModelFactory {
return LoginEntryViewModelFactory( return LoginEntryViewModelFactory(
application, getProfileUseCase, getCapabilitiesUseCase, usersRepository application, getProfileUseCase, getCapabilitiesUseCase, getSignalingSettingsUseCase, appPreferences, usersRepository
) )
} }

View File

@ -29,11 +29,13 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseView import com.nextcloud.talk.newarch.conversationsList.mvp.BaseView
import com.nextcloud.talk.newarch.features.conversationslist.ConversationsListView
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import kotlinx.android.synthetic.main.login_entry_view.view.* import kotlinx.android.synthetic.main.login_entry_view.view.*
import kotlinx.android.synthetic.main.login_web_view.view.*
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import org.mozilla.geckoview.* import org.mozilla.geckoview.*
import org.mozilla.geckoview.GeckoSessionSettings.USER_AGENT_MODE_MOBILE import org.mozilla.geckoview.GeckoSessionSettings.USER_AGENT_MODE_MOBILE
@ -48,6 +50,7 @@ class LoginEntryView(val bundle: Bundle) : BaseView() {
private lateinit var geckoView: GeckoView private lateinit var geckoView: GeckoView
private lateinit var geckoSession: GeckoSession private lateinit var geckoSession: GeckoSession
private val geckoRuntime: GeckoRuntime by inject()
private val assembledPrefix = resources?.getString(R.string.nc_talk_login_scheme) + protocolSuffix + "login/" private val assembledPrefix = resources?.getString(R.string.nc_talk_login_scheme) + protocolSuffix + "login/"
@ -67,7 +70,32 @@ class LoginEntryView(val bundle: Bundle) : BaseView() {
viewModel = viewModelProvider(factory).get(LoginEntryViewModel::class.java) viewModel = viewModelProvider(factory).get(LoginEntryViewModel::class.java)
val view = super.onCreateView(inflater, container) val view = super.onCreateView(inflater, container)
geckoView = view.stubImport.inflate() as GeckoView viewModel.state.observe(this@LoginEntryView, Observer {
when (it.state) {
LoginEntryState.FAILED -> {
router.popController(this)
}
LoginEntryState.PENDING_CHECK -> {
// everything is already setup in XML
}
LoginEntryState.CHECKING -> {
view.progressBar.isVisible = true
geckoView.isVisible = false
}
else -> {
if (router?.hasRootController() == true) {
router.popController(this)
} else {
router.setRoot(RouterTransaction.with(ConversationsListView())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
}
// all good, proceed
}
}
})
geckoView = view.geckoView
activity?.let { activity?.let {
val settings = GeckoSessionSettings.Builder() val settings = GeckoSessionSettings.Builder()
//.usePrivateMode(true) //.usePrivateMode(true)
@ -79,8 +107,7 @@ class LoginEntryView(val bundle: Bundle) : BaseView() {
geckoView.autofillEnabled = true geckoView.autofillEnabled = true
geckoSession = GeckoSession(settings.build()) geckoSession = GeckoSession(settings.build())
val runtime = GeckoRuntime.create(it) geckoSession.open(geckoRuntime)
geckoSession.open(runtime)
geckoSession.progressDelegate = createProgressDelegate() geckoSession.progressDelegate = createProgressDelegate()
geckoSession.navigationDelegate = createNavigationDelegate() geckoSession.navigationDelegate = createNavigationDelegate()
geckoView.setSession(geckoSession) geckoView.setSession(geckoSession)
@ -89,20 +116,6 @@ class LoginEntryView(val bundle: Bundle) : BaseView() {
} }
} }
viewModel.state.observe(this@LoginEntryView, Observer {
if (it.state == LoginEntryState.FAILED) {
router.popController(this)
} else if (it.state == LoginEntryState.PENDING_CHECK) {
view.progressBar.isVisible = false
view.geckoView.isVisible = true
} else if (it.state == LoginEntryState.CHECKING) {
view.progressBar.isVisible = true
view.geckoView.isVisible = false
} else {
// all good, proceed
}
})
return view return view
} }
@ -110,20 +123,17 @@ class LoginEntryView(val bundle: Bundle) : BaseView() {
return object : GeckoSession.NavigationDelegate { return object : GeckoSession.NavigationDelegate {
override fun onLoadRequest(p0: GeckoSession, p1: GeckoSession.NavigationDelegate.LoadRequest): GeckoResult<AllowOrDeny>? { override fun onLoadRequest(p0: GeckoSession, p1: GeckoSession.NavigationDelegate.LoadRequest): GeckoResult<AllowOrDeny>? {
if (p1.uri.startsWith(assembledPrefix)) { if (p1.uri.startsWith(assembledPrefix)) {
viewModel.parseData(assembledPrefix, dataSeparator, p1.uri)
return GeckoResult.DENY return GeckoResult.DENY
} }
return super.onLoadRequest(p0, p1) return super.onLoadRequest(p0, p1)
} }
override fun onLocationChange(p0: GeckoSession, p1: String?) {
super.onLocationChange(p0, p1)
viewModel.parseData(assembledPrefix, dataSeparator, p1)
}
} }
} }
private fun createProgressDelegate(): GeckoSession.ProgressDelegate { private fun createProgressDelegate(): GeckoSession.ProgressDelegate {
return object : GeckoSession.ProgressDelegate { return object : GeckoSession.ProgressDelegate {
private var initialLoad = true
override fun onPageStop(session: GeckoSession, success: Boolean) = Unit override fun onPageStop(session: GeckoSession, success: Boolean) = Unit
@ -135,8 +145,16 @@ class LoginEntryView(val bundle: Bundle) : BaseView() {
override fun onPageStart(session: GeckoSession, url: String) = Unit override fun onPageStart(session: GeckoSession, url: String) = Unit
override fun onProgressChange(session: GeckoSession, progress: Int) { override fun onProgressChange(session: GeckoSession, progress: Int) {
view?.pageProgressBar?.progress = progress if (initialLoad) {
view?.pageProgressBar?.isVisible = progress in 1..99 view?.pageProgressBar?.progress = progress
view?.pageProgressBar?.isVisible = progress in 1..99
}
if (progress == 100) {
initialLoad = false
view?.pageProgressBar?.isVisible = false
view?.geckoView?.isVisible = true
}
} }
} }
} }

View File

@ -148,13 +148,13 @@ class LoginEntryViewModel constructor(
private fun registerForPush() { private fun registerForPush() {
val token = appPreferences.pushToken val token = appPreferences.pushToken
if (!token.isNullOrBlank()) { if (!token.isNullOrBlank()) {
registerForPushWithServer(token)
} else { } else {
state.postValue(LoginEntryStateWrapper(LoginEntryState.OK, LoginEntryStateClarification.PUSH_REGISTRATION_MISSING_TOKEN)) state.postValue(LoginEntryStateWrapper(LoginEntryState.OK, LoginEntryStateClarification.PUSH_REGISTRATION_MISSING_TOKEN))
} }
} }
private fun registerForPushWithServer() { private fun registerForPushWithServer(token: String) {
} }

View File

@ -7,9 +7,10 @@ import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
import com.nextcloud.talk.newarch.domain.usecases.GetCapabilitiesUseCase import com.nextcloud.talk.newarch.domain.usecases.GetCapabilitiesUseCase
import com.nextcloud.talk.newarch.domain.usecases.GetProfileUseCase import com.nextcloud.talk.newarch.domain.usecases.GetProfileUseCase
import com.nextcloud.talk.newarch.domain.usecases.GetSignalingSettingsUseCase import com.nextcloud.talk.newarch.domain.usecases.GetSignalingSettingsUseCase
import com.nextcloud.talk.utils.preferences.AppPreferences
class LoginEntryViewModelFactory constructor(private val application: Application, private val getProfileUseCase: GetProfileUseCase, private val getCapabilitiesUseCase: GetCapabilitiesUseCase, private val getSignalingSettingsUseCase: GetSignalingSettingsUseCase, private val usersRepository: UsersRepository) : ViewModelProvider.Factory { class LoginEntryViewModelFactory constructor(private val application: Application, private val getProfileUseCase: GetProfileUseCase, private val getCapabilitiesUseCase: GetCapabilitiesUseCase, private val getSignalingSettingsUseCase: GetSignalingSettingsUseCase, private val appPreferences: AppPreferences, private val usersRepository: UsersRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T { override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return LoginEntryViewModel(application, getProfileUseCase, getCapabilitiesUseCase, getSignalingSettingsUseCase, usersRepository) as T return LoginEntryViewModel(application, getProfileUseCase, getCapabilitiesUseCase, getSignalingSettingsUseCase, appPreferences, usersRepository) as T
} }
} }

View File

@ -64,16 +64,6 @@
app:layout_flexGrow="1" app:layout_flexGrow="1"
app:layout_wrapBefore="true" app:layout_wrapBefore="true"
tools:text="Hello, this is me!" /> tools:text="Hello, this is me!" />
<TextView
android:id="@+id/quotedMessageTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textSize="12sp"
app:layout_alignSelf="center"
android:textColor="@color/warm_grey_four"
tools:text="16:08" />
</com.google.android.flexbox.FlexboxLayout> </com.google.android.flexbox.FlexboxLayout>
<ImageButton <ImageButton

View File

@ -2,21 +2,33 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/colorPrimary"> android:background="@color/colorPrimary">
<ViewStub <ProgressBar
android:id="@+id/stubImport" android:id="@+id/pageProgressBar"
android:layout_width="fill_parent" style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:layout_gravity="bottom" android:layout_height="3dp"
android:inflatedId="@+id/webViewImportLayout" android:layout_centerInParent="true"
android:layout="@layout/login_web_view" /> android:layout_marginHorizontal="8dp"
android:background="@color/white"
android:visibility="visible"/>
<org.mozilla.geckoview.GeckoView
android:id="@+id/geckoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
tools:context=".MainActivity"
android:visibility="gone"/>
<ProgressBar <ProgressBar
android:id="@+id/progressBar" android:id="@+id/progressBar"
android:layout_width="@dimen/item_height" android:layout_width="@dimen/item_height"
android:layout_height="@dimen/item_height" android:layout_height="@dimen/item_height"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:visibility="gone"
android:indeterminate="true" android:indeterminate="true"
android:indeterminateTint="@color/white" android:indeterminateTint="@color/white"
android:indeterminateTintMode="src_in" /> android:indeterminateTintMode="src_in" />

View File

@ -1,41 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ /*
~ * 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/>.
~ */
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/pageProgressBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="3dp"
android:background="@color/white"
android:visibility="gone"/>
<org.mozilla.geckoview.GeckoView
android:id="@+id/geckoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"/>
</RelativeLayout>