chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:35:01 +08:00
commit a2e318a963
2974 changed files with 158180 additions and 0 deletions
@@ -0,0 +1,32 @@
//
// TLContactsAngel.h
// TLChat
//
// Created by 李伯坤 on 2018/1/8.
// Copyright © 2018年 李伯坤. All rights reserved.
//
#import <ZZFLEX/ZZFlexibleLayoutFramework.h>
typedef NS_ENUM(NSInteger, TLContactsVCSectionType) {
TLContactsVCSectionTypeFuncation = -1,
TLContactsVCSectionTypeEnterprise = -2,
};
typedef NS_ENUM(NSInteger, TLContactsVCCellType) {
TLContactsVCCellTypeNew = -1,
TLContactsVCCellTypeGroup = -2,
TLContactsVCCellTypeTag = -3,
TLContactsVCCellTypePublic = -4,
};
@interface TLContactsAngel : ZZFLEXAngel
/// pushAction
@property (nonatomic, copy) void (^pushAction)(__kindof UIViewController *vc);
- (void)resetListWithContactsData:(NSArray *)contactsData sectionHeaders:(NSArray *)sectionHeaders;
- (instancetype)initWithHostView:(__kindof UIScrollView *)hostView pushAction:(void (^)(__kindof UIViewController *vc))pushAction;
@end
@@ -0,0 +1,143 @@
//
// TLContactsAngel.m
// TLChat
//
// Created by 李伯坤 on 2018/1/8.
// Copyright © 2018年 李伯坤. All rights reserved.
//
#import "TLContactsAngel.h"
#import <ZZFLEX/ZZFLEXAngel+Private.h>
#import <ZZFLEX/ZZFlexibleLayoutSectionModel.h>
#import "TLUserGroup.h"
#import "TLContactsItemCell.h"
#import "TLNewFriendViewController.h"
#import "TLGroupViewController.h"
#import "TLTagsViewController.h"
#import "TLOfficialAccountViewController.h"
#import "TLUserDetailViewController.h"
@interface TLContactsAngel ()
/// header
@property (nonatomic, strong) NSArray *sectionHeaders;
@end
@implementation TLContactsAngel
- (instancetype)initWithHostView:(__kindof UIScrollView *)hostView pushAction:(void (^)(__kindof UIViewController *vc))pushAction
{
if (self = [super initWithHostView:hostView]) {
self.pushAction = pushAction;
}
return self;
}
- (void)resetListWithContactsData:(NSArray *)contactsData sectionHeaders:(NSArray *)sectionHeaders
{
self.sectionHeaders = sectionHeaders;
@weakify(self);
self.clear();
/// 功能
self.addSection(TLContactsVCSectionTypeFuncation);
{
TLContactsItemModel *newModel = createContactsItemModelWithTag(TLContactsVCCellTypeNew, @"friends_new", nil, LOCSTR(@"新的朋友"), nil, nil);
TLContactsItemModel *groupModel = createContactsItemModelWithTag(TLContactsVCCellTypeGroup, @"friends_group", nil, LOCSTR(@"群聊"), nil, nil);
TLContactsItemModel *tagModel = createContactsItemModelWithTag(TLContactsVCCellTypeTag, @"friends_tag", nil, LOCSTR(@"标签"), nil, nil);
TLContactsItemModel *publicModel = createContactsItemModelWithTag(TLContactsVCCellTypePublic, @"friends_public", nil, LOCSTR(@"公众号"), nil, nil);
NSArray *funcationData = @[newModel, groupModel, tagModel, publicModel];
self.addCells(NSStringFromClass([TLContactsItemCell class])).toSection(TLContactsVCSectionTypeFuncation).withDataModelArray(funcationData).selectedAction(^ (TLContactsItemModel *model) {
@strongify(self);
if (model.tag == TLContactsVCCellTypeNew) {
TLNewFriendViewController *newFriendVC = [[TLNewFriendViewController alloc] init];
[self tryPushVC:newFriendVC];
}
else if (model.tag == TLContactsVCCellTypeGroup) {
TLGroupViewController *groupVC = [[TLGroupViewController alloc] init];
[self tryPushVC:groupVC];
}
else if (model.tag == TLContactsVCCellTypeTag) {
TLTagsViewController *tagsVC = [[TLTagsViewController alloc] init];
[self tryPushVC:tagsVC];
}
else if (model.tag == TLContactsVCCellTypePublic) {
TLOfficialAccountViewController *publicServerVC = [[TLOfficialAccountViewController alloc] init];
[self tryPushVC:publicServerVC];
}
});
}
// 企业
self.addSection(TLContactsVCSectionTypeEnterprise);
// 好友
TLContactsItemModel *(^createContactsItemModelWithUserModel)(TLUser *userModel) = ^TLContactsItemModel *(TLUser *userModel){
TLContactsItemModel *model = createContactsItemModel(userModel.avatarPath, userModel.avatarURL, userModel.showName, userModel.detailInfo.remarkInfo, userModel);
return model;
};
for (TLUserGroup *group in contactsData) {
NSInteger sectionTag = group.tag;
self.addSection(sectionTag);
self.setHeader(@"TLContactsHeaderView").toSection(sectionTag).withDataModel(group.groupName);
NSMutableArray *data = [[NSMutableArray alloc]initWithCapacity:group.users.count];
for (TLUser *user in group.users) {
TLContactsItemModel *newModel = createContactsItemModelWithUserModel(user);
[data addObject:newModel];
}
self.addCells(NSStringFromClass([TLContactsItemCell class])).toSection(sectionTag).withDataModelArray(data).selectedAction(^ (TLContactsItemModel *data) {
@strongify(self);
TLUser *user = data.userInfo;
TLUserDetailViewController *detailVC = [[TLUserDetailViewController alloc] initWithUserModel:user];
[self tryPushVC:detailVC];
});
}
}
- (void)tryPushVC:(__kindof UIViewController *)vc
{
if (self.pushAction) {
self.pushAction(vc);
}
}
#pragma mark - # Delegate
// 拼音首字母检索
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return self.sectionHeaders;
}
// 检索时空出搜索框
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
if(index == 0) {
[tableView scrollRectToVisible:CGRectMake(0, 0, tableView.width, tableView.height) animated:NO];
return -1;
}
return index;
}
// 备注
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
ZZFlexibleLayoutSectionModel *sectionModel = [self sectionModelAtIndex:indexPath.section];
if (sectionModel.sectionTag != TLContactsVCSectionTypeFuncation && sectionModel.sectionTag != TLContactsVCSectionTypeEnterprise) {
@weakify(self);
TLContactsItemModel *itemModel = self.dataModel.atIndexPath(indexPath);
UITableViewRowAction *remarkAction;
remarkAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal
title:@"备注"
handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
@strongify(self);
[TLUIUtility showSuccessHint:@"备注:暂未实现"];
}];
return @[remarkAction];
}
return @[];
}
@end
@@ -0,0 +1,14 @@
//
// TLContactsViewController.h
// TLChat
//
// Created by 李伯坤 on 16/1/23.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLViewController.h"
@interface TLContactsViewController : TLViewController
@end
@@ -0,0 +1,133 @@
//
// TLContactsViewController.m
// TLChat
//
// Created by 李伯坤 on 16/1/23.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLContactsViewController.h"
#import "TLContactsAngel.h"
#import "TLFriendHelper.h"
#import "TLSearchController.h"
#import "TLContactsSearchResultViewController.h"
#import "TLUserDetailViewController.h"
#import "TLAddContactsViewController.h"
@interface TLContactsViewController ()
/// 列表
@property (nonatomic, strong) UITableView *tableView;
/// 列表数据及控制中心
@property (nonatomic, strong) TLContactsAngel *listAngel;
/// 总好友数
@property (nonatomic, strong) UILabel *footerLabel;
/// 搜索
@property (nonatomic, strong) TLSearchController *searchController;
@end
@implementation TLContactsViewController
- (id)init
{
if (self = [super init]) {
initTabBarItem(self.tabBarItem, LOCSTR(@"通讯录"), @"tabbar_contacts", @"tabbar_contactsHL");
}
return self;
}
- (void)loadView
{
[super loadView];
// 初始化界面视图控件
[self p_loadUI];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// 开始监听通讯录数据
[self p_startMonitorContactsData];
}
#pragma mark - # Pirvate Methods
- (void)p_loadUI
{
[self.navigationItem setTitle:LOCSTR(@"通讯录")];
@weakify(self);
[self addRightBarButtonWithImage:TLImage(@"nav_add_friend") actionBlick:^{
@strongify(self);
TLAddContactsViewController *addFriendVC = [[TLAddContactsViewController alloc] init];
PushVC(addFriendVC);
}];
self.tableView = self.view.addTableView(1)
.backgroundColor([UIColor colorGrayBG]).separatorStyle(UITableViewCellSeparatorStyleNone)
.tableHeaderView(self.searchController.searchBar).tableFooterView(self.footerLabel)
.estimatedRowHeight(0).estimatedSectionFooterHeight(0).estimatedSectionHeaderHeight(0)
.masonry(^ (MASConstraintMaker *make) {
make.edges.mas_equalTo(0);
})
.view;
[self.tableView setSectionIndexBackgroundColor:[UIColor clearColor]];
[self.tableView setSectionIndexColor:[UIColor colorBlackForNavBar]];
self.listAngel = [[TLContactsAngel alloc] initWithHostView:self.tableView pushAction:^(__kindof UIViewController *vc) {
@strongify(self);
PushVC(vc);
}];
}
- (void)p_startMonitorContactsData
{
[self.listAngel resetListWithContactsData:[TLFriendHelper sharedFriendHelper].data sectionHeaders:[TLFriendHelper sharedFriendHelper].sectionHeaders];
[self.footerLabel setText:[NSString stringWithFormat:@"%ld%@", (long)[TLFriendHelper sharedFriendHelper].friendCount, LOCSTR(@"位联系人")]];
[self.tableView reloadData];
@weakify(self);
[[TLFriendHelper sharedFriendHelper] setDataChangedBlock:^(NSMutableArray *data, NSMutableArray *headers, NSInteger friendCount) {
@strongify(self);
[self.listAngel resetListWithContactsData:[TLFriendHelper sharedFriendHelper].data sectionHeaders:[TLFriendHelper sharedFriendHelper].sectionHeaders];
[self.footerLabel setText:[NSString stringWithFormat:@"%ld%@", (long)friendCount, LOCSTR(@"位联系人")]];
[self.tableView reloadData];
}];
}
#pragma mark - # Getters
- (TLSearchController *)searchController
{
if (_searchController == nil) {
TLContactsSearchResultViewController *searchVC = [[TLContactsSearchResultViewController alloc] init];
@weakify(self);
[searchVC setItemSelectedAction:^(TLContactsSearchResultViewController *searchVC, TLUser *userModel) {
@strongify(self);
[self.searchController setActive:NO];
TLUserDetailViewController *detailVC = [[TLUserDetailViewController alloc] initWithUserModel:userModel];
PushVC(detailVC);
}];
_searchController = [TLSearchController createWithResultsContrller:searchVC];
[_searchController setEnableVoiceInput:YES];
}
return _searchController;
}
- (UILabel *)footerLabel
{
if (_footerLabel == nil) {
_footerLabel= [[UILabel alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 50.0f)];
[_footerLabel setTextAlignment:NSTextAlignmentCenter];
[_footerLabel setFont:[UIFont systemFontOfSize:17.0f]];
[_footerLabel setTextColor:[UIColor grayColor]];
}
return _footerLabel;
}
@end
@@ -0,0 +1,15 @@
//
// TLContactsHeaderView.h
// TLChat
//
// Created by 李伯坤 on 16/1/26.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface TLContactsHeaderView : UITableViewHeaderFooterView <ZZFlexibleLayoutViewProtocol>
@property (nonatomic, strong) NSString *title;
@end
@@ -0,0 +1,55 @@
//
// TLContactsHeaderView.m
// TLChat
//
// Created by 李伯坤 on 16/1/26.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLContactsHeaderView.h"
@interface TLContactsHeaderView ()
@property (nonatomic, strong) UILabel *titleLabel;
@end
@implementation TLContactsHeaderView
+ (CGFloat)viewHeightByDataModel:(id)dataModel
{
return 22.0f;
}
- (void)setViewDataModel:(id)dataModel
{
[self setTitle:dataModel];
}
- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithReuseIdentifier:reuseIdentifier]) {
UIView *bgView = [UIView new];
[bgView setBackgroundColor:[UIColor colorGrayBG]];
[self setBackgroundView:bgView];
self.titleLabel = self.contentView.addLabel(1)
.font([UIFont systemFontOfSize:15])
.textColor([UIColor grayColor])
.masonry(^ (MASConstraintMaker *make){
make.left.mas_equalTo(10);
make.centerY.mas_equalTo(0);
make.right.mas_lessThanOrEqualTo(-15);
})
.view;
}
return self;
}
- (void)setTitle:(NSString *)title
{
_title = title;
[_titleLabel setText:title];
}
@end
@@ -0,0 +1,45 @@
//
// TLContactsItemCell.h
// TLChat
//
// Created by 李伯坤 on 16/1/26.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "TLUser.h"
@class TLContactsItemModel;
TLContactsItemModel *createContactsItemModel(NSString *path, NSString *url, NSString *title, NSString *subTitle, id userInfo);
TLContactsItemModel *createContactsItemModelWithTag(NSInteger tag, NSString *path, NSString *url, NSString *title, NSString *subTitle, id userInfo);
@interface TLContactsItemModel : NSObject
/// tag
@property (nonatomic, assign) NSInteger tag;
/// 图片本地路径
@property (nonatomic, strong) NSString *imagePath;
/// 图片url,优先使用
@property (nonatomic, strong) NSString *imageUrl;
/// 标题
@property (nonatomic, strong) NSString *title;
/// 副标题
@property (nonatomic, strong) NSString *subTitle;
/// 占位图
@property (nonatomic, strong) UIImage *placeholderImage;
/// 用户自定义数据
@property (nonatomic, strong) id userInfo;
@end
@interface TLContactsItemCell : UITableViewCell <ZZFlexibleLayoutViewProtocol>
@property (nonatomic, strong) TLContactsItemModel *model;
@end
@@ -0,0 +1,140 @@
//
// TLContactsItemCell.m
// TLChat
//
// Created by 李伯坤 on 16/1/26.
// Copyright © 2016年 李伯坤. All rights reserved.
//
#import "TLContactsItemCell.h"
TLContactsItemModel *createContactsItemModel(NSString *path, NSString *url, NSString *title, NSString *subTitle, id userInfo)
{
return createContactsItemModelWithTag(0, path, url, title, subTitle, userInfo);
}
TLContactsItemModel *createContactsItemModelWithTag(NSInteger tag, NSString *path, NSString *url, NSString *title, NSString *subTitle, id userInfo)
{
TLContactsItemModel *model = [[TLContactsItemModel alloc] init];
model.tag = tag;
model.imagePath = path;
model.imageUrl = url;
model.title = title;
model.subTitle = subTitle;
model.userInfo = userInfo;
return model;
}
@interface TLContactsItemCell ()
@property (nonatomic, strong) UIImageView *avatarView;
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *subTitleLabel;
@end
@implementation TLContactsItemCell
+ (CGFloat)viewHeightByDataModel:(id)dataModel
{
return 55.0f;
}
- (void)setViewDataModel:(id)dataModel
{
[self setModel:dataModel];
}
- (void)viewIndexPath:(NSIndexPath *)indexPath sectionItemCount:(NSInteger)count
{
if (indexPath.row == count - 1) {
self.removeSeparator(ZZSeparatorPositionBottom);
}
else {
self.addSeparator(ZZSeparatorPositionBottom).beginAt(10);
}
}
#pragma mark - # Cell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
[self p_initUI];
}
return self;
}
- (void)setModel:(TLContactsItemModel *)model
{
_model = model;
UIImage *localImage = (model.imagePath.length > 0 ? TLImage(model.imagePath) : nil);
if (model.imageUrl) {
UIImage *placeholder = model.placeholderImage ? model.placeholderImage : (localImage ? localImage : TLImage(DEFAULT_AVATAR_PATH));
[self.avatarView tt_setImageWithURL:TLURL(model.imageUrl) placeholderImage:placeholder];
}
else if (model.imagePath) {
[self.avatarView setImage:[UIImage imageNamed:model.imagePath]];
}
[self.nameLabel setText:model.title];
[self.subTitleLabel setText:model.subTitle];
if (model.subTitle.length > 0) {
if (self.subTitleLabel.isHidden) {
[self.subTitleLabel setHidden:NO];
[self.nameLabel mas_updateConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.avatarView).mas_offset(-9.5);
}];
}
}
else if (!self.subTitleLabel.isHidden){
[self.nameLabel mas_updateConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.avatarView);
}];
}
}
#pragma mark - # Prvate Methods
- (void)p_initUI
{
// 头像
self.avatarView = self.contentView.addImageView(1)
.masonry(^(MASConstraintMaker *make) {
make.left.top.mas_equalTo(10);
make.bottom.mas_equalTo(-10);
})
.view;
[self.avatarView mas_updateConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(self.avatarView.mas_height);
}];
// 昵称
self.nameLabel = self.contentView.addLabel(2)
.font([UIFont systemFontOfSize:17.0f])
.masonry(^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.avatarView.mas_right).mas_offset(10);
make.centerY.mas_equalTo(self.avatarView);
make.right.mas_lessThanOrEqualTo(-20);
})
.view;
// 备注
self.subTitleLabel = self.contentView.addLabel(3)
.font([UIFont systemFontOfSize:14.0f])
.textColor([UIColor grayColor])
.masonry(^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.nameLabel);
make.top.mas_equalTo(self.nameLabel.mas_bottom).mas_offset(2);
make.right.mas_lessThanOrEqualTo(-20);
})
.view;
}
@end
@implementation TLContactsItemModel
@end