Remove avatar color from CallLink table.
This commit is contained in:
parent
b9835584d8
commit
51222738df
22 changed files with 115 additions and 96 deletions
|
@ -21,8 +21,8 @@ import org.thoughtcrime.securesms.testing.assertIsNot
|
|||
import org.thoughtcrime.securesms.testing.parsedRequestBody
|
||||
import org.thoughtcrime.securesms.testing.success
|
||||
import org.whispersystems.signalservice.api.push.SignedPreKeyEntity
|
||||
import org.whispersystems.signalservice.internal.push.OneTimePreKeyCounts
|
||||
import org.whispersystems.signalservice.internal.push.PreKeyState
|
||||
import org.whispersystems.signalservice.internal.push.PreKeyStatus
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class PreKeysSyncJobTest {
|
||||
|
@ -106,8 +106,8 @@ class PreKeysSyncJobTest {
|
|||
val currentPniKeyId = pniPreKeyMeta.activeSignedPreKeyId
|
||||
|
||||
InstrumentationApplicationDependencyProvider.addMockWebRequestHandlers(
|
||||
Get("/v2/keys?identity=aci") { MockResponse().success(PreKeyStatus(100)) },
|
||||
Get("/v2/keys?identity=pni") { MockResponse().success(PreKeyStatus(100)) }
|
||||
Get("/v2/keys?identity=aci") { MockResponse().success(OneTimePreKeyCounts(100, 100)) },
|
||||
Get("/v2/keys?identity=pni") { MockResponse().success(OneTimePreKeyCounts(100, 100)) }
|
||||
)
|
||||
|
||||
// WHEN
|
||||
|
@ -133,7 +133,7 @@ class PreKeysSyncJobTest {
|
|||
val currentPniKeyId = pniPreKeyMeta.activeSignedPreKeyId
|
||||
|
||||
InstrumentationApplicationDependencyProvider.addMockWebRequestHandlers(
|
||||
Get("/v2/keys?identity=aci") { MockResponse().success(PreKeyStatus(100)) },
|
||||
Get("/v2/keys?identity=aci") { MockResponse().success(OneTimePreKeyCounts(100, 100)) },
|
||||
Put("/v2/keys/signed?identity=pni") { MockResponse().success() }
|
||||
)
|
||||
|
||||
|
@ -157,15 +157,15 @@ class PreKeysSyncJobTest {
|
|||
val currentAciKeyId = aciPreKeyMeta.activeSignedPreKeyId
|
||||
val currentPniKeyId = pniPreKeyMeta.activeSignedPreKeyId
|
||||
|
||||
val currentNextAciPreKeyId = aciPreKeyMeta.nextOneTimePreKeyId
|
||||
val currentNextPniPreKeyId = pniPreKeyMeta.nextOneTimePreKeyId
|
||||
val currentNextAciPreKeyId = aciPreKeyMeta.nextEcOneTimePreKeyId
|
||||
val currentNextPniPreKeyId = pniPreKeyMeta.nextEcOneTimePreKeyId
|
||||
|
||||
lateinit var aciPreKeyStateRequest: PreKeyState
|
||||
lateinit var pniPreKeyStateRequest: PreKeyState
|
||||
|
||||
InstrumentationApplicationDependencyProvider.addMockWebRequestHandlers(
|
||||
Get("/v2/keys?identity=aci") { MockResponse().success(PreKeyStatus(5)) },
|
||||
Get("/v2/keys?identity=pni") { MockResponse().success(PreKeyStatus(5)) },
|
||||
Get("/v2/keys?identity=aci") { MockResponse().success(OneTimePreKeyCounts(5, 5)) },
|
||||
Get("/v2/keys?identity=pni") { MockResponse().success(OneTimePreKeyCounts(5, 5)) },
|
||||
Put("/v2/keys/?identity=aci") { r ->
|
||||
aciPreKeyStateRequest = r.parsedRequestBody()
|
||||
MockResponse().success()
|
||||
|
@ -184,8 +184,8 @@ class PreKeysSyncJobTest {
|
|||
aciPreKeyMeta.activeSignedPreKeyId assertIsNot currentAciKeyId
|
||||
pniPreKeyMeta.activeSignedPreKeyId assertIsNot currentPniKeyId
|
||||
|
||||
aciPreKeyMeta.nextOneTimePreKeyId assertIsNot currentNextAciPreKeyId
|
||||
pniPreKeyMeta.nextOneTimePreKeyId assertIsNot currentNextPniPreKeyId
|
||||
aciPreKeyMeta.nextEcOneTimePreKeyId assertIsNot currentNextAciPreKeyId
|
||||
pniPreKeyMeta.nextEcOneTimePreKeyId assertIsNot currentNextPniPreKeyId
|
||||
|
||||
ApplicationDependencies.getProtocolStore().aci().identityKeyPair.publicKey.let { aciIdentityKey ->
|
||||
aciPreKeyStateRequest.identityKey assertIs aciIdentityKey
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.whispersystems.signalservice.api.push.DistributionId
|
|||
import org.whispersystems.signalservice.api.push.ServiceId
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos
|
||||
import java.lang.UnsupportedOperationException
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
@ -168,6 +169,10 @@ class BobClient(val serviceId: ServiceId, val e164: String, val identityKeyPair:
|
|||
override fun getSenderKeySharedWith(distributionId: DistributionId?): MutableSet<SignalProtocolAddress> = throw UnsupportedOperationException()
|
||||
override fun markSenderKeySharedWith(distributionId: DistributionId?, addresses: MutableCollection<SignalProtocolAddress>?) = throw UnsupportedOperationException()
|
||||
override fun clearSenderKeySharedWith(addresses: MutableCollection<SignalProtocolAddress>?) = throw UnsupportedOperationException()
|
||||
override fun storeLastResortKyberPreKey(kyberPreKeyId: Int, kyberPreKeyRecord: KyberPreKeyRecord) = throw UnsupportedOperationException()
|
||||
override fun removeKyberPreKey(kyberPreKeyId: Int) = throw UnsupportedOperationException()
|
||||
override fun loadLastResortKyberPreKeys(): List<KyberPreKeyRecord> = throw UnsupportedOperationException()
|
||||
|
||||
override fun isMultiDevice(): Boolean = throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ public class MainActivity extends PassphraseRequiredActivity implements VoiceNot
|
|||
handleGroupLinkInIntent(intent);
|
||||
handleProxyInIntent(intent);
|
||||
handleSignalMeIntent(intent);
|
||||
handleCallLinkInIntent(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,11 +21,12 @@ import java.net.URLDecoder
|
|||
*/
|
||||
object CallLinks {
|
||||
private const val ROOT_KEY = "key"
|
||||
private const val LINK_PREFIX = "https://signal.link/call/#key="
|
||||
private const val HTTPS_LINK_PREFIX = "https://signal.link/call/#key="
|
||||
private const val SNGL_LINK_PREFIX = "sgnl://signal.link/#key="
|
||||
|
||||
private val TAG = Log.tag(CallLinks::class.java)
|
||||
|
||||
fun url(linkKeyBytes: ByteArray) = "$LINK_PREFIX${CallLinkRootKey(linkKeyBytes)}"
|
||||
fun url(linkKeyBytes: ByteArray) = "$HTTPS_LINK_PREFIX${CallLinkRootKey(linkKeyBytes)}"
|
||||
|
||||
fun watchCallLink(roomId: CallLinkRoomId): Observable<CallLinkTable.CallLink> {
|
||||
return Observable.create { emitter ->
|
||||
|
@ -52,7 +53,8 @@ object CallLinks {
|
|||
|
||||
@JvmStatic
|
||||
fun parseUrl(url: String): CallLinkRootKey? {
|
||||
if (!url.startsWith(LINK_PREFIX)) {
|
||||
if (!url.startsWith(HTTPS_LINK_PREFIX) && !url.startsWith(SNGL_LINK_PREFIX)) {
|
||||
Log.w(TAG, "Invalid url prefix.")
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ import org.signal.core.ui.Buttons
|
|||
import org.signal.core.ui.theme.SignalTheme
|
||||
import org.signal.ringrtc.CallLinkRootKey
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColorPair
|
||||
import org.thoughtcrime.securesms.database.CallLinkTable
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
@ -49,7 +48,6 @@ import java.time.Instant
|
|||
@Preview
|
||||
@Composable
|
||||
private fun SignalCallRowPreview() {
|
||||
val avatarColor = remember { AvatarColor.random() }
|
||||
val callLink = remember {
|
||||
val credentials = CallLinkCredentials.generate()
|
||||
CallLinkTable.CallLink(
|
||||
|
@ -61,8 +59,7 @@ private fun SignalCallRowPreview() {
|
|||
restrictions = org.signal.ringrtc.CallLinkState.Restrictions.NONE,
|
||||
expiration = Instant.MAX,
|
||||
revoked = false
|
||||
),
|
||||
avatarColor = avatarColor
|
||||
)
|
||||
)
|
||||
}
|
||||
SignalTheme(false) {
|
||||
|
|
|
@ -7,7 +7,6 @@ package org.thoughtcrime.securesms.calls.links.create
|
|||
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
|
||||
import org.thoughtcrime.securesms.database.CallLinkTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
|
@ -24,7 +23,7 @@ import org.thoughtcrime.securesms.service.webrtc.links.SignalCallLinkManager
|
|||
class CreateCallLinkRepository(
|
||||
private val callLinkManager: SignalCallLinkManager = ApplicationDependencies.getSignalCallManager().callLinkManager
|
||||
) {
|
||||
fun ensureCallLinkCreated(credentials: CallLinkCredentials, avatarColor: AvatarColor): Single<EnsureCallLinkCreatedResult> {
|
||||
fun ensureCallLinkCreated(credentials: CallLinkCredentials): Single<EnsureCallLinkCreatedResult> {
|
||||
val callLinkRecipientId = Single.fromCallable {
|
||||
SignalDatabase.recipients.getByCallLinkRoomId(credentials.roomId)
|
||||
}
|
||||
|
@ -41,8 +40,7 @@ class CreateCallLinkRepository(
|
|||
recipientId = RecipientId.UNKNOWN,
|
||||
roomId = credentials.roomId,
|
||||
credentials = credentials,
|
||||
state = it.state,
|
||||
avatarColor = avatarColor
|
||||
state = it.state
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import io.reactivex.rxjava3.kotlin.subscribeBy
|
|||
import org.signal.ringrtc.CallLinkState.Restrictions
|
||||
import org.thoughtcrime.securesms.calls.links.CallLinks
|
||||
import org.thoughtcrime.securesms.calls.links.UpdateCallLinkRepository
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColorHash
|
||||
import org.thoughtcrime.securesms.database.CallLinkTable
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkCredentials
|
||||
|
@ -29,7 +28,6 @@ class CreateCallLinkViewModel(
|
|||
private val mutationRepository: UpdateCallLinkRepository = UpdateCallLinkRepository()
|
||||
) : ViewModel() {
|
||||
private val credentials = CallLinkCredentials.generate()
|
||||
private val avatarColor = AvatarColorHash.forCallLink(credentials.linkKeyBytes)
|
||||
private val _callLink: MutableState<CallLinkTable.CallLink> = mutableStateOf(
|
||||
CallLinkTable.CallLink(
|
||||
recipientId = RecipientId.UNKNOWN,
|
||||
|
@ -40,8 +38,7 @@ class CreateCallLinkViewModel(
|
|||
restrictions = Restrictions.NONE,
|
||||
revoked = false,
|
||||
expiration = Instant.MAX
|
||||
),
|
||||
avatarColor = avatarColor
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -63,7 +60,7 @@ class CreateCallLinkViewModel(
|
|||
}
|
||||
|
||||
fun commitCallLink(): Single<EnsureCallLinkCreatedResult> {
|
||||
return repository.ensureCallLinkCreated(credentials, avatarColor)
|
||||
return repository.ensureCallLinkCreated(credentials)
|
||||
}
|
||||
|
||||
fun setApproveAllMembers(approveAllMembers: Boolean): Single<UpdateCallLinkResult> {
|
||||
|
|
|
@ -200,8 +200,7 @@ private fun CallLinkDetailsPreview() {
|
|||
revoked = false,
|
||||
restrictions = Restrictions.NONE,
|
||||
expiration = Instant.MAX
|
||||
),
|
||||
avatarColor = avatarColor
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,6 @@ import org.thoughtcrime.securesms.calls.links.SignalCallRow
|
|||
import org.thoughtcrime.securesms.calls.links.details.CallLinkDetailsViewModel
|
||||
import org.thoughtcrime.securesms.components.AvatarImageView
|
||||
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor
|
||||
import org.thoughtcrime.securesms.database.CallLinkTable
|
||||
import org.thoughtcrime.securesms.events.WebRtcViewModel
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
@ -209,8 +208,7 @@ private fun SheetPreview() {
|
|||
linkKeyBytes = byteArrayOf(1, 2, 3, 4, 5),
|
||||
adminPassBytes = byteArrayOf(1, 2, 3, 4, 5)
|
||||
),
|
||||
state = SignalCallLinkState(),
|
||||
avatarColor = AvatarColor.random()
|
||||
state = SignalCallLinkState()
|
||||
),
|
||||
participants = listOf(Recipient.UNKNOWN).toImmutableList(),
|
||||
onShareLinkClicked = {},
|
||||
|
|
|
@ -265,7 +265,8 @@ public class WebRtcCallViewModel extends ViewModel {
|
|||
webRtcViewModel.getActiveDevice(),
|
||||
webRtcViewModel.getAvailableDevices(),
|
||||
webRtcViewModel.getRemoteDevicesCount().orElse(0),
|
||||
webRtcViewModel.getParticipantLimit());
|
||||
webRtcViewModel.getParticipantLimit(),
|
||||
webRtcViewModel.getRecipient().isCallLink());
|
||||
|
||||
if (newState.isInOutgoingRingingMode()) {
|
||||
cancelTimer();
|
||||
|
@ -339,7 +340,8 @@ public class WebRtcCallViewModel extends ViewModel {
|
|||
@NonNull SignalAudioManager.AudioDevice activeDevice,
|
||||
@NonNull Set<SignalAudioManager.AudioDevice> availableDevices,
|
||||
long remoteDevicesCount,
|
||||
@Nullable Long participantLimit)
|
||||
@Nullable Long participantLimit,
|
||||
boolean isCallLink)
|
||||
{
|
||||
final WebRtcControls.CallState callState;
|
||||
|
||||
|
@ -407,7 +409,8 @@ public class WebRtcCallViewModel extends ViewModel {
|
|||
participantLimit,
|
||||
WebRtcControls.FoldableState.flat(),
|
||||
activeDevice,
|
||||
availableDevices));
|
||||
availableDevices,
|
||||
isCallLink));
|
||||
}
|
||||
|
||||
private @NonNull WebRtcControls updateControlsFoldableState(@NonNull WebRtcControls.FoldableState foldableState, @NonNull WebRtcControls controls) {
|
||||
|
|
|
@ -27,7 +27,8 @@ public final class WebRtcControls {
|
|||
null,
|
||||
FoldableState.flat(),
|
||||
SignalAudioManager.AudioDevice.NONE,
|
||||
emptySet());
|
||||
emptySet(),
|
||||
false);
|
||||
|
||||
private final boolean isRemoteVideoEnabled;
|
||||
private final boolean isLocalVideoEnabled;
|
||||
|
@ -40,6 +41,7 @@ public final class WebRtcControls {
|
|||
private final FoldableState foldableState;
|
||||
private final SignalAudioManager.AudioDevice activeDevice;
|
||||
private final Set<SignalAudioManager.AudioDevice> availableDevices;
|
||||
private final boolean isCallLink;
|
||||
|
||||
private WebRtcControls() {
|
||||
this(false,
|
||||
|
@ -52,7 +54,8 @@ public final class WebRtcControls {
|
|||
null,
|
||||
FoldableState.flat(),
|
||||
SignalAudioManager.AudioDevice.NONE,
|
||||
emptySet());
|
||||
emptySet(),
|
||||
false);
|
||||
}
|
||||
|
||||
WebRtcControls(boolean isLocalVideoEnabled,
|
||||
|
@ -65,7 +68,8 @@ public final class WebRtcControls {
|
|||
@Nullable Long participantLimit,
|
||||
@NonNull FoldableState foldableState,
|
||||
@NonNull SignalAudioManager.AudioDevice activeDevice,
|
||||
@NonNull Set<SignalAudioManager.AudioDevice> availableDevices)
|
||||
@NonNull Set<SignalAudioManager.AudioDevice> availableDevices,
|
||||
boolean isCallLink)
|
||||
{
|
||||
this.isLocalVideoEnabled = isLocalVideoEnabled;
|
||||
this.isRemoteVideoEnabled = isRemoteVideoEnabled;
|
||||
|
@ -78,6 +82,7 @@ public final class WebRtcControls {
|
|||
this.foldableState = foldableState;
|
||||
this.activeDevice = activeDevice;
|
||||
this.availableDevices = availableDevices;
|
||||
this.isCallLink = isCallLink;
|
||||
}
|
||||
|
||||
public @NonNull WebRtcControls withFoldableState(FoldableState foldableState) {
|
||||
|
@ -91,7 +96,8 @@ public final class WebRtcControls {
|
|||
participantLimit,
|
||||
foldableState,
|
||||
activeDevice,
|
||||
availableDevices);
|
||||
availableDevices,
|
||||
isCallLink);
|
||||
}
|
||||
|
||||
boolean displayErrorControls() {
|
||||
|
@ -222,7 +228,7 @@ public final class WebRtcControls {
|
|||
}
|
||||
|
||||
boolean displayRingToggle() {
|
||||
return isPreJoin() && isGroupCall() && !hasAtLeastOneRemote;
|
||||
return isPreJoin() && isGroupCall() && !isCallLink && !hasAtLeastOneRemote;
|
||||
}
|
||||
|
||||
private boolean isError() {
|
||||
|
|
|
@ -18,7 +18,6 @@ import org.signal.core.util.requireInt
|
|||
import org.signal.core.util.requireLong
|
||||
import org.signal.core.util.requireNonNullBlob
|
||||
import org.signal.core.util.requireNonNullString
|
||||
import org.signal.core.util.requireString
|
||||
import org.signal.core.util.select
|
||||
import org.signal.core.util.update
|
||||
import org.signal.core.util.withinTransaction
|
||||
|
@ -53,7 +52,6 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
|
|||
const val RESTRICTIONS = "restrictions"
|
||||
const val REVOKED = "revoked"
|
||||
const val EXPIRATION = "expiration"
|
||||
const val AVATAR_COLOR = "avatar_color"
|
||||
const val RECIPIENT_ID = "recipient_id"
|
||||
|
||||
//language=sql
|
||||
|
@ -67,7 +65,6 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
|
|||
$RESTRICTIONS INTEGER NOT NULL,
|
||||
$REVOKED INTEGER NOT NULL,
|
||||
$EXPIRATION INTEGER NOT NULL,
|
||||
$AVATAR_COLOR TEXT NOT NULL,
|
||||
$RECIPIENT_ID INTEGER UNIQUE REFERENCES ${RecipientTable.TABLE_NAME} (${RecipientTable.ID}) ON DELETE CASCADE
|
||||
)
|
||||
"""
|
||||
|
@ -76,7 +73,7 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
|
|||
return contentValuesOf(
|
||||
NAME to name,
|
||||
RESTRICTIONS to restrictions.mapToInt(),
|
||||
EXPIRATION to expiration.toEpochMilli(),
|
||||
EXPIRATION to if (expiration == Instant.MAX) -1L else expiration.toEpochMilli(),
|
||||
REVOKED to revoked
|
||||
)
|
||||
}
|
||||
|
@ -94,7 +91,7 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
|
|||
callLink: CallLink
|
||||
) {
|
||||
writableDatabase.withinTransaction { db ->
|
||||
val recipientId = SignalDatabase.recipients.getOrInsertFromCallLinkRoomId(callLink.roomId, callLink.avatarColor)
|
||||
val recipientId = SignalDatabase.recipients.getOrInsertFromCallLinkRoomId(callLink.roomId)
|
||||
|
||||
db
|
||||
.insertInto(TABLE_NAME)
|
||||
|
@ -174,8 +171,7 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
|
|||
linkKeyBytes = callLinkRootKey.keyBytes,
|
||||
adminPassBytes = null
|
||||
),
|
||||
state = SignalCallLinkState(),
|
||||
avatarColor = AvatarColorHash.forCallLink(callLinkRootKey.keyBytes)
|
||||
state = SignalCallLinkState()
|
||||
)
|
||||
|
||||
insertCallLink(link)
|
||||
|
@ -194,8 +190,7 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
|
|||
recipientId = RecipientId.UNKNOWN,
|
||||
roomId = callLinkRoomId,
|
||||
credentials = null,
|
||||
state = SignalCallLinkState(),
|
||||
avatarColor = AvatarColor.random()
|
||||
state = SignalCallLinkState()
|
||||
)
|
||||
insertCallLink(link)
|
||||
return getCallLinkByRoomId(callLinkRoomId)!!
|
||||
|
@ -327,8 +322,7 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
|
|||
RECIPIENT_ID to data.recipientId.takeIf { it != RecipientId.UNKNOWN }?.toLong(),
|
||||
ROOM_ID to data.roomId.serialize(),
|
||||
ROOT_KEY to data.credentials?.linkKeyBytes,
|
||||
ADMIN_KEY to data.credentials?.adminPassBytes,
|
||||
AVATAR_COLOR to data.avatarColor.serialize()
|
||||
ADMIN_KEY to data.credentials?.adminPassBytes
|
||||
).apply {
|
||||
putAll(data.state.serialize())
|
||||
}
|
||||
|
@ -356,9 +350,14 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
|
|||
name = data.requireNonNullString(NAME),
|
||||
restrictions = data.requireInt(RESTRICTIONS).mapToRestrictions(),
|
||||
revoked = data.requireBoolean(REVOKED),
|
||||
expiration = Instant.ofEpochMilli(data.requireLong(EXPIRATION)).truncatedTo(ChronoUnit.DAYS)
|
||||
),
|
||||
avatarColor = AvatarColor.deserialize(data.requireString(AVATAR_COLOR))
|
||||
expiration = data.requireLong(EXPIRATION).let {
|
||||
if (it == -1L) {
|
||||
Instant.MAX
|
||||
} else {
|
||||
Instant.ofEpochMilli(it).truncatedTo(ChronoUnit.DAYS)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -375,9 +374,10 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
|
|||
val recipientId: RecipientId,
|
||||
val roomId: CallLinkRoomId,
|
||||
val credentials: CallLinkCredentials?,
|
||||
val state: SignalCallLinkState,
|
||||
val avatarColor: AvatarColor
|
||||
)
|
||||
val state: SignalCallLinkState
|
||||
) {
|
||||
val avatarColor: AvatarColor = credentials?.let { AvatarColorHash.forCallLink(it.linkKeyBytes) } ?: AvatarColor.UNKNOWN
|
||||
}
|
||||
|
||||
override fun remapRecipient(fromId: RecipientId, toId: RecipientId) {
|
||||
writableDatabase.update(TABLE_NAME)
|
||||
|
|
|
@ -568,15 +568,14 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
|||
).recipientId
|
||||
}
|
||||
|
||||
fun getOrInsertFromCallLinkRoomId(callLinkRoomId: CallLinkRoomId, avatarColor: AvatarColor): RecipientId {
|
||||
fun getOrInsertFromCallLinkRoomId(callLinkRoomId: CallLinkRoomId): RecipientId {
|
||||
return getOrInsertByColumn(
|
||||
CALL_LINK_ROOM_ID,
|
||||
callLinkRoomId.serialize(),
|
||||
contentValuesOf(
|
||||
GROUP_TYPE to GroupType.CALL_LINK.id,
|
||||
CALL_LINK_ROOM_ID to callLinkRoomId.serialize(),
|
||||
PROFILE_SHARING to 1,
|
||||
AVATAR_COLOR to avatarColor.serialize()
|
||||
PROFILE_SHARING to 1
|
||||
)
|
||||
).recipientId
|
||||
}
|
||||
|
|
|
@ -1794,7 +1794,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
recipientSettings,
|
||||
null,
|
||||
false,
|
||||
group.isActive
|
||||
group.isActive,
|
||||
null
|
||||
)
|
||||
Recipient(recipientId, details, false)
|
||||
} ?: Recipient.live(recipientId).get()
|
||||
|
|
|
@ -52,6 +52,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V193_BackCallLinksW
|
|||
import org.thoughtcrime.securesms.database.helpers.migration.V194_KyberPreKeyMigration
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V195_GroupMemberForeignKeyMigration
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V196_BackCallLinksWithRecipientV2
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V197_DropAvatarColorFromCallLinks
|
||||
|
||||
/**
|
||||
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
|
||||
|
@ -60,7 +61,7 @@ object SignalDatabaseMigrations {
|
|||
|
||||
val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass)
|
||||
|
||||
const val DATABASE_VERSION = 196
|
||||
const val DATABASE_VERSION = 197
|
||||
|
||||
@JvmStatic
|
||||
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
|
@ -255,6 +256,10 @@ object SignalDatabaseMigrations {
|
|||
if (oldVersion < 196) {
|
||||
V196_BackCallLinksWithRecipientV2.migrate(context, db, oldVersion, newVersion)
|
||||
}
|
||||
|
||||
if (oldVersion < 197) {
|
||||
V197_DropAvatarColorFromCallLinks.migrate(context, db, oldVersion, newVersion)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.database.helpers.migration
|
||||
|
||||
import android.app.Application
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabase
|
||||
|
||||
/**
|
||||
* Because getting the color is a simple modulo operation, there is no need to store it in the database.
|
||||
*/
|
||||
object V197_DropAvatarColorFromCallLinks : SignalDatabaseMigration {
|
||||
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
db.execSQL("ALTER TABLE call_link DROP COLUMN avatar_color")
|
||||
}
|
||||
}
|
|
@ -8,13 +8,11 @@ import org.signal.core.util.orNull
|
|||
import org.signal.libsignal.protocol.util.Pair
|
||||
import org.signal.ringrtc.CallException
|
||||
import org.signal.ringrtc.CallLinkRootKey
|
||||
import org.signal.ringrtc.CallLinkState
|
||||
import org.thoughtcrime.securesms.attachments.Attachment
|
||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
|
||||
import org.thoughtcrime.securesms.attachments.TombstoneAttachment
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiUtil
|
||||
import org.thoughtcrime.securesms.contactshare.Contact
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColorHash
|
||||
import org.thoughtcrime.securesms.crypto.SecurityEvent
|
||||
import org.thoughtcrime.securesms.database.CallLinkTable
|
||||
import org.thoughtcrime.securesms.database.CallTable
|
||||
|
@ -119,7 +117,6 @@ import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMe
|
|||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.StickerPackOperation
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.ViewOnceOpen
|
||||
import java.io.IOException
|
||||
import java.time.Instant
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
@ -1200,13 +1197,7 @@ object SyncMessageProcessor {
|
|||
linkKeyBytes = callLinkRootKey.keyBytes,
|
||||
adminPassBytes = callLinkUpdate.adminPassKey?.toByteArray()
|
||||
),
|
||||
state = SignalCallLinkState(
|
||||
name = "",
|
||||
restrictions = CallLinkState.Restrictions.UNKNOWN,
|
||||
revoked = false,
|
||||
expiration = Instant.MIN
|
||||
),
|
||||
avatarColor = AvatarColorHash.forCallLink(callLinkRootKey.keyBytes)
|
||||
state = SignalCallLinkState()
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.annimon.stream.Stream;
|
|||
|
||||
import org.signal.core.util.ThreadUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColor;
|
||||
import org.thoughtcrime.securesms.database.CallLinkTable;
|
||||
import org.thoughtcrime.securesms.database.DistributionListTables;
|
||||
import org.thoughtcrime.securesms.database.GroupTable;
|
||||
|
@ -219,10 +220,10 @@ public final class LiveRecipient {
|
|||
avatarId = Optional.of(groupRecord.get().getAvatarId());
|
||||
}
|
||||
|
||||
return new RecipientDetails(title, null, avatarId, false, false, record.getRegistered(), record, members, false, groupRecord.get().isActive());
|
||||
return new RecipientDetails(title, null, avatarId, false, false, record.getRegistered(), record, members, false, groupRecord.get().isActive(), null);
|
||||
}
|
||||
|
||||
return new RecipientDetails(null, null, Optional.empty(), false, false, record.getRegistered(), record, null, false, false);
|
||||
return new RecipientDetails(null, null, Optional.empty(), false, false, record.getRegistered(), record, null, false, false, null);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
|
@ -247,10 +248,10 @@ public final class LiveRecipient {
|
|||
if (callLink != null) {
|
||||
String name = callLink.getState().getName();
|
||||
|
||||
return RecipientDetails.forCallLink(name, record);
|
||||
return RecipientDetails.forCallLink(name, record, callLink.getAvatarColor());
|
||||
}
|
||||
|
||||
return RecipientDetails.forCallLink(null, record);
|
||||
return RecipientDetails.forCallLink(null, record, AvatarColor.UNKNOWN);
|
||||
}
|
||||
|
||||
synchronized void set(@NonNull Recipient recipient) {
|
||||
|
|
|
@ -98,7 +98,8 @@ public class RecipientDetails {
|
|||
@NonNull RecipientRecord record,
|
||||
@Nullable List<RecipientId> participantIds,
|
||||
boolean isReleaseChannel,
|
||||
boolean isActiveGroup)
|
||||
boolean isActiveGroup,
|
||||
@Nullable AvatarColor avatarColor)
|
||||
{
|
||||
this.groupAvatarId = groupAvatarId;
|
||||
this.systemContactPhoto = Util.uri(record.getSystemContactPhotoUri());
|
||||
|
@ -141,7 +142,7 @@ public class RecipientDetails {
|
|||
this.mentionSetting = record.getMentionSetting();
|
||||
this.wallpaper = record.getWallpaper();
|
||||
this.chatColors = record.getChatColors();
|
||||
this.avatarColor = record.getAvatarColor();
|
||||
this.avatarColor = avatarColor != null ? avatarColor : record.getAvatarColor();
|
||||
this.about = record.getAbout();
|
||||
this.aboutEmoji = record.getAboutEmoji();
|
||||
this.systemProfileName = record.getSystemProfileName();
|
||||
|
@ -227,15 +228,15 @@ public class RecipientDetails {
|
|||
}
|
||||
}
|
||||
|
||||
return new RecipientDetails(null, settings.getSystemDisplayName(), Optional.empty(), systemContact, isSelf, registeredState, settings, null, isReleaseChannel, false);
|
||||
return new RecipientDetails(null, settings.getSystemDisplayName(), Optional.empty(), systemContact, isSelf, registeredState, settings, null, isReleaseChannel, false, null);
|
||||
}
|
||||
|
||||
public static @NonNull RecipientDetails forDistributionList(String title, @Nullable List<RecipientId> members, @NonNull RecipientRecord record) {
|
||||
return new RecipientDetails(title, null, Optional.empty(), false, false, record.getRegistered(), record, members, false, false);
|
||||
return new RecipientDetails(title, null, Optional.empty(), false, false, record.getRegistered(), record, members, false, false, null);
|
||||
}
|
||||
|
||||
public static @NonNull RecipientDetails forCallLink(String name, @NonNull RecipientRecord record) {
|
||||
return new RecipientDetails(name, null, Optional.empty(), false, false, record.getRegistered(), record, Collections.emptyList(), false, false);
|
||||
public static @NonNull RecipientDetails forCallLink(String name, @NonNull RecipientRecord record, @NonNull AvatarColor avatarColor) {
|
||||
return new RecipientDetails(name, null, Optional.empty(), false, false, record.getRegistered(), record, Collections.emptyList(), false, false, avatarColor);
|
||||
}
|
||||
|
||||
public static @NonNull RecipientDetails forUnknown() {
|
||||
|
|
|
@ -26,15 +26,12 @@ import org.signal.core.util.concurrent.SignalExecutors;
|
|||
import org.signal.core.util.concurrent.SimpleTask;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.ringrtc.CallLinkRootKey;
|
||||
import org.signal.ringrtc.CallLinkState;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.WebRtcCallActivity;
|
||||
import org.thoughtcrime.securesms.calls.links.CallLinks;
|
||||
import org.thoughtcrime.securesms.contacts.sync.ContactDiscovery;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationIntents;
|
||||
import org.thoughtcrime.securesms.conversation.colors.AvatarColorHash;
|
||||
import org.thoughtcrime.securesms.database.CallLinkTable;
|
||||
import org.thoughtcrime.securesms.database.CallTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
|
@ -45,16 +42,12 @@ import org.thoughtcrime.securesms.groups.v2.GroupInviteLinkUrl;
|
|||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.proxy.ProxyBottomSheetFragment;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkCredentials;
|
||||
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId;
|
||||
import org.thoughtcrime.securesms.service.webrtc.links.SignalCallLinkState;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
|
||||
import org.whispersystems.signalservice.api.push.ServiceId;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
public class CommunicationActions {
|
||||
|
@ -343,8 +336,7 @@ public class CommunicationActions {
|
|||
public static void handlePotentialCallLinkUrl(@NonNull FragmentActivity activity, @NonNull String potentialUrl) {
|
||||
CallLinkRootKey rootKey = CallLinks.parseUrl(potentialUrl);
|
||||
if (rootKey == null) {
|
||||
Log.w(TAG, "Failed to parse root key from call link.");
|
||||
// TODO [alex] -- Display a dialog informing them that the URL was invalid.
|
||||
Log.w(TAG, "Failed to parse root key from call link");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -356,13 +348,17 @@ public class CommunicationActions {
|
|||
* the user's database if one does not already exist.
|
||||
*
|
||||
* @param fragment The fragment, which will be used for context and permissions routing.
|
||||
* @param rootKey The root key of the call link.
|
||||
*/
|
||||
public static void startVideoCall(@NonNull Fragment fragment, @NonNull CallLinkRootKey rootKey) {
|
||||
startVideoCall(new FragmentCallContext(fragment), rootKey);
|
||||
}
|
||||
|
||||
private static void startVideoCall(@NonNull CallContext callContext, @NonNull CallLinkRootKey rootKey) {
|
||||
if (!FeatureFlags.adHocCalling()) {
|
||||
Toast.makeText(callContext.getContext(), R.string.CommunicationActions_cant_join_call, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleTask.run(() -> {
|
||||
CallLinkRoomId roomId = CallLinkRoomId.fromBytes(rootKey.deriveRoomId());
|
||||
CallLinkTable.CallLink callLink = SignalDatabase.callLinks().getOrCreateCallLinkByRootKey(rootKey);
|
||||
|
|
|
@ -104,7 +104,7 @@ public final class FeatureFlags {
|
|||
private static final String PAYPAL_RECURRING_DONATIONS = "android.recurringPayPalDonations.3";
|
||||
private static final String TEXT_FORMATTING = "android.textFormatting.2";
|
||||
private static final String ANY_ADDRESS_PORTS_KILL_SWITCH = "android.calling.fieldTrial.anyAddressPortsKillSwitch";
|
||||
private static final String AD_HOC_CALLING = "android.calling.ad.hoc";
|
||||
private static final String AD_HOC_CALLING = "android.calling.ad.hoc.2";
|
||||
private static final String EDIT_MESSAGE_RECEIVE = "android.editMessage.receive";
|
||||
private static final String EDIT_MESSAGE_SEND = "android.editMessage.send";
|
||||
private static final String MAX_ATTACHMENT_COUNT = "android.attachments.maxCount";
|
||||
|
@ -169,13 +169,13 @@ public final class FeatureFlags {
|
|||
EDIT_MESSAGE_RECEIVE,
|
||||
EDIT_MESSAGE_SEND,
|
||||
MAX_ATTACHMENT_COUNT,
|
||||
MAX_ATTACHMENT_SIZE_MB
|
||||
MAX_ATTACHMENT_SIZE_MB,
|
||||
AD_HOC_CALLING
|
||||
);
|
||||
|
||||
@VisibleForTesting
|
||||
static final Set<String> NOT_REMOTE_CAPABLE = SetUtil.newHashSet(
|
||||
PHONE_NUMBER_PRIVACY,
|
||||
AD_HOC_CALLING
|
||||
PHONE_NUMBER_PRIVACY
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
@ -158,7 +158,8 @@ object RecipientDatabaseTestUtils {
|
|||
),
|
||||
participants,
|
||||
isReleaseChannel,
|
||||
isActive
|
||||
isActive,
|
||||
null
|
||||
),
|
||||
resolved
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue