FlexHttpVC.m 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /**
  2. * Copyright (c) 2017-present, zhenglibao, Inc.
  3. * email: 798393829@qq.com
  4. * All rights reserved.
  5. *
  6. * This source code is licensed under the MIT-style license found in the
  7. * LICENSE file in the root directory of this source tree.
  8. */
  9. #import "FlexHttpVC.h"
  10. #import "FlexUtils.h"
  11. #import "FlexNode.h"
  12. #import "FlexSetPreviewVC.h"
  13. #import "FlexPreviewUtil.h"
  14. static NSString* gLastVisitedUrl = nil;
  15. @interface FlexHttpViewerVC : FlexBaseVC
  16. @property (nonatomic,copy) NSString* url;
  17. @end
  18. @implementation FlexHttpViewerVC
  19. /*
  20. * 重写以防止变量绑定异常导致查看xml时有内存泄漏
  21. */
  22. - (void)setValue:(id)value forKey:(NSString *)key
  23. {
  24. }
  25. -(void)viewDidLoad{
  26. [super viewDidLoad];
  27. self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:FlexPreviewLocalizeString(@"refresh") style:UIBarButtonItemStylePlain target:self action:@selector(reloadFlexView)];
  28. [self viewFlexWithUrl:self.url];
  29. }
  30. - (void)reloadFlexView
  31. {
  32. [self viewFlexWithUrl:self.url];
  33. }
  34. -(void)viewFlexWithUrl:(NSString*)url
  35. {
  36. __weak FlexHttpViewerVC* weakSelf = self;
  37. dispatch_queue_t queue = dispatch_get_global_queue(
  38. DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  39. dispatch_async(queue,^{
  40. NSError* error = nil;
  41. NSData* data = FlexFetchHttpRes(url, &error);
  42. dispatch_async(dispatch_get_main_queue(), ^{
  43. [weakSelf onViewFlex:data error:error];
  44. });
  45. });
  46. }
  47. -(void)onViewFlex:(NSData*)flexData
  48. error:(NSError*)error
  49. {
  50. if(flexData!=nil){
  51. [self resetByFlexData:flexData];
  52. }else{
  53. NSString* status;
  54. if(error==nil){
  55. status = @"Unknown error";
  56. }else{
  57. status = [error localizedDescription];
  58. }
  59. FlexShowToast(status, 1.0f);
  60. }
  61. }
  62. @end
  63. @interface FlexHttpVC ()<UITableViewDelegate,UITableViewDataSource>
  64. {
  65. UITableView* _table;
  66. UITextField* _pathLabel;
  67. UILabel* _statusBar;
  68. NSArray* _layouts;
  69. BOOL _bLoading;
  70. }
  71. @end
  72. @implementation FlexHttpVC
  73. -(NSBundle *)bundleForRes{
  74. NSBundle *bundle = [NSBundle bundleForClass:[self class]];
  75. NSURL *bundleURL = [bundle URLForResource:@"ZZUIKit" withExtension:@"bundle"];
  76. NSBundle *resourceBundle = [NSBundle bundleWithURL: bundleURL];
  77. return resourceBundle;
  78. }
  79. -(NSBundle *)bundleForStrings{
  80. NSBundle *bundle = [NSBundle bundleForClass:[self class]];
  81. NSURL *bundleURL = [bundle URLForResource:@"ZZUIKit" withExtension:@"bundle"];
  82. NSBundle *resourceBundle = [NSBundle bundleWithURL: bundleURL];
  83. return resourceBundle;
  84. }
  85. - (void)viewDidLoad {
  86. [super viewDidLoad];
  87. self.navigationItem.title = FlexPreviewLocalizeString(@"HttpVCTitle");
  88. _table.delegate = self;
  89. _table.dataSource = self;
  90. if (self.url == nil) {
  91. self.url = gLastVisitedUrl;
  92. }
  93. [self loadData];
  94. }
  95. - (void)didReceiveMemoryWarning {
  96. [super didReceiveMemoryWarning];
  97. }
  98. - (void)viewWillDisappear:(BOOL)animated
  99. {
  100. [super viewWillDisappear:animated];
  101. gLastVisitedUrl = self.url;
  102. }
  103. //-(NSBundle*)bundleForStrings
  104. //{
  105. // return FlexPreviewBundle();
  106. //}
  107. -(NSString*)getFlexName
  108. {
  109. NSString* flexName = NSStringFromClass([FlexHttpVC class]);
  110. NSBundle *frameworkBundle = [NSBundle bundleForClass:[FlexHttpVC class]];
  111. NSString *resourcePath = [frameworkBundle pathForResource:flexName ofType:@"xml" inDirectory:@"FlexLibPreview.bundle"];
  112. return resourcePath;
  113. }
  114. - (void)reloadFlexView
  115. {
  116. [self loadData];
  117. }
  118. - (NSArray<UIKeyCommand *> *)keyCommands
  119. {
  120. NSMutableArray* result = [[super keyCommands]mutableCopy];
  121. // close: control + w
  122. [result addObject:[UIKeyCommand keyCommandWithInput:@"w"
  123. modifierFlags:UIKeyModifierControl
  124. action:@selector(closeViewer)]];
  125. return result;
  126. }
  127. -(void)closeViewer
  128. {
  129. if(self.navigationController.childViewControllers.count>1){
  130. [self.navigationController popViewControllerAnimated:YES];
  131. }else{
  132. [self.navigationController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
  133. }
  134. }
  135. +(void)presentInVC:(UIViewController*)parentVC{
  136. FlexHttpVC* vc = [[FlexHttpVC alloc]init];
  137. if(parentVC.navigationController != nil){
  138. [parentVC.navigationController pushViewController:vc animated:YES];
  139. }else{
  140. UINavigationController* nav = [[UINavigationController alloc]initWithRootViewController:vc];
  141. [parentVC presentViewController:nav animated:YES completion:nil];
  142. }
  143. }
  144. #pragma mark - UITableView delegate
  145. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  146. {
  147. return _layouts.count/2 ;
  148. }
  149. - (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
  150. static NSString *identifier = @"HttpCellIdentifier";
  151. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
  152. if (cell == nil) {
  153. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
  154. }
  155. NSString* name = [_layouts objectAtIndex:indexPath.row*2+1];
  156. cell.textLabel.text = name;
  157. cell.textLabel.font = [UIFont systemFontOfSize:16];
  158. if([name hasSuffix:@"/"]){
  159. cell.textLabel.textColor = colorFromString(@"#0921ea", nil);
  160. }else if([name hasSuffix:@".xml"]){
  161. cell.textLabel.textColor = colorFromString(@"#157efb", nil);
  162. }else{
  163. cell.textLabel.textColor = [UIColor blackColor];
  164. }
  165. cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
  166. cell.detailTextLabel.text = @"";
  167. return cell;
  168. }
  169. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
  170. {
  171. return 60;
  172. }
  173. -(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  174. {
  175. [tableView deselectRowAtIndexPath:indexPath animated:YES];
  176. NSString* href = [_layouts objectAtIndex:indexPath.row*2];
  177. NSString* name = [_layouts objectAtIndex:indexPath.row*2+1];
  178. NSString* url = self.url ;
  179. if(![url hasSuffix:@"/"])
  180. url = [url stringByAppendingString:@"/"];
  181. url = [url stringByAppendingString:href];
  182. if([href hasSuffix:@"/"]){
  183. self.url = url;
  184. [self loadData];
  185. }else{
  186. FlexHttpViewerVC* vc = [[FlexHttpViewerVC alloc]init];
  187. vc.url = url;
  188. vc.navigationItem.title = name;
  189. [self.navigationController pushViewController:vc animated:YES];
  190. }
  191. }
  192. #pragma mark - load data
  193. /**
  194. * 返回提取内容,<a href="path">title</a>
  195. * 将path和title一对一加入到数组中返回
  196. */
  197. +(NSMutableArray*)extractLinks:(NSString*)data
  198. {
  199. NSString * patton = @"<a href=\"([^<>]+)\">([^<>]+)</a>";
  200. NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:patton options:NSRegularExpressionCaseInsensitive error:nil];
  201. NSArray* array = [regex matchesInString:data options:0 range:NSMakeRange(0, data.length)];
  202. NSString *link,*name = nil;
  203. NSMutableArray* result = [NSMutableArray array];
  204. for (NSTextCheckingResult* b in array)
  205. {
  206. link = [data substringWithRange:[b rangeAtIndex:1]];
  207. name = [data substringWithRange:[b rangeAtIndex:2]];
  208. if([name hasSuffix:@"/"] || [name hasSuffix:@".xml"])
  209. {
  210. [result addObject:link];
  211. [result addObject:name];
  212. }
  213. }
  214. return result;
  215. }
  216. -(void)loadInBackground:(NSString*)url
  217. {
  218. NSError* error = nil;
  219. NSData* data = FlexFetchHttpRes(url, &error);
  220. NSMutableArray* links = nil;
  221. if(data != nil){
  222. NSString* sdata = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
  223. links = [FlexHttpVC extractLinks:sdata];
  224. }
  225. __weak FlexHttpVC* weakSelf = self;
  226. dispatch_async(dispatch_get_main_queue(), ^{
  227. [weakSelf onLoadFinish:links error:error];
  228. });
  229. }
  230. -(void)onLoadFinish:(NSMutableArray*)links
  231. error:(NSError*)error
  232. {
  233. _bLoading = NO;
  234. NSString* status ;
  235. if(links != nil){
  236. status = @"Success";
  237. _layouts = links;
  238. [_table reloadData];
  239. }else{
  240. if(error==nil){
  241. status = @"Unknown error";
  242. }else{
  243. status = [error localizedDescription];
  244. }
  245. }
  246. _statusBar.text = status;
  247. }
  248. -(void)loadData
  249. {
  250. NSString* url = self.url;
  251. if(url == nil){
  252. url = FlexGetPreviewBaseUrl();
  253. if(url == nil)
  254. return;
  255. }
  256. if(_bLoading)
  257. return;
  258. _bLoading = YES;
  259. self.url = url;
  260. _pathLabel.text = url;
  261. _statusBar.text = @"loading...";
  262. __weak FlexHttpVC* weakSelf = self;
  263. dispatch_queue_t queue = dispatch_get_global_queue(
  264. DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  265. dispatch_async(queue,^{
  266. [weakSelf loadInBackground:url];
  267. });
  268. }
  269. #pragma mark - actions
  270. -(void)onGoUp
  271. {
  272. NSString* s = [self.url stringByDeletingLastPathComponent];
  273. if(s.length>7){
  274. s = [s stringByReplacingOccurrencesOfString:@":/" withString:@"://"];
  275. self.url = s;
  276. [self loadData];
  277. }
  278. }
  279. -(void)onGoHome
  280. {
  281. self.url = FlexGetPreviewBaseUrl();
  282. [self loadData];
  283. }
  284. -(void)onRefresh
  285. {
  286. [self loadData];
  287. }
  288. -(void)onSetting
  289. {
  290. [FlexSetPreviewVC presentInVC:self];
  291. }
  292. @end