MOFirstInfoSetVC.m 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. //
  2. // MOFirstInfoSetVC.m
  3. // MiMoLive
  4. //
  5. // Created by SuperC on 2023/10/9.
  6. //
  7. #import "MOFirstInfoSetVC.h"
  8. #import "POLanguageVC.h"
  9. #import "MOImagePickerController.h"
  10. #import "MOAnchorRecommendVC.h"
  11. #import "UIImage+YYAdd.h"
  12. #import "MOBacklogTimeSelectView.h"
  13. @interface MOFirstInfoSetVC ()<TZImagePickerControllerDelegate, UITextFieldDelegate>
  14. @property (weak, nonatomic) IBOutlet UILabel *tipOneLab;
  15. @property (weak, nonatomic) IBOutlet UILabel *tipTwoLab;
  16. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *titleBottom;
  17. @property (weak, nonatomic) IBOutlet UIImageView *bgImgView;
  18. @property (weak, nonatomic) IBOutlet UIView *centerView;
  19. @property (weak, nonatomic) IBOutlet UIImageView *headImgView;
  20. @property (weak, nonatomic) IBOutlet UIButton *manBtn;
  21. @property (weak, nonatomic) IBOutlet UIButton *womanBtn;
  22. @property (weak, nonatomic) IBOutlet UIImageView *nameBgImgView;
  23. @property (weak, nonatomic) IBOutlet UITextField *nameTef;
  24. @property (weak, nonatomic) IBOutlet UIButton *randomNameButton;
  25. @property (weak, nonatomic) IBOutlet UIImageView *birthdayBgImgView;
  26. @property (weak, nonatomic) IBOutlet UILabel *birthdayLabel;
  27. @property (weak, nonatomic) IBOutlet UIButton *doneBtn;
  28. @property (weak, nonatomic) IBOutlet NSLayoutConstraint *doneBtnBottom;
  29. /** 头像的Url */
  30. @property (nonatomic, copy) NSString *headImgUrl;
  31. /** 头像 */
  32. @property (nonatomic, strong) UIImage *headImg;
  33. @property (nonatomic, copy) NSString *birthdayString;
  34. @property (nonatomic, copy) NSArray *nicknames;
  35. @property (nonatomic, assign) NSInteger lastNicknameIndex;
  36. @property (nonatomic, copy) NSArray *avatars;
  37. #if !TARGET_IPHONE_SIMULATOR
  38. @property (nonatomic, strong) SSDKUser *userData;
  39. #endif
  40. /** 男生随机对象 */
  41. @property (nonatomic, strong) NSDictionary *maleDict;
  42. /** 女生随机对象 */
  43. @property (nonatomic, strong) NSDictionary *femaleDict;
  44. @end
  45. @implementation MOFirstInfoSetVC
  46. - (void)viewDidLoad {
  47. [super viewDidLoad];
  48. [self initData];
  49. [self setupUI];
  50. #if !TARGET_IPHONE_SIMULATOR
  51. [self loadRandomProfileData];
  52. #endif
  53. }
  54. - (void)initData {
  55. self.headImgUrl = @"";
  56. self.birthdayString = @"2000-01-01";
  57. self.lastNicknameIndex = -1;
  58. }
  59. #if !TARGET_IPHONE_SIMULATOR
  60. /// 预输入用户数据,第三方登录的才有
  61. - (void)preFillUpUserData:(SSDKUser *)userData {
  62. self.userData = userData;
  63. // MOLogV(@"name = %@, icon = %@, bigIcon = %@, gender = %zd, birthday = %@", userData.nickname, userData.icon, userData.bigIcon, userData.gender, userData.birthday);
  64. }
  65. - (void)loadRandomProfileData {
  66. WEAKSELF
  67. [kHttpManager toGetTheRandomProfileWithParams:nil andBlock:^(id _Nonnull data, NSError * _Nonnull error) {
  68. if(kCode_Success){
  69. NSLog(@"%@",[[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:data options:0 error:nil] encoding:NSUTF8StringEncoding]);
  70. NSDictionary *theData = (NSDictionary *)data[@"data"];
  71. weakSelf.maleDict = [MODataManager objectOrNilForKey:@"male" fromDictionary:theData];
  72. weakSelf.femaleDict = [MODataManager objectOrNilForKey:@"female" fromDictionary:theData];
  73. [weakSelf toUpdataTheNicknamesAndAvatars];
  74. if (weakSelf.userData.nickname.length > 0) {//第三方登录有昵称
  75. weakSelf.nameTef.text = weakSelf.userData.nickname;
  76. } else {
  77. if (weakSelf.nicknames.count > 0) {//获取配置昵称随机
  78. weakSelf.nameTef.text = [weakSelf randomNickname];
  79. }
  80. }
  81. if (self.userData.icon.length > 0) {//第三方登录有头像
  82. [weakSelf.headImgView sd_setImageWithURL:[NSURL URLWithString:self.userData.icon] placeholderImage:[UIImage imageNamed:@"icon_mine_placeHolder"] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
  83. weakSelf.headImg = image;
  84. [weakSelf uploadOssS3];
  85. }];
  86. } else {
  87. if (weakSelf.avatars.count > 0) {//获取配置头像随机
  88. weakSelf.headImgUrl = [self randomAvatar];
  89. [weakSelf.headImgView sd_setImageWithURL:[NSURL URLWithString:weakSelf.headImgUrl] placeholderImage:[UIImage imageNamed:@"icon_mine_placeHolder"]];
  90. }
  91. }
  92. }
  93. else{
  94. MOLogV(@"toGetTheRandomProfileWithParams 接口报错了");
  95. }
  96. }];
  97. }
  98. #endif
  99. - (void)toUpdataTheNicknamesAndAvatars{
  100. if(self.womanBtn.selected){
  101. self.nicknames = [MODataManager objectOrNilForKey:@"nicknames" fromDictionary:self.femaleDict];
  102. self.avatars = [MODataManager objectOrNilForKey:@"avatars" fromDictionary:self.femaleDict];
  103. }
  104. else{
  105. self.nicknames = [MODataManager objectOrNilForKey:@"nicknames" fromDictionary:self.maleDict];
  106. self.avatars = [MODataManager objectOrNilForKey:@"avatars" fromDictionary:self.maleDict];
  107. }
  108. }
  109. - (NSString *)randomAvatar {
  110. if (self.avatars.count == 0) return @"";
  111. if (self.avatars.count == 1) {
  112. return self.avatars.firstObject;
  113. }
  114. NSUInteger index = arc4random_uniform((uint32_t)self.avatars.count);
  115. return self.avatars[index];
  116. }
  117. - (NSString *)randomNickname {
  118. if (self.nicknames.count == 0) return @"";
  119. if (self.nicknames.count == 1) {
  120. self.lastNicknameIndex = 0;
  121. return self.nicknames.firstObject;
  122. }
  123. NSInteger newIndex = self.lastNicknameIndex;
  124. while (self.nicknames.count > 1 && newIndex == self.lastNicknameIndex) {
  125. newIndex = arc4random_uniform((uint32_t)self.nicknames.count);
  126. }
  127. self.lastNicknameIndex = newIndex;
  128. return self.nicknames[newIndex];
  129. }
  130. - (void)randomNameButtonAction {
  131. [self toUpdateTheAvatars];//更改头像
  132. //更改昵称
  133. NSString *nickname = [self randomNickname];
  134. self.nameTef.text = nickname;
  135. [self updateDoneButtonState];
  136. }
  137. - (void)setupUI{
  138. self.centerView.backgroundColor = [UIColor clearColor];
  139. self.titleBottom.constant = kScaleWidth(80);
  140. self.tipOneLab.font = [MOTextTools poppinsExtraBoldFont:36];
  141. self.tipOneLab.textColor = [MOTools colorWithHexString:@"#FFFFFF"];
  142. self.tipOneLab.text = NSLocalString(@"mimo_2_live_welcome");
  143. self.tipOneLab.numberOfLines = 1;
  144. self.tipOneLab.adjustsFontSizeToFitWidth = YES;
  145. self.tipTwoLab.font = [MOTextTools poppinsSemiBoldFont:28];
  146. self.tipTwoLab.textColor = [MOTools colorWithHexString:@"#FFFFFF"];
  147. self.tipTwoLab.text = NSLocalString(@"mimo_login_set_info");
  148. self.tipOneLab.numberOfLines = 1;
  149. self.tipOneLab.adjustsFontSizeToFitWidth = YES;
  150. [self.centerView sendSubviewToBack:self.headImgView];
  151. self.headImgView.userInteractionEnabled = YES;
  152. self.headImgView.layer.cornerRadius = 60;
  153. self.headImgView.layer.masksToBounds = YES;
  154. [self.headImgView setImage:[UIImage imageNamed:@"icon_mine_placeHolder"]];
  155. self.headImgView.contentMode = UIViewContentModeScaleAspectFill;
  156. UITapGestureRecognizer *headTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(headImgClick)];
  157. [self.headImgView addGestureRecognizer:headTap];
  158. [self.manBtn setTitle:NSLocalString(@"mimo_login_gender_man") forState:UIControlStateNormal];
  159. [self.manBtn setImage:[UIImage imageNamed:@"icon_wel_male"] forState:UIControlStateNormal];
  160. [self.manBtn setImage:[UIImage imageNamed:@"icon_wel_male"] forState:UIControlStateSelected];
  161. [self.manBtn setBackgroundImage:[UIImage imageNamed:@"img_selected_gender_bg"] forState:UIControlStateSelected];
  162. [self.manBtn setFont:[MOTextTools poppinsBoldFont:16]];
  163. [self.manBtn setTitleColor:[MOTools colorWithHexString:@"#33C9FF"] forState:UIControlStateNormal];
  164. self.manBtn.titleEdgeInsets = UIEdgeInsetsMake(0.0, 4.0, 0.0, 0.0);
  165. self.manBtn.imageEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 4.0);
  166. self.manBtn.backgroundColor = [MOTools colorWithHexString:@"#17171A" alpha:0.2];
  167. self.manBtn.layer.masksToBounds = YES;
  168. self.manBtn.layer.cornerRadius = 12;
  169. #if !TARGET_IPHONE_SIMULATOR
  170. if (self.userData && self.userData.gender == 0) {
  171. self.manBtn.selected = YES;
  172. }
  173. #endif
  174. [self.womanBtn setTitle:NSLocalString(@"mimo_login_gender_woman") forState:UIControlStateNormal];
  175. [self.womanBtn setImage:[UIImage imageNamed:@"icon_wel_female"] forState:UIControlStateNormal];
  176. [self.womanBtn setImage:[UIImage imageNamed:@"icon_wel_female"] forState:UIControlStateSelected];
  177. [self.womanBtn setBackgroundImage:[UIImage imageNamed:@"img_selected_gender_bg"] forState:UIControlStateSelected];
  178. [self.womanBtn setFont:[MOTextTools poppinsBoldFont:16]];
  179. [self.womanBtn setTitleColor:[MOTools colorWithHexString:@"#FF4DA6"] forState:UIControlStateNormal];
  180. self.womanBtn.titleEdgeInsets = UIEdgeInsetsMake(0.0, 4.0, 0.0, 0.0);
  181. self.womanBtn.imageEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 4.0);
  182. self.womanBtn.backgroundColor = [MOTools colorWithHexString:@"#17171A" alpha:0.2];
  183. self.womanBtn.layer.masksToBounds = YES;
  184. self.womanBtn.layer.cornerRadius = 12;
  185. #if !TARGET_IPHONE_SIMULATOR
  186. if (self.userData && self.userData.gender == 1) {
  187. self.womanBtn.selected = YES;
  188. }
  189. #endif
  190. self.nameBgImgView.image = [[UIImage imageNamed:@"img_info_border_bg"] imageByResizeToSize:CGSizeMake(SCREENWIDTH - 48, 52)];
  191. [self.nameTef setFont:[MOTextTools poppinsRegularFont:16]];
  192. self.nameTef.textColor = kBaseTextColor_1;
  193. self.nameTef.backgroundColor = [UIColor clearColor];
  194. self.nameTef.delegate = self;
  195. [self.nameTef addTarget:self action:@selector(nameTextFieldChanged:) forControlEvents:UIControlEventEditingChanged];
  196. self.nameTef.placeholder = NSLocalString(@"mimo_login_nick_name_placeholder");
  197. self.birthdayBgImgView.image = [[UIImage imageNamed:@"img_info_border_bg"] imageByResizeToSize:CGSizeMake(SCREENWIDTH - 48, 52)];
  198. self.birthdayBgImgView.userInteractionEnabled = YES;
  199. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(birthdayBgImgViewTapAction)];
  200. [self.birthdayBgImgView addGestureRecognizer:tap];
  201. self.birthdayLabel.font = [MOTextTools poppinsRegularFont:16];
  202. self.birthdayLabel.textColor = kBaseTextColor_1;
  203. self.birthdayLabel.text = [NSString stringWithFormat:@"%@", self.birthdayString];
  204. [self.doneBtn setFont:[MOTextTools poppinsSemiBoldFont:16]];
  205. [self.doneBtn setTitleColor:[MOTools colorWithHexString:@"#FFFFFF"] forState:UIControlStateNormal];
  206. [self.doneBtn setTitle:NSLocalString(@"mimo_login_next_text") forState:UIControlStateNormal];
  207. self.doneBtn.layer.masksToBounds = YES;
  208. self.doneBtn.layer.cornerRadius = 12;
  209. NSArray *colorArr = @[kBaseColorLeft,kBaseColorRight];
  210. UIImage *image = [MOTools createGradientRectImageWithBounds:CGRectMake(0, 0, (SCREENWIDTH - 24.0 * 2), 48.0) Colors:colorArr GradientType:0];
  211. [self.doneBtn setBackgroundImage:image forState:UIControlStateNormal];
  212. self.doneBtnBottom.constant = kBottomSafeAreaInset + 16;
  213. self.doneBtn.alpha = 0.5;
  214. self.randomNameButton.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
  215. [self.randomNameButton setTitle:NSLocalString(@"mimo_login_name_random") forState:UIControlStateNormal];
  216. [self.randomNameButton setTitleColor:kBaseTextColor_3 forState:UIControlStateNormal];
  217. self.randomNameButton.titleLabel.font = [MOTextTools poppinsRegularFont:14];
  218. [self.randomNameButton addTarget:self action:@selector(randomNameButtonAction) forControlEvents:UIControlEventTouchUpInside];
  219. [self updateDoneButtonState];
  220. }
  221. #pragma mark - UITextFieldDelegate
  222. - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
  223. if (textField == self.nameTef) {
  224. NSString *toBeString = [textField.text stringByReplacingCharactersInRange:range withString:string];
  225. return toBeString.length <= 16;
  226. }
  227. return YES;
  228. }
  229. - (void)nameTextFieldChanged:(UITextField *)textField {
  230. [self updateDoneButtonState];
  231. }
  232. - (void)updateDoneButtonState {
  233. BOOL hasGender = self.manBtn.selected || self.womanBtn.selected;
  234. BOOL hasName = self.nameTef.text.length >= 2;
  235. BOOL hasAvatar = self.headImg || self.headImgUrl.length > 0;
  236. // self.doneBtn.enabled = hasGender && hasName && hasAvatar;
  237. self.doneBtn.alpha = (hasGender && hasName && hasAvatar) ? 1.0 : 0.5;
  238. }
  239. - (void)birthdayBgImgViewTapAction {
  240. WEAKSELF
  241. MOBacklogTimeSelectView *setRemindTimeView = [[MOBacklogTimeSelectView alloc] initForOperateSuccessWithFrame:CGRectMake(0, 0, SCREENWIDTH, SCREENHEIGHT)];
  242. setRemindTimeView.doneBtnBlock = ^(NSDate * _Nonnull endDate) {
  243. NSDateFormatter *dateFormatter = [NSDateFormatter getSingletonDateFormatterWithFormat:@"yyyy-MM-dd"];
  244. self.birthdayString = [dateFormatter stringFromDate:endDate];
  245. weakSelf.birthdayLabel.text = self.birthdayString;
  246. };
  247. [setRemindTimeView show];
  248. }
  249. - (void)viewDidAppear:(BOOL)animated {
  250. [super viewDidAppear:animated];
  251. // 不允许右滑返回
  252. [self.navigationController.interactivePopGestureRecognizer setEnabled:NO];
  253. }
  254. ///头像点击
  255. - (void)headImgClick {
  256. MOImagePickerController *imagePickerController = [[MOImagePickerController alloc] initWithMaxImagesCount:1 columnNumber:4 delegate:self pushPhotoPickerVc:YES];
  257. imagePickerController.cropRect = CGRectMake(0, 200.0, SCREENWIDTH, SCREENWIDTH);
  258. imagePickerController.allowCrop = YES;
  259. [self presentViewController:imagePickerController animated:YES completion:nil];
  260. }
  261. - (IBAction)manBtnClick:(id)sender {
  262. if(self.manBtn.selected){
  263. return;
  264. }
  265. self.manBtn.selected = YES;
  266. self.womanBtn.selected = NO;
  267. [self toUpdataTheNicknamesAndAvatars];//更新头像和昵称源
  268. [self randomNameButtonAction];//更新昵称
  269. }
  270. - (IBAction)womanBtnClick:(id)sender {
  271. if(self.womanBtn.selected){
  272. return;
  273. }
  274. self.manBtn.selected = NO;
  275. self.womanBtn.selected = YES;
  276. [self toUpdataTheNicknamesAndAvatars];
  277. [self randomNameButtonAction];//更新昵称
  278. }
  279. - (void)toUpdateTheAvatars{
  280. #if !TARGET_IPHONE_SIMULATOR
  281. if (self.userData.icon.length > 0) {//第三方登录有头像
  282. //不做处理
  283. } else {
  284. if (self.avatars.count > 0) {//获取配置头像随机
  285. self.headImgUrl = [self randomAvatar];
  286. [self.headImgView sd_setImageWithURL:[NSURL URLWithString:self.headImgUrl] placeholderImage:[UIImage imageNamed:@"icon_mine_placeHolder"]];
  287. }
  288. }
  289. #endif
  290. }
  291. ///下一步按钮点击
  292. - (IBAction)nextStepClick:(id)sender {
  293. if(self.headImg == nil && self.headImgUrl.length == 0){
  294. [MBProgressHUD showTipMessageInView:NSLocalString(@"mimo_family_apply_avatar_empty_tip")];
  295. return;
  296. }
  297. if (!self.manBtn.isSelected && !self.womanBtn.isSelected) {
  298. [MBProgressHUD showTipMessageInView:NSLocalString(@"mimo_user_edit_select_gender_title")];
  299. return;
  300. }
  301. NSInteger gender = 1;
  302. if(self.manBtn.selected == YES){
  303. gender = 1;
  304. } else {
  305. gender = 2;
  306. }
  307. if(self.nameTef.text.length == 0){
  308. [MBProgressHUD showTipMessageInView:NSLocalString(@"mimo_common_enter_nickname")];
  309. return;
  310. }
  311. if(self.nameTef.text.length == 1){//昵称过短
  312. [MBProgressHUD showTipMessageInView:NSLocalString(@"mimo_login_nick_name_short_tips")];
  313. return;
  314. }
  315. NSDictionary *dict = @{@"avatar":self.headImgUrl,
  316. @"gender":@(gender),
  317. @"nickname":self.nameTef.text,
  318. @"birthday":self.birthdayString};
  319. WEAKSELF
  320. [kHttpManager toSettingInfoWithParams:dict andBlock:^(id _Nonnull data, NSError * _Nonnull error) {
  321. if(kCode_Success){
  322. // [MBProgressHUD showTipMessageInWindow:NSLocalString(@"mimo_common_success")];
  323. NSDictionary *baseDict = data[@"data"];
  324. //更新头像
  325. NSString *avatarString = [MODataManager objectOrNilForKey:@"avatar" fromDictionary:baseDict];
  326. if(avatarString.length > 0){
  327. [[NSUserDefaults standardUserDefaults] setObject:avatarString forKey:kAvatar];
  328. }
  329. //更新性别信息
  330. NSInteger gender = [[MODataManager objectOrNilForKey:@"gender" fromDictionary:baseDict] integerValue];
  331. [[NSUserDefaults standardUserDefaults] setObject:@(gender) forKey:kGender];
  332. //更新昵称信息
  333. NSString *nickNameString = [MODataManager objectOrNilForKey:@"nickname" fromDictionary:baseDict];
  334. if(nickNameString.length > 0){
  335. [[NSUserDefaults standardUserDefaults] setObject:nickNameString forKey:kNickName];
  336. }
  337. [[NSUserDefaults standardUserDefaults] synchronize];
  338. [weakSelf toMainVC];
  339. }
  340. else{
  341. kShowNetError(data)
  342. }
  343. }];
  344. }
  345. - (void)toMainVC {
  346. if (self.navigationController.presentingViewController) {//如果是present出来的要dismiss
  347. [self.navigationController dismissViewControllerAnimated:YES completion:nil];
  348. }
  349. MOMainTabController *mainTabbar = [MOMainTabController sharedSingleton];
  350. [mainTabbar toResetSetupTabbar];
  351. [UIApplication sharedApplication].keyWindow.rootViewController = mainTabbar;
  352. }
  353. - (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray<UIImage *> *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto infos:(NSArray<NSDictionary *> *)infos{
  354. self.headImg = photos.firstObject;
  355. [self.headImgView setImage:self.headImg];
  356. [self uploadOssS3];
  357. }
  358. - (void)uploadOssS3 {
  359. NSDictionary *dict = @{@"type":@(1),
  360. @"suffix":@"jpg"};
  361. WEAKSELF
  362. [kHttpManager getBaseOssS3WithParams:dict andBlock:^(id _Nonnull data, NSError * _Nonnull error) {
  363. if(kCode_Success){
  364. NSDictionary *tempDict = data[@"data"];
  365. NSString *baseUrl = [MODataManager objectOrNilForKey:@"preSignUrl" fromDictionary:tempDict];
  366. weakSelf.headImgUrl = [MODataManager objectOrNilForKey:@"fileUrl" fromDictionary:tempDict];
  367. [weakSelf updateDoneButtonState];
  368. NSData *imageData = UIImageJPEGRepresentation(weakSelf.headImg, 1);
  369. [kHttpManager sendSingleChatImage:imageData params:nil type:@"image/jpg" andBaseUrl:baseUrl withUploadProgressHandler:^(NSProgress * uploadProgress) {
  370. float progress = 1.0*uploadProgress.completedUnitCount/uploadProgress.totalUnitCount;
  371. MOLogV(@"Image upload Progress: %.2f%%", progress * 100);
  372. } andCompletionBlock:^(id _Nonnull data, NSError * _Nonnull error) {
  373. if(error == nil){
  374. MOLogV(@"图片上传成功~");
  375. }
  376. }];
  377. }
  378. else{
  379. kShowNetError(data)
  380. }
  381. }];
  382. }
  383. @end