|
@@ -8,109 +8,137 @@
|
|
//
|
|
//
|
|
|
|
|
|
#import "TCViewController.h"
|
|
#import "TCViewController.h"
|
|
-#import <SocketRocket/SRWebSocket.h>
|
|
|
|
|
|
+
|
|
|
|
+#import <SocketRocket/SocketRocket.h>
|
|
|
|
+
|
|
#import "TCChatCell.h"
|
|
#import "TCChatCell.h"
|
|
|
|
|
|
@interface TCMessage : NSObject
|
|
@interface TCMessage : NSObject
|
|
|
|
|
|
-- (instancetype)initWithMessage:(NSString *)message fromMe:(BOOL)fromMe;
|
|
|
|
|
|
+- (instancetype)initWithMessage:(NSString *)message incoming:(BOOL)incoming;
|
|
|
|
|
|
-@property (nonatomic, retain, readonly) NSString *message;
|
|
|
|
-@property (nonatomic, readonly) BOOL fromMe;
|
|
|
|
|
|
+@property (nonatomic, copy, readonly) NSString *message;
|
|
|
|
+@property (nonatomic, assign, readonly, getter=isIncoming) BOOL incoming;
|
|
|
|
|
|
@end
|
|
@end
|
|
|
|
|
|
|
|
+@implementation TCMessage
|
|
|
|
+
|
|
|
|
+- (instancetype)initWithMessage:(NSString *)message incoming:(BOOL)incoming
|
|
|
|
+{
|
|
|
|
+ self = [super init];
|
|
|
|
+ if (!self) return self;
|
|
|
|
+
|
|
|
|
+ _incoming = incoming;
|
|
|
|
+ _message = message;
|
|
|
|
|
|
-@interface TCViewController () <SRWebSocketDelegate, UITextViewDelegate>
|
|
|
|
|
|
+ return self;
|
|
|
|
+}
|
|
|
|
|
|
@end
|
|
@end
|
|
|
|
|
|
-@implementation TCViewController {
|
|
|
|
|
|
+
|
|
|
|
+@interface TCViewController () <SRWebSocketDelegate, UITextViewDelegate>
|
|
|
|
+{
|
|
SRWebSocket *_webSocket;
|
|
SRWebSocket *_webSocket;
|
|
- NSMutableArray *_messages;
|
|
|
|
|
|
+ NSMutableArray<TCMessage *> *_messages;
|
|
}
|
|
}
|
|
|
|
|
|
-@synthesize inputView = _inputView;
|
|
|
|
|
|
+@end
|
|
|
|
+
|
|
|
|
+@implementation TCViewController
|
|
|
|
|
|
-#pragma mark - View lifecycle
|
|
|
|
|
|
+///--------------------------------------
|
|
|
|
+#pragma mark - View
|
|
|
|
+///--------------------------------------
|
|
|
|
|
|
- (void)viewDidLoad;
|
|
- (void)viewDidLoad;
|
|
{
|
|
{
|
|
[super viewDidLoad];
|
|
[super viewDidLoad];
|
|
|
|
+
|
|
_messages = [[NSMutableArray alloc] init];
|
|
_messages = [[NSMutableArray alloc] init];
|
|
-
|
|
|
|
- [self.tableView reloadData];
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-- (void)_reconnect;
|
|
|
|
|
|
+- (void)viewWillAppear:(BOOL)animated
|
|
{
|
|
{
|
|
- _webSocket.delegate = nil;
|
|
|
|
- [_webSocket close];
|
|
|
|
-
|
|
|
|
- _webSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"ws://localhost:9000/chat"]]];
|
|
|
|
- _webSocket.delegate = self;
|
|
|
|
-
|
|
|
|
- self.title = @"Opening Connection...";
|
|
|
|
- [_webSocket open];
|
|
|
|
|
|
+ [super viewWillAppear:animated];
|
|
|
|
|
|
|
|
+ [self reconnect:nil];
|
|
}
|
|
}
|
|
|
|
|
|
-- (void)viewWillAppear:(BOOL)animated
|
|
|
|
|
|
+- (void)viewDidAppear:(BOOL)animated
|
|
{
|
|
{
|
|
- [super viewWillAppear:animated];
|
|
|
|
- [self _reconnect];
|
|
|
|
|
|
+ [super viewDidAppear:animated];
|
|
|
|
+
|
|
|
|
+ [_inputView becomeFirstResponder];
|
|
}
|
|
}
|
|
|
|
|
|
-- (void)reconnect:(id)sender;
|
|
|
|
|
|
+- (void)viewDidDisappear:(BOOL)animated
|
|
{
|
|
{
|
|
- [self _reconnect];
|
|
|
|
|
|
+ [super viewDidDisappear:animated];
|
|
|
|
+
|
|
|
|
+ [_webSocket close];
|
|
|
|
+ _webSocket = nil;
|
|
}
|
|
}
|
|
|
|
|
|
-- (void)sendPing:(id)sender;
|
|
|
|
|
|
+///--------------------------------------
|
|
|
|
+#pragma mark - Actions
|
|
|
|
+///--------------------------------------
|
|
|
|
+
|
|
|
|
+- (IBAction)reconnect:(id)sender
|
|
{
|
|
{
|
|
- [_webSocket sendPing:nil];
|
|
|
|
|
|
+ _webSocket.delegate = nil;
|
|
|
|
+ [_webSocket close];
|
|
|
|
+
|
|
|
|
+ _webSocket = [[SRWebSocket alloc] initWithURL:[NSURL URLWithString:@"wss://echo.websocket.org"]];
|
|
|
|
+ _webSocket.delegate = self;
|
|
|
|
+
|
|
|
|
+ self.title = @"Opening Connection...";
|
|
|
|
+ [_webSocket open];
|
|
}
|
|
}
|
|
|
|
|
|
-- (void)viewDidAppear:(BOOL)animated;
|
|
|
|
|
|
+- (void)sendPing:(id)sender;
|
|
{
|
|
{
|
|
- [super viewDidAppear:animated];
|
|
|
|
-
|
|
|
|
- [_inputView becomeFirstResponder];
|
|
|
|
|
|
+ [_webSocket sendPing:nil];
|
|
}
|
|
}
|
|
|
|
|
|
-- (void)viewDidDisappear:(BOOL)animated
|
|
|
|
|
|
+///--------------------------------------
|
|
|
|
+#pragma mark - Messages
|
|
|
|
+///--------------------------------------
|
|
|
|
+
|
|
|
|
+- (void)_addMessage:(TCMessage *)message
|
|
{
|
|
{
|
|
- [super viewDidDisappear:animated];
|
|
|
|
-
|
|
|
|
- _webSocket.delegate = nil;
|
|
|
|
- [_webSocket close];
|
|
|
|
- _webSocket = nil;
|
|
|
|
|
|
+ [_messages addObject:message];
|
|
|
|
+ [self.tableView insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:_messages.count - 1 inSection:0] ]
|
|
|
|
+ withRowAnimation:UITableViewRowAnimationNone];
|
|
|
|
+ [self.tableView scrollRectToVisible:self.tableView.tableFooterView.frame animated:YES];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+///--------------------------------------
|
|
#pragma mark - UITableViewController
|
|
#pragma mark - UITableViewController
|
|
|
|
+///--------------------------------------
|
|
|
|
|
|
-
|
|
|
|
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
|
|
|
|
|
|
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
|
{
|
|
{
|
|
return _messages.count;
|
|
return _messages.count;
|
|
}
|
|
}
|
|
|
|
|
|
-- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
|
|
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
{
|
|
- TCChatCell *chatCell = (id)cell;
|
|
|
|
- TCMessage *message = [_messages objectAtIndex:indexPath.row];
|
|
|
|
- chatCell.textView.text = message.message;
|
|
|
|
- chatCell.nameLabel.text = message.fromMe ? @"Me" : @"Other";
|
|
|
|
-}
|
|
|
|
|
|
+ TCMessage *message = _messages[indexPath.row];
|
|
|
|
|
|
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
-{
|
|
|
|
- TCMessage *message = [_messages objectAtIndex:indexPath.row];
|
|
|
|
|
|
+ TCChatCell *cell = [self.tableView dequeueReusableCellWithIdentifier:message.incoming ? @"ReceivedCell" : @"SentCell"
|
|
|
|
+ forIndexPath:indexPath];
|
|
|
|
|
|
- return [self.tableView dequeueReusableCellWithIdentifier:message.fromMe ? @"SentCell" : @"ReceivedCell"];
|
|
|
|
|
|
+ cell.textView.text = message.message;
|
|
|
|
+ cell.nameLabel.text = message.incoming ? @"Other" : @"Me";
|
|
|
|
+
|
|
|
|
+ return cell;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+///--------------------------------------
|
|
#pragma mark - SRWebSocketDelegate
|
|
#pragma mark - SRWebSocketDelegate
|
|
|
|
+///--------------------------------------
|
|
|
|
|
|
- (void)webSocketDidOpen:(SRWebSocket *)webSocket;
|
|
- (void)webSocketDidOpen:(SRWebSocket *)webSocket;
|
|
{
|
|
{
|
|
@@ -121,17 +149,15 @@
|
|
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;
|
|
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;
|
|
{
|
|
{
|
|
NSLog(@":( Websocket Failed With Error %@", error);
|
|
NSLog(@":( Websocket Failed With Error %@", error);
|
|
-
|
|
|
|
|
|
+
|
|
self.title = @"Connection Failed! (see logs)";
|
|
self.title = @"Connection Failed! (see logs)";
|
|
_webSocket = nil;
|
|
_webSocket = nil;
|
|
}
|
|
}
|
|
|
|
|
|
-- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;
|
|
|
|
|
|
+- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessageWithString:(nonnull NSString *)string
|
|
{
|
|
{
|
|
- NSLog(@"Received \"%@\"", message);
|
|
|
|
- [_messages addObject:[[TCMessage alloc] initWithMessage:message fromMe:NO]];
|
|
|
|
- [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_messages.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
|
|
|
|
- [self.tableView scrollRectToVisible:self.tableView.tableFooterView.frame animated:YES];
|
|
|
|
|
|
+ NSLog(@"Received \"%@\"", string);
|
|
|
|
+ [self _addMessage:[[TCMessage alloc] initWithMessage:string incoming:YES]];
|
|
}
|
|
}
|
|
|
|
|
|
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;
|
|
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;
|
|
@@ -143,46 +169,27 @@
|
|
|
|
|
|
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload;
|
|
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload;
|
|
{
|
|
{
|
|
- NSLog(@"Websocket received pong");
|
|
|
|
|
|
+ NSLog(@"WebSocket received pong");
|
|
}
|
|
}
|
|
|
|
|
|
-- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
|
|
|
|
-{
|
|
|
|
- if ([text rangeOfString:@"\n"].location != NSNotFound) {
|
|
|
|
- NSString *message = [[textView.text stringByReplacingCharactersInRange:range withString:text] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
|
|
- [_webSocket send:message];
|
|
|
|
- [_messages addObject:[[TCMessage alloc] initWithMessage:message fromMe:YES]];
|
|
|
|
-
|
|
|
|
- [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:_messages.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
|
|
|
|
- [self.tableView scrollRectToVisible:self.tableView.tableFooterView.frame animated:YES];
|
|
|
|
-
|
|
|
|
- textView.text = @"";
|
|
|
|
- return NO;
|
|
|
|
- }
|
|
|
|
- return YES;
|
|
|
|
-}
|
|
|
|
|
|
+///--------------------------------------
|
|
|
|
+#pragma mark - UITextViewDelegate
|
|
|
|
+///--------------------------------------
|
|
|
|
|
|
-- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation;
|
|
|
|
|
|
+- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
|
|
{
|
|
{
|
|
- return YES;
|
|
|
|
-}
|
|
|
|
|
|
+ if ([text rangeOfString:@"\n"].location != NSNotFound) {
|
|
|
|
+ NSString *message = [textView.text stringByReplacingCharactersInRange:range withString:text];
|
|
|
|
+ message = [message stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
|
|
|
|
-@end
|
|
|
|
|
|
+ [_webSocket sendString:message];
|
|
|
|
|
|
-@implementation TCMessage
|
|
|
|
|
|
+ [self _addMessage:[[TCMessage alloc] initWithMessage:message incoming:NO]];
|
|
|
|
|
|
-@synthesize message = _message;
|
|
|
|
-@synthesize fromMe = _fromMe;
|
|
|
|
-
|
|
|
|
-- (instancetype)initWithMessage:(NSString *)message fromMe:(BOOL)fromMe;
|
|
|
|
-{
|
|
|
|
- self = [super init];
|
|
|
|
- if (self) {
|
|
|
|
- _fromMe = fromMe;
|
|
|
|
- _message = message;
|
|
|
|
|
|
+ textView.text = nil;
|
|
|
|
+ return NO;
|
|
}
|
|
}
|
|
-
|
|
|
|
- return self;
|
|
|
|
|
|
+ return YES;
|
|
}
|
|
}
|
|
|
|
|
|
@end
|
|
@end
|