pbind 0.6.2 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/pbind/command.rb +2 -0
- data/lib/pbind/command/mock.rb +1 -1
- data/lib/pbind/command/serv.rb +78 -16
- data/lib/pbind/command/view.rb +86 -0
- data/lib/pbind/gem_version.rb +1 -1
- data/lib/pbind/minify.rb +52 -0
- data/source/PBLiveLoader/NSInputStream+Reader.m +10 -0
- data/source/PBLiveLoader/PBLLInspector.h +2 -2
- data/source/PBLiveLoader/PBLLInspector.m +385 -22
- data/source/PBLiveLoader/PBLLInspectorController.h +2 -0
- data/source/PBLiveLoader/PBLLInspectorController.m +71 -17
- data/source/PBLiveLoader/PBLLInspectorTipsController.h +23 -0
- data/source/PBLiveLoader/PBLLInspectorTipsController.m +140 -0
- data/source/PBLiveLoader/PBLLOptions.h +1 -1
- data/source/PBLiveLoader/PBLLRemoteWatcher.h +6 -0
- data/source/PBLiveLoader/PBLLRemoteWatcher.m +155 -29
- data/source/PBLiveLoader/PBLLResource.h +25 -0
- data/source/PBLiveLoader/PBLLResource.m +208 -0
- data/source/PBLiveLoader/PBLiveLoader.m +44 -8
- metadata +8 -3
@@ -11,8 +11,21 @@
|
|
11
11
|
|
12
12
|
#import "PBLLInspector.h"
|
13
13
|
#import "PBLLRemoteWatcher.h"
|
14
|
+
#import "PBLLResource.h"
|
14
15
|
#import <Pbind/Pbind.h>
|
15
16
|
|
17
|
+
@interface _PBLLWrapperNavigationController : UINavigationController
|
18
|
+
|
19
|
+
@end
|
20
|
+
|
21
|
+
@implementation _PBLLWrapperNavigationController
|
22
|
+
|
23
|
+
- (UIStatusBarStyle)preferredStatusBarStyle {
|
24
|
+
return UIStatusBarStyleLightContent;
|
25
|
+
}
|
26
|
+
|
27
|
+
@end
|
28
|
+
|
16
29
|
@interface PBLLInspectorController () <UISearchBarDelegate>
|
17
30
|
{
|
18
31
|
UISearchBar *_searchBar;
|
@@ -25,27 +38,77 @@
|
|
25
38
|
- (void)viewDidLoad {
|
26
39
|
[super viewDidLoad];
|
27
40
|
// Do any additional setup after loading the view.
|
41
|
+
self.title = [PBLLResource pbindTitle];
|
42
|
+
UIColor *primaryColor = [PBLLResource pbindColor];
|
43
|
+
UINavigationBar *navigationBar = self.navigationController.navigationBar;
|
44
|
+
[navigationBar setBarTintColor:primaryColor];
|
45
|
+
[navigationBar setTintColor:[UIColor whiteColor]];
|
46
|
+
[navigationBar setBackgroundImage:[UIImage new] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
|
47
|
+
[navigationBar setShadowImage:[UIImage new]];
|
48
|
+
[navigationBar setTranslucent:NO];
|
49
|
+
[navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}];
|
50
|
+
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self action:@selector(dismiss)];
|
51
|
+
|
28
52
|
self.edgesForExtendedLayout = UIRectEdgeNone;
|
29
53
|
self.view.backgroundColor = [UIColor whiteColor];
|
30
54
|
CGRect frame = self.view.bounds;
|
31
55
|
frame.size.height = 44.f;
|
32
|
-
frame.origin.y = 16.f;
|
33
56
|
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:frame];
|
34
|
-
searchBar.
|
57
|
+
searchBar.barTintColor = primaryColor;
|
58
|
+
searchBar.text = [PBLLRemoteWatcher globalWatcher].defaultIP;
|
35
59
|
searchBar.delegate = self;
|
36
60
|
searchBar.returnKeyType = UIReturnKeyJoin;
|
61
|
+
searchBar.barStyle = UISearchBarStyleMinimal;
|
37
62
|
[self.view addSubview:searchBar];
|
38
63
|
_searchBar = searchBar;
|
64
|
+
[searchBar becomeFirstResponder];
|
65
|
+
|
66
|
+
// Help label
|
67
|
+
UILabel *helpLabel = [[UILabel alloc] init];
|
68
|
+
helpLabel.font = [UIFont systemFontOfSize:14.f];
|
69
|
+
helpLabel.numberOfLines = 0;
|
70
|
+
helpLabel.textColor = PBColorMake(@"666");
|
71
|
+
helpLabel.text = @(
|
72
|
+
"Input the IP of the pbind server started by:\n"
|
73
|
+
"\n"
|
74
|
+
" > gem install pbind" "\n"
|
75
|
+
" > cd [path-to-xcodeproj]" "\n"
|
76
|
+
" > pbind serv" "\n"
|
77
|
+
"\n"
|
78
|
+
"Then click [Join] to start online debugging.");
|
79
|
+
[self.view addSubview:helpLabel];
|
80
|
+
|
81
|
+
frame.origin.y += frame.size.height + 44.f;
|
82
|
+
frame.origin.x = 32.f;
|
83
|
+
frame.size.width = frame.size.width - 64.f;
|
84
|
+
frame.size.height = [helpLabel sizeThatFits:frame.size].height;
|
85
|
+
helpLabel.frame = frame;
|
39
86
|
|
40
87
|
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTap:)];
|
41
88
|
[self.view addGestureRecognizer:tap];
|
42
89
|
}
|
43
90
|
|
91
|
+
+ (void)presentFromViewController:(UIViewController *)viewController {
|
92
|
+
PBLLInspectorController *inspectorVC = [[PBLLInspectorController alloc] init];
|
93
|
+
UINavigationController *nav = [[_PBLLWrapperNavigationController alloc] initWithRootViewController:inspectorVC];
|
94
|
+
[viewController presentViewController:nav animated:YES completion:nil];
|
95
|
+
}
|
96
|
+
|
44
97
|
- (void)viewWillAppear:(BOOL)animated {
|
45
98
|
[super viewWillAppear:animated];
|
46
99
|
[PBLLInspector sharedInspector].hidden = YES;
|
47
100
|
}
|
48
101
|
|
102
|
+
- (void)viewDidAppear:(BOOL)animated {
|
103
|
+
[super viewDidAppear:animated];
|
104
|
+
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
|
105
|
+
}
|
106
|
+
|
107
|
+
- (void)viewWillDisappear:(BOOL)animated {
|
108
|
+
[super viewWillDisappear:animated];
|
109
|
+
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
|
110
|
+
}
|
111
|
+
|
49
112
|
- (void)viewDidDisappear:(BOOL)animated {
|
50
113
|
[super viewDidDisappear:animated];
|
51
114
|
[PBLLInspector sharedInspector].hidden = NO;
|
@@ -56,19 +119,6 @@
|
|
56
119
|
// Dispose of any resources that can be recreated.
|
57
120
|
}
|
58
121
|
|
59
|
-
- (NSString *)defaultIP {
|
60
|
-
NSString *ip = [[NSUserDefaults standardUserDefaults] objectForKey:@"pbind.server.ip"];
|
61
|
-
if (ip == nil) {
|
62
|
-
ip = @"192.168.1.10";
|
63
|
-
}
|
64
|
-
return ip;
|
65
|
-
}
|
66
|
-
|
67
|
-
- (void)setDefaultIP:(NSString *)ip {
|
68
|
-
[[NSUserDefaults standardUserDefaults] setObject:ip forKey:@"pbind.server.ip"];
|
69
|
-
[[NSUserDefaults standardUserDefaults] synchronize];
|
70
|
-
}
|
71
|
-
|
72
122
|
#pragma mark - UISearchBarDelegate
|
73
123
|
|
74
124
|
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
|
@@ -77,9 +127,8 @@
|
|
77
127
|
return;
|
78
128
|
}
|
79
129
|
|
80
|
-
[self setDefaultIP:ip];
|
81
130
|
[[PBLLRemoteWatcher globalWatcher] connect:ip];
|
82
|
-
[self
|
131
|
+
[self dismiss];
|
83
132
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
84
133
|
[PBTopController().view pb_reloadClient];
|
85
134
|
});
|
@@ -91,6 +140,11 @@
|
|
91
140
|
[_searchBar resignFirstResponder];
|
92
141
|
}
|
93
142
|
|
143
|
+
- (void)dismiss {
|
144
|
+
[_searchBar resignFirstResponder];
|
145
|
+
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
|
146
|
+
}
|
147
|
+
|
94
148
|
@end
|
95
149
|
|
96
150
|
#endif
|
@@ -0,0 +1,23 @@
|
|
1
|
+
//
|
2
|
+
// PBLLInspectorTipsController.h
|
3
|
+
// Pbind
|
4
|
+
//
|
5
|
+
// Created by galen on 17/7/29.
|
6
|
+
//
|
7
|
+
|
8
|
+
#import "PBLLOptions.h"
|
9
|
+
#include <targetconditionals.h>
|
10
|
+
|
11
|
+
#if (PBLIVE_ENABLED)
|
12
|
+
|
13
|
+
#import <UIKit/UIKit.h>
|
14
|
+
|
15
|
+
@interface PBLLInspectorTipsController : UIViewController
|
16
|
+
|
17
|
+
@property (nonatomic, strong) NSString *tips;
|
18
|
+
|
19
|
+
@property (nonatomic, strong) NSString *code;
|
20
|
+
|
21
|
+
@end
|
22
|
+
|
23
|
+
#endif
|
@@ -0,0 +1,140 @@
|
|
1
|
+
//
|
2
|
+
// PBLLInspectorTipsController.m
|
3
|
+
// Pbind
|
4
|
+
//
|
5
|
+
// Created by galen on 17/7/29.
|
6
|
+
//
|
7
|
+
|
8
|
+
#import "PBLLInspectorTipsController.h"
|
9
|
+
|
10
|
+
#if (PBLIVE_ENABLED)
|
11
|
+
|
12
|
+
#import "PBLLRemoteWatcher.h"
|
13
|
+
#import "PBLLResource.h"
|
14
|
+
#import <Pbind/Pbind.h>
|
15
|
+
|
16
|
+
@interface PBLLInspectorTipsController ()
|
17
|
+
|
18
|
+
@property (nonatomic, strong) UILabel *tipsLabel;
|
19
|
+
@property (nonatomic, strong) UIToolbar *toolbar;
|
20
|
+
@property (nonatomic, assign) CGFloat preferredWidth;
|
21
|
+
@property (nonatomic, strong) UIBarButtonItem *codeOrTipsItem;
|
22
|
+
|
23
|
+
@end
|
24
|
+
|
25
|
+
@implementation PBLLInspectorTipsController
|
26
|
+
|
27
|
+
static BOOL kDisplaysCode = NO;
|
28
|
+
|
29
|
+
- (void)viewDidLoad {
|
30
|
+
[super viewDidLoad];
|
31
|
+
// Do any additional setup after loading the view.
|
32
|
+
|
33
|
+
CGRect rect = [UIScreen mainScreen].bounds;
|
34
|
+
_preferredWidth = rect.size.width * 2.f / 3.f;
|
35
|
+
|
36
|
+
rect.origin.x = 16.f;
|
37
|
+
rect.origin.y = 16.f;
|
38
|
+
UILabel *label = [[UILabel alloc] initWithFrame:rect];
|
39
|
+
label.textColor = [UIColor whiteColor];
|
40
|
+
label.text = self.tips;
|
41
|
+
label.font = [UIFont systemFontOfSize:12.f];
|
42
|
+
label.numberOfLines = 0;
|
43
|
+
rect.size.height = [label sizeThatFits:rect.size].height;
|
44
|
+
label.frame = rect;
|
45
|
+
|
46
|
+
[self.view addSubview:label];
|
47
|
+
_tipsLabel = label;
|
48
|
+
|
49
|
+
UIToolbar *toolbar = [[UIToolbar alloc] init];
|
50
|
+
[toolbar setBarTintColor:self.popoverPresentationController.backgroundColor];
|
51
|
+
[toolbar setTintColor:[UIColor whiteColor]];
|
52
|
+
|
53
|
+
NSMutableArray *items = [NSMutableArray arrayWithCapacity:4];
|
54
|
+
[items addObject:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self action:@selector(handleClose:)]];
|
55
|
+
[items addObject:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]];
|
56
|
+
if (self.code != nil) {
|
57
|
+
_codeOrTipsItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:self action:@selector(handleToggleCode:)];
|
58
|
+
[items addObject:_codeOrTipsItem];
|
59
|
+
|
60
|
+
[items addObject:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]];
|
61
|
+
}
|
62
|
+
// Copy
|
63
|
+
[items addObject:[[UIBarButtonItem alloc] initWithImage:[PBLLResource copyImage] style:UIBarButtonItemStylePlain target:self action:@selector(handleCopy:)]];
|
64
|
+
#if !(TARGET_IPHONE_SIMULATOR)
|
65
|
+
// Post
|
66
|
+
UIBarButtonItem *postItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemReply target:self action:@selector(handlePost:)];
|
67
|
+
[items addObject:postItem];
|
68
|
+
#endif
|
69
|
+
|
70
|
+
toolbar.items = items;
|
71
|
+
[self.view addSubview:toolbar];
|
72
|
+
_toolbar = toolbar;
|
73
|
+
|
74
|
+
[self render];
|
75
|
+
}
|
76
|
+
|
77
|
+
- (void)render {
|
78
|
+
[self renderWithAnimated:NO];
|
79
|
+
}
|
80
|
+
|
81
|
+
- (void)renderWithAnimated:(BOOL)animated {
|
82
|
+
dispatch_block_t renderBlock = ^{
|
83
|
+
if (_code != nil) {
|
84
|
+
if (kDisplaysCode) {
|
85
|
+
_codeOrTipsItem.title = @"Value";
|
86
|
+
_tipsLabel.text = _code;
|
87
|
+
} else {
|
88
|
+
_codeOrTipsItem.title = @"Code";
|
89
|
+
_tipsLabel.text = _tips;
|
90
|
+
}
|
91
|
+
} else {
|
92
|
+
_tipsLabel.text = _tips;
|
93
|
+
}
|
94
|
+
|
95
|
+
CGRect rect = CGRectMake(16.f, 16.f, _preferredWidth - 32.f, CGFLOAT_MAX);
|
96
|
+
rect.size.height = [_tipsLabel sizeThatFits:rect.size].height;
|
97
|
+
_tipsLabel.frame = rect;
|
98
|
+
|
99
|
+
rect.origin.x = 0.f;
|
100
|
+
rect.origin.y += rect.size.height + 16.f;
|
101
|
+
rect.size.width = _preferredWidth;
|
102
|
+
rect.size.height = 44.f;
|
103
|
+
_toolbar.frame = rect;
|
104
|
+
|
105
|
+
rect.size.height += rect.origin.y;
|
106
|
+
self.preferredContentSize = rect.size;
|
107
|
+
};
|
108
|
+
if (animated) {
|
109
|
+
[UIView animateWithDuration:.25f animations:renderBlock completion:^(BOOL finished) {
|
110
|
+
[self.popoverPresentationController.containerView setNeedsLayout];
|
111
|
+
}];
|
112
|
+
} else {
|
113
|
+
renderBlock();
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
#pragma mark - BarButtonItem
|
118
|
+
|
119
|
+
- (void)handleClose:(id)sender {
|
120
|
+
[self dismissViewControllerAnimated:YES completion:nil];
|
121
|
+
}
|
122
|
+
|
123
|
+
- (void)handleToggleCode:(id)sender {
|
124
|
+
kDisplaysCode = !kDisplaysCode;
|
125
|
+
[self renderWithAnimated:YES];
|
126
|
+
}
|
127
|
+
|
128
|
+
- (void)handleCopy:(id)sender {
|
129
|
+
[UIPasteboard generalPasteboard].string = _tipsLabel.text;
|
130
|
+
}
|
131
|
+
|
132
|
+
#if !(TARGET_IPHONE_SIMULATOR)
|
133
|
+
- (void)handlePost:(id)sender {
|
134
|
+
[[PBLLRemoteWatcher globalWatcher] sendLog:_tips];
|
135
|
+
}
|
136
|
+
#endif
|
137
|
+
|
138
|
+
@end
|
139
|
+
|
140
|
+
#endif
|
@@ -24,6 +24,8 @@
|
|
24
24
|
- (void)remoteWatcher:(PBLLRemoteWatcher *)watcher didCreateFile:(NSString *)fileName;
|
25
25
|
- (void)remoteWatcher:(PBLLRemoteWatcher *)watcher didDeleteFile:(NSString *)fileName;
|
26
26
|
|
27
|
+
- (void)remoteWatcher:(PBLLRemoteWatcher *)watcher didChangeConnectState:(BOOL)connected;
|
28
|
+
|
27
29
|
@end
|
28
30
|
|
29
31
|
@interface PBLLRemoteWatcher : NSObject
|
@@ -35,8 +37,12 @@
|
|
35
37
|
|
36
38
|
- (void)requestAPI:(NSString *)api success:(void (^)(NSData *))success failure:(void (^)(NSError *))failure;
|
37
39
|
|
40
|
+
- (void)sendLog:(NSString *)log;
|
41
|
+
|
38
42
|
@property (nonatomic, assign) id<PBLLRemoteWatcherDelegate> delegate;
|
39
43
|
|
44
|
+
@property (nonatomic, strong, readonly) NSString *defaultIP;
|
45
|
+
|
40
46
|
@end
|
41
47
|
|
42
48
|
#endif
|
@@ -16,17 +16,25 @@
|
|
16
16
|
{
|
17
17
|
NSInputStream *inputStream;
|
18
18
|
NSOutputStream *outputStream;
|
19
|
-
void (^
|
19
|
+
void (^apiSuccessBlock)(NSData *);
|
20
|
+
void (^apiFailureBolck)(NSError *);
|
20
21
|
BOOL streamOpened;
|
21
22
|
NSData *apiReqData;
|
22
23
|
NSString *tempResourcesPath;
|
23
24
|
NSString *connectedIP;
|
25
|
+
NSInteger retryCount;
|
24
26
|
}
|
25
27
|
|
26
28
|
@end
|
27
29
|
|
28
30
|
@implementation PBLLRemoteWatcher
|
29
31
|
|
32
|
+
static const NSTimeInterval kTimeoutSeconds = 3.f;
|
33
|
+
static NSString *const kServerIPUserDefaultsKey = @"pbind.server.ip";
|
34
|
+
static NSString *const kDefaultServerIP = @"192.168.1.10";
|
35
|
+
static const NSInteger kServerPort = 8082;
|
36
|
+
static const NSInteger kMaxRetryCount = 5;
|
37
|
+
|
30
38
|
+ (instancetype)globalWatcher {
|
31
39
|
static PBLLRemoteWatcher *o;
|
32
40
|
static dispatch_once_t onceToken;
|
@@ -39,10 +47,15 @@
|
|
39
47
|
- (void)connect:(NSString *)ip {
|
40
48
|
[self close];
|
41
49
|
|
50
|
+
if (ip == nil) {
|
51
|
+
return;
|
52
|
+
}
|
53
|
+
|
42
54
|
connectedIP = ip;
|
55
|
+
[[NSUserDefaults standardUserDefaults] setObject:ip forKey:kServerIPUserDefaultsKey];
|
43
56
|
CFReadStreamRef readStream;
|
44
57
|
CFWriteStreamRef writeStream;
|
45
|
-
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)ip,
|
58
|
+
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)ip, kServerPort, &readStream, &writeStream);
|
46
59
|
inputStream = (__bridge NSInputStream *)readStream;
|
47
60
|
outputStream = (__bridge NSOutputStream *)writeStream;
|
48
61
|
inputStream.delegate = self;
|
@@ -54,11 +67,15 @@
|
|
54
67
|
}
|
55
68
|
|
56
69
|
- (void)connectDefaultIP {
|
57
|
-
|
70
|
+
[self connect:self.defaultIP];
|
71
|
+
}
|
72
|
+
|
73
|
+
- (NSString *)defaultIP {
|
74
|
+
NSString *ip = [[NSUserDefaults standardUserDefaults] objectForKey:kServerIPUserDefaultsKey];
|
58
75
|
if (ip == nil) {
|
59
|
-
ip =
|
76
|
+
ip = kDefaultServerIP;
|
60
77
|
}
|
61
|
-
|
78
|
+
return ip;
|
62
79
|
}
|
63
80
|
|
64
81
|
- (void)requestAPI:(NSString *)api success:(void (^)(NSData *))success failure:(void (^)(NSError *))failure {
|
@@ -69,13 +86,31 @@
|
|
69
86
|
return;
|
70
87
|
}
|
71
88
|
|
72
|
-
|
73
|
-
|
89
|
+
apiSuccessBlock = success;
|
90
|
+
apiFailureBolck = failure;
|
91
|
+
|
92
|
+
NSData *reqData = [self dataWithMessage:api event:PBLLRemoteEventJsonRequest];
|
74
93
|
if (streamOpened) {
|
75
|
-
[
|
94
|
+
[self sendData:reqData];
|
76
95
|
} else {
|
77
|
-
apiReqData =
|
96
|
+
// apiReqData = reqData;
|
97
|
+
failure(nil);
|
98
|
+
return;
|
78
99
|
}
|
100
|
+
|
101
|
+
NSLog(@"---- perform delay onTimeout");
|
102
|
+
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onTimeout) object:nil];
|
103
|
+
[self performSelector:@selector(onTimeout) withObject:nil afterDelay:kTimeoutSeconds];
|
104
|
+
}
|
105
|
+
|
106
|
+
- (void)onTimeout {
|
107
|
+
if (apiFailureBolck) {
|
108
|
+
apiFailureBolck([NSError errorWithDomain:@"PBLLRemoteWatcher"
|
109
|
+
code:-1
|
110
|
+
userInfo:@{NSLocalizedDescriptionKey: @"Server no response"}]);
|
111
|
+
apiFailureBolck = nil;
|
112
|
+
}
|
113
|
+
apiSuccessBlock = nil;
|
79
114
|
}
|
80
115
|
|
81
116
|
- (void)close {
|
@@ -90,10 +125,67 @@
|
|
90
125
|
streamOpened = NO;
|
91
126
|
}
|
92
127
|
|
128
|
+
#pragma mark - Communication
|
129
|
+
|
130
|
+
typedef NS_ENUM(NSUInteger, PBLLRemoteEvent) {
|
131
|
+
// client events
|
132
|
+
PBLLRemoteEventConnected = 0xC0,
|
133
|
+
PBLLRemoteEventJsonRequest = 0xC1,
|
134
|
+
PBLLRemoteEventLog = 0xC2,
|
135
|
+
|
136
|
+
// server events - data
|
137
|
+
PBLLRemoteEventDataJson = 0xD0,
|
138
|
+
|
139
|
+
// server events - error
|
140
|
+
PBLLRemoteEventErrorIgnored = 0xE0,
|
141
|
+
|
142
|
+
// server events - file
|
143
|
+
PBLLRemoteEventFileCreated = 0xF0,
|
144
|
+
PBLLRemoteEventFileUpdated = 0xF1,
|
145
|
+
PBLLRemoteEventFileDeleted = 0xF2,
|
146
|
+
};
|
147
|
+
|
148
|
+
- (void)sendMessage:(NSString *)message {
|
149
|
+
NSData *msgData = [message dataUsingEncoding:NSUTF8StringEncoding];
|
150
|
+
[self sendData:msgData];
|
151
|
+
}
|
152
|
+
|
153
|
+
- (void)sendLog:(NSString *)log {
|
154
|
+
[self sendMessage:log event:PBLLRemoteEventLog];
|
155
|
+
}
|
156
|
+
|
157
|
+
- (void)sendConnectedMessage {
|
158
|
+
NSString *osModel = [[UIDevice currentDevice] name];
|
159
|
+
NSString *osVersion = [[UIDevice currentDevice] systemVersion];
|
160
|
+
NSString *deviceName = [NSString stringWithFormat:@"%@(%@)", osModel, osVersion];
|
161
|
+
[self sendMessage:deviceName event:PBLLRemoteEventConnected];
|
162
|
+
}
|
163
|
+
|
164
|
+
- (void)sendMessage:(NSString *)message event:(PBLLRemoteEvent)event {
|
165
|
+
NSData *data = [self dataWithMessage:message event:event];
|
166
|
+
[self sendData:data];
|
167
|
+
}
|
168
|
+
|
169
|
+
- (void)sendData:(NSData *)data {
|
170
|
+
if (!streamOpened) {
|
171
|
+
return;
|
172
|
+
}
|
173
|
+
|
174
|
+
[outputStream write:[data bytes] maxLength:[data length]];
|
175
|
+
}
|
176
|
+
|
177
|
+
- (NSData *)dataWithMessage:(NSString *)message event:(PBLLRemoteEvent)event {
|
178
|
+
NSData *msgData = [message dataUsingEncoding:NSUTF8StringEncoding];
|
179
|
+
NSUInteger len = msgData.length + 1;
|
180
|
+
NSMutableData *data = [[NSMutableData alloc] initWithCapacity:len];
|
181
|
+
[data appendBytes:&event length:1];
|
182
|
+
[data appendData:msgData];
|
183
|
+
return data;
|
184
|
+
}
|
185
|
+
|
93
186
|
#pragma mark - NSStreamDelegate
|
94
187
|
|
95
188
|
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
|
96
|
-
NSLog(@"socket: %i, %@", (int)eventCode, aStream);
|
97
189
|
switch (eventCode) {
|
98
190
|
case NSStreamEventOpenCompleted:
|
99
191
|
break;
|
@@ -102,47 +194,71 @@
|
|
102
194
|
if (!streamOpened) {
|
103
195
|
streamOpened = YES;
|
104
196
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
[outputStream write:[msgData bytes] maxLength:[msgData length]];
|
197
|
+
[self sendConnectedMessage];
|
198
|
+
|
199
|
+
if ([self.delegate respondsToSelector:@selector(remoteWatcher:didChangeConnectState:)]) {
|
200
|
+
[self.delegate remoteWatcher:self didChangeConnectState:YES];
|
201
|
+
}
|
111
202
|
}
|
112
203
|
|
113
|
-
if (apiReqData != nil) {
|
114
|
-
[
|
115
|
-
apiReqData = nil;
|
116
|
-
}
|
204
|
+
// if (apiReqData != nil) {
|
205
|
+
// [self sendData:apiReqData];
|
206
|
+
// apiReqData = nil;
|
207
|
+
// }
|
117
208
|
}
|
118
209
|
break;
|
119
210
|
case NSStreamEventHasBytesAvailable:
|
120
211
|
if (aStream == inputStream) {
|
121
|
-
NSLog(@"inputStream is ready.");
|
122
|
-
|
123
212
|
uint8_t type[1];
|
124
213
|
[inputStream read:type maxLength:1];
|
125
|
-
|
126
|
-
|
214
|
+
PBLLRemoteEvent event = *type;
|
215
|
+
switch (event) {
|
216
|
+
case PBLLRemoteEventDataJson: { // Got json
|
217
|
+
NSString *jsonName = [inputStream readString];
|
127
218
|
NSData *jsonData = [inputStream readData];
|
128
|
-
|
129
|
-
|
219
|
+
NSLog(@"---- cancel onTimeout");
|
220
|
+
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onTimeout) object:nil];
|
221
|
+
if (apiSuccessBlock != nil) {
|
222
|
+
apiSuccessBlock(jsonData);
|
223
|
+
apiSuccessBlock = nil;
|
224
|
+
}
|
225
|
+
apiFailureBolck = nil;
|
226
|
+
[self sendMessage:jsonName event:PBLLRemoteEventDataJson];
|
227
|
+
break;
|
228
|
+
}
|
229
|
+
case PBLLRemoteEventErrorIgnored: { // Ingores API
|
230
|
+
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onTimeout) object:nil];
|
231
|
+
if (apiFailureBolck != nil) {
|
232
|
+
apiFailureBolck([NSError errorWithDomain:@"PBLLRemoteWatcher" code:-2 userInfo:@{NSLocalizedDescriptionKey: @"User ignores the API"}]);
|
130
233
|
}
|
234
|
+
apiSuccessBlock = nil;
|
131
235
|
break;
|
132
236
|
}
|
133
|
-
case
|
237
|
+
case PBLLRemoteEventFileCreated: { // Create file
|
134
238
|
NSString *fileName = [inputStream readString];
|
239
|
+
if (fileName == nil) {
|
240
|
+
break;
|
241
|
+
}
|
242
|
+
[self sendMessage:fileName event:event];
|
135
243
|
[self.delegate remoteWatcher:self didCreateFile:fileName];
|
136
244
|
break;
|
137
245
|
}
|
138
|
-
case
|
246
|
+
case PBLLRemoteEventFileUpdated: { // Update file
|
139
247
|
NSString *fileName = [inputStream readString];
|
248
|
+
if (fileName == nil) {
|
249
|
+
break;
|
250
|
+
}
|
140
251
|
NSData *fileData = [inputStream readData];
|
252
|
+
[self sendMessage:fileName event:event];
|
141
253
|
[self.delegate remoteWatcher:self didUpdateFile:fileName withData:fileData];
|
142
254
|
break;
|
143
255
|
}
|
144
|
-
case
|
256
|
+
case PBLLRemoteEventFileDeleted: { // Delete file
|
145
257
|
NSString *fileName = [inputStream readString];
|
258
|
+
if (fileName == nil) {
|
259
|
+
break;
|
260
|
+
}
|
261
|
+
[self sendMessage:fileName event:event];
|
146
262
|
[self.delegate remoteWatcher:self didDeleteFile:fileName];
|
147
263
|
break;
|
148
264
|
}
|
@@ -153,14 +269,24 @@
|
|
153
269
|
break;
|
154
270
|
case NSStreamEventErrorOccurred:
|
155
271
|
if (aStream == outputStream) {
|
272
|
+
retryCount++;
|
273
|
+
if (retryCount >= kMaxRetryCount) {
|
274
|
+
retryCount = 0;
|
275
|
+
break;
|
276
|
+
}
|
277
|
+
|
156
278
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
157
279
|
[self connect:connectedIP];
|
158
280
|
});
|
159
281
|
}
|
282
|
+
NSLog(@"[PBLLRemoteWatcher] %@", [aStream streamError]);
|
160
283
|
break;
|
161
284
|
case NSStreamEventEndEncountered:
|
162
285
|
if (aStream == inputStream) {
|
163
286
|
[self close];
|
287
|
+
if ([self.delegate respondsToSelector:@selector(remoteWatcher:didChangeConnectState:)]) {
|
288
|
+
[self.delegate remoteWatcher:self didChangeConnectState:NO];
|
289
|
+
}
|
164
290
|
}
|
165
291
|
break;
|
166
292
|
default:
|