RichTextEditViewController.m 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131
  1. //
  2. // RichTextEditViewController.m
  3. // RichTextEditDemo
  4. //
  5. // Created by aron on 2017/7/19.
  6. // Copyright © 2017年 aron. All rights reserved.
  7. //
  8. #import "RichTextEditViewController.h"
  9. #import <Masonry.h>
  10. #import <MobileCoreServices/MobileCoreServices.h>
  11. #import "UtilMacro.h"
  12. #import "MMFileUploadUtil.h"
  13. #import "MMRichContentUtil.h"
  14. #import "MMRichTextConfig.h"
  15. #import "MMDraftUtil.h"
  16. #import "MMRichTitleModel.h"
  17. #import "MMRichTextModel.h"
  18. #import "MMRichImageModel.h"
  19. #import "MMDraftModel.h"
  20. #import "MMRichTitleCell.h"
  21. #import "MMRichTextCell.h"
  22. #import "MMRichImageCell.h"
  23. #import "SmartBar.h"
  24. #import "LYLPhotoTailoringTool.h"
  25. #import "RichFileCell.h"
  26. #import "RichModel.h"
  27. #import "FWZGetNoteBookTool.h"
  28. #import "FWZFileGetTool.h"
  29. #define bottomOffsetHeight convertLength(49)
  30. #define BARHEIGHT 42.5f
  31. @interface RichTextEditViewController () <UITableViewDelegate, UITableViewDataSource, UINavigationControllerDelegate, UIImagePickerControllerDelegate, RichTextEditDelegate,SmartBarDelegate> {
  32. BOOL _isRefreshShow;
  33. }
  34. @property (nonatomic, strong) UITableView* tableView;
  35. @property (nonatomic, strong) UILabel *refreshTipLabel;
  36. @property (strong, nonatomic) SmartBar *SmartBar;
  37. @property (nonatomic, strong) UIView *editToolbar;
  38. @property (nonatomic, strong) MMRichTitleModel* titleModel;
  39. @property (nonatomic, strong) NSMutableArray* datas;
  40. @property (nonatomic, strong) NSIndexPath* activeIndexPath;
  41. @property (nonatomic, copy) NSString* tid;///<论坛ID
  42. @property (nonatomic, strong) MMDraftModel* draft;
  43. @property (nonatomic, assign) BOOL shouldShowAccessoryView;
  44. @property (nonatomic, assign) BOOL isOnUploading;
  45. @end
  46. @implementation RichTextEditViewController
  47. - (instancetype)initWithTid:(NSString*)tid {
  48. self = [super init];
  49. if (self) {
  50. _tid = tid;
  51. }
  52. return self;
  53. }
  54. - (instancetype)initWithDraft:(MMDraftModel*)draft {
  55. self = [super init];
  56. if (self) {
  57. _tid = draft.tid;
  58. _draft = draft;
  59. }
  60. return self;
  61. }
  62. - (SmartBar *)SmartBar
  63. {
  64. if (!_SmartBar) {
  65. _SmartBar = [[SmartBar alloc] init];
  66. }
  67. return _SmartBar;
  68. }
  69. - (void)viewDidLoad {
  70. [super viewDidLoad];
  71. self.title = @"编辑文章";
  72. self.view.backgroundColor = [UIColor whiteColor];
  73. self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStylePlain target:self action:@selector(onUpload)];
  74. UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
  75. button.backgroundColor = [UIColor clearColor];
  76. [button addTarget:self action:@selector(backButtonTapped) forControlEvents:UIControlEventTouchUpInside];
  77. button.frame = CGRectMake(0, 0, 40, 40);
  78. [button setTitle:@"Back" forState:UIControlStateNormal];
  79. self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button];
  80. // register cell
  81. [self.tableView registerClass:MMRichTitleCell.class forCellReuseIdentifier:NSStringFromClass(MMRichTitleCell.class)];
  82. [self.tableView registerClass:MMRichTextCell.class forCellReuseIdentifier:NSStringFromClass(MMRichTextCell.class)];
  83. [self.tableView registerClass:MMRichImageCell.class forCellReuseIdentifier:NSStringFromClass(MMRichImageCell.class)];
  84. [self.tableView registerClass:RichFileCell.class forCellReuseIdentifier:NSStringFromClass(RichFileCell.class)];
  85. // Datas
  86. if (_draft) {
  87. if ((MMRichTitleModel*)_draft.titleModel) {
  88. _titleModel = (MMRichTitleModel*)_draft.titleModel;
  89. } else {
  90. _titleModel = [MMRichTitleModel new];
  91. }
  92. _datas = [NSMutableArray array];
  93. if (_draft.contentModels) {
  94. [_datas addObjectsFromArray:_draft.contentModels];
  95. } else {
  96. [_datas addObject:[MMRichTextModel new]];
  97. }
  98. } else {
  99. _titleModel = [MMRichTitleModel new];
  100. _datas = [NSMutableArray array];
  101. [_datas addObject:[MMRichTextModel new]];
  102. }
  103. self.SmartBar.delegate = self;
  104. [self.view addSubview:self.SmartBar];
  105. [self.SmartBar mas_makeConstraints:^(MASConstraintMaker *make) {
  106. make.left.right.mas_equalTo(self.view);
  107. make.height.mas_offset(BARHEIGHT);
  108. if (@available(iOS 11.0, *)) {
  109. make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom).offset(BARHEIGHT);
  110. } else {
  111. make.bottom.equalTo(self.view.mas_bottom).offset(BARHEIGHT);
  112. }
  113. }];
  114. [self.view addSubview:self.tableView];
  115. [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
  116. make.left.top.right.mas_equalTo(self.view);
  117. make.bottom.mas_equalTo(self.SmartBar.mas_top);
  118. }];
  119. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardWillShow:) name:UIKeyboardWillShowNotification object:nil];
  120. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardWillHide:) name:UIKeyboardWillHideNotification object:nil];
  121. }
  122. #pragma mark - KeyBoard
  123. - (void)keyBoardWillShow:(NSNotification *)note
  124. {
  125. // 获取用户信息
  126. NSDictionary *userInfo = [NSDictionary dictionaryWithDictionary:note.userInfo];
  127. // 获取键盘高度
  128. CGRect keyBoardBounds = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
  129. CGFloat keyBoardHeight = keyBoardBounds.size.height;
  130. // 获取键盘动画时间
  131. CGFloat animationTime = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
  132. // 定义好动作
  133. WS(weakSelf);
  134. [UIView animateWithDuration:animationTime animations:^{
  135. [weakSelf.SmartBar mas_updateConstraints:^(MASConstraintMaker *make) {
  136. if (@available(iOS 11.0, *)) {
  137. make.bottom.equalTo(weakSelf.view.mas_safeAreaLayoutGuideBottom).offset(-keyBoardHeight);
  138. } else {
  139. make.bottom.equalTo(weakSelf.view.mas_bottom).offset(-keyBoardHeight);
  140. }
  141. }];
  142. [weakSelf.view layoutIfNeeded];
  143. } completion:^(BOOL finished) {
  144. }];
  145. }
  146. - (void)keyBoardWillHide:(NSNotification *)note
  147. {
  148. // 获取用户信息
  149. NSDictionary *userInfo = [NSDictionary dictionaryWithDictionary:note.userInfo];
  150. // 获取键盘动画时间
  151. CGFloat animationTime = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
  152. WS(weakSelf);
  153. [UIView animateWithDuration:animationTime animations:^{
  154. [weakSelf.SmartBar mas_updateConstraints:^(MASConstraintMaker *make) {
  155. if (@available(iOS 11.0, *)) {
  156. make.bottom.equalTo(weakSelf.view.mas_safeAreaLayoutGuideBottom).offset(BARHEIGHT);
  157. } else {
  158. make.bottom.equalTo(weakSelf.view.mas_bottom).offset(BARHEIGHT);
  159. }
  160. }];
  161. [weakSelf.view layoutIfNeeded];
  162. } completion:^(BOOL finished) {
  163. }];
  164. }
  165. - (void)viewDidAppear:(BOOL)animated {
  166. [super viewDidAppear:animated];
  167. /// 禁用返回手势
  168. if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
  169. self.navigationController.interactivePopGestureRecognizer.enabled = NO;
  170. }
  171. }
  172. - (void)viewWillDisappear:(BOOL)animated {
  173. [super viewWillDisappear:animated];
  174. // 开启返回手势
  175. if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
  176. self.navigationController.interactivePopGestureRecognizer.enabled = YES;
  177. }
  178. }
  179. - (void)viewDidLayoutSubviews {
  180. [super viewDidLayoutSubviews];
  181. }
  182. - (UITableView *)tableView {
  183. if (!_tableView) {
  184. UITableView* tableView = [UITableView new];
  185. tableView.delegate = self;
  186. tableView.dataSource = self;
  187. // tableView.estimatedRowHeight = 200;
  188. // tableView.rowHeight = UITableViewAutomaticDimension;
  189. tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  190. [tableView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTableViewTap)]];
  191. tableView.contentInset = UIEdgeInsetsMake(0, 0, bottomOffsetHeight, 0);
  192. _tableView = tableView;
  193. }
  194. return _tableView;
  195. }
  196. - (void)dealloc {
  197. [[NSNotificationCenter defaultCenter] removeObserver:self];
  198. NSLog(@"===dealloc===");
  199. }
  200. - (void)updateImages:(NSArray *)images
  201. {
  202. NSMutableArray *imageArr = [NSMutableArray array];
  203. for (UIImage *image in images) {
  204. [imageArr addObject:UIImageJPEGRepresentation(image,1.0f)];
  205. }
  206. WS(weakSelf);
  207. NSString *urlString = [[NSString alloc] initWithFormat:@"%@%@",BaseUrl,Modify_UserImages_Post];
  208. [[HttpManager sharedHttpManager] HeaderUploadUrl:urlString parameters:@{} pictureArray:imageArr pictureKey:@"file" success:^(id _Nonnull responseObject) {
  209. NSArray * dataArray = responseObject;
  210. NSMutableArray * addArray = [NSMutableArray array];
  211. for (NSInteger i = 0; i < dataArray.count; i ++) {
  212. NSDictionary * dict = dataArray[i];
  213. MMRichImageModel * model = [[MMRichImageModel alloc] init];
  214. model.remoteImageUrlString = dict[@"AbsolutePath"];
  215. model.image = images[i];
  216. [addArray addObject:model];
  217. }
  218. [weakSelf handleInsertModelArray:addArray];
  219. } failure:^(NSError * _Nonnull error) {
  220. SHOWERROR([ZYCTool handerResultData:error]);
  221. }];
  222. }
  223. - (void)handleInsertModelArray:(NSArray *)array{
  224. WS(weakSelf);
  225. __block NSBlockOperation *operation;
  226. __block NSBlockOperation *operation1;
  227. NSMutableArray * operArray = [NSMutableArray array];
  228. for (NSInteger i = 0; i < array.count; i ++) {
  229. RichModel * model = array[i];
  230. operation = [NSBlockOperation blockOperationWithBlock:^{
  231. dispatch_semaphore_t sema = dispatch_semaphore_create(0);
  232. NSLog(@"上传成功=================");
  233. if (!weakSelf.activeIndexPath) {
  234. weakSelf.activeIndexPath = [NSIndexPath indexPathForRow:0 inSection:1];
  235. }
  236. NSIndexPath* addIndexPath = [NSIndexPath indexPathForRow:weakSelf.activeIndexPath.row + 1 inSection:weakSelf.activeIndexPath.section];
  237. NSIndexPath* nextIndexPath = [NSIndexPath indexPathForRow:weakSelf.activeIndexPath.row + 2 inSection:weakSelf.activeIndexPath.section];
  238. if (weakSelf.activeIndexPath.row == (weakSelf.datas.count - 1)) {
  239. [weakSelf.datas addObject:model];
  240. dispatch_async(dispatch_get_main_queue(), ^{
  241. [weakSelf.tableView reloadData];
  242. [weakSelf addTextNodeAtIndexPath:nextIndexPath textContent:nil];
  243. dispatch_semaphore_signal(sema);
  244. });
  245. }else{
  246. dispatch_async(dispatch_get_main_queue(), ^{
  247. [weakSelf.tableView beginUpdates];
  248. [weakSelf.datas insertObject:model atIndex:addIndexPath.row];
  249. [weakSelf.tableView insertRowsAtIndexPaths:@[addIndexPath] withRowAnimation:UITableViewRowAnimationNone];
  250. [weakSelf.tableView endUpdates];
  251. [weakSelf.tableView scrollToRowAtIndexPath:addIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
  252. if (addIndexPath.row < weakSelf.datas.count - 1) {
  253. NSIndexPath* nextIndexPath = [NSIndexPath indexPathForRow:addIndexPath.row + 1 inSection:addIndexPath.section];
  254. id nextData = weakSelf.datas[nextIndexPath.row];
  255. if ([nextData isKindOfClass:[MMRichTextModel class]]) {
  256. // Image节点-后面:下面是text,光标移动到下面一行,并且在最前面添加一个换行,定位光标在最前面
  257. [weakSelf.tableView scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
  258. MMRichTextModel* textModel = ((MMRichTextModel*)nextData);
  259. textModel.selectedRange = NSMakeRange(0, 0);
  260. textModel.shouldUpdateSelectedRange = YES;
  261. [weakSelf positionAtIndex:nextIndexPath];
  262. } else if ([nextData isKindOfClass:[MMRichImageModel class]]) {
  263. // 添加文字到下一行
  264. [weakSelf addTextNodeAtIndexPath:nextIndexPath textContent:@""];
  265. }else{
  266. [weakSelf addTextNodeAtIndexPath:nextIndexPath textContent:@""];
  267. }
  268. } else {
  269. // 添加文字到下一行
  270. NSIndexPath* nextIndexPath = [NSIndexPath indexPathForRow:addIndexPath.row + 1 inSection:addIndexPath.section];
  271. [weakSelf addTextNodeAtIndexPath:nextIndexPath textContent:@""];
  272. [weakSelf positionAtIndex:nextIndexPath];
  273. }
  274. dispatch_semaphore_signal(sema);
  275. });
  276. }
  277. dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
  278. }];
  279. if (i > 0) {
  280. [operation addDependency:operation1]; //请求3依赖请求2
  281. }
  282. [operArray addObject:operation];
  283. operation1 = operation;
  284. }
  285. NSOperationQueue *queue = [[NSOperationQueue alloc] init];
  286. [queue addOperations:operArray waitUntilFinished:NO];
  287. }
  288. #pragma mark backbtntap
  289. - (void)backButtonTapped {
  290. // 保存草稿箱
  291. if (_draft) {
  292. if ([MMRichContentUtil validateTitle:_titleModel]
  293. || [MMRichContentUtil validataContentNotEmptyWithRichContents:_datas]) {
  294. MMDraftModel* draftData = [MMDraftUtil draftModelWithTitleModel:_titleModel contents:_datas tid:_tid draftId:_draft.draftId];
  295. [MMDraftUtil saveDraftData:draftData];
  296. } else {
  297. // 删除草稿箱
  298. [MMDraftUtil delateDraftData:_draft];
  299. }
  300. } else {
  301. if ([MMRichContentUtil validateTitle:_titleModel]
  302. || [MMRichContentUtil validataContentNotEmptyWithRichContents:_datas]) {
  303. MMDraftModel* draftData = [MMDraftUtil draftModelWithTitleModel:_titleModel contents:_datas tid:_tid draftId:0];
  304. [MMDraftUtil saveDraftData:draftData];
  305. }
  306. }
  307. [self.navigationController popViewControllerAnimated:YES];
  308. }
  309. #pragma mark - ......::::::: ui actoin :::::::......
  310. - (void)onUpload {
  311. if (_isOnUploading) {
  312. return;
  313. }
  314. // 验证输入
  315. // 1、验证内容
  316. if (![MMRichContentUtil validataContentNotEmptyWithRichContents:_datas]) {
  317. UIAlertView* alert = [[UIAlertView alloc] initWithTitle:nil message:@"输入内容" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil, nil];
  318. [alert show];
  319. return;
  320. }
  321. // 2、验证title
  322. if (![MMRichContentUtil validateTitle:_titleModel]) {
  323. UIAlertView* alert = [[UIAlertView alloc] initWithTitle:nil message:@"输入标题" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil, nil];
  324. [alert show];
  325. return;
  326. }
  327. // 3、验证内容是否超过上限
  328. if (![MMRichContentUtil validataContentNotOverflowWithRichContents:_datas]) {
  329. UIAlertView* alert = [[UIAlertView alloc] initWithTitle:nil message:@"输入内容" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil, nil];
  330. [alert show];
  331. return;
  332. }
  333. // 4、验证图片时候上传成功
  334. if (![MMRichContentUtil validateImagesWithRichContents:self.datas]) {
  335. // 还有图片没上传或者图片失败的情况
  336. return;
  337. }
  338. // 发送内容
  339. _isOnUploading = YES;
  340. NSString* html = [MMRichContentUtil htmlContentFromRichContents:self.datas];
  341. NSArray* images = [MMRichContentUtil imagesFromRichContents:self.datas];
  342. // 处理发送...
  343. // FIXME: ZYT TODO 处理发送...
  344. }
  345. - (void)onTableViewTap {
  346. NSIndexPath* lastIndexPath = [NSIndexPath indexPathForRow:_datas.count - 1 inSection:1];
  347. UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:lastIndexPath];
  348. if ([cell isKindOfClass:[MMRichTextCell class]]) {
  349. [((MMRichTextCell*)cell) mm_beginEditing];
  350. } else if ([cell isKindOfClass:[MMRichImageCell class]]) {
  351. [((MMRichImageCell*)cell) mm_beginEditing];
  352. }else{
  353. [((RichFileCell*)cell) mm_beginEditing];
  354. }
  355. }
  356. #pragma mark - Node Handler
  357. - (void)addTextNodeAtIndexPath:(NSIndexPath*)indexPath textContent:(NSString*)textContent {
  358. WS(weakSelf);
  359. dispatch_async(dispatch_get_main_queue(), ^{
  360. MMRichTextModel* textModel = [MMRichTextModel new];
  361. textModel.textContent = [textContent isEqualToString:@"\n"] ? @"" : textContent == nil ? @"" : textContent;
  362. textModel.textContentHeight = [MMRichContentUtil computeHeightInTextVIewWithContent:textModel.textContent];
  363. [weakSelf.tableView beginUpdates];
  364. [weakSelf.datas insertObject:textModel atIndex:indexPath.row];
  365. [weakSelf.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
  366. [weakSelf.tableView endUpdates];
  367. [weakSelf.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
  368. });
  369. // 定位到新增的元素
  370. [self positionAtIndex:indexPath];
  371. }
  372. - (void)deleteItemAtIndexPathes:(NSArray<NSIndexPath*>*)actionIndexPathes shouldPositionPrevious:(BOOL)shouldPositionPrevious {
  373. if (actionIndexPathes.count > 0) {
  374. // 处理删除
  375. for (NSInteger i = actionIndexPathes.count - 1; i >= 0; i--) {
  376. NSIndexPath* actionIndexPath = actionIndexPathes[i];
  377. id obj = _datas[actionIndexPath.row];
  378. if ([obj isKindOfClass:[MMRichImageModel class]]) {
  379. [MMDraftUtil deleteImageContent:(MMRichImageModel*)obj];
  380. }
  381. [_datas removeObjectAtIndex:actionIndexPath.row];
  382. }
  383. [self.tableView beginUpdates];
  384. [self.tableView deleteRowsAtIndexPaths:actionIndexPathes withRowAnimation:UITableViewRowAnimationAutomatic];
  385. [self.tableView endUpdates];
  386. // 定位动到上一行
  387. if (shouldPositionPrevious) {
  388. [self positionToPreItemAtIndexPath:actionIndexPathes.firstObject];
  389. }
  390. }
  391. }
  392. - (void)deleteItemAtIndexPath:(NSIndexPath*)actionIndexPath shouldPositionPrevious:(BOOL)shouldPositionPrevious {
  393. // 定位动到上一行
  394. if (shouldPositionPrevious) {
  395. [self positionToPreItemAtIndexPath:actionIndexPath];
  396. }
  397. // 处理删除
  398. [_datas removeObjectAtIndex:actionIndexPath.row];
  399. [self.tableView beginUpdates];
  400. [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:actionIndexPath.row inSection:actionIndexPath.section]] withRowAnimation:UITableViewRowAnimationAutomatic];
  401. [self.tableView endUpdates];
  402. }
  403. /**
  404. 定位到指定的元素
  405. */
  406. - (void)positionAtIndex:(NSIndexPath*)indexPath {
  407. UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
  408. if ([cell isKindOfClass:[MMRichTextCell class]]) {
  409. [((MMRichTextCell*)cell) mm_beginEditing];
  410. } else if ([cell isKindOfClass:[MMRichImageCell class]]) {
  411. [((MMRichImageCell*)cell) mm_beginEditing];
  412. }else{
  413. [((RichFileCell*)cell) mm_beginEditing];
  414. }
  415. }
  416. // 定位动到上一行
  417. - (void)positionToPreItemAtIndexPath:(NSIndexPath*)actionIndexPath {
  418. NSIndexPath* preIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row - 1 inSection:actionIndexPath.section];
  419. [self positionAtIndex:preIndexPath];
  420. }
  421. // 定位动到上一行
  422. - (void)positionToNextItemAtIndexPath:(NSIndexPath*)actionIndexPath {
  423. NSIndexPath* preIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row + 1 inSection:actionIndexPath.section];
  424. [self positionAtIndex:preIndexPath];
  425. }
  426. #pragma mark - SmartBarDelegete
  427. - (void)didSelectBarAddBtnIsShow:(BOOL)isShow
  428. {
  429. [self.view endEditing:YES];
  430. }
  431. - (void)didSelectBarKeyBtnIsShow:(BOOL)isShow
  432. {
  433. [self.view endEditing:YES];
  434. }
  435. - (void)didSelectBarWithType:(SmartBarType)type
  436. {
  437. WS(weakSelf);
  438. switch (type) {
  439. case SmartBarPhoto:
  440. {
  441. [self chatBarDidPhotoAction];
  442. }
  443. break;
  444. case SmartBarCamera:
  445. {
  446. [[LYLPhotoTailoringTool sharedTool] selectPhotoWithPhoroOrCamera:SelectPhotoWithTypePhoroOrCamera2 crop:YES showImgBlock:^(NSString *imageUrlStr) {
  447. } choosImgBlock:^(UIImage *image) {
  448. [weakSelf updateImages:@[image]];
  449. }];
  450. }
  451. break;
  452. case SmartBarNotes:
  453. {
  454. [[FWZGetNoteBookTool sharedTool] openNoteBookListChooseNoteBookBlock:^(NSMutableArray<MyNoteBookSubModel *> * _Nonnull noteArr) {
  455. NSLog(@"SmartBarNotes %@",noteArr);
  456. [weakSelf disSelectNoteBook:noteArr];
  457. }];
  458. }
  459. break;
  460. case SmartBarCollection:
  461. {
  462. [[FWZGetNoteBookTool sharedTool] openCollectListChooseCollectBlock:^(NSMutableArray<MyFavoriteSubModel *> * _Nonnull collectArr) {
  463. NSLog(@"SmartBarCollection %@",collectArr);
  464. [weakSelf disSelectCollect:collectArr];
  465. }];
  466. }
  467. break;
  468. case SmartBarFile:
  469. {
  470. WS(weakSelf);
  471. [[FWZFileGetTool sharedTool] openFileWithCrop:YES showImgBlock:^(NSString * _Nonnull fileUrlStr) {
  472. } choosFileBlock:^(NSData * _Nonnull fileData, NSString * _Nonnull fileName) {
  473. SHOWLOADING
  474. [[HttpManager sharedHttpManager] HeaderUploadFileUrl:Host(Modify_UserImages_Post) parameters:@{} fileData:fileData fileKey:@"file" fileName:fileName mimeType:@"multipart/form-data" success:^(id _Nonnull responseObject) {
  475. REMOVESHOW
  476. NSLog(@"上传成功的文件%@",responseObject);
  477. [weakSelf fileSizeWithData:fileData withDict:responseObject[0]];
  478. } failure:^(NSError * _Nonnull error) {
  479. REMOVESHOW
  480. }];
  481. }];
  482. }
  483. break;
  484. default:
  485. break;
  486. }
  487. }
  488. - (void)disSelectNoteBook:(NSMutableArray<MyNoteBookSubModel *>*_Nonnull )noteArr{
  489. RichModel * model = [[RichModel alloc] init];
  490. NSMutableArray * array = [NSMutableArray array];
  491. for (MyNoteBookSubModel *dataModel in noteArr ) {
  492. switch (dataModel.AttributeValue) {
  493. case 1:
  494. {
  495. model.Id = dataModel.MiddleId;
  496. model.AvatarUrl = dataModel.AvatarUrl;
  497. model.Author = dataModel.Name;
  498. model.Name = dataModel.Name;
  499. model.Title = dataModel.Title;
  500. model.type = CollectDataType_Note;
  501. }
  502. break;
  503. case 2:
  504. {
  505. model.Id = dataModel.MiddleId;
  506. model.AvatarUrl = dataModel.AvatarUrl;
  507. model.Author = dataModel.Name;
  508. model.Name = dataModel.Name;
  509. model.Title = dataModel.Title;
  510. model.type = CollectDataType_NoteFile;
  511. }
  512. break;
  513. default:
  514. break;
  515. }
  516. [array addObject:model];
  517. }
  518. [self handleInsertModelArray:array];
  519. }
  520. - (void)disSelectCollect:(NSMutableArray<MyFavoriteSubModel *> * _Nonnull) collectArr{
  521. RichModel * model = [[RichModel alloc] init];
  522. NSMutableArray * array = [NSMutableArray array];
  523. for (MyFavoriteSubModel *dataModel in collectArr ) {
  524. switch (dataModel.AttributeValue) {
  525. case 1:
  526. {
  527. model.Id = dataModel.MiddleId;
  528. model.AvatarUrl = dataModel.AvatarUrl;
  529. model.Author = dataModel.Name;
  530. model.Name = dataModel.Name;
  531. model.Title = dataModel.Title;
  532. model.type = CollectDataType_Collect;
  533. }
  534. break;
  535. case 2:
  536. {
  537. RichModel * model = [[RichModel alloc] init];
  538. model.Id = dataModel.MiddleId;
  539. model.AvatarUrl = dataModel.AvatarUrl;
  540. model.Author = dataModel.Name;
  541. model.Name = dataModel.Name;
  542. model.Title = dataModel.Title;
  543. model.type = CollectDataType_CollectFile;
  544. }
  545. break;
  546. default:
  547. break;
  548. }
  549. }
  550. [self handleInsertModelArray:array];
  551. }
  552. - (void)fileSizeWithData:(NSData *)fileData withDict:(NSDictionary *)dict
  553. {
  554. unsigned long long size = [fileData length];
  555. NSString * fileZise;
  556. if (size >= pow(10, 9)) { // size >= 1GB
  557. fileZise = [NSString stringWithFormat:@"%.2fGB", size / pow(10, 9)];
  558. } else if (size >= pow(10, 6)) { // 1GB > size >= 1MB
  559. fileZise = [NSString stringWithFormat:@"%.2fMB", size / pow(10, 6)];
  560. } else if (size >= pow(10, 3)) { // 1MB > size >= 1KB
  561. fileZise = [NSString stringWithFormat:@"%.2fKB", size / pow(10, 3)];
  562. } else { // 1KB > size
  563. fileZise = [NSString stringWithFormat:@"%lluB", size];
  564. }
  565. [self didSelectFile:dict withSize:fileZise];
  566. }
  567. - (void)didSelectFile:(NSDictionary *)dict withSize:(NSString *)fileSize
  568. {
  569. RichModel * model = [[RichModel alloc] init];
  570. model.Id = [dict[@"FileId"] integerValue];
  571. model.AvatarUrl = dict[@"AbsolutePath"];
  572. model.Author =dict[@"FileName"];
  573. model.Name = dict[@"FileName"];
  574. model.Title = dict[@"FileName"];
  575. model.type = CollectDataType_File;
  576. [self handleInsertModelArray:@[model]];
  577. }
  578. - (void)chatBarDidPhotoAction
  579. {
  580. WS(weakSelf);
  581. [self.view endEditing:YES];
  582. TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:9 delegate:nil];
  583. [imagePickerVc setNavLeftBarButtonSettingBlock:^(UIButton *leftButton){
  584. leftButton.hidden = YES;
  585. }];
  586. imagePickerVc.showSelectBtn = NO;
  587. imagePickerVc.allowCrop = YES;
  588. imagePickerVc.cropRect = CGRectMake(0, (SCREEN_HEIGHT - SCREEN_WIDTH) * 0.5, SCREEN_WIDTH, SCREEN_WIDTH);
  589. imagePickerVc.allowTakePicture = NO;
  590. imagePickerVc.allowTakeVideo = NO;
  591. imagePickerVc.allowPickingOriginalPhoto = NO;
  592. imagePickerVc.allowPickingGif = NO;
  593. [imagePickerVc setIsStatusBarDefault:YES];
  594. [imagePickerVc setNaviTitleColor:[UIColor blackColor]];
  595. [imagePickerVc setBarItemTextColor:[UIColor blackColor]];
  596. [imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
  597. PHAsset *asset = assets.firstObject;
  598. switch (asset.mediaType) {
  599. case PHAssetMediaTypeVideo: {
  600. } break;
  601. case PHAssetMediaTypeImage: {
  602. [weakSelf updateImages:photos];
  603. } break;
  604. case PHAssetMediaTypeAudio:
  605. break;
  606. case PHAssetMediaTypeUnknown:
  607. break;
  608. default: break;
  609. }
  610. }];
  611. [self presentViewController:imagePickerVc animated:YES completion:nil];
  612. }
  613. #pragma mark - ......::::::: RichTextEditDelegate :::::::......
  614. - (void)mm_preInsertTextLineAtIndexPath:(NSIndexPath*)actionIndexPath textContent:(NSString*)textContent {
  615. UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:actionIndexPath];
  616. if ([cell isKindOfClass:[MMRichTextCell class]]) {
  617. // 不处理
  618. } else if ([cell isKindOfClass:[MMRichImageCell class]]) {
  619. NSIndexPath* preIndexPath = nil;
  620. if (actionIndexPath.row > 0) {
  621. preIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row - 1 inSection:actionIndexPath.section];
  622. id preData = _datas[preIndexPath.row];
  623. if ([preData isKindOfClass:[MMRichTextModel class]]) {
  624. // Image节点-前面:上面是text,光标移动到上面一行,并且在最后添加一个换行,定位光标在最后将
  625. [self.tableView scrollToRowAtIndexPath:preIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
  626. // 设置为编辑模式
  627. UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:preIndexPath];
  628. if ([cell isKindOfClass:[MMRichTextCell class]]) {
  629. [((MMRichTextCell*)cell) mm_beginEditing];
  630. } else if ([cell isKindOfClass:[MMRichImageCell class]]) {
  631. [((MMRichImageCell*)cell) mm_beginEditing];
  632. }else{
  633. [((RichFileCell*)cell) mm_beginEditing];
  634. }
  635. } else if ([preData isKindOfClass:[MMRichImageModel class]]) {
  636. // Image节点-前面:上面是图片或者空,在上面添加一个Text节点,光标移动到上面一行,
  637. [self addTextNodeAtIndexPath:actionIndexPath textContent:textContent];
  638. }else{
  639. [self addTextNodeAtIndexPath:actionIndexPath textContent:textContent];
  640. }
  641. } else {
  642. // 上面为空,添加一个新的单元格
  643. [self addTextNodeAtIndexPath:actionIndexPath textContent:textContent];
  644. }
  645. }else{
  646. NSIndexPath* preIndexPath = nil;
  647. if (actionIndexPath.row > 0) {
  648. preIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row - 1 inSection:actionIndexPath.section];
  649. id preData = _datas[preIndexPath.row];
  650. if ([preData isKindOfClass:[MMRichTextModel class]]) {
  651. // Image节点-前面:上面是text,光标移动到上面一行,并且在最后添加一个换行,定位光标在最后将
  652. [self.tableView scrollToRowAtIndexPath:preIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
  653. // 设置为编辑模式
  654. UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:preIndexPath];
  655. if ([cell isKindOfClass:[MMRichTextCell class]]) {
  656. [((MMRichTextCell*)cell) mm_beginEditing];
  657. } else if ([cell isKindOfClass:[MMRichImageCell class]]) {
  658. [((MMRichImageCell*)cell) mm_beginEditing];
  659. }else{
  660. [((RichFileCell*)cell) mm_beginEditing];
  661. }
  662. } else if ([preData isKindOfClass:[MMRichImageModel class]]) {
  663. // Image节点-前面:上面是图片或者空,在上面添加一个Text节点,光标移动到上面一行,
  664. [self addTextNodeAtIndexPath:actionIndexPath textContent:textContent];
  665. }else{
  666. [self addTextNodeAtIndexPath:actionIndexPath textContent:textContent];
  667. }
  668. } else {
  669. // 上面为空,添加一个新的单元格
  670. [self addTextNodeAtIndexPath:actionIndexPath textContent:textContent];
  671. }
  672. }
  673. }
  674. - (void)mm_postInsertTextLineAtIndexPath:(NSIndexPath*)actionIndexPath textContent:(NSString *)textContent {
  675. UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:actionIndexPath];
  676. if ([cell isKindOfClass:[MMRichTextCell class]]) {
  677. // 不处理
  678. } else if ([cell isKindOfClass:[MMRichImageCell class]]) {
  679. NSIndexPath* nextIndexPath = nil;
  680. nextIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row + 1 inSection:actionIndexPath.section];
  681. if (actionIndexPath.row < _datas.count-1) {
  682. id nextData = _datas[nextIndexPath.row];
  683. if ([nextData isKindOfClass:[MMRichTextModel class]]) {
  684. // Image节点-后面:下面是text,光标移动到下面一行,并且在最前面添加一个换行,定位光标在最前面
  685. [self.tableView scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
  686. // 添加文字到下一行
  687. MMRichTextModel* textModel = ((MMRichTextModel*)nextData);
  688. textModel.textContent = [NSString stringWithFormat:@"%@%@", textContent, textModel.textContent];
  689. textModel.textContentHeight = [MMRichContentUtil computeHeightInTextVIewWithContent:textModel.textContent];
  690. if ([textContent isEqualToString:@"\n"]) {
  691. textModel.selectedRange = NSMakeRange(0, 0);
  692. } else {
  693. textModel.selectedRange = NSMakeRange(textContent.length, 0);
  694. }
  695. textModel.shouldUpdateSelectedRange = YES;
  696. // 设置为编辑模式
  697. UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:nextIndexPath];
  698. if ([cell isKindOfClass:[MMRichTextCell class]]) {
  699. [((MMRichTextCell*)cell) mm_beginEditing];
  700. } else if ([cell isKindOfClass:[MMRichImageCell class]]) {
  701. [((MMRichImageCell*)cell) mm_beginEditing];
  702. }else{
  703. [((RichFileCell*)cell) mm_beginEditing];
  704. }
  705. } else if ([nextData isKindOfClass:[MMRichImageModel class]]) {
  706. // Image节点-后面:下面是图片或者空,在下面添加一个Text节点,光标移动到下面一行
  707. [self addTextNodeAtIndexPath:nextIndexPath textContent:textContent];
  708. }else{
  709. [self addTextNodeAtIndexPath:nextIndexPath textContent:textContent];
  710. }
  711. } else {
  712. // Image节点-后面:下面是图片或者空,在下面添加一个Text节点,光标移动到下面一行
  713. [self addTextNodeAtIndexPath:nextIndexPath textContent:textContent];
  714. }
  715. }else{
  716. NSIndexPath* nextIndexPath = nil;
  717. nextIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row + 1 inSection:actionIndexPath.section];
  718. if (actionIndexPath.row < _datas.count - 1) {
  719. id nextData = _datas[nextIndexPath.row];
  720. if ([nextData isKindOfClass:[MMRichTextModel class]]) {
  721. // Image节点-后面:下面是text,光标移动到下面一行,并且在最前面添加一个换行,定位光标在最前面
  722. [self.tableView scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
  723. // 添加文字到下一行
  724. MMRichTextModel* textModel = ((MMRichTextModel*)nextData);
  725. textModel.textContent = [NSString stringWithFormat:@"%@%@", textContent, textModel.textContent];
  726. textModel.textContentHeight = [MMRichContentUtil computeHeightInTextVIewWithContent:textModel.textContent];
  727. if ([textContent isEqualToString:@"\n"]) {
  728. textModel.selectedRange = NSMakeRange(0, 0);
  729. } else {
  730. textModel.selectedRange = NSMakeRange(textContent.length, 0);
  731. }
  732. textModel.shouldUpdateSelectedRange = YES;
  733. // 设置为编辑模式
  734. UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:nextIndexPath];
  735. if ([cell isKindOfClass:[MMRichTextCell class]]) {
  736. [((MMRichTextCell*)cell) mm_beginEditing];
  737. } else if ([cell isKindOfClass:[MMRichImageCell class]]) {
  738. [((MMRichImageCell*)cell) mm_beginEditing];
  739. }else{
  740. [((RichFileCell*)cell) mm_beginEditing];
  741. }
  742. } else if ([nextData isKindOfClass:[MMRichImageModel class]]) {
  743. // Image节点-后面:下面是图片或者空,在下面添加一个Text节点,光标移动到下面一行
  744. [self addTextNodeAtIndexPath:nextIndexPath textContent:textContent];
  745. }else {
  746. // Image节点-后面:下面是图片或者空,在下面添加一个Text节点,光标移动到下面一行
  747. [self addTextNodeAtIndexPath:nextIndexPath textContent:textContent];
  748. }
  749. }else {
  750. // Image节点-后面:下面是图片或者空,在下面添加一个Text节点,光标移动到下面一行
  751. [self addTextNodeAtIndexPath:nextIndexPath textContent:textContent];
  752. }
  753. }
  754. }
  755. - (void)mm_preDeleteItemAtIndexPath:(NSIndexPath*)actionIndexPath {
  756. UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:actionIndexPath];
  757. if ([cell isKindOfClass:[MMRichTextCell class]]) {
  758. // 处理Text节点
  759. if (actionIndexPath.row < _datas.count) {
  760. if (actionIndexPath.row <= 0) {
  761. MMRichTextModel* textModel = (MMRichTextModel*)_datas[actionIndexPath.row];
  762. if (_datas.count == 1) {
  763. // Text节点-当前的Text为空-前面-没有其他元素-:不处理
  764. // Text节点-当前的Text不为空-前面-没有其他元素-:不处理
  765. } else {
  766. if (textModel.textContent.length == 0) {
  767. // Text节点-当前的Text为空-前面-有其他元素-:删除这一行,定位光标到下面图片的最后
  768. [self positionToNextItemAtIndexPath:actionIndexPath];
  769. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:NO];
  770. } else {
  771. // Text节点-当前的Text不为空-前面-有其他元素-:不处理
  772. }
  773. }
  774. } else {
  775. MMRichTextModel* textModel = (MMRichTextModel*)_datas[actionIndexPath.row];
  776. if (textModel.textContent.length == 0) {
  777. // Text节点-当前的Text为空-前面-有其他元素-:删除这一行,定位光标到上面图片的最后
  778. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:YES];
  779. } else {
  780. // 当前节点不为空
  781. // Text节点-当前的Text不为空-前面-:上面是图片,定位光标到上面图片的最后
  782. // Text节点不存在相邻的情况,所以直接定位上上一个元素即可
  783. [self positionToPreItemAtIndexPath:actionIndexPath];
  784. }
  785. }
  786. }
  787. } else if ([cell isKindOfClass:[MMRichImageCell class]]) {
  788. // 处理Image节点
  789. if (actionIndexPath.row < _datas.count) {
  790. if (actionIndexPath.row <= 0) {
  791. // Image节点-前面-上面为空:不处理
  792. // 第一行不处理
  793. } else {
  794. NSIndexPath* preIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row - 1 inSection:actionIndexPath.section];
  795. if (preIndexPath.row < _datas.count) {
  796. id preData = _datas[preIndexPath.row];
  797. if ([preData isKindOfClass:[MMRichTextModel class]]) {
  798. if (((MMRichTextModel*)preData).textContent.length == 0) {
  799. // mage节点-前面-上面为Text(为空):删除上面Text节点
  800. [self deleteItemAtIndexPath:preIndexPath shouldPositionPrevious:NO];
  801. } else {
  802. [self positionToPreItemAtIndexPath:actionIndexPath];
  803. }
  804. } else if ([preData isKindOfClass:[MMRichImageModel class]]) {
  805. [self positionToPreItemAtIndexPath:actionIndexPath];
  806. }else{
  807. [self positionToPreItemAtIndexPath:actionIndexPath];
  808. }
  809. }
  810. }
  811. }
  812. }else{
  813. if (actionIndexPath.row < _datas.count) {
  814. if (actionIndexPath.row <= 0) {
  815. // Image节点-前面-上面为空:不处理
  816. // 第一行不处理
  817. } else {
  818. NSIndexPath* preIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row - 1 inSection:actionIndexPath.section];
  819. if (preIndexPath.row < _datas.count) {
  820. id preData = _datas[preIndexPath.row];
  821. if ([preData isKindOfClass:[MMRichTextModel class]]) {
  822. if (((MMRichTextModel*)preData).textContent.length == 0) {
  823. // mage节点-前面-上面为Text(为空):删除上面Text节点
  824. [self deleteItemAtIndexPath:preIndexPath shouldPositionPrevious:NO];
  825. } else {
  826. [self positionToPreItemAtIndexPath:actionIndexPath];
  827. }
  828. } else if ([preData isKindOfClass:[MMRichImageModel class]]) {
  829. [self positionToPreItemAtIndexPath:actionIndexPath];
  830. }else{
  831. [self positionToPreItemAtIndexPath:actionIndexPath];
  832. }
  833. }
  834. }
  835. }
  836. }
  837. }
  838. - (void)mm_PostDeleteItemAtIndexPath:(NSIndexPath*)actionIndexPath {
  839. UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:actionIndexPath];
  840. if ([cell isKindOfClass:[MMRichTextCell class]]) {
  841. // 不处理
  842. // Text节点-当前的Text不为空-后面-:正常删除
  843. // Text节点-当前的Text为空-后面-:正常删除,和第三种情况:为空的情况处理一样
  844. } else if ([cell isKindOfClass:[MMRichImageCell class]]) {
  845. // 处理Image节点
  846. if (actionIndexPath.row < _datas.count) {
  847. // 处理第一个节点
  848. if (actionIndexPath.row <= 0) {
  849. if (_datas.count > 1) {
  850. // Image节点-后面-上面为空-列表多于一个元素:删除当前节点,光标放在后面元素之前
  851. [self positionToNextItemAtIndexPath:actionIndexPath];
  852. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:NO];
  853. } else {
  854. // Image节点-后面-上面为空-列表只有一个元素:添加一个Text节点,删除当前Image节点,光标放在添加的Text节点上
  855. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:NO];
  856. [self addTextNodeAtIndexPath:actionIndexPath textContent:nil];
  857. }
  858. } else {
  859. // 处理非第一个节点
  860. NSIndexPath* preIndexPath = nil;
  861. if (actionIndexPath.row > 0) {
  862. preIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row - 1 inSection:actionIndexPath.section];
  863. id preData = _datas[preIndexPath.row];
  864. if ([preData isKindOfClass:[MMRichTextModel class]]) {
  865. NSIndexPath* nextIndexPath = nil;
  866. if (actionIndexPath.row < _datas.count - 1) {
  867. nextIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row + 1 inSection:actionIndexPath.section];
  868. }
  869. if (nextIndexPath) {
  870. id nextData = _datas[nextIndexPath.row];
  871. if ([nextData isKindOfClass:[MMRichTextModel class]]) {
  872. // Image节点-后面-上面为Text-下面为Text:删除Image节点,合并下面的Text到上面,删除下面Text节点,定位到上面元素的后面
  873. ((MMRichTextModel*)preData).textContent = [NSString stringWithFormat:@"%@\n%@", ((MMRichTextModel*)preData).textContent, ((MMRichTextModel*)nextData).textContent];
  874. ((MMRichTextModel*)preData).textContentHeight = [MMRichContentUtil computeHeightInTextVIewWithContent:((MMRichTextModel*)preData).textContent];
  875. ((MMRichTextModel*)preData).selectedRange = NSMakeRange(((MMRichTextModel*)preData).textContent.length, 0);
  876. ((MMRichTextModel*)preData).shouldUpdateSelectedRange = YES;
  877. [self deleteItemAtIndexPathes:@[actionIndexPath, nextIndexPath] shouldPositionPrevious:YES];
  878. } else {
  879. // Image节点-后面-上面为Text-下面为图片或者空:删除Image节点,定位到上面元素的后面
  880. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:YES];
  881. }
  882. } else {
  883. // Image节点-后面-上面为Text-下面为图片或者空:删除Image节点,定位到上面元素的后面
  884. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:YES];
  885. }
  886. } else if ([preData isKindOfClass:[MMRichImageModel class]]) {
  887. // Image节点-后面-上面为图片:删除Image节点,定位到上面元素的后面
  888. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:YES];
  889. }else{
  890. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:YES];
  891. }
  892. }
  893. }
  894. }
  895. }else{
  896. if (actionIndexPath.row < _datas.count) {
  897. // 处理第一个节点
  898. if (actionIndexPath.row <= 0) {
  899. if (_datas.count > 1) {
  900. // Image节点-后面-上面为空-列表多于一个元素:删除当前节点,光标放在后面元素之前
  901. [self positionToNextItemAtIndexPath:actionIndexPath];
  902. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:NO];
  903. } else {
  904. // Image节点-后面-上面为空-列表只有一个元素:添加一个Text节点,删除当前Image节点,光标放在添加的Text节点上
  905. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:NO];
  906. [self addTextNodeAtIndexPath:actionIndexPath textContent:nil];
  907. }
  908. } else {
  909. // 处理非第一个节点
  910. NSIndexPath* preIndexPath = nil;
  911. if (actionIndexPath.row > 0) {
  912. preIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row - 1 inSection:actionIndexPath.section];
  913. id preData = _datas[preIndexPath.row];
  914. if ([preData isKindOfClass:[MMRichTextModel class]]) {
  915. NSIndexPath* nextIndexPath = nil;
  916. if (actionIndexPath.row < _datas.count - 1) {
  917. nextIndexPath = [NSIndexPath indexPathForRow:actionIndexPath.row + 1 inSection:actionIndexPath.section];
  918. }
  919. if (nextIndexPath) {
  920. id nextData = _datas[nextIndexPath.row];
  921. if ([nextData isKindOfClass:[MMRichTextModel class]]) {
  922. // Image节点-后面-上面为Text-下面为Text:删除Image节点,合并下面的Text到上面,删除下面Text节点,定位到上面元素的后面
  923. ((MMRichTextModel*)preData).textContent = [NSString stringWithFormat:@"%@\n%@", ((MMRichTextModel*)preData).textContent, ((MMRichTextModel*)nextData).textContent];
  924. ((MMRichTextModel*)preData).textContentHeight = [MMRichContentUtil computeHeightInTextVIewWithContent:((MMRichTextModel*)preData).textContent];
  925. ((MMRichTextModel*)preData).selectedRange = NSMakeRange(((MMRichTextModel*)preData).textContent.length, 0);
  926. ((MMRichTextModel*)preData).shouldUpdateSelectedRange = YES;
  927. [self deleteItemAtIndexPathes:@[actionIndexPath, nextIndexPath] shouldPositionPrevious:YES];
  928. } else {
  929. // Image节点-后面-上面为Text-下面为图片或者空:删除Image节点,定位到上面元素的后面
  930. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:YES];
  931. }
  932. } else {
  933. // Image节点-后面-上面为Text-下面为图片或者空:删除Image节点,定位到上面元素的后面
  934. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:YES];
  935. }
  936. } else if ([preData isKindOfClass:[MMRichImageModel class]]) {
  937. // Image节点-后面-上面为图片:删除Image节点,定位到上面元素的后面
  938. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:YES];
  939. }else{
  940. [self deleteItemAtIndexPath:actionIndexPath shouldPositionPrevious:YES];
  941. }
  942. }
  943. }
  944. }
  945. }
  946. }
  947. // 更新ActionIndexpath
  948. - (void)mm_updateActiveIndexPath:(NSIndexPath*)activeIndexPath {
  949. _activeIndexPath = activeIndexPath;
  950. NSLog(@"mm_updateActiveIndexPath ===== %@", activeIndexPath);
  951. }
  952. // 重新加载
  953. - (void)mm_reloadItemAtIndexPath:(NSIndexPath*)actionIndexPath {
  954. NSLog(@"======删除图片");
  955. }
  956. - (void)mm_uploadFailedAtIndexPath:(NSIndexPath *)actionIndexPath {
  957. }
  958. - (void)mm_uploadDonedAtIndexPath:(NSIndexPath *)actionIndexPath {
  959. }
  960. - (void)mm_shouldShowAccessoryView:(BOOL)shouldShow {
  961. _shouldShowAccessoryView = shouldShow;
  962. }
  963. - (BOOL)mm_shouldCellShowPlaceholder {
  964. return [MMRichContentUtil shouldShowPlaceHolderFromRichContents:_datas];
  965. }
  966. #pragma mark - ......::::::: UITableView Handler :::::::......
  967. - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  968. return 2;
  969. }
  970. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  971. // Title
  972. if (section == 0) {
  973. return 1;
  974. }
  975. // Content
  976. return _datas.count;
  977. }
  978. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  979. if (indexPath.section == 0) {
  980. return _titleModel.cellHeight;
  981. } else if (indexPath.section == 1) {
  982. id obj = _datas[indexPath.row];
  983. if ([obj isKindOfClass:[MMRichTextModel class]]) {
  984. MMRichTextModel* textModel = (MMRichTextModel*)obj;
  985. return textModel.textContentHeight;
  986. } else if ([obj isKindOfClass:[MMRichImageModel class]]) {
  987. MMRichImageModel* imageModel = (MMRichImageModel*)obj;
  988. return imageModel.imageContentHeight;
  989. }else{
  990. return 128.f;
  991. }
  992. }
  993. return 1;
  994. }
  995. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  996. // Title
  997. if (indexPath.section == 0) {
  998. MMRichTitleCell* cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(MMRichTitleCell.class)];
  999. cell.delegate = self;
  1000. [cell updateWithData:_titleModel indexPath:indexPath];
  1001. return cell;
  1002. }
  1003. // Content
  1004. id obj = _datas[indexPath.row];
  1005. if ([obj isKindOfClass:[MMRichTextModel class]]) {
  1006. MMRichTextCell* cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(MMRichTextCell.class)];
  1007. cell.delegate = self;
  1008. [cell updateWithData:obj indexPath:indexPath];
  1009. return cell;
  1010. }
  1011. if ([obj isKindOfClass:[MMRichImageModel class]]) {
  1012. MMRichImageCell* cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(MMRichImageCell.class)];
  1013. cell.delegate = self;
  1014. [cell updateWithData:obj];
  1015. return cell;
  1016. }
  1017. if ([obj isKindOfClass:[RichModel class]]) {
  1018. RichFileCell* cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(RichFileCell.class)];
  1019. cell.delegate = self;
  1020. [cell updateWithData:obj];
  1021. return cell;
  1022. }
  1023. static NSString* cellID = @"cellId";
  1024. UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellID];
  1025. if (!cell) {
  1026. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
  1027. }
  1028. return cell;
  1029. }
  1030. - (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
  1031. return NO;
  1032. }
  1033. @end