This commit is contained in:
Valere 2019-07-04 10:53:46 +02:00
parent a0bd206308
commit 95d83db90c
18 changed files with 373 additions and 113 deletions

View File

@ -0,0 +1,13 @@
package im.vector.matrix.android.api.session

import androidx.lifecycle.LiveData

interface InitialSyncProgressService {

fun getLiveStatus() : LiveData<Status?>

data class Status(
val statusText: Int?,
val percentProgress: Int = 0
)
}

View File

@ -49,14 +49,15 @@ interface Session :
FilterService,
FileService,
PushRuleService,
PushersService {
PushersService,
InitialSyncProgressService {

/**
* The params associated to the session
*/
val sessionParams: SessionParams

val myUserId : String
val myUserId: String
get() = sessionParams.credentials.userId



View File

@ -0,0 +1,97 @@
package im.vector.matrix.android.internal.session

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import im.vector.matrix.android.api.session.InitialSyncProgressService
import timber.log.Timber
import javax.inject.Inject


@SessionScope
class DefaultInitialSyncProgressService @Inject constructor() : InitialSyncProgressService {

var status = MutableLiveData<InitialSyncProgressService.Status>()

var rootTask: TaskInfo? = null

override fun getLiveStatus(): LiveData<InitialSyncProgressService.Status?> {
return status
}


fun startTask(nameRes: Int, totalProgress: Int, parentWeight: Float = 1f) {
if (rootTask == null) {
rootTask = TaskInfo(nameRes, totalProgress)
} else {
val currentLeaf = rootTask!!.leaf()
val newTask = TaskInfo(nameRes, totalProgress)
newTask.parent = currentLeaf
newTask.offset = currentLeaf.currentProgress
currentLeaf.child = newTask
newTask.parentWeight = parentWeight
}
reportProgress(0)
}

fun reportProgress(progress: Int) {
rootTask?.leaf()?.incrementProgress(progress)
}

fun endTask(nameRes: Int) {
val endedTask = rootTask?.leaf()
if (endedTask?.nameRes == nameRes) {
//close it
val parent = endedTask.parent
parent?.child = null
parent?.incrementProgress(endedTask.offset + (endedTask.totalProgress * endedTask.parentWeight).toInt())
}
if (endedTask?.parent == null) {
this@DefaultInitialSyncProgressService.status.postValue(null)
}
}

fun endAll() {
this@DefaultInitialSyncProgressService.status.postValue(null)
}


inner class TaskInfo(var nameRes: Int,
var totalProgress: Int) {
var parent: TaskInfo? = null
var child: TaskInfo? = null
var parentWeight: Float = 1f
var currentProgress: Int = 0
var offset: Int = 0

fun leaf(): TaskInfo {
var last = this
while (last.child != null) {
last = last.child!!
}
return last
}

fun incrementProgress(progress: Int) {
currentProgress = progress
// val newProgress = Math.min(currentProgress + progress, totalProgress)
parent?.let {
val parentProgress = (currentProgress * parentWeight).toInt()
it.incrementProgress(offset + parentProgress)
}
if (parent == null) {
Timber.e("--- ${leaf().nameRes}: ${currentProgress}")
this@DefaultInitialSyncProgressService.status.postValue(
InitialSyncProgressService.Status(leaf().nameRes, currentProgress)
)
}
}
}

}

public inline fun <T> reportSubtask(reporter: DefaultInitialSyncProgressService?, nameRes: Int, totalProgress: Int, parentWeight: Float = 1f, block: () -> T): T {
reporter?.startTask(nameRes, totalProgress, parentWeight)
return block().also {
reporter?.endTask(nameRes)
}
}

View File

@ -24,6 +24,7 @@ import androidx.work.WorkManager
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.pushrules.PushRuleService
import im.vector.matrix.android.api.session.InitialSyncProgressService
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.cache.CacheService
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
@ -64,7 +65,8 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
private val fileService: FileService,
private val syncThread: SyncThread,
private val contentUrlResolver: ContentUrlResolver,
private val contentUploadProgressTracker: ContentUploadStateTracker)
private val contentUploadProgressTracker: ContentUploadStateTracker,
private val initialSyncProgressService: InitialSyncProgressService)
: Session,
RoomService by roomService,
RoomDirectoryService by roomDirectoryService,
@ -74,9 +76,10 @@ internal class DefaultSession @Inject constructor(override val sessionParams: Se
CacheService by cacheService,
SignOutService by signOutService,
FilterService by filterService,
FileService by fileService,
PushRuleService by pushRuleService,
PushersService by pushersService {
PushersService by pushersService,
FileService by fileService,
InitialSyncProgressService by initialSyncProgressService {

private var isOpen = false


View File

@ -19,6 +19,7 @@ package im.vector.matrix.android.internal.session
import dagger.BindsInstance
import dagger.Component
import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.session.InitialSyncProgressService
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.internal.crypto.CryptoModule
import im.vector.matrix.android.internal.di.MatrixComponent

View File

@ -25,6 +25,7 @@ import dagger.multibindings.IntoSet
import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.session.InitialSyncProgressService
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.internal.database.LiveEntityObserver
import im.vector.matrix.android.internal.database.configureEncryption
@ -132,4 +133,7 @@ internal abstract class SessionModule {
@IntoSet
abstract fun bindUserEntityUpdater(groupSummaryUpdater: UserEntityUpdater): LiveEntityObserver

@Binds
abstract fun bindInitialSyncProgressService(initialSyncProgressService: DefaultInitialSyncProgressService): InitialSyncProgressService

}

View File

@ -26,6 +26,8 @@ import im.vector.matrix.android.internal.crypto.CryptoManager
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
import im.vector.matrix.android.internal.session.SessionScope
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
import im.vector.matrix.android.internal.session.sync.model.ToDeviceSyncResponse
import timber.log.Timber
@ -35,8 +37,10 @@ import javax.inject.Inject
internal class CryptoSyncHandler @Inject constructor(private val cryptoManager: CryptoManager,
private val sasVerificationService: DefaultSasVerificationService) {

fun handleToDevice(toDevice: ToDeviceSyncResponse) {
toDevice.events?.forEach { event ->
fun handleToDevice(toDevice: ToDeviceSyncResponse, initialSyncProgressService: DefaultInitialSyncProgressService? = null) {
val total = toDevice.events?.size ?: 0
toDevice.events?.forEachIndexed { index, event ->
initialSyncProgressService?.reportProgress(((index / total.toFloat()) * 100).toInt())
// Decrypt event if necessary
decryptEvent(event, null)
if (TextUtils.equals(event.getClearType(), EventType.MESSAGE)

View File

@ -17,10 +17,11 @@
package im.vector.matrix.android.internal.session.sync

import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.R
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.internal.database.model.GroupEntity
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.SessionScope
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
import im.vector.matrix.android.internal.session.sync.model.GroupsSyncResponse
import im.vector.matrix.android.internal.session.sync.model.InvitedGroupSync
import io.realm.Realm
@ -34,21 +35,48 @@ internal class GroupSyncHandler @Inject constructor(private val monarchy: Monarc
data class LEFT(val data: Map<String, Any>) : HandlingStrategy()
}

fun handle(roomsSyncResponse: GroupsSyncResponse) {
fun handle(roomsSyncResponse: GroupsSyncResponse, reporter: DefaultInitialSyncProgressService? = null) {
monarchy.runTransactionSync { realm ->
handleGroupSync(realm, GroupSyncHandler.HandlingStrategy.JOINED(roomsSyncResponse.join))
handleGroupSync(realm, GroupSyncHandler.HandlingStrategy.INVITED(roomsSyncResponse.invite))
handleGroupSync(realm, GroupSyncHandler.HandlingStrategy.LEFT(roomsSyncResponse.leave))
handleGroupSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), reporter)
handleGroupSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), reporter)
handleGroupSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave), reporter)
}
}

// PRIVATE METHODS *****************************************************************************

private fun handleGroupSync(realm: Realm, handlingStrategy: HandlingStrategy) {
private fun handleGroupSync(realm: Realm, handlingStrategy: HandlingStrategy, reporter: DefaultInitialSyncProgressService?) {
val groups = when (handlingStrategy) {
is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedGroup(realm, it.key) }
is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedGroup(realm, it.key) }
is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftGroup(realm, it.key) }
is HandlingStrategy.JOINED -> {
val total = handlingStrategy.data.size
reporter?.startTask(R.string.initial_sync_start_importing_account_groups, total, 0.6f)
var current = 0
handlingStrategy.data.map {
reporter?.reportProgress((current / total.toFloat() * 100).toInt())
current++
handleJoinedGroup(realm, it.key)
}
}
is HandlingStrategy.INVITED -> {
val total = handlingStrategy.data.size
reporter?.startTask(R.string.initial_sync_start_importing_account_groups, total, 0.3f)
var current = 0
handlingStrategy.data.map {
reporter?.reportProgress((current / total.toFloat() * 100).toInt())
current++
handleInvitedGroup(realm, it.key)
}
}
is HandlingStrategy.LEFT -> {
val total = handlingStrategy.data.size
reporter?.startTask(R.string.initial_sync_start_importing_account_groups, total, 0.1f)
var current = 0
handlingStrategy.data.map {
reporter?.reportProgress((current / total.toFloat() * 100).toInt())
current++
handleLeftGroup(realm, it.key)
}
}
}
realm.insertOrUpdate(groups)
}

View File

@ -17,6 +17,7 @@
package im.vector.matrix.android.internal.session.sync

import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.R
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toModel
@ -32,6 +33,7 @@ import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.query.find
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
import im.vector.matrix.android.internal.session.notification.DefaultPushRuleService
import im.vector.matrix.android.internal.session.notification.ProcessEventForPushTask
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
@ -60,11 +62,11 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch
data class LEFT(val data: Map<String, RoomSync>) : HandlingStrategy()
}

fun handle(roomsSyncResponse: RoomsSyncResponse) {
fun handle(roomsSyncResponse: RoomsSyncResponse, reporter: DefaultInitialSyncProgressService? = null) {
monarchy.runTransactionSync { realm ->
handleRoomSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join))
handleRoomSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite))
handleRoomSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave))
handleRoomSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), reporter)
handleRoomSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), reporter)
handleRoomSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave), reporter)
}

//handle event for bing rule checks
@ -87,11 +89,37 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch

// PRIVATE METHODS *****************************************************************************

private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy) {
private fun handleRoomSync(realm: Realm, handlingStrategy: HandlingStrategy, reporter: DefaultInitialSyncProgressService?) {

val rooms = when (handlingStrategy) {
is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) }
is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedRoom(realm, it.key, it.value) }
is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(realm, it.key, it.value) }
is HandlingStrategy.JOINED -> {
val total = handlingStrategy.data.size
reporter?.startTask(R.string.initial_sync_start_importing_account_joined_rooms, total, 0.6f)
var current = 0
handlingStrategy.data.map {
reporter?.reportProgress((current / total.toFloat() * 100).toInt())
current++
handleJoinedRoom(realm, it.key, it.value).also {
reporter?.endTask(R.string.initial_sync_start_importing_account_joined_rooms)
}
}

}
is HandlingStrategy.INVITED -> {
val total = handlingStrategy.data.size
reporter?.startTask(R.string.initial_sync_start_importing_account_invited_rooms, total, 0.4f)
var current = 0
handlingStrategy.data.map {
reporter?.reportProgress((current / total.toFloat() * 100).toInt())
current++
handleInvitedRoom(realm, it.key, it.value)
}.also {
reporter?.endTask(R.string.initial_sync_start_importing_account_invited_rooms)
}
}
is HandlingStrategy.LEFT -> {
handlingStrategy.data.map { handleLeftRoom(realm, it.key, it.value) }
}
}
realm.insertOrUpdate(rooms)
}

View File

@ -17,7 +17,10 @@
package im.vector.matrix.android.internal.session.sync

import arrow.core.Try
import im.vector.matrix.android.R
import im.vector.matrix.android.internal.crypto.CryptoManager
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
import im.vector.matrix.android.internal.session.reportSubtask
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
import timber.log.Timber
import javax.inject.Inject
@ -27,12 +30,15 @@ internal class SyncResponseHandler @Inject constructor(private val roomSyncHandl
private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
private val groupSyncHandler: GroupSyncHandler,
private val cryptoSyncHandler: CryptoSyncHandler,
private val cryptoManager: CryptoManager) {
private val cryptoManager: CryptoManager,
private val initialSyncProgressService: DefaultInitialSyncProgressService) {

fun handleResponse(syncResponse: SyncResponse, fromToken: String?, isCatchingUp: Boolean): Try<SyncResponse> {
return Try {
Timber.v("Start handling sync")
val isInitialSync = fromToken == null
Timber.v("Start handling sync, is InitialSync: ${isInitialSync}")
val reporter = initialSyncProgressService.takeIf { isInitialSync }

if (!cryptoManager.isStarted()) {
Timber.v("Should start cryptoManager")
cryptoManager.start(isInitialSync)
@ -41,23 +47,36 @@ internal class SyncResponseHandler @Inject constructor(private val roomSyncHandl
// Handle the to device events before the room ones
// to ensure to decrypt them properly
Timber.v("Handle toDevice")
if (syncResponse.toDevice != null) {
cryptoSyncHandler.handleToDevice(syncResponse.toDevice)
reportSubtask(reporter, R.string.initial_sync_start_importing_account_crypto, 100, 0.2f) {
if (syncResponse.toDevice != null) {
cryptoSyncHandler.handleToDevice(syncResponse.toDevice, reporter)
}
}
Timber.v("Handle rooms")
if (syncResponse.rooms != null) {
roomSyncHandler.handle(syncResponse.rooms)

reportSubtask(reporter, R.string.initial_sync_start_importing_account_rooms, 100, 0.5f) {
if (syncResponse.rooms != null) {
roomSyncHandler.handle(syncResponse.rooms, reporter)
}
}
Timber.v("Handle groups")
if (syncResponse.groups != null) {
groupSyncHandler.handle(syncResponse.groups)

reportSubtask(reporter, R.string.initial_sync_start_importing_account_groups, 100, 0.2f) {
Timber.v("Handle groups")
if (syncResponse.groups != null) {
groupSyncHandler.handle(syncResponse.groups, reporter)
}
}
Timber.v("Handle accoundData")
if (syncResponse.accountData != null) {
userAccountDataSyncHandler.handle(syncResponse.accountData)

reportSubtask(reporter, R.string.initial_sync_start_importing_account_data, 100, 0.1f) {
Timber.v("Handle accoundData")
if (syncResponse.accountData != null) {
userAccountDataSyncHandler.handle(syncResponse.accountData)
}
}

Timber.v("On sync completed")
cryptoSyncHandler.onSyncCompleted(syncResponse)

}
Timber.v("Finish handling sync in $measure ms")
syncResponse

View File

@ -19,14 +19,18 @@ package im.vector.matrix.android.internal.session.sync
import arrow.core.Try
import arrow.core.failure
import arrow.core.recoverWith
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.R
import im.vector.matrix.android.api.auth.data.Credentials
import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.failure.MatrixError
import im.vector.matrix.android.internal.auth.SessionParamsStore
import im.vector.matrix.android.internal.network.executeRequest
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
import im.vector.matrix.android.internal.session.filter.FilterRepository
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
import im.vector.matrix.android.internal.task.Task
import im.vector.matrix.android.internal.util.tryTransactionAsync
import javax.inject.Inject

internal interface SyncTask : Task<SyncTask.Params, Unit> {
@ -40,7 +44,9 @@ internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
private val filterRepository: FilterRepository,
private val syncResponseHandler: SyncResponseHandler,
private val sessionParamsStore: SessionParamsStore,
private val syncTokenStore: SyncTokenStore
private val initialSyncProgressService: DefaultInitialSyncProgressService,
private val syncTokenStore: SyncTokenStore,
private val monarchy: Monarchy
) : SyncTask {


@ -55,6 +61,10 @@ internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
requestParams["timeout"] = timeout.toString()
requestParams["filter"] = filterRepository.getFilter()

val isInitialSync = token == null
if (isInitialSync) {
initialSyncProgressService.startTask(R.string.initial_sync_start_importing_account, 100)
}
return executeRequest<SyncResponse> {
apiCall = syncAPI.sync(requestParams)
}.recoverWith { throwable ->
@ -67,7 +77,13 @@ internal class DefaultSyncTask @Inject constructor(private val syncAPI: SyncAPI,
// Transmit the throwable
throwable.failure()
}.flatMap { syncResponse ->
syncResponseHandler.handleResponse(syncResponse, token, false)
syncResponseHandler.handleResponse(syncResponse, token, false).also {
if (isInitialSync) {
monarchy.tryTransactionAsync {
initialSyncProgressService.endAll()
}
}
}
}.map {
syncTokenStore.saveToken(it.nextBatch)
}

View File

@ -228,4 +228,13 @@
<!-- All translations should be the same across all Riot clients, please use the same translation than RiotWeb -->
<string name="verification_emoji_pin">Pin</string>


<string name="initial_sync_start_importing_account">Initial Sync:\nImporting account…</string>
<string name="initial_sync_start_importing_account_crypto">Initial Sync:\nImporting crypto</string>
<string name="initial_sync_start_importing_account_rooms">Initial Sync:\nImporting Rooms</string>
<string name="initial_sync_start_importing_account_joined_rooms">Initial Sync:\nImporting Joined Rooms</string>
<string name="initial_sync_start_importing_account_invited_rooms">Initial Sync:\nImporting Invited Rooms</string>
<string name="initial_sync_start_importing_account_left_rooms">Initial Sync:\nImporting Left Rooms</string>
<string name="initial_sync_start_importing_account_groups">Initial Sync:\nImporting Communities</string>
<string name="initial_sync_start_importing_account_data">Initial Sync:\nImporting Account Data</string>
</resources>

View File

@ -17,6 +17,7 @@
package im.vector.riotx.features.home

import android.app.ProgressDialog
import android.app.TimePickerDialog
import android.content.Context
import android.content.Intent
import android.os.Bundle
@ -24,6 +25,7 @@ import android.view.MenuItem
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar
import androidx.core.view.GravityCompat
import androidx.core.view.isVisible
import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Observer
@ -45,6 +47,8 @@ import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler
import im.vector.riotx.features.workers.signout.SignOutViewModel
import im.vector.riotx.push.fcm.FcmHelper
import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.android.synthetic.main.merge_overlay_waiting_view.*
import timber.log.Timber
import javax.inject.Inject


@ -114,6 +118,25 @@ class HomeActivity : VectorBaseActivity(), ToolbarConfigurable {
notificationDrawerManager.clearAllEvents()
intent.removeExtra(EXTRA_CLEAR_EXISTING_NOTIFICATION)
}

activeSessionHolder.getSafeActiveSession()?.getLiveStatus()?.observe(this, Observer {
Timber.e("${it?.statusText?.let { getString(it) }} ${it?.percentProgress}")
if (it == null) {
waiting_view.isVisible = false
} else {
waiting_view_status_horizontal_progress.apply {
isIndeterminate = false
max = 100
progress = it.percentProgress
isVisible = true
}
waiting_view_status_text.apply {
text = it.statusText?.let { res -> getString(res) }
isVisible = true
}
waiting_view.isVisible = true
}
})
}

override fun onNewIntent(intent: Intent?) {

View File

@ -30,7 +30,7 @@ import kotlinx.android.synthetic.main.activity_bug_report.*
import timber.log.Timber

/**
* Form to send a bug report
* Form to send a bug reportSubtask
*/
class BugReportActivity : VectorBaseActivity() {

@ -56,7 +56,7 @@ class BugReportActivity : VectorBaseActivity() {

forSuggestion = intent.getBooleanExtra("FOR_SUGGESTION", false)

// Default screen is for bug report, so modify it for suggestion
// Default screen is for bug reportSubtask, so modify it for suggestion
if (forSuggestion) {
supportActionBar?.setTitle(R.string.send_suggestion)

@ -101,7 +101,7 @@ class BugReportActivity : VectorBaseActivity() {


/**
* Send the bug report
* Send the bug reportSubtask
*/
private fun sendBugReport() {
bug_report_scrollview.alpha = 0.3f

View File

@ -68,11 +68,11 @@ class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSes
// the http client
private val mOkHttpClient = OkHttpClient()

// the pending bug report call
// the pending bug reportSubtask call
private var mBugReportCall: Call? = null


// boolean to cancel the bug report
// boolean to cancel the bug reportSubtask
private val mIsCancelled = false

/**
@ -96,16 +96,16 @@ class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSes
private val LOGCAT_CMD_DEBUG = arrayOf("logcat", "-d", "-v", "threadtime", "*:*")

/**
* Bug report upload listener
* Bug reportSubtask upload listener
*/
interface IMXBugReportListener {
/**
* The bug report has been cancelled
* The bug reportSubtask has been cancelled
*/
fun onUploadCancelled()

/**
* The bug report upload failed.
* The bug reportSubtask upload failed.
*
* @param reason the failure reason
*/
@ -119,13 +119,13 @@ class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSes
fun onProgress(progress: Int)

/**
* The bug report upload succeeded.
* The bug reportSubtask upload succeeded.
*/
fun onUploadSucceed()
}

/**
* Send a bug report.
* Send a bug reportSubtask.
*
* @param context the application context
* @param forSuggestion true to send a suggestion
@ -407,7 +407,7 @@ class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSes
override fun onPostExecute(reason: String?) {
mBugReportCall = null

// delete when the bug report has been successfully sent
// delete when the bug reportSubtask has been successfully sent
for (file in mBugReportFiles) {
file.delete()
}
@ -431,7 +431,7 @@ class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSes
}

/**
* Send a bug report either with email or with Vector.
* Send a bug reportSubtask either with email or with Vector.
*/
fun openBugReportScreen(activity: Activity, forSuggestion: Boolean = false) {
screenshot = takeScreenshot(activity)
@ -442,7 +442,7 @@ class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSes
}

//==============================================================================================================
// crash report management
// crash reportSubtask management
//==============================================================================================================

/**
@ -472,7 +472,7 @@ class BugReporter @Inject constructor(private val activeSessionHolder: ActiveSes
}

/**
* Save the crash report
* Save the crash reportSubtask
*
* @param context the context
* @param crashDescription teh crash description

View File

@ -22,66 +22,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar" />

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/waiting_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?vctr_waiting_background_color"
android:visibility="gone"
tools:visibility="visible">

<LinearLayout
android:id="@+id/waiting_view_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/layout_horizontal_margin"
android:background="?attr/colorBackgroundFloating"
android:orientation="vertical"
android:padding="@dimen/layout_horizontal_margin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="@dimen/dialog_width_ratio">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">

<ProgressBar
android:id="@+id/waiting_view_status_circular_progress"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="6dp"
android:layout_marginRight="6dp" />

<TextView
android:id="@+id/waiting_view_status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="?riotx_text_secondary"
android:visibility="gone"
tools:text="Waiting status..."
tools:visibility="visible" />

</LinearLayout>

<ProgressBar
android:id="@+id/waiting_view_status_horizontal_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginTop="10dp"
android:visibility="gone"
tools:max="100"
tools:progress="30"
tools:visibility="visible" />

</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
<include layout="@layout/merge_overlay_waiting_view"/>

</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -15,6 +15,8 @@
android:id="@+id/homeDetailFragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<include layout="@layout/merge_overlay_waiting_view" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>


@ -24,4 +26,5 @@
android:layout_height="match_parent"
android:layout_gravity="start" />


</androidx.drawerlayout.widget.DrawerLayout>

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/waiting_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?vctr_waiting_background_color"
android:visibility="gone"
tools:visibility="visible">

<LinearLayout
android:id="@+id/waiting_view_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/layout_horizontal_margin"
android:background="?attr/colorBackgroundFloating"
android:orientation="vertical"
android:padding="@dimen/layout_horizontal_margin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="@dimen/dialog_width_ratio">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">

<ProgressBar
android:id="@+id/waiting_view_status_circular_progress"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="6dp"
android:layout_marginRight="6dp" />

<TextView
android:id="@+id/waiting_view_status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textColor="?riotx_text_secondary"
android:visibility="gone"
tools:text="Waiting status..."
tools:visibility="visible" />

</LinearLayout>

<ProgressBar
android:id="@+id/waiting_view_status_horizontal_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_marginTop="10dp"
android:visibility="gone"
tools:max="100"
tools:progress="30"
tools:visibility="visible" />

</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

</merge>