433 lines
20 KiB
Objective-C
433 lines
20 KiB
Objective-C
//
|
|
// DDDynamicDataView.m
|
|
// DingDangApp
|
|
//
|
|
// Created by apple on 2023/5/31.
|
|
//
|
|
|
|
#import "DDDynamicDataView.h"
|
|
#import "DDDynamicDataTableViewCell.h"
|
|
#import "UIScrollView+ListViewAutoplaySJAdd.h"
|
|
#import <SJVideoPlayer/SJVideoPlayer.h>
|
|
#import "DDMyInfoReportViewController.h"
|
|
#import "DynamicCommentViewController.h"
|
|
#import "Api+DDDynamicApi.h"
|
|
#import "Api+DDMineApi.h"
|
|
@interface DDDynamicDataView ()<SJPlayerAutoplayDelegate>
|
|
@property (nonatomic, strong) SJVideoPlayer * videoPlayer;
|
|
@property (nonatomic, copy) void(^scrollCallback)(UIScrollView *scrollView);
|
|
|
|
@end
|
|
@implementation DDDynamicDataView
|
|
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
|
|
!self.scrollCallback ?: self.scrollCallback(scrollView);
|
|
}
|
|
|
|
#pragma mark - JXPagingViewListViewDelegate
|
|
- (UIView *)listView {
|
|
return self;
|
|
}
|
|
|
|
- (UIScrollView *)listScrollView {
|
|
return self.myTableView;
|
|
}
|
|
|
|
- (void)listViewDidScrollCallback:(void (^)(UIScrollView *))callback {
|
|
self.scrollCallback = callback;
|
|
}
|
|
-(UITableView *)myTableView
|
|
{
|
|
if (!_myTableView) {
|
|
_myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0,kWidth, self.height)
|
|
style:UITableViewStyleGrouped];
|
|
_myTableView.dataSource = self;
|
|
_myTableView.delegate = self;
|
|
_myTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
|
_myTableView.separatorColor = [UIColor clearColor];
|
|
_myTableView.backgroundColor = [UIColor jk_colorWithHexString:@"#ffffff"];
|
|
[_myTableView registerClass:DDDynamicDataTableViewCell.class forCellReuseIdentifier:@"DDDynamicDataTableViewCell"];
|
|
[ToolsObject customResetTableView:_myTableView];
|
|
WeakSelf(weakSelf)
|
|
_myTableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
|
|
[weakSelf originRequest];
|
|
}];
|
|
// _myTableView.mj_footer = [MJRefreshFooter footerWithRefreshingBlock:^{
|
|
// weakSelf.pageNum ++ ;
|
|
// [weakSelf refreshListData];
|
|
// }];
|
|
}
|
|
return _myTableView;
|
|
}
|
|
- (NSMutableArray *)listArr{
|
|
if (!_listArr){
|
|
_listArr = @[].mutableCopy;
|
|
}return _listArr;
|
|
}
|
|
- (instancetype)initWithFrame:(CGRect)frame
|
|
{
|
|
self = [super initWithFrame:frame];
|
|
if (self) {
|
|
self.backgroundColor = UIColor.clearColor;
|
|
[self addSubview:self.myTableView];
|
|
}
|
|
return self;
|
|
}
|
|
-(void)originRequest
|
|
{
|
|
self.pageNum = 1;
|
|
[self refreshListData];
|
|
}
|
|
- (void)setDynamicScene:(NSString *)dynamicScene{
|
|
_dynamicScene = dynamicScene;
|
|
[self originRequest];
|
|
}
|
|
- (void)refreshListData{
|
|
WeakSelf(weakSelf)
|
|
if(self.type == 0){
|
|
[Api monentsRecommendList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
|
[weakSelf.myTableView.mj_header endRefreshing];
|
|
[weakSelf.myTableView.mj_footer endRefreshing];
|
|
if(code == 200){
|
|
if (weakSelf.pageNum == 1) {
|
|
[weakSelf.listArr removeAllObjects];
|
|
}
|
|
NSArray *list = [DDDynamicModel DD_ModelsWithArray:data.data];
|
|
[weakSelf.listArr addObjectsFromArray:list];
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[weakSelf.myTableView.mj_header endRefreshing];
|
|
[weakSelf.myTableView.mj_footer endRefreshing];
|
|
[weakSelf.myTableView reloadData];
|
|
});
|
|
}
|
|
} page:@(self.pageNum).stringValue pageSize:@"20" types:@"0,2"];
|
|
}else if(self.type == 1){
|
|
[Api monentsLatestList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
|
[weakSelf.myTableView.mj_header endRefreshing];
|
|
[weakSelf.myTableView.mj_footer endRefreshing];
|
|
if(code == 200){
|
|
if (weakSelf.pageNum == 1) {
|
|
[weakSelf.listArr removeAllObjects];
|
|
}
|
|
NSArray *list = [DDDynamicModel DD_ModelsWithArray:data.data[@"dynamicList"]];
|
|
[weakSelf.listArr addObjectsFromArray:list];
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[weakSelf.myTableView.mj_header endRefreshing];
|
|
[weakSelf.myTableView.mj_footer endRefreshing];
|
|
[weakSelf.myTableView reloadData];
|
|
});
|
|
}
|
|
} dynamicId:@"" pageSize:@"20" types:@"0,2"];
|
|
}else{
|
|
[Api monentsFollowerList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
|
[weakSelf.myTableView.mj_header endRefreshing];
|
|
[weakSelf.myTableView.mj_footer endRefreshing];
|
|
if(code == 200){
|
|
if (weakSelf.pageNum == 1) {
|
|
[weakSelf.listArr removeAllObjects];
|
|
}
|
|
NSArray *list = [DDDynamicModel DD_ModelsWithArray:data.data[@"dynamicList"]];
|
|
[weakSelf.listArr addObjectsFromArray:list];
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[weakSelf.myTableView.mj_header endRefreshing];
|
|
[weakSelf.myTableView.mj_footer endRefreshing];
|
|
[weakSelf.myTableView reloadData];
|
|
});
|
|
}
|
|
} dynamicId:@"" pageSize:@"20" types:@"0,2"];
|
|
}
|
|
|
|
|
|
return;
|
|
NSMutableDictionary *requestDict = [NSMutableDictionary dictionary];
|
|
[requestDict setObject:@(999) forKey:@"current_page"];
|
|
[requestDict setObject:@(self.pageNum) forKey:@"page_number"];
|
|
[requestDict setObject:[ToolsObject IsNullWithObject:self.dynamicScene]?@"":self.dynamicScene forKey:@"scene"];
|
|
|
|
[NetworkRequest requestPOST:@"/dynamic/list" parameters:requestDict block:^(BaseResponse * _Nonnull response) {
|
|
if (response.code == 200) {
|
|
if ([ToolsObject IsNullWithObject:response.data]) {
|
|
[weakSelf.myTableView.mj_header endRefreshing];
|
|
[weakSelf.myTableView.mj_footer endRefreshing];
|
|
return;
|
|
}
|
|
if (weakSelf.pageNum == 1) {
|
|
[weakSelf.listArr removeAllObjects];
|
|
}
|
|
[weakSelf.listArr addObjectsFromArray:[NSArray yy_modelArrayWithClass:DDDynamicModel.class json:response.data[@"record"]]];
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[weakSelf.myTableView.mj_header endRefreshing];
|
|
[weakSelf.myTableView.mj_footer endRefreshing];
|
|
[weakSelf.myTableView reloadData];
|
|
});
|
|
if ([response.data[@"next"]integerValue] == 0) {
|
|
[weakSelf.myTableView.mj_footer endRefreshingWithNoMoreData];
|
|
}
|
|
}
|
|
}];
|
|
|
|
}
|
|
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
|
|
{
|
|
return CGFLOAT_MIN;
|
|
}
|
|
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
|
|
{
|
|
return CGFLOAT_MIN;
|
|
}
|
|
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
|
|
{
|
|
return 1;
|
|
}
|
|
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
|
{
|
|
return self.listArr.count;
|
|
}
|
|
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
DDDynamicModel * model = self.listArr[indexPath.row];
|
|
return model.rowHeight;
|
|
}
|
|
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
static NSString *indentifiers = @"DDDynamicDataTableViewCell";
|
|
DDDynamicDataTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:indentifiers];
|
|
if (!cell) {
|
|
cell = [[DDDynamicDataTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:indentifiers];
|
|
}
|
|
cell.rowIndexPath = indexPath;
|
|
cell.model = self.listArr[indexPath.row];
|
|
WeakSelf(weakSelf)
|
|
cell.clickSupportBlock = ^(DDDynamicModel * _Nonnull dynamicModel, NSIndexPath * _Nonnull index) {
|
|
NSString * uid = [AccountInfoStorage instance].getUid;
|
|
[Api monentsLike:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
|
if(code == 200){
|
|
dynamicModel.isLike = !dynamicModel.isLike;
|
|
if (dynamicModel.isLike) {
|
|
dynamicModel.likeCount = [NSString stringWithFormat:@"%d",dynamicModel.likeCount.intValue + 1];
|
|
}else {
|
|
if (dynamicModel.likeCount.intValue == 0) {
|
|
dynamicModel.likeCount = @"0";
|
|
} else {
|
|
dynamicModel.likeCount = [NSString stringWithFormat:@"%d",dynamicModel.likeCount.intValue - 1];
|
|
}
|
|
}
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[weakSelf.myTableView reloadRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationNone];
|
|
});
|
|
}
|
|
} dynamicId:dynamicModel.dynamicId uid:uid status:dynamicModel.isLike ? @"0":@"1" likedUid:dynamicModel.uid worldId:[NSString stringWithFormat:@"%ld", dynamicModel.worldId]];
|
|
return;
|
|
NSMutableDictionary *parameter =[NSMutableDictionary dictionary];
|
|
[parameter setValue:dynamicModel.id forKey:@"dynamic_id"];
|
|
if (dynamicModel.is_give_like) {
|
|
[parameter setValue:@"nolike" forKey:@"scene"];
|
|
}else{
|
|
[parameter setValue:@"like" forKey:@"scene"];
|
|
}
|
|
[NetworkRequest requestPOST:@"/dynamic/set/like" parameters:parameter block:^(BaseResponse * _Nonnull response) {
|
|
if (response.code == 200){
|
|
dynamicModel.is_give_like = !dynamicModel.is_give_like;
|
|
if (dynamicModel.is_give_like) {
|
|
dynamicModel.support = [NSString stringWithFormat:@"%d",dynamicModel.support.intValue + 1];
|
|
}else {
|
|
if (dynamicModel.support.intValue == 0) {
|
|
dynamicModel.support = @"0";
|
|
} else {
|
|
dynamicModel.support = [NSString stringWithFormat:@"%d",dynamicModel.support.intValue - 1];
|
|
}
|
|
}
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[weakSelf.myTableView reloadRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationNone];
|
|
});
|
|
}else{
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[weakSelf.myTableView reloadRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationNone];
|
|
});
|
|
}
|
|
}];
|
|
};
|
|
cell.clickPlayVoideoBlock = ^(DDDynamicModel * _Nonnull dynamicModel, NSIndexPath * _Nonnull index) {
|
|
[weakSelf sj_playerNeedPlayNewAssetAtIndexPath:index];
|
|
};
|
|
cell.clickHeaderImageBlock = ^(DDDynamicModel * _Nonnull dynamicModel) {
|
|
if (dynamicModel.in_live) {
|
|
RoomUserInfoModel *userModel = [[RoomUserInfoModel alloc]init];
|
|
userModel.user_id = dynamicModel.user_id;
|
|
[[ToolsObject shareTools] jumpToRoomVC:dynamicModel.in_live_room_id followUser:userModel];
|
|
}else{
|
|
[ToolsObject pushMyInformationViewController:dynamicModel.uid];
|
|
}
|
|
};
|
|
cell.clickAttentionBlock = ^(DDDynamicModel * _Nonnull dynamicModel, NSIndexPath * _Nonnull index) {
|
|
NSString * uid = [[AccountInfoStorage instance] getUid];
|
|
NSString * ticket = [[AccountInfoStorage instance] getTicket];
|
|
NSString * type = @"1";
|
|
[Api attentionCompletion:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
|
|
if(code == 200){
|
|
[ToolsObject addPopVieToText:@"关注成功"];
|
|
return;
|
|
}
|
|
[ToolsObject addPopVieToText:@"关注失败"];
|
|
} uid:uid likedUid:dynamicModel.uid ticket:ticket type:type];
|
|
|
|
};
|
|
cell.clickRemoveBlock = ^(DDDynamicModel * _Nonnull dynamicModel, NSIndexPath * _Nonnull index) {
|
|
NSMutableDictionary *requestDict = [NSMutableDictionary dictionary];
|
|
[requestDict setObject:dynamicModel.id forKey:@"dynamic_id"];
|
|
[NetworkRequest requestPOST:@"/dynamic/del/dynamic" parameters:requestDict block:^(BaseResponse * _Nonnull response) {
|
|
if (response.code == 200) {
|
|
[weakSelf.listArr removeObjectAtIndex:index.row];
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[weakSelf.myTableView reloadData];
|
|
});
|
|
}
|
|
}];
|
|
};
|
|
cell.clickReportBlock = ^(DDDynamicModel * _Nonnull dynamicModel, NSIndexPath * _Nonnull index) {
|
|
DDMyInfoReportViewController * jubaoVC = [[DDMyInfoReportViewController alloc] init];
|
|
jubaoVC.juBaoType = 3;
|
|
jubaoVC.jubao_id = dynamicModel.id;
|
|
[[ToolsObject getCurrentViewController].navigationController pushViewController:jubaoVC animated:YES];
|
|
};
|
|
cell.clickDynamicCommentBlock = ^(DDDynamicModel * _Nonnull dynamicModel, NSIndexPath * _Nonnull index) {
|
|
// DynamicCommentViewController *vc = [[DynamicCommentViewController alloc]init];
|
|
// vc.dynamic_id = dynamicModel.id;
|
|
// vc.dynamic_userId = dynamicModel.user_id;
|
|
// vc.reloadCellCommentNum = ^(NSString * _Nonnull commentNum) {
|
|
// dynamicModel.comment_num = commentNum;
|
|
// dispatch_async(dispatch_get_main_queue(), ^{
|
|
// [weakSelf.myTableView reloadRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationNone];
|
|
// });
|
|
// };
|
|
// XPSemiModalConfiguration *config = [XPSemiModalConfiguration defaultConfiguration];
|
|
// config.backgroundOpacity = 0.5;
|
|
// config.enableBackgroundAnimation = NO;
|
|
// config.enableShadow = NO;
|
|
// config.shouldDismissModal = YES;
|
|
// [[ToolsObject getCurrentViewController] presentSemiModalViewController:vc contentHeight:kHeight-400 configuration:config completion:nil dismissClickBlock:nil];
|
|
};
|
|
cell.clickCantSeeBlock = ^(DDDynamicModel * _Nonnull dynamicModel, NSIndexPath * _Nonnull index) {
|
|
[weakSelf.listArr removeObjectAtIndex:index.row];
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[weakSelf.myTableView reloadData];
|
|
});
|
|
};
|
|
cell.clickBlackBlock = ^(DDDynamicModel * _Nonnull dynamicModel, NSIndexPath * _Nonnull index) {
|
|
[weakSelf.listArr removeObjectAtIndex:index.row];
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[weakSelf.myTableView reloadData];
|
|
});
|
|
};
|
|
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
return cell;
|
|
}
|
|
- (void)sj_playerNeedPlayNewAssetAtIndexPath:(NSIndexPath *)indexPath {
|
|
DDDynamicModel *model = self.listArr[indexPath.row];
|
|
if (!_videoPlayer) {
|
|
_videoPlayer = [SJVideoPlayer player];
|
|
}
|
|
SJEdgeControlButtonItem *playItem = [_videoPlayer.defaultEdgeControlLayer.bottomAdapter itemForTag:SJEdgeControlLayerTopItem_Back];
|
|
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(itemDidPlay:) name:SJEdgeControlButtonItemPerformedActionNotification object:playItem];
|
|
|
|
SJEdgeControlButtonItem *playItem1 = [_videoPlayer.defaultEdgeControlLayer.bottomAdapter itemForTag:SJEdgeControlLayerBottomItem_FullBtn];
|
|
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(itemDidPlay:) name:SJEdgeControlButtonItemPerformedActionNotification object:playItem1];
|
|
_videoPlayer.playbackObserver.playbackDidFinishExeBlock = ^(__kindof SJBaseVideoPlayer * _Nonnull player) {
|
|
[player replay];
|
|
};
|
|
_videoPlayer.delayInSecondsForHiddenPlaceholderImageView = 0.3;
|
|
_videoPlayer.muted = YES;
|
|
_videoPlayer.playerVolume = 0;
|
|
_videoPlayer.URLAsset = [[SJVideoPlayerURLAsset alloc] initWithURL:[NSURL URLWithString:model.video] playModel:[SJPlayModel playModelWithTableView:self.myTableView indexPath:indexPath]];
|
|
[self showVideoPlayer:NO];
|
|
}
|
|
- (void)showVideoPlayer:(BOOL)mute{
|
|
[self.videoPlayer pause];
|
|
if (!self.videoPlayer.isFitOnScreen) {
|
|
[self.videoPlayer setFitOnScreen:YES animated:YES];
|
|
WeakSelf(weakSelf)
|
|
self.videoPlayer.fitOnScreenObserver.fitOnScreenWillBeginExeBlock = ^(id<SJFitOnScreenManager> _Nonnull mgr) {
|
|
if (mgr.isFitOnScreen) {
|
|
[weakSelf.videoPlayer play];
|
|
if (mute) {
|
|
weakSelf.videoPlayer.playerVolume = 0;
|
|
}else{
|
|
weakSelf.videoPlayer.playerVolume = 1;
|
|
weakSelf.videoPlayer.muted = NO;
|
|
}
|
|
}
|
|
};
|
|
|
|
}else{
|
|
[self.videoPlayer setFitOnScreen:NO animated:YES];
|
|
[self.videoPlayer pause];
|
|
WeakSelf(weakSelf)
|
|
self.videoPlayer.fitOnScreenObserver.fitOnScreenWillBeginExeBlock = ^(id<SJFitOnScreenManager> _Nonnull mgr) {
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
[weakSelf.videoPlayer stop];
|
|
weakSelf.videoPlayer = nil;
|
|
});
|
|
};
|
|
}
|
|
}
|
|
-(void)itemDidPlay:(NSNotification *)notification {
|
|
SJEdgeControlButtonItem *item = notification.object;
|
|
if (item.tag == SJEdgeControlLayerTopItem_Back || item.tag == SJEdgeControlLayerBottomItem_FullBtn) {
|
|
[self.videoPlayer setFitOnScreen:NO animated:YES];
|
|
[self.videoPlayer pause];
|
|
WeakSelf(weakSelf)
|
|
self.videoPlayer.fitOnScreenObserver.fitOnScreenWillBeginExeBlock = ^(id<SJFitOnScreenManager> _Nonnull mgr) {
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
[weakSelf.videoPlayer stop];
|
|
weakSelf.videoPlayer = nil;
|
|
});
|
|
};
|
|
}
|
|
}
|
|
- (void)requestAddFollow:(DDDynamicModel *)dynamicModel withIndexPath:(NSIndexPath *)index{
|
|
|
|
if ([ToolsObject IsNullWithObject:dynamicModel.user_id]) {
|
|
[ToolsObject addPopVieToText:@"没有获取到该用户信息"];
|
|
return;
|
|
}
|
|
[ToolsObject ShowSVProgressHUD:@""];
|
|
NSMutableDictionary *parameter =@{@"followed_user_id":dynamicModel.user_id}.mutableCopy;
|
|
WeakSelf(weakSelf)
|
|
__block DDDynamicModel * tempModel = dynamicModel;
|
|
[NetworkRequest requestPOST:@"/dynamic/attention" parameters:parameter block:^(BaseResponse * _Nonnull response) {
|
|
if (response.code == 200) {
|
|
[ToolsObject addPopVieToText:@"关注成功"];
|
|
tempModel.user.is_attention = !tempModel.user.is_attention;
|
|
[weakSelf.listArr replaceObjectAtIndex:index.row withObject:tempModel];
|
|
[weakSelf.myTableView reloadRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationNone];
|
|
}
|
|
}];
|
|
}
|
|
- (void)requestcancelFollow:(DDDynamicModel *)dynamicModel withIndexPath:(NSIndexPath *)index{
|
|
|
|
if ([ToolsObject IsNullWithObject:dynamicModel.user_id]) {
|
|
[ToolsObject addPopVieToText:@"没有获取到该用户信息"];
|
|
return;
|
|
}
|
|
[ToolsObject ShowSVProgressHUD:@""];
|
|
NSMutableDictionary *parameter =@{@"followed_user_id":dynamicModel.user_id}.mutableCopy;
|
|
__block DDDynamicModel * tempModel = dynamicModel;
|
|
WeakSelf(weakSelf)
|
|
[NetworkRequest requestPOST:@"/dynamic/cancel/attention" parameters:parameter block:^(BaseResponse * _Nonnull response) {
|
|
if (response.code == 200) {
|
|
tempModel.user.is_attention = !tempModel.user.is_attention;
|
|
[weakSelf.listArr replaceObjectAtIndex:index.row withObject:tempModel];
|
|
[weakSelf.myTableView reloadRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationNone];
|
|
}
|
|
}];
|
|
}
|
|
|
|
/*
|
|
// Only override drawRect: if you perform custom drawing.
|
|
// An empty implementation adversely affects performance during animation.
|
|
- (void)drawRect:(CGRect)rect {
|
|
// Drawing code
|
|
}
|
|
*/
|
|
|
|
@end
|