Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into revert-mention-hig…
Browse files Browse the repository at this point in the history
…hlight

# Conflicts:
#	app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/state/MessageComposerStateHolder.kt
  • Loading branch information
ohassine committed Dec 30, 2024
2 parents 246d351 + 8bf8c7f commit 249c1d9
Show file tree
Hide file tree
Showing 130 changed files with 4,162 additions and 809 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-prod-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ jobs:
build-flavour: prod
build-variant: compatrelease
- name: Attach APK and version file to release
uses: softprops/action-gh-release@v2.1.0
uses: softprops/action-gh-release@v2.2.0
with:
files: |
app/build/outputs/apk/prodCompatrelease/*.apk
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/generate-changelog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
npx [email protected] -t "$PREVIOUS_TAG...$CURRENT_TAG"
- name: 'Attach changelog to tag'
uses: softprops/action-gh-release@v2.1.0
uses: softprops/action-gh-release@v2.2.0
env:
GITHUB_TOKEN: ${{ secrets.ANDROID_BOB_GH_TOKEN }}
with:
Expand Down
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ dependencies {
implementation(libs.aboutLibraries.core)
implementation(libs.aboutLibraries.ui)
implementation(libs.compose.qr.code)
implementation(libs.audio.amplituda)

// screenshot testing
screenshotTestImplementation(libs.compose.ui.tooling)
Expand Down
28 changes: 28 additions & 0 deletions app/src/main/kotlin/com/wire/android/WireApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ import co.touchlab.kermit.platformLogWriter
import com.wire.android.analytics.ObserveCurrentSessionAnalyticsUseCase
import com.wire.android.datastore.GlobalDataStore
import com.wire.android.datastore.UserDataStoreProvider
import com.wire.android.debug.DatabaseProfilingManager
import com.wire.android.di.ApplicationScope
import com.wire.android.di.KaliumCoreLogic
import com.wire.android.feature.analytics.AnonymousAnalyticsManager
import com.wire.android.feature.analytics.AnonymousAnalyticsManagerImpl
import com.wire.android.feature.analytics.AnonymousAnalyticsRecorderImpl
import com.wire.android.feature.analytics.globalAnalyticsManager
Expand All @@ -47,12 +49,15 @@ import com.wire.kalium.logger.KaliumLogLevel
import com.wire.kalium.logger.KaliumLogger
import com.wire.kalium.logic.CoreLogger
import com.wire.kalium.logic.CoreLogic
import com.wire.kalium.logic.feature.session.CurrentSessionResult
import dagger.Lazy
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
Expand Down Expand Up @@ -89,6 +94,12 @@ class WireApplication : BaseApp() {
@Inject
lateinit var currentScreenManager: CurrentScreenManager

@Inject
lateinit var databaseProfilingManager: DatabaseProfilingManager

@Inject
lateinit var analyticsManager: Lazy<AnonymousAnalyticsManager>

override val workManagerConfiguration: Configuration
get() = Configuration.Builder()
.setWorkerFactory(wireWorkerFactory.get())
Expand Down Expand Up @@ -117,9 +128,22 @@ class WireApplication : BaseApp() {

appLogger.i("$TAG global observers")
globalObserversManager.get().observe()

observeRecentlyEndedCall()
}
}

private suspend fun observeRecentlyEndedCall() {
coreLogic.get().getGlobalScope().session.currentSessionFlow().filterIsInstance(CurrentSessionResult.Success::class)
.filter { session -> session.accountInfo.isValid() }
.flatMapLatest { session ->
coreLogic.get().getSessionScope(session.accountInfo.userId).calls.observeRecentlyEndedCallMetadata()
}
.collect { metadata ->
analyticsManager.get().sendEvent(AnalyticsEvent.RecentlyEndedCallEvent(metadata))
}
}

private fun enableStrictMode() {
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(
Expand Down Expand Up @@ -183,6 +207,10 @@ class WireApplication : BaseApp() {
logDeviceInformation()
// 5. Verify if we can initialize Anonymous Analytics
initializeAnonymousAnalytics()
// 6. Observe and update profiling when needed
globalAppScope.launch {
databaseProfilingManager.observeAndUpdateProfiling()
}
}

private fun initializeAnonymousAnalytics() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Wire
* Copyright (C) 2024 Wire Swiss GmbH
*
* 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.wire.android.debug

import com.wire.android.datastore.GlobalDataStore
import com.wire.android.di.KaliumCoreLogic
import com.wire.kalium.logic.CoreLogic
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.functional.mapToRightOr
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.scan
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class DatabaseProfilingManager @Inject constructor(
@KaliumCoreLogic private val coreLogic: CoreLogic,
private val globalDataStore: GlobalDataStore,
) {

suspend fun observeAndUpdateProfiling() {
globalDataStore.isLoggingEnabled()
.flatMapLatest { isLoggingEnabled ->
coreLogic.getGlobalScope().sessionRepository.allValidSessionsFlow()
.mapToRightOr(emptyList())
.map { it.map { it.userId } }
.scan(emptyList<UserId>()) { previousList, currentList -> currentList - previousList.toSet() }
.map { userIds -> isLoggingEnabled to userIds }
}
.filter { (_, userIds) -> userIds.isNotEmpty() }
.distinctUntilChanged()
.collect { (isLoggingEnabled, userIds) ->
userIds.forEach { userId ->
coreLogic.getSessionScope(userId).debug.changeProfiling(isLoggingEnabled)
}
}
}
}
4 changes: 4 additions & 0 deletions app/src/main/kotlin/com/wire/android/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import linc.com.amplituda.Amplituda
import javax.inject.Qualifier
import javax.inject.Singleton

Expand Down Expand Up @@ -84,6 +85,9 @@ object AppModule {
}
}

@Provides
fun provideAmplituda(appContext: Context): Amplituda = Amplituda(appContext)

@Singleton
@Provides
fun provideCurrentTimestampProvider(): CurrentTimestampProvider = { System.currentTimeMillis() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ package com.wire.android.di.accountScoped

import com.wire.android.di.CurrentAccount
import com.wire.android.di.KaliumCoreLogic
import dagger.Module
import dagger.Provides
import com.wire.kalium.logic.CoreLogic
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.feature.call.CallsScope
Expand All @@ -40,6 +38,8 @@ import com.wire.kalium.logic.feature.call.usecase.TurnLoudSpeakerOnUseCase
import com.wire.kalium.logic.feature.call.usecase.UnMuteCallUseCase
import com.wire.kalium.logic.feature.call.usecase.video.SetVideoSendStateUseCase
import com.wire.kalium.logic.feature.call.usecase.video.UpdateVideoStateUseCase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent
import dagger.hilt.android.scopes.ViewModelScoped
Expand Down Expand Up @@ -197,4 +197,14 @@ class CallsModule {
@Provides
fun provideIsEligibleToStartCall(callsScope: CallsScope) =
callsScope.isEligibleToStartCall

@ViewModelScoped
@Provides
fun provideObserveConferenceCallingEnabledUseCase(callsScope: CallsScope) =
callsScope.observeConferenceCallingEnabled

@ViewModelScoped
@Provides
fun provideObserveInCallReactionsUseCase(callsScope: CallsScope) =
callsScope.observeInCallReactions
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ import com.wire.kalium.logic.feature.asset.ObserveAssetStatusesUseCase
import com.wire.kalium.logic.feature.asset.ObservePaginatedAssetImageMessages
import com.wire.kalium.logic.feature.asset.ScheduleNewAssetMessageUseCase
import com.wire.kalium.logic.feature.asset.UpdateAssetMessageTransferStatusUseCase
import com.wire.kalium.logic.feature.incallreaction.SendInCallReactionUseCase
import com.wire.kalium.logic.feature.message.DeleteMessageUseCase
import com.wire.kalium.logic.feature.message.GetMessageByIdUseCase
import com.wire.kalium.logic.feature.message.GetNotificationsUseCase
import com.wire.kalium.logic.feature.message.GetPaginatedFlowOfMessagesByConversationUseCase
import com.wire.kalium.logic.feature.message.GetPaginatedFlowOfMessagesBySearchQueryAndConversationIdUseCase
import com.wire.kalium.logic.feature.message.GetSearchedConversationMessagePositionUseCase
import com.wire.kalium.logic.feature.message.GetSenderNameByMessageIdUseCase
import com.wire.kalium.logic.feature.message.MarkMessagesAsNotifiedUseCase
import com.wire.kalium.logic.feature.message.MessageScope
import com.wire.kalium.logic.feature.message.ObserveMessageReactionsUseCase
Expand Down Expand Up @@ -216,4 +218,14 @@ class MessageModule {
@Provides
fun provideRemoveMessageDraftUseCase(messageScope: MessageScope): RemoveMessageDraftUseCase =
messageScope.removeMessageDraftUseCase

@ViewModelScoped
@Provides
fun provideSendInCallReactionUseCase(messageScope: MessageScope): SendInCallReactionUseCase =
messageScope.sendInCallReactionUseCase

@ViewModelScoped
@Provides
fun provideGetSenderNameByMessageIdUseCase(messageScope: MessageScope): GetSenderNameByMessageIdUseCase =
messageScope.getSenderNameByMessageId
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import com.wire.kalium.logic.feature.personaltoteamaccount.CanMigrateFromPersona
import com.wire.kalium.logic.feature.publicuser.GetAllContactsUseCase
import com.wire.kalium.logic.feature.publicuser.GetKnownUserUseCase
import com.wire.kalium.logic.feature.publicuser.RefreshUsersWithoutMetadataUseCase
import com.wire.kalium.logic.feature.server.GetTeamUrlUseCase
import com.wire.kalium.logic.feature.user.DeleteAccountUseCase
import com.wire.kalium.logic.feature.user.GetSelfUserUseCase
import com.wire.kalium.logic.feature.user.GetUserInfoUseCase
Expand Down Expand Up @@ -191,6 +192,11 @@ class UserModule {
fun provideGetSelfUseCase(userScope: UserScope): GetSelfUserUseCase =
userScope.getSelfUser

@ViewModelScoped
@Provides
fun provideGetTeamUrlUseCase(userScope: UserScope): GetTeamUrlUseCase =
userScope.getTeamUrl

@ViewModelScoped
@Provides
fun provideGetAvatarAssetUseCase(userScope: UserScope): GetAvatarAssetUseCase =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ fun ConversationDetailsWithEvents.toConversationItem(
),
userId = conversationDetails.otherUser.id,
blockingState = conversationDetails.otherUser.BlockState,
isUserDeleted = conversationDetails.otherUser.deleted,
teamId = conversationDetails.otherUser.teamId,
isArchived = conversationDetails.conversation.archived,
mlsVerificationStatus = conversationDetails.conversation.mlsVerificationStatus,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ package com.wire.android.mapper
import com.wire.android.model.ImageAsset
import com.wire.android.ui.calling.model.UICallParticipant
import com.wire.kalium.logic.data.call.Participant
import com.wire.kalium.logic.data.conversation.ClientId
import javax.inject.Inject

class UICallParticipantMapper @Inject constructor(
private val userTypeMapper: UserTypeMapper,
) {
fun toUICallParticipant(participant: Participant) = UICallParticipant(
fun toUICallParticipant(participant: Participant, currentClientId: ClientId) = UICallParticipant(
id = participant.id,
clientId = participant.clientId,
isSelfUser = participant.clientId == currentClientId.value,
name = participant.name,
isMuted = participant.isMuted,
isSpeaking = participant.isSpeaking,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,24 @@
*/
package com.wire.android.media.audiomessage

import androidx.annotation.StringRes
import com.wire.android.R

data class AudioState(
val audioMediaPlayingState: AudioMediaPlayingState,
val currentPositionInMs: Int,
val totalTimeInMs: TotalTimeInMs
val totalTimeInMs: TotalTimeInMs,
val wavesMask: List<Int>
) {
companion object {
val DEFAULT = AudioState(AudioMediaPlayingState.Stopped, 0, TotalTimeInMs.NotKnown)
val DEFAULT = AudioState(AudioMediaPlayingState.Stopped, 0, TotalTimeInMs.NotKnown, listOf())
}

// if the back-end returned the total time, we use that, in case it didn't we use what we get from
// the [ConversationAudioMessagePlayer.kt] which will emit the time once the users play the audio.
fun sanitizeTotalTime(otherClientTotalTime: Int): TotalTimeInMs {
if (otherClientTotalTime != 0) {
return TotalTimeInMs.Known(otherClientTotalTime)
return TotalTimeInMs.Known(otherClientTotalTime)
}

return totalTimeInMs
Expand All @@ -43,6 +47,27 @@ data class AudioState(
}
}

@Suppress("MagicNumber")
enum class AudioSpeed(val value: Float, @StringRes val titleRes: Int) {
NORMAL(1f, R.string.audio_speed_1),
FAST(1.5f, R.string.audio_speed_1_5),
MAX(2f, R.string.audio_speed_2);

fun toggle(): AudioSpeed = when (this) {
NORMAL -> FAST
FAST -> MAX
MAX -> NORMAL
}

companion object {
fun fromFloat(speed: Float): AudioSpeed = when {
(speed < FAST.value) -> NORMAL
(speed < MAX.value) -> FAST
else -> MAX
}
}
}

sealed class AudioMediaPlayingState {
object Playing : AudioMediaPlayingState()
object Stopped : AudioMediaPlayingState()
Expand Down Expand Up @@ -75,6 +100,11 @@ sealed class AudioMediaPlayerStateUpdate(
override val messageId: String,
val totalTimeInMs: Int
) : AudioMediaPlayerStateUpdate(messageId)

data class WaveMaskUpdate(
override val messageId: String,
val waveMask: List<Int>
) : AudioMediaPlayerStateUpdate(messageId)
}

sealed class RecordAudioMediaPlayerStateUpdate {
Expand All @@ -89,4 +119,8 @@ sealed class RecordAudioMediaPlayerStateUpdate {
data class TotalTimeUpdate(
val totalTimeInMs: Int
) : RecordAudioMediaPlayerStateUpdate()

data class WaveMaskUpdate(
val waveMask: List<Int>
) : RecordAudioMediaPlayerStateUpdate()
}
Loading

0 comments on commit 249c1d9

Please sign in to comment.