mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-08-03 11:49:04 -04:00
checkpoint
This commit is contained in:
parent
8a5af51ec7
commit
37f6ca19f7
26 changed files with 357 additions and 166 deletions
|
@ -1,4 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:async_tools/async_tools.dart';
|
||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||
|
@ -15,7 +17,6 @@ class RenderStateElement {
|
|||
{required this.message,
|
||||
required this.isLocal,
|
||||
this.reconciled = false,
|
||||
this.reconciledOffline = false,
|
||||
this.sent = false,
|
||||
this.sentOffline = false});
|
||||
|
||||
|
@ -27,7 +28,7 @@ class RenderStateElement {
|
|||
if (sent && !sentOffline) {
|
||||
return MessageSendState.delivered;
|
||||
}
|
||||
if (reconciled && !reconciledOffline) {
|
||||
if (reconciled) {
|
||||
return MessageSendState.sent;
|
||||
}
|
||||
return MessageSendState.sending;
|
||||
|
@ -36,7 +37,6 @@ class RenderStateElement {
|
|||
proto.Message message;
|
||||
bool isLocal;
|
||||
bool reconciled;
|
||||
bool reconciledOffline;
|
||||
bool sent;
|
||||
bool sentOffline;
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
|
|||
);
|
||||
|
||||
// Make crypto
|
||||
await _initMessagesCrypto();
|
||||
await _initCrypto();
|
||||
|
||||
// Reconciled messages key
|
||||
await _initReconciledMessagesCubit();
|
||||
|
@ -109,9 +109,13 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
|
|||
}
|
||||
|
||||
// Make crypto
|
||||
Future<void> _initMessagesCrypto() async {
|
||||
Future<void> _initCrypto() async {
|
||||
_messagesCrypto = await _activeAccountInfo
|
||||
.makeConversationCrypto(_remoteIdentityPublicKey);
|
||||
_localMessagesCryptoSystem =
|
||||
await Veilid.instance.getCryptoSystem(_localMessagesRecordKey.kind);
|
||||
_identityCryptoSystem =
|
||||
await _activeAccountInfo.localAccount.identityMaster.identityCrypto;
|
||||
}
|
||||
|
||||
// Open local messages key
|
||||
|
@ -144,13 +148,16 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
|
|||
_updateRcvdMessagesState(_rcvdMessagesCubit!.state);
|
||||
}
|
||||
|
||||
Future<VeilidCrypto> _makeLocalMessagesCrypto() async =>
|
||||
VeilidCryptoPrivate.fromTypedKey(
|
||||
_activeAccountInfo.userLogin.identitySecret, 'tabledb');
|
||||
|
||||
// Open reconciled chat record key
|
||||
Future<void> _initReconciledMessagesCubit() async {
|
||||
final tableName = _localConversationRecordKey.toString();
|
||||
|
||||
xxx whats the right encryption for reconciled messages cubit?
|
||||
final crypto = await _makeLocalMessagesCrypto();
|
||||
|
||||
final crypto = VeilidCryptoPrivate.fromTypedKey(kind, secretKey);
|
||||
_reconciledMessagesCubit = TableDBArrayCubit(
|
||||
open: () async => TableDBArray.make(table: tableName, crypto: crypto),
|
||||
decodeElement: proto.Message.fromBuffer);
|
||||
|
@ -183,8 +190,8 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
|
|||
if (sentMessages == null) {
|
||||
return;
|
||||
}
|
||||
// Don't reconcile, the sending machine will have already added
|
||||
// to the reconciliation queue on that machine
|
||||
|
||||
await _reconcileMessages(sentMessages, _sentMessagesCubit);
|
||||
|
||||
// Update the view
|
||||
_renderState();
|
||||
|
@ -197,16 +204,18 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
|
|||
return;
|
||||
}
|
||||
|
||||
await _reconcileMessages(rcvdMessages, _rcvdMessagesCubit);
|
||||
|
||||
singleFuture(_rcvdMessagesCubit!, () async {
|
||||
// Get the timestamp of our most recent reconciled message
|
||||
final lastReconciledMessageTs =
|
||||
await _reconciledMessagesCubit!.operate((r) async {
|
||||
final len = r.length;
|
||||
await _reconciledMessagesCubit!.operate((arr) async {
|
||||
final len = arr.length;
|
||||
if (len == 0) {
|
||||
return null;
|
||||
} else {
|
||||
final lastMessage =
|
||||
await r.getItemProtobuf(proto.Message.fromBuffer, len - 1);
|
||||
await arr.getProtobuf(proto.Message.fromBuffer, len - 1);
|
||||
if (lastMessage == null) {
|
||||
throw StateError('should have gotten last message');
|
||||
}
|
||||
|
@ -232,11 +241,9 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
|
|||
});
|
||||
}
|
||||
|
||||
// Called when the reconciled messages list gets a change
|
||||
// This can happen when multiple clients for the same identity are
|
||||
// reading and reconciling the same remote chat
|
||||
// Called when the reconciled messages window gets a change
|
||||
void _updateReconciledMessagesState(
|
||||
DHTLogBusyState<proto.Message> avmessages) {
|
||||
TableDBArrayBusyState<proto.Message> avmessages) {
|
||||
// Update the view
|
||||
_renderState();
|
||||
}
|
||||
|
@ -252,10 +259,62 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
|
|||
// });
|
||||
}
|
||||
|
||||
Future<Uint8List> _hashSignature(proto.Signature signature) async =>
|
||||
(await _localMessagesCryptoSystem
|
||||
.generateHash(signature.toVeilid().decode()))
|
||||
.decode();
|
||||
|
||||
Future<void> _signMessage(proto.Message message) async {
|
||||
// Generate data to sign
|
||||
final data = Uint8List.fromList(utf8.encode(message.writeToJson()));
|
||||
|
||||
// Sign with our identity
|
||||
final signature = await _identityCryptoSystem.sign(
|
||||
_activeAccountInfo.localAccount.identityMaster.identityPublicKey,
|
||||
_activeAccountInfo.userLogin.identitySecret.value,
|
||||
data);
|
||||
|
||||
// Add to the message
|
||||
message.signature = signature.toProto();
|
||||
}
|
||||
|
||||
Future<void> _processMessageToSend(
|
||||
proto.Message message, proto.Message? previousMessage) async {
|
||||
// Get the previous message if we don't have one
|
||||
previousMessage ??= await _sentMessagesCubit!.operate((r) async =>
|
||||
r.length == 0
|
||||
? null
|
||||
: await r.getProtobuf(proto.Message.fromBuffer, r.length - 1));
|
||||
|
||||
if (previousMessage == null) {
|
||||
// If there's no last sent message,
|
||||
// we start at a hash of the identity public key
|
||||
message.id = (await _localMessagesCryptoSystem.generateHash(
|
||||
_activeAccountInfo.localAccount.identityMaster.identityPublicKey
|
||||
.decode()))
|
||||
.decode();
|
||||
} else {
|
||||
// If there is a last message, we generate the hash
|
||||
// of the last message's signature and use it as our next id
|
||||
message.id = await _hashSignature(previousMessage.signature);
|
||||
}
|
||||
|
||||
// Now sign it
|
||||
await _signMessage(message);
|
||||
}
|
||||
|
||||
// Async process to send messages in the background
|
||||
Future<void> _processSendingMessages(IList<proto.Message> messages) async {
|
||||
// Go through and assign ids to all the messages in order
|
||||
proto.Message? previousMessage;
|
||||
final processedMessages = messages.toList();
|
||||
for (final message in processedMessages) {
|
||||
await _processMessageToSend(message, previousMessage);
|
||||
previousMessage = message;
|
||||
}
|
||||
|
||||
await _sentMessagesCubit!.operateAppendEventual((writer) =>
|
||||
writer.tryAddItems(messages.map((m) => m.writeToBuffer()).toList()));
|
||||
writer.tryAddAll(messages.map((m) => m.writeToBuffer()).toList()));
|
||||
}
|
||||
|
||||
Future<void> _reconcileMessagesInner(
|
||||
|
@ -345,9 +404,8 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
|
|||
keyMapper: (x) => x.value.timestamp,
|
||||
values: sentMessages.elements,
|
||||
);
|
||||
final reconciledMessagesMap =
|
||||
IMap<Int64, DHTLogElementState<proto.Message>>.fromValues(
|
||||
keyMapper: (x) => x.value.timestamp,
|
||||
final reconciledMessagesMap = IMap<Int64, proto.Message>.fromValues(
|
||||
keyMapper: (x) => x.timestamp,
|
||||
values: reconciledMessages.elements,
|
||||
);
|
||||
final sendingMessagesMap = IMap<Int64, proto.Message>.fromValues(
|
||||
|
@ -416,7 +474,7 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
|
|||
emit(AsyncValue.data(renderedState));
|
||||
}
|
||||
|
||||
void addTextMessage({required proto.Message_Text messageText}) {
|
||||
void sendTextMessage({required proto.Message_Text messageText}) {
|
||||
final message = proto.Message()
|
||||
..id = generateNextId()
|
||||
..author = _activeAccountInfo.localAccount.identityMaster
|
||||
|
@ -425,7 +483,6 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
|
|||
..timestamp = Veilid.instance.now().toInt64()
|
||||
..text = messageText;
|
||||
|
||||
_unreconciledMessagesQueue.addSync(message);
|
||||
_sendingMessagesQueue.addSync(message);
|
||||
|
||||
// Update the view
|
||||
|
@ -456,15 +513,18 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
|
|||
final TypedKey _remoteMessagesRecordKey;
|
||||
|
||||
late final VeilidCrypto _messagesCrypto;
|
||||
late final VeilidCryptoSystem _localMessagesCryptoSystem;
|
||||
late final VeilidCryptoSystem _identityCryptoSystem;
|
||||
|
||||
DHTLogCubit<proto.Message>? _sentMessagesCubit;
|
||||
DHTLogCubit<proto.Message>? _rcvdMessagesCubit;
|
||||
TableDBArrayCubit<proto.Message>? _reconciledMessagesCubit;
|
||||
|
||||
late final PersistentQueue<proto.Message> _unreconciledMessagesQueue;
|
||||
late final PersistentQueue<proto.Message> _unreconciledMessagesQueue; xxx can we eliminate this? and make rcvd messages cubit listener work like sent?
|
||||
late final PersistentQueue<proto.Message> _sendingMessagesQueue;
|
||||
|
||||
StreamSubscription<DHTLogBusyState<proto.Message>>? _sentSubscription;
|
||||
StreamSubscription<DHTLogBusyState<proto.Message>>? _rcvdSubscription;
|
||||
StreamSubscription<DHTLogBusyState<proto.Message>>? _reconciledSubscription;
|
||||
StreamSubscription<TableDBArrayBusyState<proto.Message>>?
|
||||
_reconciledSubscription;
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ class ChatComponent extends StatelessWidget {
|
|||
..viewLimit = viewLimit ?? 0;
|
||||
protoMessageText.attachments.addAll(attachments);
|
||||
|
||||
_messagesCubit.addTextMessage(messageText: protoMessageText);
|
||||
_messagesCubit.sendTextMessage(messageText: protoMessageText);
|
||||
}
|
||||
|
||||
void _handleSendPressed(types.PartialText message) {
|
||||
|
|
|
@ -65,7 +65,7 @@ class ChatListCubit extends DHTShortArrayCubit<proto.Chat>
|
|||
await operateWrite((writer) async {
|
||||
// See if we have added this chat already
|
||||
for (var i = 0; i < writer.length; i++) {
|
||||
final cbuf = await writer.getItem(i);
|
||||
final cbuf = await writer.get(i);
|
||||
if (cbuf == null) {
|
||||
throw Exception('Failed to get chat');
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ class ChatListCubit extends DHTShortArrayCubit<proto.Chat>
|
|||
..remoteConversationRecordKey = remoteConversationRecordKey.toProto();
|
||||
|
||||
// Add chat
|
||||
final added = await writer.tryAddItem(chat.writeToBuffer());
|
||||
final added = await writer.tryAdd(chat.writeToBuffer());
|
||||
if (!added) {
|
||||
throw Exception('Failed to add chat');
|
||||
}
|
||||
|
@ -106,15 +106,14 @@ class ChatListCubit extends DHTShortArrayCubit<proto.Chat>
|
|||
activeChatCubit.setActiveChat(null);
|
||||
}
|
||||
for (var i = 0; i < writer.length; i++) {
|
||||
final c =
|
||||
await writer.getItemProtobuf(proto.Chat.fromBuffer, i);
|
||||
final c = await writer.getProtobuf(proto.Chat.fromBuffer, i);
|
||||
if (c == null) {
|
||||
throw Exception('Failed to get chat');
|
||||
}
|
||||
if (c.localConversationRecordKey ==
|
||||
localConversationRecordKeyProto) {
|
||||
// Found the right chat
|
||||
await writer.removeItem(i);
|
||||
await writer.remove(i);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,7 +159,7 @@ class ContactInvitationListCubit
|
|||
// Add ContactInvitationRecord to account's list
|
||||
// if this fails, don't keep retrying, user can try again later
|
||||
await operateWrite((writer) async {
|
||||
if (await writer.tryAddItem(cinvrec.writeToBuffer()) == false) {
|
||||
if (await writer.tryAdd(cinvrec.writeToBuffer()) == false) {
|
||||
throw Exception('Failed to add contact invitation record');
|
||||
}
|
||||
});
|
||||
|
@ -179,14 +179,14 @@ class ContactInvitationListCubit
|
|||
// Remove ContactInvitationRecord from account's list
|
||||
final deletedItem = await operateWrite((writer) async {
|
||||
for (var i = 0; i < writer.length; i++) {
|
||||
final item = await writer.getItemProtobuf(
|
||||
final item = await writer.getProtobuf(
|
||||
proto.ContactInvitationRecord.fromBuffer, i);
|
||||
if (item == null) {
|
||||
throw Exception('Failed to get contact invitation record');
|
||||
}
|
||||
if (item.contactRequestInbox.recordKey.toVeilid() ==
|
||||
contactRequestInboxRecordKey) {
|
||||
await writer.removeItem(i);
|
||||
await writer.remove(i);
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ class ContactListCubit extends DHTShortArrayCubit<proto.Contact> {
|
|||
// Add Contact to account's list
|
||||
// if this fails, don't keep retrying, user can try again later
|
||||
await operateWrite((writer) async {
|
||||
if (!await writer.tryAddItem(contact.writeToBuffer())) {
|
||||
if (!await writer.tryAdd(contact.writeToBuffer())) {
|
||||
throw Exception('Failed to add contact record');
|
||||
}
|
||||
});
|
||||
|
@ -72,13 +72,13 @@ class ContactListCubit extends DHTShortArrayCubit<proto.Contact> {
|
|||
// Remove Contact from account's list
|
||||
final deletedItem = await operateWrite((writer) async {
|
||||
for (var i = 0; i < writer.length; i++) {
|
||||
final item = await writer.getItemProtobuf(proto.Contact.fromBuffer, i);
|
||||
final item = await writer.getProtobuf(proto.Contact.fromBuffer, i);
|
||||
if (item == null) {
|
||||
throw Exception('Failed to get contact');
|
||||
}
|
||||
if (item.localConversationRecordKey ==
|
||||
contact.localConversationRecordKey) {
|
||||
await writer.removeItem(i);
|
||||
await writer.remove(i);
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -486,7 +486,7 @@ class Message_ControlDelete extends $pb.GeneratedMessage {
|
|||
factory Message_ControlDelete.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Message.ControlDelete', package: const $pb.PackageName(_omitMessageNames ? '' : 'veilidchat'), createEmptyInstance: create)
|
||||
..pc<$0.TypedKey>(1, _omitFieldNames ? '' : 'ids', $pb.PbFieldType.PM, subBuilder: $0.TypedKey.create)
|
||||
..p<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'ids', $pb.PbFieldType.PY)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
|
@ -512,7 +512,7 @@ class Message_ControlDelete extends $pb.GeneratedMessage {
|
|||
static Message_ControlDelete? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$0.TypedKey> get ids => $_getList(0);
|
||||
$core.List<$core.List<$core.int>> get ids => $_getList(0);
|
||||
}
|
||||
|
||||
class Message_ControlErase extends $pb.GeneratedMessage {
|
||||
|
@ -696,8 +696,8 @@ class Message_ControlModeration extends $pb.GeneratedMessage {
|
|||
factory Message_ControlModeration.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Message.ControlModeration', package: const $pb.PackageName(_omitMessageNames ? '' : 'veilidchat'), createEmptyInstance: create)
|
||||
..pc<$0.TypedKey>(1, _omitFieldNames ? '' : 'acceptedIds', $pb.PbFieldType.PM, subBuilder: $0.TypedKey.create)
|
||||
..pc<$0.TypedKey>(2, _omitFieldNames ? '' : 'rejectedIds', $pb.PbFieldType.PM, subBuilder: $0.TypedKey.create)
|
||||
..p<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'acceptedIds', $pb.PbFieldType.PY)
|
||||
..p<$core.List<$core.int>>(2, _omitFieldNames ? '' : 'rejectedIds', $pb.PbFieldType.PY)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
|
@ -723,10 +723,46 @@ class Message_ControlModeration extends $pb.GeneratedMessage {
|
|||
static Message_ControlModeration? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$0.TypedKey> get acceptedIds => $_getList(0);
|
||||
$core.List<$core.List<$core.int>> get acceptedIds => $_getList(0);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.List<$0.TypedKey> get rejectedIds => $_getList(1);
|
||||
$core.List<$core.List<$core.int>> get rejectedIds => $_getList(1);
|
||||
}
|
||||
|
||||
class Message_ControlReadReceipt extends $pb.GeneratedMessage {
|
||||
factory Message_ControlReadReceipt() => create();
|
||||
Message_ControlReadReceipt._() : super();
|
||||
factory Message_ControlReadReceipt.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory Message_ControlReadReceipt.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Message.ControlReadReceipt', package: const $pb.PackageName(_omitMessageNames ? '' : 'veilidchat'), createEmptyInstance: create)
|
||||
..p<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'readIds', $pb.PbFieldType.PY)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
Message_ControlReadReceipt clone() => Message_ControlReadReceipt()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
Message_ControlReadReceipt copyWith(void Function(Message_ControlReadReceipt) updates) => super.copyWith((message) => updates(message as Message_ControlReadReceipt)) as Message_ControlReadReceipt;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Message_ControlReadReceipt create() => Message_ControlReadReceipt._();
|
||||
Message_ControlReadReceipt createEmptyInstance() => create();
|
||||
static $pb.PbList<Message_ControlReadReceipt> createRepeated() => $pb.PbList<Message_ControlReadReceipt>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Message_ControlReadReceipt getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Message_ControlReadReceipt>(create);
|
||||
static Message_ControlReadReceipt? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$core.List<$core.int>> get readIds => $_getList(0);
|
||||
}
|
||||
|
||||
enum Message_Kind {
|
||||
|
|
|
@ -172,7 +172,7 @@ const Message$json = {
|
|||
{'1': 'moderation', '3': 11, '4': 1, '5': 11, '6': '.veilidchat.Message.ControlModeration', '9': 0, '10': 'moderation'},
|
||||
{'1': 'signature', '3': 12, '4': 1, '5': 11, '6': '.veilid.Signature', '10': 'signature'},
|
||||
],
|
||||
'3': [Message_Text$json, Message_Secret$json, Message_ControlDelete$json, Message_ControlErase$json, Message_ControlSettings$json, Message_ControlPermissions$json, Message_ControlMembership$json, Message_ControlModeration$json],
|
||||
'3': [Message_Text$json, Message_Secret$json, Message_ControlDelete$json, Message_ControlErase$json, Message_ControlSettings$json, Message_ControlPermissions$json, Message_ControlMembership$json, Message_ControlModeration$json, Message_ControlReadReceipt$json],
|
||||
'8': [
|
||||
{'1': 'kind'},
|
||||
],
|
||||
|
@ -208,7 +208,7 @@ const Message_Secret$json = {
|
|||
const Message_ControlDelete$json = {
|
||||
'1': 'ControlDelete',
|
||||
'2': [
|
||||
{'1': 'ids', '3': 1, '4': 3, '5': 11, '6': '.veilid.TypedKey', '10': 'ids'},
|
||||
{'1': 'ids', '3': 1, '4': 3, '5': 12, '10': 'ids'},
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -248,8 +248,16 @@ const Message_ControlMembership$json = {
|
|||
const Message_ControlModeration$json = {
|
||||
'1': 'ControlModeration',
|
||||
'2': [
|
||||
{'1': 'accepted_ids', '3': 1, '4': 3, '5': 11, '6': '.veilid.TypedKey', '10': 'acceptedIds'},
|
||||
{'1': 'rejected_ids', '3': 2, '4': 3, '5': 11, '6': '.veilid.TypedKey', '10': 'rejectedIds'},
|
||||
{'1': 'accepted_ids', '3': 1, '4': 3, '5': 12, '10': 'acceptedIds'},
|
||||
{'1': 'rejected_ids', '3': 2, '4': 3, '5': 12, '10': 'rejectedIds'},
|
||||
],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use messageDescriptor instead')
|
||||
const Message_ControlReadReceipt$json = {
|
||||
'1': 'ControlReadReceipt',
|
||||
'2': [
|
||||
{'1': 'read_ids', '3': 1, '4': 3, '5': 12, '10': 'readIds'},
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -272,15 +280,15 @@ final $typed_data.Uint8List messageDescriptor = $convert.base64Decode(
|
|||
'HQoKdmlld19saW1pdBgFIAEoDVIJdmlld0xpbWl0EjgKC2F0dGFjaG1lbnRzGAYgAygLMhYudm'
|
||||
'VpbGlkY2hhdC5BdHRhY2htZW50UgthdHRhY2htZW50c0IICgZfdG9waWNCCwoJX3JlcGx5X2lk'
|
||||
'GkgKBlNlY3JldBIeCgpjaXBoZXJ0ZXh0GAEgASgMUgpjaXBoZXJ0ZXh0Eh4KCmV4cGlyYXRpb2'
|
||||
'4YAiABKARSCmV4cGlyYXRpb24aMwoNQ29udHJvbERlbGV0ZRIiCgNpZHMYASADKAsyEC52ZWls'
|
||||
'aWQuVHlwZWRLZXlSA2lkcxosCgxDb250cm9sRXJhc2USHAoJdGltZXN0YW1wGAEgASgEUgl0aW'
|
||||
'1lc3RhbXAaRwoPQ29udHJvbFNldHRpbmdzEjQKCHNldHRpbmdzGAEgASgLMhgudmVpbGlkY2hh'
|
||||
'dC5DaGF0U2V0dGluZ3NSCHNldHRpbmdzGk8KEkNvbnRyb2xQZXJtaXNzaW9ucxI5CgtwZXJtaX'
|
||||
'NzaW9ucxgBIAEoCzIXLnZlaWxpZGNoYXQuUGVybWlzc2lvbnNSC3Blcm1pc3Npb25zGksKEUNv'
|
||||
'bnRyb2xNZW1iZXJzaGlwEjYKCm1lbWJlcnNoaXAYASABKAsyFi52ZWlsaWRjaGF0Lk1lbWJlcn'
|
||||
'NoaXBSCm1lbWJlcnNoaXAafQoRQ29udHJvbE1vZGVyYXRpb24SMwoMYWNjZXB0ZWRfaWRzGAEg'
|
||||
'AygLMhAudmVpbGlkLlR5cGVkS2V5UgthY2NlcHRlZElkcxIzCgxyZWplY3RlZF9pZHMYAiADKA'
|
||||
'syEC52ZWlsaWQuVHlwZWRLZXlSC3JlamVjdGVkSWRzQgYKBGtpbmQ=');
|
||||
'4YAiABKARSCmV4cGlyYXRpb24aIQoNQ29udHJvbERlbGV0ZRIQCgNpZHMYASADKAxSA2lkcxos'
|
||||
'CgxDb250cm9sRXJhc2USHAoJdGltZXN0YW1wGAEgASgEUgl0aW1lc3RhbXAaRwoPQ29udHJvbF'
|
||||
'NldHRpbmdzEjQKCHNldHRpbmdzGAEgASgLMhgudmVpbGlkY2hhdC5DaGF0U2V0dGluZ3NSCHNl'
|
||||
'dHRpbmdzGk8KEkNvbnRyb2xQZXJtaXNzaW9ucxI5CgtwZXJtaXNzaW9ucxgBIAEoCzIXLnZlaW'
|
||||
'xpZGNoYXQuUGVybWlzc2lvbnNSC3Blcm1pc3Npb25zGksKEUNvbnRyb2xNZW1iZXJzaGlwEjYK'
|
||||
'Cm1lbWJlcnNoaXAYASABKAsyFi52ZWlsaWRjaGF0Lk1lbWJlcnNoaXBSCm1lbWJlcnNoaXAaWQ'
|
||||
'oRQ29udHJvbE1vZGVyYXRpb24SIQoMYWNjZXB0ZWRfaWRzGAEgAygMUgthY2NlcHRlZElkcxIh'
|
||||
'CgxyZWplY3RlZF9pZHMYAiADKAxSC3JlamVjdGVkSWRzGi8KEkNvbnRyb2xSZWFkUmVjZWlwdB'
|
||||
'IZCghyZWFkX2lkcxgBIAMoDFIHcmVhZElkc0IGCgRraW5k');
|
||||
|
||||
@$core.Deprecated('Use reconciledMessageDescriptor instead')
|
||||
const ReconciledMessage$json = {
|
||||
|
|
|
@ -146,7 +146,7 @@ message Message {
|
|||
// A 'delete' control message
|
||||
// Deletes a set of messages by their ids
|
||||
message ControlDelete {
|
||||
repeated veilid.TypedKey ids = 1;
|
||||
repeated bytes ids = 1;
|
||||
}
|
||||
// An 'erase' control message
|
||||
// Deletes a set of messages from before some timestamp
|
||||
|
@ -175,8 +175,13 @@ message Message {
|
|||
// A 'moderation' control message
|
||||
// Accepts or rejects a set of messages
|
||||
message ControlModeration {
|
||||
repeated veilid.TypedKey accepted_ids = 1;
|
||||
repeated veilid.TypedKey rejected_ids = 2;
|
||||
repeated bytes accepted_ids = 1;
|
||||
repeated bytes rejected_ids = 2;
|
||||
}
|
||||
|
||||
// A 'read receipt' control message
|
||||
message ControlReadReceipt {
|
||||
repeated bytes read_ids = 1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue