Merge pull request #8058 from vector-im/misc/fre/count_up_timer

Improve CountUpTimer ticks precision
This commit is contained in:
Florian Renaud 2023-02-06 12:15:12 +01:00 committed by GitHub
commit fb4cceb476
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
56 changed files with 207 additions and 114 deletions

1
changelog.d/8058.misc Normal file
View file

@ -0,0 +1 @@
Improve the `CountUpTimer` implementation

View file

@ -110,7 +110,7 @@ class VideoViewHolder constructor(itemView: View) :
// Log.v("FOO", "isPlaying $isPlaying $progress/$duration")
eventListener?.get()?.onEvent(AttachmentEvents.VideoEvent(isPlaying, progress, duration))
}
it.resume()
it.start()
}
}
try {

View file

@ -53,4 +53,12 @@ android {
dependencies {
implementation libs.jetbrains.coroutinesAndroid
// TESTS
testImplementation libs.tests.junit
testImplementation libs.tests.kluent
testImplementation libs.mockk.mockk
testImplementation(libs.jetbrains.coroutinesTest) {
exclude group: "org.jetbrains.kotlinx", module: "kotlinx-coroutines-debug"
}
}

View file

@ -16,43 +16,37 @@
package im.vector.lib.core.utils.timer
import im.vector.lib.core.utils.flow.tickerFlow
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import java.util.concurrent.atomic.AtomicBoolean
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicLong
@OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
class CountUpTimer(initialTime: Long = 0L, private val intervalInMs: Long = 1_000) {
class CountUpTimer(
private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main),
private val clock: Clock = DefaultClock(),
private val intervalInMs: Long = 1_000,
) {
private val coroutineScope = CoroutineScope(Dispatchers.Main)
private val resumed: AtomicBoolean = AtomicBoolean(false)
private var counterJob: Job? = null
private val clock: Clock = DefaultClock()
private val lastTime: AtomicLong = AtomicLong()
private val elapsedTime: AtomicLong = AtomicLong(initialTime)
init {
startCounter()
}
private val lastTime: AtomicLong = AtomicLong(clock.epochMillis())
private val elapsedTime: AtomicLong = AtomicLong(0)
private fun startCounter() {
tickerFlow(coroutineScope, intervalInMs)
.filter { resumed.get() }
.map { elapsedTime() }
.onEach { tickListener?.onTick(it) }
.launchIn(coroutineScope)
counterJob = coroutineScope.launch {
while (true) {
delay(intervalInMs - elapsedTime() % intervalInMs)
tickListener?.onTick(elapsedTime())
}
}
}
var tickListener: TickListener? = null
fun elapsedTime(): Long {
return if (resumed.get()) {
return if (counterJob?.isActive == true) {
val now = clock.epochMillis()
elapsedTime.addAndGet(now - lastTime.getAndSet(now))
} else {
@ -60,19 +54,27 @@ class CountUpTimer(initialTime: Long = 0L, private val intervalInMs: Long = 1_00
}
}
fun start(initialTime: Long = 0L) {
elapsedTime.set(initialTime)
resume()
}
fun pause() {
tickListener?.onTick(elapsedTime())
resumed.set(false)
counterJob?.cancel()
counterJob = null
}
fun resume() {
lastTime.set(clock.epochMillis())
resumed.set(true)
startCounter()
}
fun stop() {
tickListener?.onTick(elapsedTime())
coroutineScope.cancel()
counterJob?.cancel()
counterJob = null
elapsedTime.set(0L)
}
fun interface TickListener {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 New Vector Ltd
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,23 +14,14 @@
* limitations under the License.
*/
package im.vector.app.core.time
package im.vector.lib.core.utils.test.fakes
import javax.inject.Inject
import im.vector.lib.core.utils.timer.Clock
import io.mockk.every
import io.mockk.mockk
interface Clock {
fun epochMillis(): Long
}
class DefaultClock @Inject constructor() : Clock {
/**
* Provides a UTC epoch in milliseconds
*
* This value is not guaranteed to be correct with reality
* as a User can override the system time and date to any values.
*/
override fun epochMillis(): Long {
return System.currentTimeMillis()
class FakeClock : Clock by mockk() {
fun givenEpoch(epoch: Long) {
every { epochMillis() } returns epoch
}
}

View file

@ -0,0 +1,94 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.lib.core.utils.timer
import im.vector.lib.core.utils.test.fakes.FakeClock
import io.mockk.every
import io.mockk.mockk
import io.mockk.verifySequence
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.currentTime
import kotlinx.coroutines.test.runTest
import org.junit.Test
private const val AN_INTERVAL = 500L
private const val AN_INITIAL_TIME = 2_333L
@OptIn(ExperimentalCoroutinesApi::class)
internal class CountUpTimerTest {
private val fakeClock = FakeClock()
@Test
fun `when pausing and resuming the timer, the timer ticks the right values at the right moments`() = runTest {
every { fakeClock.epochMillis() } answers { currentTime }
val tickListener = mockk<CountUpTimer.TickListener>(relaxed = true)
val timer = CountUpTimer(
coroutineScope = this,
clock = fakeClock,
intervalInMs = AN_INTERVAL,
).also { it.tickListener = tickListener }
timer.start()
advanceTimeBy(AN_INTERVAL / 2) // no tick
timer.pause() // tick
advanceTimeBy(AN_INTERVAL * 10) // no tick
timer.resume() // no tick
advanceTimeBy(AN_INTERVAL * 4) // tick * 4
timer.stop() // tick
verifySequence {
tickListener.onTick(AN_INTERVAL / 2)
tickListener.onTick(AN_INTERVAL)
tickListener.onTick(AN_INTERVAL * 2)
tickListener.onTick(AN_INTERVAL * 3)
tickListener.onTick(AN_INTERVAL * 4)
tickListener.onTick(AN_INTERVAL * 4 + AN_INTERVAL / 2)
}
}
@Test
fun `given an initial time, the timer ticks the right values at the right moments`() = runTest {
every { fakeClock.epochMillis() } answers { currentTime }
val tickListener = mockk<CountUpTimer.TickListener>(relaxed = true)
val timer = CountUpTimer(
coroutineScope = this,
clock = fakeClock,
intervalInMs = AN_INTERVAL,
).also { it.tickListener = tickListener }
timer.start(AN_INITIAL_TIME)
advanceTimeBy(AN_INTERVAL) // tick
timer.pause() // tick
advanceTimeBy(AN_INTERVAL * 10) // no tick
timer.resume() // no tick
advanceTimeBy(AN_INTERVAL * 4) // tick * 4
timer.stop() // tick
val offset = AN_INITIAL_TIME % AN_INTERVAL
verifySequence {
tickListener.onTick(AN_INITIAL_TIME + AN_INTERVAL - offset)
tickListener.onTick(AN_INITIAL_TIME + AN_INTERVAL)
tickListener.onTick(AN_INITIAL_TIME + AN_INTERVAL * 2 - offset)
tickListener.onTick(AN_INITIAL_TIME + AN_INTERVAL * 3 - offset)
tickListener.onTick(AN_INITIAL_TIME + AN_INTERVAL * 4 - offset)
tickListener.onTick(AN_INITIAL_TIME + AN_INTERVAL * 5 - offset)
tickListener.onTick(AN_INITIAL_TIME + AN_INTERVAL * 5)
}
}
}

View file

@ -176,7 +176,7 @@ PreferenceManager\.getDefaultSharedPreferences==2
R\.string\.template_
### Use the Clock interface, or use `measureTimeMillis`
System\.currentTimeMillis\(\)===3
System\.currentTimeMillis\(\)===2
### Remove extra space between the name and the description
\* @\w+ \w+ +

View file

@ -347,6 +347,7 @@ android {
dependencies {
implementation project(':vector')
implementation project(':vector-config')
implementation project(':library:core-utils')
debugImplementation project(':library:ui-styles')
implementation libs.dagger.hilt
implementation 'androidx.multidex:multidex:2.0.1'

View file

@ -43,8 +43,8 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
import im.vector.app.core.time.DefaultClock
import im.vector.app.espresso.tools.waitUntilViewVisible
import im.vector.lib.core.utils.timer.DefaultClock
import org.hamcrest.Matcher
import org.hamcrest.Matchers
import org.hamcrest.StringDescription

View file

@ -24,7 +24,7 @@ import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import im.vector.app.core.time.DefaultClock
import im.vector.lib.core.utils.timer.DefaultClock
import org.junit.rules.TestWatcher
import org.junit.runner.Description
import timber.log.Timber

View file

@ -28,7 +28,6 @@ import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
import im.vector.app.core.utils.checkPermissions
import im.vector.app.core.utils.registerForPermissionsResult
@ -41,6 +40,7 @@ import im.vector.app.features.debug.sas.DebugSasEmojiActivity
import im.vector.app.features.debug.settings.DebugPrivateSettingsActivity
import im.vector.app.features.qrcode.QrCodeScannerActivity
import im.vector.application.databinding.ActivityDebugMenuBinding
import im.vector.lib.core.utils.timer.Clock
import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkDefaultActivity
import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkTestActivity
import im.vector.lib.ui.styles.debug.DebugMaterialThemeDarkVectorActivity

View file

@ -18,10 +18,10 @@ package im.vector.app.fdroid
import android.content.Context
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.time.Clock
import im.vector.app.fdroid.receiver.AlarmSyncBroadcastReceiver
import im.vector.app.features.settings.BackgroundSyncMode
import im.vector.app.features.settings.VectorPreferences
import im.vector.lib.core.utils.timer.Clock
import timber.log.Timber
import javax.inject.Inject

View file

@ -28,7 +28,7 @@ import androidx.core.content.getSystemService
import im.vector.app.core.extensions.singletonEntryPoint
import im.vector.app.core.platform.PendingIntentCompat
import im.vector.app.core.services.VectorSyncAndroidService
import im.vector.app.core.time.Clock
import im.vector.lib.core.utils.timer.Clock
import org.matrix.android.sdk.api.session.sync.job.SyncAndroidService
import timber.log.Timber

View file

@ -22,8 +22,8 @@ import com.google.firebase.appdistribution.FirebaseAppDistribution
import com.google.firebase.appdistribution.FirebaseAppDistributionException
import im.vector.app.core.di.DefaultPreferences
import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.time.Clock
import im.vector.app.features.home.NightlyProxy
import im.vector.lib.core.utils.timer.Clock
import timber.log.Timber
import javax.inject.Inject

View file

@ -40,8 +40,6 @@ import im.vector.app.core.dispatchers.CoroutineDispatchers
import im.vector.app.core.error.DefaultErrorFormatter
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.time.Clock
import im.vector.app.core.time.DefaultClock
import im.vector.app.core.utils.AndroidSystemSettingsProvider
import im.vector.app.core.utils.SystemSettingsProvider
import im.vector.app.features.analytics.AnalyticsTracker
@ -63,6 +61,8 @@ import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.ui.SharedPreferencesUiStateRepository
import im.vector.app.features.ui.UiStateRepository
import im.vector.application.BuildConfig
import im.vector.lib.core.utils.timer.Clock
import im.vector.lib.core.utils.timer.DefaultClock
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
@ -106,9 +106,6 @@ import javax.inject.Singleton
@Binds
abstract fun bindAutoAcceptInvites(autoAcceptInvites: CompileTimeAutoAcceptInvites): AutoAcceptInvites
@Binds
abstract fun bindDefaultClock(clock: DefaultClock): Clock
@Binds
abstract fun bindEmojiSpanify(emojiCompatWrapper: EmojiCompatWrapper): EmojiSpanify
@ -243,4 +240,8 @@ import javax.inject.Singleton
fun providesDefaultSharedPreferences(context: Context): SharedPreferences {
return PreferenceManager.getDefaultSharedPreferences(context.applicationContext)
}
@Singleton
@Provides
fun providesDefaultClock(): Clock = DefaultClock()
}

View file

@ -22,7 +22,7 @@ import android.text.format.DateUtils
import im.vector.app.core.resources.DateProvider
import im.vector.app.core.resources.LocaleProvider
import im.vector.app.core.resources.toTimestamp
import im.vector.app.core.time.Clock
import im.vector.lib.core.utils.timer.Clock
import org.threeten.bp.LocalDateTime
import org.threeten.bp.Period
import org.threeten.bp.format.DateTimeFormatter

View file

@ -21,7 +21,6 @@ import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import im.vector.app.core.dialogs.UnrecognizedCertificateDialog
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.time.Clock
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.home.AvatarRenderer
@ -31,6 +30,7 @@ import im.vector.app.features.rageshake.BugReporter
import im.vector.app.features.session.SessionListener
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.ui.UiStateRepository
import im.vector.lib.core.utils.timer.Clock
import kotlinx.coroutines.CoroutineScope
@InstallIn(SingletonComponent::class)

View file

@ -27,12 +27,12 @@ import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper.Listener
import im.vector.app.core.extensions.insertBeforeLast
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
import im.vector.app.core.utils.checkPermissions
import im.vector.app.core.utils.onPermissionDeniedDialog
import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.features.media.createUCropWithDefaultSettings
import im.vector.lib.core.utils.timer.Clock
import im.vector.lib.multipicker.MultiPicker
import im.vector.lib.multipicker.entity.MultiPickerImageType
import java.io.File

View file

@ -18,7 +18,7 @@ package im.vector.app.core.dialogs
import androidx.fragment.app.Fragment
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.time.Clock
import im.vector.lib.core.utils.timer.Clock
import javax.inject.Inject
/**

View file

@ -34,10 +34,10 @@ import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.extensions.startForegroundCompat
import im.vector.app.core.platform.PendingIntentCompat
import im.vector.app.core.time.Clock
import im.vector.app.core.time.DefaultClock
import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.settings.BackgroundSyncMode
import im.vector.lib.core.utils.timer.Clock
import im.vector.lib.core.utils.timer.DefaultClock
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.session.sync.job.SyncAndroidService
import timber.log.Timber

View file

@ -16,10 +16,10 @@
package im.vector.app.features.analytics
import im.vector.app.core.time.Clock
import im.vector.app.features.analytics.plan.Error
import im.vector.lib.core.utils.compat.removeIfCompat
import im.vector.lib.core.utils.flow.tickerFlow
import im.vector.lib.core.utils.timer.Clock
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob

View file

@ -47,12 +47,12 @@ import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.platform.VectorMenuProvider
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.OnSnapPositionChangeListener
import im.vector.app.core.utils.SnapOnScrollListener
import im.vector.app.core.utils.attachSnapHelperWithListener
import im.vector.app.databinding.FragmentAttachmentsPreviewBinding
import im.vector.app.features.media.createUCropWithDefaultSettings
import im.vector.lib.core.utils.timer.Clock
import kotlinx.parcelize.Parcelize
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.content.ContentAttachmentData

View file

@ -19,7 +19,6 @@ package im.vector.app.features.call.conference
import im.vector.app.R
import im.vector.app.core.network.await
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.ensureProtocol
import im.vector.app.core.utils.toBase32String
import im.vector.app.features.call.conference.jwt.JitsiJWTFactory
@ -27,6 +26,7 @@ import im.vector.app.features.displayname.getBestName
import im.vector.app.features.raw.wellknown.getElementWellknown
import im.vector.app.features.settings.VectorLocaleProvider
import im.vector.app.features.themes.ThemeProvider
import im.vector.lib.core.utils.timer.Clock
import okhttp3.Request
import org.jitsi.meet.sdk.JitsiMeetUserInfo
import org.matrix.android.sdk.api.extensions.tryOrNull

View file

@ -22,8 +22,8 @@ import android.os.IBinder
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.core.extensions.startForegroundCompat
import im.vector.app.core.services.VectorAndroidService
import im.vector.app.core.time.Clock
import im.vector.app.features.notifications.NotificationUtils
import im.vector.lib.core.utils.timer.Clock
import javax.inject.Inject
@AndroidEntryPoint

View file

@ -22,8 +22,8 @@ import androidx.lifecycle.ViewModel
import com.nulabinc.zxcvbn.Strength
import im.vector.app.R
import im.vector.app.core.platform.WaitingViewData
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.LiveEvent
import im.vector.lib.core.utils.timer.Clock
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.listeners.ProgressListener
import org.matrix.android.sdk.api.session.Session

View file

@ -18,7 +18,6 @@ package im.vector.app.features.crypto.verification
import android.content.Context
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.time.Clock
import im.vector.app.features.analytics.plan.ViewRoom
import im.vector.app.features.displayname.getBestName
import im.vector.app.features.home.AvatarRenderer
@ -27,6 +26,7 @@ import im.vector.app.features.home.room.detail.arguments.TimelineArgs
import im.vector.app.features.popup.PopupAlertManager
import im.vector.app.features.popup.VerificationVectorAlert
import im.vector.lib.core.utils.compat.getParcelableCompat
import im.vector.lib.core.utils.timer.Clock
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService

View file

@ -16,8 +16,8 @@
package im.vector.app.features.home
import im.vector.app.core.time.Clock
import im.vector.app.features.settings.VectorPreferences
import im.vector.lib.core.utils.timer.Clock
import javax.inject.Inject
class SetUnverifiedSessionsAlertShownUseCase @Inject constructor(

View file

@ -17,9 +17,9 @@
package im.vector.app.features.home
import im.vector.app.config.Config
import im.vector.app.core.time.Clock
import im.vector.app.features.VectorFeatures
import im.vector.app.features.settings.VectorPreferences
import im.vector.lib.core.utils.timer.Clock
import javax.inject.Inject
class ShouldShowUnverifiedSessionsAlertUseCase @Inject constructor(

View file

@ -32,7 +32,7 @@ import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.VectorViewModelAction
import im.vector.app.core.session.clientinfo.DeleteUnusedClientInformationUseCase
import im.vector.app.core.time.Clock
import im.vector.lib.core.utils.timer.Clock
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn

View file

@ -16,7 +16,7 @@
package im.vector.app.features.home.room.detail
import im.vector.app.core.time.Clock
import im.vector.lib.core.utils.timer.Clock
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageType

View file

@ -33,8 +33,8 @@ import com.airbnb.epoxy.EpoxyModel
import com.airbnb.epoxy.EpoxyTouchHelperCallback
import com.airbnb.epoxy.EpoxyViewHolder
import im.vector.app.R
import im.vector.app.core.time.Clock
import im.vector.app.features.themes.ThemeUtils
import im.vector.lib.core.utils.timer.Clock
import timber.log.Timber
import kotlin.math.abs
import kotlin.math.min

View file

@ -86,7 +86,6 @@ import im.vector.app.core.platform.VectorMenuProvider
import im.vector.app.core.platform.showOptimizedSnackbar
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.UserPreferencesProvider
import im.vector.app.core.time.Clock
import im.vector.app.core.ui.views.CurrentCallsView
import im.vector.app.core.ui.views.CurrentCallsViewPresenter
import im.vector.app.core.ui.views.FailedMessagesWarningView
@ -186,6 +185,7 @@ import im.vector.app.features.widgets.WidgetActivity
import im.vector.app.features.widgets.WidgetArgs
import im.vector.app.features.widgets.WidgetKind
import im.vector.app.features.widgets.permissions.RoomWidgetPermissionBottomSheet
import im.vector.lib.core.utils.timer.Clock
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

View file

@ -200,7 +200,7 @@ class AudioMessageHelper @Inject constructor(
amplitudeTicker?.stop()
amplitudeTicker = CountUpTimer(intervalInMs = 50).apply {
tickListener = CountUpTimer.TickListener { onAmplitudeTick() }
resume()
start()
}
}
@ -218,10 +218,6 @@ class AudioMessageHelper @Inject constructor(
}
}
private fun resumeRecordingAmplitudes() {
amplitudeTicker?.resume()
}
private fun stopRecordingAmplitudes() {
amplitudeTicker?.stop()
amplitudeTicker = null
@ -231,7 +227,7 @@ class AudioMessageHelper @Inject constructor(
playbackTicker?.stop()
playbackTicker = CountUpTimer().apply {
tickListener = CountUpTimer.TickListener { onPlaybackTick(id) }
resume()
start()
}
onPlaybackTick(id)
}

View file

@ -29,7 +29,6 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.getVectorLastMessageContent
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.time.Clock
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsComposer
import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom
@ -52,6 +51,7 @@ import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState
import im.vector.app.features.voicebroadcast.model.asVoiceBroadcastEvent
import im.vector.app.features.voicebroadcast.usecase.GetVoiceBroadcastStateEventLiveUseCase
import im.vector.app.features.voicebroadcast.voiceBroadcastId
import im.vector.lib.core.utils.timer.Clock
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest

View file

@ -23,10 +23,10 @@ import androidx.constraintlayout.widget.ConstraintLayout
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.hardware.vibrate
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.databinding.ViewVoiceMessageRecorderBinding
import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
import im.vector.lib.core.utils.timer.Clock
import im.vector.lib.core.utils.timer.CountUpTimer
import javax.inject.Inject
import kotlin.math.floor
@ -193,7 +193,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
val isLocked = startFromLocked || lastKnownState is RecordingUiState.Locked
onRecordingTick(isLocked, milliseconds + startMs)
}
resume()
start()
}
onRecordingTick(startFromLocked, milliseconds = startMs)
}

View file

@ -27,7 +27,6 @@ import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.hardware.vibrate
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.PERMISSIONS_FOR_VOICE_MESSAGE
import im.vector.app.core.utils.checkPermissions
import im.vector.app.core.utils.onPermissionDeniedSnackbar
@ -41,6 +40,7 @@ import im.vector.app.features.home.room.detail.composer.MessageComposerViewState
import im.vector.app.features.home.room.detail.composer.SendMode
import im.vector.app.features.home.room.detail.composer.boolean
import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
import im.vector.lib.core.utils.timer.Clock
import javax.inject.Inject
@AndroidEntryPoint

View file

@ -30,11 +30,11 @@ import im.vector.app.core.epoxy.loadingItem
import im.vector.app.core.epoxy.noResultItem
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.resources.UserPreferencesProvider
import im.vector.app.core.time.Clock
import im.vector.app.core.ui.list.GenericHeaderItem_
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.timeline.format.DisplayableEventFormatter
import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
import im.vector.lib.core.utils.timer.Clock
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event

View file

@ -31,7 +31,6 @@ import im.vector.app.core.epoxy.LoadingItem_
import im.vector.app.core.extensions.localDateTime
import im.vector.app.core.extensions.nextOrNull
import im.vector.app.core.extensions.prevOrNull
import im.vector.app.core.time.Clock
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.JitsiState
import im.vector.app.features.home.room.detail.RoomDetailAction
@ -64,6 +63,7 @@ import im.vector.app.features.media.AttachmentData
import im.vector.app.features.media.ImageContentRenderer
import im.vector.app.features.media.VideoContentRenderer
import im.vector.app.features.settings.VectorPreferences
import im.vector.lib.core.utils.timer.Clock
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel

View file

@ -26,13 +26,13 @@ import im.vector.app.core.date.DateFormatKind
import im.vector.app.core.date.VectorDateFormatter
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.time.Clock
import im.vector.app.core.ui.list.genericFooterItem
import im.vector.app.core.ui.list.genericHeaderItem
import im.vector.app.core.ui.list.genericItem
import im.vector.app.core.ui.list.genericLoaderItem
import im.vector.app.features.html.EventHtmlRenderer
import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
import im.vector.lib.core.utils.timer.Clock
import me.gujun.android.span.span
import name.fraser.neil.plaintext.diff_match_patch
import org.matrix.android.sdk.api.session.events.model.Event

View file

@ -32,7 +32,6 @@ import im.vector.app.core.extensions.getVectorLastMessageContent
import im.vector.app.core.files.LocalFilesHelper
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.DimensionConverter
import im.vector.app.core.utils.containsOnlyEmojis
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
@ -83,6 +82,7 @@ import im.vector.app.features.voice.AudioWaveformView
import im.vector.app.features.voicebroadcast.isVoiceBroadcast
import im.vector.app.features.voicebroadcast.model.MessageVoiceBroadcastInfoContent
import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
import im.vector.lib.core.utils.timer.Clock
import me.gujun.android.span.span
import org.matrix.android.sdk.api.MatrixUrls.isMxcUrl
import org.matrix.android.sdk.api.session.Session

View file

@ -31,11 +31,11 @@ import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
import im.vector.app.core.epoxy.ClickListener
import im.vector.app.core.epoxy.onClick
import im.vector.app.core.time.Clock
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.room.detail.RoomDetailAction
import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
import im.vector.lib.core.utils.timer.Clock
import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
import org.matrix.android.sdk.api.session.crypto.verification.VerificationState

View file

@ -23,8 +23,8 @@ import im.vector.app.core.date.VectorDateFormatter
import im.vector.app.core.resources.DateProvider
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.resources.toTimestamp
import im.vector.app.core.time.Clock
import im.vector.app.features.home.AvatarRenderer
import im.vector.lib.core.utils.timer.Clock
import javax.inject.Inject
class LiveLocationBottomSheetController @Inject constructor(

View file

@ -27,9 +27,9 @@ import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
import im.vector.app.core.epoxy.onClick
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.TextUtils
import im.vector.app.features.home.AvatarRenderer
import im.vector.lib.core.utils.timer.Clock
import im.vector.lib.core.utils.timer.CountUpTimer
import org.matrix.android.sdk.api.util.MatrixItem
import org.threeten.bp.Duration
@ -79,10 +79,12 @@ abstract class LiveLocationUserItem : VectorEpoxyModel<LiveLocationUserItem.Hold
}
}
holder.timer.tickListener = CountUpTimer.TickListener {
holder.itemLastUpdatedAtTextView.text = getFormattedLastUpdatedAt(locationUpdateTimeMillis)
holder.timer.apply {
tickListener = CountUpTimer.TickListener {
holder.itemLastUpdatedAtTextView.text = getFormattedLastUpdatedAt(locationUpdateTimeMillis)
}
start()
}
holder.timer.resume()
holder.view.setOnClickListener { callback?.onUserSelected(matrixItem.id) }
}

View file

@ -25,7 +25,6 @@ import im.vector.app.R
import im.vector.app.core.extensions.createIgnoredUri
import im.vector.app.core.platform.PendingIntentCompat
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.time.Clock
import im.vector.app.features.home.HomeActivity
import im.vector.app.features.home.room.detail.RoomDetailActivity
import im.vector.app.features.home.room.detail.arguments.TimelineArgs
@ -34,6 +33,7 @@ import im.vector.app.features.location.live.map.LiveLocationMapViewArgs
import im.vector.app.features.notifications.NotificationActionIds
import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.themes.ThemeUtils
import im.vector.lib.core.utils.timer.Clock
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -20,9 +20,9 @@ import android.content.Context
import androidx.core.net.toUri
import dagger.hilt.android.qualifiers.ApplicationContext
import im.vector.app.core.intent.getMimeTypeFromUri
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.saveMedia
import im.vector.app.features.notifications.NotificationUtils
import im.vector.lib.core.utils.timer.Clock
import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.session.Session
import java.io.File

View file

@ -21,10 +21,10 @@ import im.vector.app.core.extensions.getVectorLastMessageContent
import im.vector.app.core.extensions.takeAs
import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.time.Clock
import im.vector.app.features.displayname.getBestName
import im.vector.app.features.home.room.detail.timeline.format.DisplayableEventFormatter
import im.vector.app.features.home.room.detail.timeline.format.NoticeEventFormatter
import im.vector.lib.core.utils.timer.Clock
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.content.ContentUrlResolver

View file

@ -23,11 +23,11 @@ import androidx.core.app.RemoteInput
import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.time.Clock
import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.extensions.toAnalyticsJoinedRoom
import im.vector.app.features.analytics.plan.JoinedRoom
import im.vector.app.features.session.coroutineScope
import im.vector.lib.core.utils.timer.Clock
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.Session

View file

@ -50,7 +50,6 @@ import im.vector.app.core.extensions.createIgnoredUri
import im.vector.app.core.platform.PendingIntentCompat
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.services.CallAndroidService
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.startNotificationChannelSettingsIntent
import im.vector.app.features.MainActivity
import im.vector.app.features.call.VectorCallActivity
@ -65,6 +64,7 @@ import im.vector.app.features.home.room.threads.arguments.ThreadTimelineArgs
import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.settings.troubleshoot.TestNotificationReceiver
import im.vector.app.features.themes.ThemeUtils
import im.vector.lib.core.utils.timer.Clock
import timber.log.Timber
import javax.inject.Inject
import javax.inject.Singleton

View file

@ -24,7 +24,6 @@ import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
import com.tapadoo.alerter.Alerter
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.isAnimationEnabled
import im.vector.app.features.MainActivity
import im.vector.app.features.analytics.ui.consent.AnalyticsOptInActivity
@ -32,6 +31,7 @@ import im.vector.app.features.home.room.list.home.release.ReleaseNotesActivity
import im.vector.app.features.pin.PinActivity
import im.vector.app.features.signout.hard.SignedOutActivity
import im.vector.app.features.themes.ThemeUtils
import im.vector.lib.core.utils.timer.Clock
import timber.log.Timber
import java.lang.ref.WeakReference
import javax.inject.Inject

View file

@ -31,7 +31,6 @@ import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R
import im.vector.app.core.intent.getMimeTypeFromUri
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.saveMedia
import im.vector.app.core.utils.shareMedia
import im.vector.app.databinding.FragmentRoomUploadsBinding
@ -39,6 +38,7 @@ import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.roomprofile.RoomProfileArgs
import im.vector.lib.core.utils.timer.Clock
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.util.toMatrixItem
import javax.inject.Inject

View file

@ -27,12 +27,12 @@ import im.vector.app.R
import im.vector.app.core.di.DefaultPreferences
import im.vector.app.core.resources.BuildMeta
import im.vector.app.core.resources.StringProvider
import im.vector.app.core.time.Clock
import im.vector.app.features.VectorFeatures
import im.vector.app.features.disclaimer.SHARED_PREF_KEY
import im.vector.app.features.home.ShortcutsHandler
import im.vector.app.features.homeserver.ServerUrlsRepository
import im.vector.app.features.themes.ThemeUtils
import im.vector.lib.core.utils.timer.Clock
import org.matrix.android.sdk.api.extensions.tryOrNull
import timber.log.Timber
import javax.inject.Inject

View file

@ -16,7 +16,7 @@
package im.vector.app.features.settings.devices.v2.list
import im.vector.app.core.time.Clock
import im.vector.lib.core.utils.timer.Clock
import java.util.concurrent.TimeUnit
import javax.inject.Inject

View file

@ -36,9 +36,9 @@ import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.safeOpenOutputStream
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.platform.VectorMenuProvider
import im.vector.app.core.time.Clock
import im.vector.app.core.utils.selectTxtFileToWrite
import im.vector.app.databinding.FragmentDevtoolKeyrequestsBinding
import im.vector.lib.core.utils.timer.Clock
import org.matrix.android.sdk.api.extensions.tryOrNull
import javax.inject.Inject

View file

@ -492,12 +492,9 @@ class VoiceBroadcastPlayerImpl @Inject constructor(
fun startPlaybackTicker(id: String) {
playbackTicker?.stop()
playbackTicker = CountUpTimer(
initialTime = playbackTracker.getPlaybackTime(id)?.toLong() ?: 0L,
intervalInMs = 50L
).apply {
playbackTicker = CountUpTimer(intervalInMs = 50L).apply {
tickListener = CountUpTimer.TickListener { onPlaybackTick(id, it.toInt()) }
resume()
start(initialTime = playbackTracker.getPlaybackTime(id)?.toLong() ?: 0L)
}
}

View file

@ -245,9 +245,9 @@ class VoiceBroadcastRecorderQ(
) {
fun start() {
recordingTicker?.stop()
recordingTicker = CountUpTimer().apply {
tickListener = CountUpTimer.TickListener { onTick(elapsedTime()) }
resume()
recordingTicker = CountUpTimer().also {
it.tickListener = CountUpTimer.TickListener { tick -> onTick(tick) }
it.start()
}
}

View file

@ -16,7 +16,7 @@
package im.vector.app.test.fakes
import im.vector.app.core.time.Clock
import im.vector.lib.core.utils.timer.Clock
import io.mockk.every
import io.mockk.mockk