Skip to content

Commit d7c8b45

Browse files
committed
Add annotations (in this PR limited to subscribe only to support Chat SDK reactions - ably/ably-chat-swift#293).
Reference implementation - ably/ably-js#1953 Docstrings - ably/specification#292 Annotation subscription (both summary and raw) is tested in ably/ably-chat-swift#293 (see integration test).
1 parent b00162a commit d7c8b45

27 files changed

Lines changed: 805 additions & 14 deletions

Ably.xcodeproj/project.pbxproj

Lines changed: 72 additions & 0 deletions
Large diffs are not rendered by default.

Source/ARTAnnotation.m

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#import "ARTAnnotation.h"
2+
#import "ARTJsonEncoder.h"
3+
#import "ARTJsonLikeEncoder.h"
4+
#import "ARTAnnotation+Private.h"
5+
#import "ARTNSArray+ARTFunctional.h"
6+
#import "ARTInternalLog.h"
7+
8+
@implementation ARTAnnotation
9+
10+
- (instancetype)initWithId:(NSString *)annotationId
11+
action:(ARTAnnotationAction)action
12+
clientId:(NSString *)clientId
13+
name:(NSString *)name
14+
count:(NSNumber *)count
15+
data:(id)data
16+
encoding:(NSString *)encoding
17+
timestamp:(NSDate *)timestamp
18+
serial:(NSString *)serial
19+
messageSerial:(NSString *)messageSerial
20+
type:(NSString *)type
21+
extras:(id<ARTJsonCompatible>)extras {
22+
if (self = [self init]) {
23+
_id = annotationId;
24+
_action = action;
25+
_clientId = clientId;
26+
_name = name;
27+
_count = count;
28+
_data = data;
29+
_encoding = encoding;
30+
_timestamp = timestamp;
31+
_serial = serial;
32+
_messageSerial = messageSerial;
33+
_type = type;
34+
_extras = extras;
35+
}
36+
return self;
37+
}
38+
39+
- (NSString *)description {
40+
NSMutableString *description = [[super description] mutableCopy];
41+
[description deleteCharactersInRange:NSMakeRange(description.length - (description.length>2 ? 2:0), 2)];
42+
[description appendFormat:@",\n"];
43+
[description appendFormat:@" id: %@,\n", self.id];
44+
[description appendFormat:@" action: %@\n", ARTAnnotationActionToStr(self.action)];
45+
[description appendFormat:@" clientId: %@,\n", self.clientId];
46+
[description appendFormat:@" name: %@\n", self.name];
47+
[description appendFormat:@" count: %@\n", self.count];
48+
[description appendFormat:@" data: %@\n", self.data];
49+
[description appendFormat:@" encoding: %@,\n", self.encoding];
50+
[description appendFormat:@" timestamp: %@,\n", self.timestamp];
51+
[description appendFormat:@" serial: %@\n", self.serial];
52+
[description appendFormat:@" messageSerial: %@\n", self.messageSerial];
53+
[description appendFormat:@" type: %@\n", self.type];
54+
[description appendFormat:@" extras: %@\n", self.extras];
55+
[description appendFormat:@"}"];
56+
return description;
57+
}
58+
59+
- (id)copyWithZone:(NSZone *)zone {
60+
ARTAnnotation *annotation = [[self.class allocWithZone:zone] init];
61+
annotation->_id = self.id;
62+
annotation->_clientId = self.clientId;
63+
annotation->_timestamp = self.timestamp;
64+
annotation->_data = [self.data copy];
65+
annotation->_extras = self.extras;
66+
annotation->_encoding = self.encoding;
67+
annotation->_action = self.action;
68+
annotation->_serial = self.serial;
69+
annotation->_messageSerial = self.messageSerial;
70+
annotation->_type = self.type;
71+
annotation->_name = self.name;
72+
annotation->_count = self.count;
73+
return annotation;
74+
}
75+
76+
- (id)decodeWithEncoder:(ARTDataEncoder*)encoder error:(NSError **)error {
77+
ARTDataEncoderOutput *decoded = [encoder decode:self.data encoding:self.encoding];
78+
if (decoded.errorInfo && error) {
79+
*error = [NSError errorWithDomain:ARTAblyErrorDomain code:decoded.errorInfo.code userInfo:@{NSLocalizedDescriptionKey: @"decoding failed",
80+
NSLocalizedFailureReasonErrorKey: decoded.errorInfo.message}];
81+
}
82+
id ret = [self copy];
83+
((ARTAnnotation *)ret)->_data = decoded.data;
84+
((ARTAnnotation *)ret)->_encoding = decoded.encoding;
85+
return ret;
86+
}
87+
88+
- (id)encodeWithEncoder:(ARTDataEncoder*)encoder error:(NSError **)error {
89+
ARTDataEncoderOutput *encoded = [encoder encode:self.data];
90+
if (encoded.errorInfo && error) {
91+
*error = [NSError errorWithDomain:ARTAblyErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"encoding failed",
92+
NSLocalizedFailureReasonErrorKey: encoded.errorInfo.message}];
93+
}
94+
id ret = [self copy];
95+
((ARTAnnotation *)ret)->_data = encoded.data;
96+
((ARTAnnotation *)ret)->_encoding = [NSString artAddEncoding:encoded.encoding toString:self.encoding];
97+
return ret;
98+
}
99+
100+
@end
101+
102+
NSString *ARTAnnotationActionToStr(ARTAnnotationAction action) {
103+
switch (action) {
104+
case ARTAnnotationCreate:
105+
return @"Create"; //0
106+
case ARTAnnotationDelete:
107+
return @"Delete"; //1
108+
}
109+
return @"Unknown";
110+
}
111+
112+
#pragma mark - ARTEvent
113+
114+
@implementation ARTEvent (AnnotationType)
115+
116+
- (instancetype)initWithAnnotationType:(NSString *)type {
117+
return [self initWithString:[NSString stringWithFormat:@"ARTAnnotation:%@", type]];
118+
}
119+
120+
+ (instancetype)newWithAnnotationType:(NSString *)type {
121+
return [[self alloc] initWithAnnotationType:type];
122+
}
123+
124+
@end

Source/ARTBaseMessage.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ - (NSString *)description {
5757
[description appendFormat:@" timestamp: %@,\n", self.timestamp];
5858
[description appendFormat:@" encoding: %@,\n", self.encoding];
5959
[description appendFormat:@" data: %@\n", self.data];
60+
[description appendFormat:@" extras: %@\n", self.extras];
6061
[description appendFormat:@"}"];
6162
return description;
6263
}

Source/ARTJsonLikeEncoder.m

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#import "ARTMessage.h"
66
#import "ARTPresence.h"
77
#import "ARTPresenceMessage.h"
8+
#import "ARTAnnotation.h"
89
#import "ARTProtocolMessage.h"
910
#import "ARTProtocolMessage+Private.h"
1011
#import "ARTNSDictionary+ARTDictionaryUtil.h"
@@ -298,6 +299,7 @@ - (ARTMessage *)messageFromDictionary:(NSDictionary *)input protocolMessage:(ART
298299
if (operation && [operation isKindOfClass:[NSDictionary class]]) {
299300
message.operation = [ARTMessageOperation createFromDictionary:operation];
300301
}
302+
message.summary = [input objectForKey:@"summary"];
301303

302304
return message;
303305
}
@@ -334,7 +336,18 @@ - (ARTPresenceAction)presenceActionFromInt:(int) action
334336
}
335337
ARTLogError(_logger, @"RS:%p ARTJsonEncoder invalid ARTPresenceAction %d", _rest, action);
336338
return ARTPresenceAbsent;
337-
339+
}
340+
341+
- (ARTAnnotationAction)annotationActionFromInt:(int)action
342+
{
343+
switch (action) {
344+
case 0:
345+
return ARTAnnotationCreate;
346+
case 1:
347+
return ARTAnnotationDelete;
348+
}
349+
ARTLogError(_logger, @"RS:%p ARTJsonEncoder invalid ARTAnnotationAction %d", _rest, action);
350+
return ARTAnnotationCreate;
338351
}
339352

340353
- (int)intFromPresenceMessageAction:(ARTPresenceAction) action
@@ -390,6 +403,43 @@ - (NSArray *)presenceMessagesFromArray:(NSArray *)input {
390403
return output;
391404
}
392405

406+
- (ARTAnnotation *)annotationFromDictionary:(NSDictionary *)input {
407+
ARTLogVerbose(_logger, @"RS:%p ARTJsonLikeEncoder<%@>: annotationFromDictionary %@", _rest, [_delegate formatAsString], input);
408+
if (![input isKindOfClass:[NSDictionary class]]) {
409+
return nil;
410+
}
411+
int action = [[input artNumber:@"action"] intValue];
412+
ARTAnnotation *annotation = [[ARTAnnotation alloc] initWithId:[input artString:@"id"]
413+
action:[self annotationActionFromInt:action]
414+
clientId:[input artString:@"clientId"]
415+
name:[input artString:@"name"]
416+
count:[input artNumber:@"count"]
417+
data:[input objectForKey:@"data"]
418+
encoding:[input artString:@"encoding"]
419+
timestamp:[input artTimestamp:@"timestamp"]
420+
serial:[input artString:@"serial"]
421+
messageSerial:[input artString:@"messageSerial"]
422+
type:[input artString:@"type"]
423+
extras:[input objectForKey:@"extras"]];
424+
return annotation;
425+
}
426+
427+
- (NSArray *)annotationsFromArray:(NSArray *)input {
428+
if (![input isKindOfClass:[NSArray class]]) {
429+
return nil;
430+
}
431+
432+
NSMutableArray *output = [NSMutableArray array];
433+
for (NSDictionary *item in input) {
434+
ARTAnnotation *annotation = [self annotationFromDictionary:item];
435+
if (!annotation) {
436+
return nil;
437+
}
438+
[output addObject:annotation];
439+
}
440+
return output;
441+
}
442+
393443
- (NSDictionary *)messageToDictionary:(ARTMessage *)message {
394444
NSMutableDictionary *output = [NSMutableDictionary dictionary];
395445
if (message.id) {
@@ -765,6 +815,7 @@ - (ARTProtocolMessage *)protocolMessageFromDictionary:(NSDictionary *)input {
765815
NSMutableArray *messages = [[input objectForKey:@"messages"] mutableCopy];
766816
message.messages = [self messagesFromArray:messages protocolMessage:message];
767817
message.presence = [self presenceMessagesFromArray:[input objectForKey:@"presence"]];
818+
message.annotations = [self annotationsFromArray:[input objectForKey:@"annotations"]];
768819

769820
return message;
770821
}

Source/ARTMessage.m

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,16 @@ - (NSString *)description {
3030
[description deleteCharactersInRange:NSMakeRange(description.length - (description.length>2 ? 2:0), 2)];
3131
[description appendFormat:@",\n"];
3232
[description appendFormat:@" name: %@\n", self.name];
33-
if (self.extras) {
34-
[description appendFormat:@" extras: %@\n", self.extras];
35-
}
33+
[description appendFormat:@" action: %@\n", ARTMessageActionToStr(self.action)];
34+
[description appendFormat:@" serial: %@\n", self.serial];
35+
[description appendFormat:@" updateSerial: %@\n", self.updateSerial];
36+
[description appendFormat:@" version: %@\n", self.version];
37+
[description appendFormat:@" createdAt: %@\n", self.createdAt];
38+
[description appendFormat:@" updatedAt: %@\n", self.updatedAt];
39+
[description appendFormat:@" refType: %@\n", self.refType];
40+
[description appendFormat:@" refSerial: %@\n", self.refSerial];
41+
[description appendFormat:@" operation: %@\n", self.operation];
42+
[description appendFormat:@" summary: %@\n", self.summary];
3643
[description appendFormat:@"}"];
3744
return description;
3845
}
@@ -49,6 +56,7 @@ - (id)copyWithZone:(NSZone *)zone {
4956
message.operation = self.operation;
5057
message.refType = self.refType;
5158
message.refSerial = self.refSerial;
59+
message.summary = self.summary;
5260
return message;
5361
}
5462

@@ -59,6 +67,22 @@ - (NSInteger)messageSize {
5967

6068
@end
6169

70+
NSString *ARTMessageActionToStr(ARTMessageAction action) {
71+
switch (action) {
72+
case ARTMessageActionCreate:
73+
return @"Create";
74+
case ARTMessageActionUpdate:
75+
return @"Update";
76+
case ARTMessageActionDelete:
77+
return @"Delete";
78+
case ARTMessageActionMeta:
79+
return @"Meta";
80+
case ARTMessageActionMessageSummary:
81+
return @"Summary";
82+
}
83+
return @"Unknown";
84+
}
85+
6286
@implementation ARTMessage (Decoding)
6387

6488
+ (instancetype)fromEncoded:(NSDictionary *)jsonObject channelOptions:(ARTChannelOptions *)options error:(NSError **)error {

Source/ARTProtocolMessage.m

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ - (id)init {
2121
_timestamp = nil;
2222
_messages = nil;
2323
_presence = nil;
24+
_annotations = nil;
2425
_flags = 0;
2526
_error = nil;
2627
_connectionDetails = nil;
@@ -52,6 +53,7 @@ - (NSString *)description {
5253
[description appendFormat:@" flags.resumed: %@,\n", NSStringFromBOOL(self.resumed)];
5354
[description appendFormat:@" messages: %@\n", self.messages];
5455
[description appendFormat:@" presence: %@\n", self.presence];
56+
[description appendFormat:@" annotations: %@\n", self.annotations];
5557
[description appendFormat:@" params: %@\n", self.params];
5658
[description appendFormat:@"}"];
5759
return description;
@@ -70,6 +72,7 @@ - (id)copyWithZone:(NSZone *)zone {
7072
pm.timestamp = self.timestamp;
7173
pm.messages = self.messages;
7274
pm.presence = self.presence;
75+
pm.annotations = self.annotations;
7376
pm.flags = self.flags;
7477
pm.error = self.error;
7578
pm.connectionDetails = self.connectionDetails;
@@ -100,6 +103,9 @@ - (BOOL)mergeFrom:(ARTProtocolMessage *)src maxSize:(NSInteger)maxSize {
100103
case ARTProtocolMessagePresence:
101104
proposed = [self.presence arrayByAddingObjectsFromArray:src.presence];
102105
break;
106+
case ARTProtocolMessageAnnotation:
107+
proposed = [self.annotations arrayByAddingObjectsFromArray:src.annotations];
108+
break;
103109
default:
104110
proposed = nil;
105111
return NO;
@@ -120,6 +126,9 @@ - (BOOL)mergeFrom:(ARTProtocolMessage *)src maxSize:(NSInteger)maxSize {
120126
case ARTProtocolMessagePresence:
121127
self.presence = proposed;
122128
return YES;
129+
case ARTProtocolMessageAnnotation:
130+
self.annotations = proposed;
131+
return YES;
123132
default:
124133
return NO;
125134
}
@@ -156,7 +165,7 @@ - (BOOL)mergeWithMessages:(NSArray<ARTMessage*>*)messages wouldExceedMaxSize:(NS
156165
}
157166

158167
- (BOOL)ackRequired {
159-
return self.action == ARTProtocolMessageMessage || self.action == ARTProtocolMessagePresence;
168+
return self.action == ARTProtocolMessageMessage || self.action == ARTProtocolMessagePresence || self.action == ARTProtocolMessageAnnotation;
160169
}
161170

162171
- (BOOL)hasPresence {
@@ -215,6 +224,8 @@ - (ARTConnectionDetails *)getConnectionDetails {
215224
return @"Sync"; //16
216225
case ARTProtocolMessageAuth:
217226
return @"Auth"; //17
227+
case ARTProtocolMessageAnnotation:
228+
return @"Annotation"; //21
218229
}
219230

220231
// Because we blindly assign the action field of a ProtocolMessage received over the wire to a variable of type ARTProtocolMessageAction, we can't rely on the compiler's exhaustive checking of switch statements for ARTProtocolMessageAction.

0 commit comments

Comments
 (0)