├── .gitignore ├── .gitmodules ├── API Problem.md ├── CHANGES.md ├── JLRubyChina.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── JLRubyChina.xccheckout ├── JLRubyChina.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── JLRubyChina.xccheckout ├── JLRubyChina ├── Categories │ ├── NSDate+RubyChina.h │ ├── NSDate+RubyChina.m │ ├── NSString+stringFromValue.h │ ├── NSString+stringFromValue.m │ ├── UIImage+nimbusImageNamed.h │ ├── UIImage+nimbusImageNamed.m │ ├── UIView+findViewController.h │ └── UIView+findViewController.m ├── Common │ ├── RCAPIClient.h │ ├── RCAPIClient.m │ └── RCJSONKeys.h ├── Controller │ ├── RCAboutAppC.h │ ├── RCAboutAppC.m │ ├── RCAboutAppC.xib │ ├── RCContentPhotoBrowerC.h │ ├── RCContentPhotoBrowerC.m │ ├── RCCoolSitesC.h │ ├── RCCoolSitesC.m │ ├── RCForumNodesC.h │ ├── RCForumNodesC.m │ ├── RCForumTopicsC.h │ ├── RCForumTopicsC.m │ ├── RCLeftMenuC.h │ ├── RCLeftMenuC.m │ ├── RCLoginC.h │ ├── RCLoginC.m │ ├── RCMoreC.h │ ├── RCMoreC.m │ ├── RCNodesCloudTagC.h │ ├── RCNodesCloudTagC.m │ ├── RCPostC.h │ ├── RCPostC.m │ ├── RCQuickReplyC.h │ ├── RCQuickReplyC.m │ ├── RCTopMembersC.h │ ├── RCTopMembersC.m │ ├── RCTopMembersC_list.h │ ├── RCTopMembersC_list.m │ ├── RCTopicDetailC.h │ ├── RCTopicDetailC.m │ ├── RCUserHomepageC.h │ ├── RCUserHomepageC.m │ ├── RCWikiC.h │ └── RCWikiC.m ├── Entities │ ├── RCAccountEntity.h │ ├── RCAccountEntity.m │ ├── RCKeywordEntity.h │ ├── RCKeywordEntity.m │ ├── RCNodeEntity.h │ ├── RCNodeEntity.m │ ├── RCNodeSectionEntity.h │ ├── RCNodeSectionEntity.m │ ├── RCReplyEntity.h │ ├── RCReplyEntity.m │ ├── RCSiteEntity.h │ ├── RCSiteEntity.m │ ├── RCSiteSectionEntity.h │ ├── RCSiteSectionEntity.m │ ├── RCTopicDetailEntity.h │ ├── RCTopicDetailEntity.m │ ├── RCTopicEntity.h │ ├── RCTopicEntity.m │ ├── RCUserEntity.h │ ├── RCUserEntity.m │ ├── RCUserFullEntity.h │ └── RCUserFullEntity.m ├── JLRubyChina-Dis-Info.plist ├── JLRubyChina-Info.plist ├── JLRubyChina-Prefix.pch ├── JLTesterHome-Dis-Info.plist ├── JLTesterHome-Info.plist ├── JLV2EX-Info.plist ├── MacroDefines.h ├── Models │ ├── RCBaseTableModel.h │ ├── RCBaseTableModel.m │ ├── RCCoolSitesModel.h │ ├── RCCoolSitesModel.m │ ├── RCForumNodesModel.h │ ├── RCForumNodesModel.m │ ├── RCForumTopicsModel.h │ ├── RCForumTopicsModel.m │ ├── RCLoginModel.h │ ├── RCLoginModel.m │ ├── RCPostModel.h │ ├── RCPostModel.m │ ├── RCReplyModel.h │ ├── RCReplyModel.m │ ├── RCTopMembersModel.h │ ├── RCTopMembersModel.m │ ├── RCTopMembersModel_list.h │ ├── RCTopMembersModel_list.m │ ├── RCTopicActionModel.h │ ├── RCTopicActionModel.m │ ├── RCTopicDetailModel.h │ ├── RCTopicDetailModel.m │ ├── RCUserHomepageModel.h │ └── RCUserHomepageModel.m ├── RCAppDelegate.h ├── RCAppDelegate.m ├── RCGlobalConfig.h ├── RCGlobalConfig.m ├── Util │ ├── RCRegularParser.h │ └── RCRegularParser.m ├── Views │ ├── RCHomepageHeaderView.h │ ├── RCHomepageHeaderView.m │ ├── RCNodeCell.h │ ├── RCNodeCell.m │ ├── RCReplyCell.h │ ├── RCReplyCell.m │ ├── RCSiteCell.h │ ├── RCSiteCell.m │ ├── RCTopicBodyView.h │ ├── RCTopicBodyView.m │ ├── RCTopicCell.h │ ├── RCTopicCell.m │ ├── RCUserCell.h │ ├── RCUserCell.m │ ├── RCUserLauncherButtonView.h │ └── RCUserLauncherButtonView.m ├── en.lproj │ └── InfoPlist.strings └── main.m ├── JLRubyChinaTests ├── JLRubyChinaTests-Info.plist ├── JLRubyChinaTests.m └── en.lproj │ └── InfoPlist.strings ├── Podfile ├── Podfile.lock ├── README.md ├── Resource ├── Images │ ├── Common │ │ ├── 37x-Checkmark.png │ │ ├── 37x-Checkmark@2x.png │ │ ├── QuickReply │ │ │ ├── MessageEntryBackground.png │ │ │ ├── MessageEntryBackground@2x.png │ │ │ ├── MessageEntryInputField.png │ │ │ ├── MessageEntryInputField@2x.png │ │ │ ├── MessageEntrySendButton.png │ │ │ ├── MessageEntrySendButton@2x.png │ │ │ ├── MessageEntrySendButtonPressed.png │ │ │ └── MessageEntrySendButtonPressed@2x.png │ │ ├── head_b.png │ │ ├── head_b@2x.png │ │ ├── head_s.png │ │ ├── head_s@2x.png │ │ ├── icon_menu.png │ │ ├── icon_menu@2x.png │ │ ├── more_photo.png │ │ └── more_photo@2x.png │ └── Forums │ │ ├── RubyChina │ │ └── IconDefault │ │ │ ├── Default-375w-667h@2x.png │ │ │ ├── Default-414w-736h@3x.png │ │ │ ├── Default-568h@2x.png │ │ │ ├── Default.png │ │ │ ├── Default@2x.png │ │ │ ├── icon.png │ │ │ ├── icon │ │ │ ├── icon.png │ │ │ ├── icon120.png │ │ │ ├── icon58.png │ │ │ ├── icon80.png │ │ │ ├── icon@2x.png │ │ │ └── logo512.png │ │ │ ├── icon120.png │ │ │ ├── icon512.png │ │ │ ├── icon58.png │ │ │ ├── icon80.png │ │ │ ├── icon@2x.png │ │ │ ├── pure_icon@2x.png │ │ │ ├── ruby-logo.png │ │ │ └── ruby-logo@2x.png │ │ ├── TesterHome │ │ └── IconDefault │ │ │ ├── Default-568h@2x.png │ │ │ ├── Default.png │ │ │ ├── Default@2x.png │ │ │ ├── icon.png │ │ │ ├── icon120.png │ │ │ ├── icon58.png │ │ │ ├── icon80.png │ │ │ ├── icon@2x.png │ │ │ ├── ruby-logo.png │ │ │ └── ruby-logo@2x.png │ │ └── V2EX │ │ ├── IconDefault │ │ ├── Default-568h@2x.png │ │ ├── Default.png │ │ ├── Default@2x.png │ │ ├── icon.png │ │ ├── icon120.png │ │ ├── icon58.png │ │ ├── icon80.png │ │ ├── icon@2x.png │ │ ├── logo.png │ │ ├── ruby-logo.png │ │ └── ruby-logo@2x.png │ │ └── Screenshots │ │ ├── 0110_1.png │ │ ├── 0110_2.png │ │ └── 0110_3.png └── Screenshots │ ├── ErrorResolve │ ├── not_found_pods.png │ └── open_xcworkspace.jpg │ ├── default.png │ ├── home_activity_topics.png │ ├── home_page.png │ ├── left_menu_side.png │ ├── more.png │ ├── node_select.png │ ├── nodes.png │ ├── outside_link_sites.png │ ├── top_members.png │ └── topic_reply.png ├── TODO.md └── vendor └── Reachability ├── Reachability.h └── Reachability.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | 19 | #CocoaPods 20 | Pods 21 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/TSEmojiView"] 2 | path = vendor/TSEmojiView 3 | url = https://github.com/jimneylee/TSEmojiView.git 4 | [submodule "vendor/JLNimbusTimeline"] 5 | path = vendor/JLNimbusTimeline 6 | url = https://github.com/jimneylee/JLNimbusTimeline.git 7 | [submodule "vendor/JASidePanels"] 8 | path = vendor/JASidePanels 9 | url = https://github.com/gotosleep/JASidePanels.git 10 | [submodule "vendor/MarkdownSyntaxEditor"] 11 | path = vendor/MarkdownSyntaxEditor 12 | url = https://github.com/jimneylee/MarkdownSyntaxEditor.git 13 | [submodule "vendor/320Categories"] 14 | path = vendor/320Categories 15 | url = https://github.com/jimneylee/320Categories.git 16 | -------------------------------------------------------------------------------- /API Problem.md: -------------------------------------------------------------------------------- 1 | 社区API开放接口问题反馈 2 | 3 | 后台API接口有几个还需要完善下,具体问题如下: 4 | 1、帖子回复列表: 5 | API: http://ruby-china.org/api/topics/16194.json 6 | 7 | * a、回复列表未按id排序,会错乱,建议在接口中处理。 8 | 参照帖子:http://ruby-china.org/topics/16194 9 | 10 | * b、已删除的楼层,在回复列表数据中无法判断 11 | 接口数据建议放一个占位数据,客户端解析发帖没有id,认为帖子已删除。跟网页一致显示已删除。保证楼层跳转正确。 12 | 13 | 3、帖子的(取消)关注成功返回是json、(取消)关注失败返回是false,而收藏成功返回是true or false 14 | API: http://ruby-china.org/api/v2/topics/:id/follow.json 15 | API: http://ruby-china.org/api/v2/topics/:id/unfollow.json 16 | API: http://ruby-china.org/api/v2/topics/:id/favorite.json 17 | 返回结果不统一,建议统一格式返回 18 | 19 | 4、个人主页接口中最近5条帖子的信息不完整 20 | API: http://ruby-china.org/api/users/:user.json 21 | 22 | 5、建议增加精华贴接口,这样方便大家通过客户端查阅社区优秀的帖子 23 | 24 | 6、http://ruby-china.org/api/topics.json 默认是热门贴。 25 | 建议增加一个type类型,实现分类查看: 默认 /  优质帖子 / 无人问津 / 最新创建 26 | 27 | 望采纳!Merry Christmas! -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | **************************************************** 2 | V1.2.0 3 | 1、修复表情显示不完整问题 4 | 2、修复回复多行,回复按钮无法点击问题 5 | 3、修复第一个回复崩溃的问题 6 | 4、修复回复列表未排序的问题 7 | 8 | **************************************************** 9 | V1.1.1 10 | 1、帖子正文支持markdown语法,正则匹配还有很多问题,待完善 11 | 2、显示帖子和回复中图片 12 | 3、兼容ios6 13 | 4、添加网络断开/2g3g/wifi切换的时间侦听和提示 14 | 15 | **************************************************** 16 | V1.1.0 17 | 1、回复支持表情选择功能 18 | 2、发帖支持markdown语法 19 | 20 | **************************************************** 21 | V1.0.0 22 | 1、首页热门帖子显示 23 | 2、帖子详细浏览、帖子回复列表,待支持markdown语法解析显示 24 | 3、帖子关注、收藏、回复及@某人 25 | 4、发帖到指定分类,待支持表情选择 26 | 5、分类节点列表查看,待做分组与排序 27 | 6、酷站分组显示 28 | 7、会员TOP N查看 29 | 8、我的主页,已发帖子、收藏帖子查看,待做详细资料 30 | 9、Ruby China Wiki 31 | 10、更多功能包含:清空缓存、更新检测、给我评分、关于APP -------------------------------------------------------------------------------- /JLRubyChina.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JLRubyChina.xcodeproj/project.xcworkspace/xcshareddata/JLRubyChina.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 7D4F33C3-4B34-48A4-904B-63B784DE6E8F 9 | IDESourceControlProjectName 10 | JLRubyChina 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 89A2599F-171F-4ABC-B940-6960B71B8B35 14 | https://git.oschina.net/jimneylee/JLRubyChina-iPhone.git 15 | 16 | IDESourceControlProjectPath 17 | JLRubyChina.xcodeproj/project.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 89A2599F-171F-4ABC-B940-6960B71B8B35 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://git.oschina.net/jimneylee/JLRubyChina-iPhone.git 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | 89A2599F-171F-4ABC-B940-6960B71B8B35 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 89A2599F-171F-4ABC-B940-6960B71B8B35 36 | IDESourceControlWCCName 37 | JLRubyChina-iPhone 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /JLRubyChina.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /JLRubyChina.xcworkspace/xcshareddata/JLRubyChina.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | D7E329C1-831E-4961-BC5F-DCF0760536B7 9 | IDESourceControlProjectName 10 | JLRubyChina 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 3696B39AF9A7D45AA2A36BD621E04A71FEC24306 14 | https://github.com/jimneylee/JLNimbusTimeline.git 15 | 61BE18A5930DA2ABE9DDA67B3F71C81D12CD46A9 16 | https://github.com/gotosleep/JASidePanels.git 17 | A0EA22F907A77FD19F76C743593B2249B390F456 18 | https://github.com/jimneylee/MarkdownSyntaxEditor.git 19 | B12BDDCD638DC62B878AE944EF431929C4E405C0 20 | https://github.com/jimneylee/JLRubyChina-iPhone.git 21 | E252D7BD2F0F58EA499CABA45B3A8E07286F0E94 22 | https://github.com/jimneylee/320Categories.git 23 | F0BB51E5AD498528F60E05CFD675B5B2ED0B3A2B 24 | https://github.com/jimneylee/TSEmojiView.git 25 | 26 | IDESourceControlProjectPath 27 | JLRubyChina.xcworkspace 28 | IDESourceControlProjectRelativeInstallPathDictionary 29 | 30 | 3696B39AF9A7D45AA2A36BD621E04A71FEC24306 31 | ../vendor/JLNimbusTimeline 32 | 61BE18A5930DA2ABE9DDA67B3F71C81D12CD46A9 33 | ../vendor/JASidePanels 34 | A0EA22F907A77FD19F76C743593B2249B390F456 35 | ../vendor/MarkdownSyntaxEditor 36 | B12BDDCD638DC62B878AE944EF431929C4E405C0 37 | .. 38 | E252D7BD2F0F58EA499CABA45B3A8E07286F0E94 39 | ../vendor/320Categories 40 | F0BB51E5AD498528F60E05CFD675B5B2ED0B3A2B 41 | ../vendor/TSEmojiView 42 | 43 | IDESourceControlProjectURL 44 | https://github.com/jimneylee/JLRubyChina-iPhone.git 45 | IDESourceControlProjectVersion 46 | 111 47 | IDESourceControlProjectWCCIdentifier 48 | B12BDDCD638DC62B878AE944EF431929C4E405C0 49 | IDESourceControlProjectWCConfigurations 50 | 51 | 52 | IDESourceControlRepositoryExtensionIdentifierKey 53 | public.vcs.git 54 | IDESourceControlWCCIdentifierKey 55 | E252D7BD2F0F58EA499CABA45B3A8E07286F0E94 56 | IDESourceControlWCCName 57 | 320Categories 58 | 59 | 60 | IDESourceControlRepositoryExtensionIdentifierKey 61 | public.vcs.git 62 | IDESourceControlWCCIdentifierKey 63 | 61BE18A5930DA2ABE9DDA67B3F71C81D12CD46A9 64 | IDESourceControlWCCName 65 | JASidePanels 66 | 67 | 68 | IDESourceControlRepositoryExtensionIdentifierKey 69 | public.vcs.git 70 | IDESourceControlWCCIdentifierKey 71 | 3696B39AF9A7D45AA2A36BD621E04A71FEC24306 72 | IDESourceControlWCCName 73 | JLNimbusTimeline 74 | 75 | 76 | IDESourceControlRepositoryExtensionIdentifierKey 77 | public.vcs.git 78 | IDESourceControlWCCIdentifierKey 79 | B12BDDCD638DC62B878AE944EF431929C4E405C0 80 | IDESourceControlWCCName 81 | JLRubyChina-iPhone 82 | 83 | 84 | IDESourceControlRepositoryExtensionIdentifierKey 85 | public.vcs.git 86 | IDESourceControlWCCIdentifierKey 87 | A0EA22F907A77FD19F76C743593B2249B390F456 88 | IDESourceControlWCCName 89 | MarkdownSyntaxEditor 90 | 91 | 92 | IDESourceControlRepositoryExtensionIdentifierKey 93 | public.vcs.git 94 | IDESourceControlWCCIdentifierKey 95 | F0BB51E5AD498528F60E05CFD675B5B2ED0B3A2B 96 | IDESourceControlWCCName 97 | TSEmojiView 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /JLRubyChina/Categories/NSDate+RubyChina.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+RubyChina.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDate (RubyChina) 12 | 13 | + (NSDate*)dateFromSourceDateString:(NSString*)dateString; 14 | 15 | + (NSDate *)formatDateWith_T_FromString:(NSString *)dateString; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /JLRubyChina/Categories/NSDate+RubyChina.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+RubyChina.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "NSDate+RubyChina.h" 10 | 11 | @implementation NSDate (RubyChina) 12 | 13 | /////////////////////////////////////////////////////////////////////////////////////////////////// 14 | + (NSDate*)dateFromSourceDateString:(NSString*)dateString 15 | { 16 | NSDate* date = nil; 17 | NSRange range = NSMakeRange(0, 0); 18 | if (dateString && [dateString isKindOfClass:[NSString class]] && dateString.length) { 19 | //2013-12-10T20:17:42.707+08:00 20 | range = [dateString rangeOfString:@"."]; 21 | if (range.length) { 22 | dateString = [dateString substringToIndex:range.location]; 23 | } 24 | date = [NSDate formatDateWith_T_FromString:dateString]; 25 | } 26 | return date; 27 | } 28 | 29 | /////////////////////////////////////////////////////////////////////////////////////////////////// 30 | + (NSDate *)formatDateWith_T_FromString:(NSString *)string { 31 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 32 | [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'+08:00'"]; 33 | return [dateFormatter dateFromString:string]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /JLRubyChina/Categories/NSString+stringFromValue.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+stringFromValue.h 3 | // SinaMBlogNimbus 4 | // 5 | // Created by jimneylee on 13-10-14. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (stringFromValue) 12 | 13 | + (NSString*)stringFromValue:(id)value; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /JLRubyChina/Categories/NSString+stringFromValue.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+stringFromValue.m 3 | // SinaMBlogNimbus 4 | // 5 | // Created by jimneylee on 13-10-14. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "NSString+stringFromValue.h" 10 | 11 | @implementation NSString (stringFromValue) 12 | 13 | + (NSString*)stringFromValue:(id)value 14 | { 15 | if (value) { 16 | if ([value isKindOfClass:[NSString class]]) { 17 | return value; 18 | } 19 | else if ([value isKindOfClass:[NSNumber class]]) { 20 | return [value stringValue]; 21 | } 22 | else { 23 | return @""; 24 | } 25 | } 26 | else { 27 | return @""; 28 | } 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /JLRubyChina/Categories/UIImage+nimbusImageNamed.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+nimbusImageNamed.h 3 | // SinaMBlogNimbus 4 | // 5 | // Created by Lee jimney on 10/7/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (nimbusImageNamed) 12 | 13 | + (UIImage*)nimbusImageNamed:(NSString*)imageName; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /JLRubyChina/Categories/UIImage+nimbusImageNamed.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+nimbusImageNamed.m 3 | // SinaMBlogNimbus 4 | // 5 | // Created by Lee jimney on 10/7/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "UIImage+nimbusImageNamed.h" 10 | 11 | @implementation UIImage (nimbusImageNamed) 12 | 13 | + (UIImage*)nimbusImageNamed:(NSString*)imageName 14 | { 15 | NSString* imagePath = NIPathForBundleResource(nil, imageName); 16 | UIImage* image = [[Nimbus imageMemoryCache] objectWithName:imagePath]; 17 | if (nil == image) { 18 | image = [UIImage imageWithContentsOfFile:imagePath]; 19 | // And then store it in memory. 20 | [[Nimbus imageMemoryCache] storeObject:image withName:imagePath]; 21 | } 22 | return image; 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /JLRubyChina/Categories/UIView+findViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+findViewController.h 3 | // SinaMBlogNimbus 4 | // 5 | // Created by jimneylee on 13-12-2. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (findViewController) 12 | 13 | - (UIViewController *)viewController; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /JLRubyChina/Categories/UIView+findViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+findViewController.m 3 | // SinaMBlogNimbus 4 | // 5 | // Created by jimneylee on 13-12-2. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "UIView+findViewController.h" 10 | 11 | @implementation UIView (findViewController) 12 | - (UIViewController *)viewController { 13 | // Traverse responder chain. Return first found view controller, which will be the view's view controller. 14 | UIResponder *responder = self; 15 | while ((responder = [responder nextResponder])) 16 | if ([responder isKindOfClass:[UIViewController class]]) 17 | return (UIViewController *)responder; 18 | 19 | // If the view controller isn't found, return nil. 20 | return nil; 21 | } 22 | @end -------------------------------------------------------------------------------- /JLRubyChina/Common/RCAPIClient.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCAPIClient.h 3 | // SinaMBlogNimbus 4 | // 5 | // Created by jimneylee on 13-7-25. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLAFAPIBaseClient.h" 10 | 11 | /* RubyChina 12 | GET ruby-china.org/api/topics.json 13 | GET ruby-china.org/api/topics/node/:id.json 14 | POST ruby-china.org/api/topics.json 15 | GET ruby-china.org/api/topics/:id.json 16 | POST ruby-china.org/api/topics/:id/replies.json 17 | GET ruby-china.org/api/nodes.json 18 | GET ruby-china.org/api/sites.json 19 | PUT ruby-china.org/api/user/favorite/:user/:topic.json 20 | GET ruby-china.org/api/users.json 21 | GET ruby-china.org/api/users/:user.json 22 | GET ruby-china.org/api/users/:user/topics.json 23 | GET ruby-china.org/api/users/:user/topics/favorite.json 24 | POST ruby-china.org/api/topics/:id/follow.json 25 | POST ruby-china.org/api/topics/:id/unfollow.json 26 | POST ruby-china.org/api/topics/:id/favorite.json 27 | GET ruby-china.org/api/users/temp_access_token.json 28 | */ 29 | 30 | /* V2EX 31 | ('/api/site/stats.json', SiteStatsHandler), 32 | ('/api/site/info.json', SiteInfoHandler), 33 | ('/api/nodes/all.json', NodesAllHandler), 34 | ('/api/nodes/show.json', NodesShowHandler), 35 | ('/api/topics/latest.json', TopicsLatestHandler), 36 | ('/api/topics/show.json', TopicsShowHandler), 37 | ('/api/topics/create.json', TopicsCreateHandler), 38 | ('/api/replies/show.json', RepliesShowHandler), 39 | ('/api/members/show.json', MembersShowHandler), 40 | ('/api/currency.json', CurrencyHandler) 41 | */ 42 | 43 | @interface RCAPIClient : JLAFAPIBaseClient 44 | 45 | + (RCAPIClient*)sharedClient; 46 | 47 | //================================================================================ 48 | // account sing in 49 | //================================================================================ 50 | 51 | // 登录 52 | + (NSString*)relativePathForSignIn; 53 | 54 | //================================================================================ 55 | // topic read 56 | //================================================================================ 57 | 58 | // 热帖 59 | + (NSString*)relativePathForTopicsWithPageIndex:(unsigned int)pageIndex 60 | pageSize:(unsigned int)pageSize; 61 | 62 | // 查看帖子详细 TODO:评论没有按实现先后排序,有错乱 63 | + (NSString*)relativePathForTopicDetailWithTopicId:(unsigned long)topicId; 64 | 65 | // 帖子回复列表 66 | + (NSString*)relativePathForTopicRepliesWithTopicId:(unsigned long)topicId 67 | pageIndex:(unsigned int)pageIndex 68 | pageSize:(unsigned int)pageSize; 69 | 70 | // 节点帖子 71 | + (NSString*)relativePathForTopicsWithNodeId:(unsigned int)nodeId 72 | pageIndex:(unsigned int)pageIndex 73 | pageSize:(unsigned int)pageSize; 74 | 75 | // 用户发的帖子列表 TODO:此接口总是返回最新的15条:http://ruby-china.org/api/v2/users/huacnlee/topics.json?page=1&per_page=30 76 | + (NSString*)relativePathForPostedTopicsWithUserLoginId:(NSString*)loginId 77 | pageIndex:(unsigned int)pageIndex 78 | pageSize:(unsigned int)pageSize; 79 | 80 | // 用户收藏帖子列表 81 | + (NSString*)relativePathForFavoritedTopicsWithUserLoginId:(NSString*)loginId 82 | pageIndex:(unsigned int)pageIndex 83 | pageSize:(unsigned int)pageSize; 84 | 85 | // 论坛所有节点 86 | + (NSString*)relativePathForForumNodes; 87 | 88 | // 酷站 89 | + (NSString*)relativePathForCoolSites; 90 | 91 | // TOP会员 92 | + (NSString*)relativePathForTopMembersWithPageIndex:(unsigned int)pageIndex 93 | pageSize:(unsigned int)pageSize; 94 | 95 | //================================================================================ 96 | // topic write 97 | //================================================================================ 98 | 99 | // 发布新帖 100 | + (NSString*)relativePathForPostNewTopic; 101 | 102 | // 回复帖子 103 | + (NSString*)relativePathForReplyTopicId:(unsigned long)topicId; 104 | 105 | // 收藏帖子 106 | + (NSString*)relativePathForFavoriteTopicId:(unsigned long)topicId; 107 | 108 | // 关注帖子 109 | + (NSString*)relativePathForFollowTopicId:(unsigned long)topicId; 110 | 111 | // 取消关注帖子 112 | + (NSString*)relativePathForUnfollowTopicId:(unsigned long)topicId; 113 | 114 | //================================================================================ 115 | // user page 116 | //================================================================================ 117 | 118 | // 用户主页 119 | + (NSString*)relativePathForVisitUserHomepageWithLoginId:(NSString*)username; 120 | 121 | @end 122 | 123 | NSString *const kAPIBaseURLString; -------------------------------------------------------------------------------- /JLRubyChina/Common/RCJSONKeys.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCJSONKeys.h 3 | // RCAPIClient 4 | // 5 | // Created by Lee jimney on 7/31/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #ifndef JLRubyChina_SMJSONKeys_h 10 | #define JLRubyChina_SMJSONKeys_h 11 | 12 | //========================================================================== 13 | // common 14 | #define JSON_ID @"id" 15 | #define JSON_LOGIN @"login" 16 | #define JSON_PRIVATE_TOKEN @"private_token" 17 | #define JSON_AVATAR_URL @"avatar_url" 18 | #define JSON_USER @"user" 19 | #define JSON_TITLE @"title" 20 | #define JSON_CREATEED_AT @"created_at" 21 | #define JSON_UPDATEED_AT @"updated_at" 22 | #define JSON_REPLIED_AT @"replied_at" 23 | #define JSON_REPLIES_COUNT @"replies_count" 24 | #define JSON_NODE_NAME @"node_name" 25 | #define JSON_NODE_ID @"node_id" 26 | #define JSON_LAST_REPLY_USER_ID @"last_reply_user_id" 27 | #define JSON_LAST_REPLY_USER_LOGIN @"last_reply_user_login" 28 | #define JSON_BODY @"body" 29 | #define JSON_BODY_HTML @"body_html" 30 | #define JSON_HITS_COUNT @"hits" 31 | #define JSON_REPLIES_LIST @"replies" 32 | #define JSON_NAME @"name" 33 | #define JSON_TOPICS_LIST @"topics" 34 | #define JSON_TOPICS_COUNT @"topics_count" 35 | #define JSON_SUMMARY @"summary" 36 | #define JSON_SECTION_ID @"section_id" 37 | #define JSON_SECTION_NAME @"section_name" 38 | #define JSON_SORT @"sort" 39 | #define JSON_SITE_SECTION_ID @"_id" 40 | #define JSON_SITES_LIST @"sites" 41 | #define JSON_DESCRIPTION @"desc" 42 | #define JSON_FAV_ICON @"favicon" 43 | #define JSON_URL @"url" 44 | 45 | // addition for V2EX 46 | #define JSON_USERNAME @"username" 47 | #define JSON_NODE @"node" 48 | #define JSON_MEMBER @"member" 49 | #define JSON_TAGLINE @"tagline" 50 | #define JSON_AVATAR_MINI @"avatar_mini" 51 | #define JSON_CONTENT @"content" 52 | #define JSON_REPLIES @"replies" 53 | #define JSON_CREATED @"created" 54 | #define JSON_LAST_MODIFIED @"last_modified" 55 | #define JSON_TOPICS @"topics" 56 | #define JSON_HEADER @"header" 57 | #define JSON_FOOTER @"footer" 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCAboutAppC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCAboutAppC.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/14/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class NIAttributedLabel; 12 | @interface RCAboutAppC : UIViewController 13 | 14 | @property (nonatomic, strong) IBOutlet NIAttributedLabel* nameLabel; 15 | @property (nonatomic, strong) IBOutlet NIAttributedLabel* siteUrlLabel; 16 | @property (nonatomic, strong) IBOutlet UITextView* siteIntroduceTextView; 17 | @property (nonatomic, strong) IBOutlet NIAttributedLabel* devIntroduceLabel; 18 | @property (nonatomic, strong) IBOutlet NIAttributedLabel* versionLabel; 19 | 20 | - (instancetype)initWithCreateLauchImage:(BOOL)toCreateLauchImage; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCContentPhotoBrowerC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SNPhotoBrowerC.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-10-21. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCContentPhotoBrowerC : UIViewController 12 | 13 | - (id)initWithPhotoUrls:(NSArray*)photos; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCCoolSitesC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCCoolSitesC.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-12. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCCoolSitesC : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCForumNodesC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCForumNodesC.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusTableViewController.h" 10 | 11 | @interface RCForumNodesC : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCForumTopicsC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCForumTopicsC.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusTableViewController.h" 10 | 11 | @interface RCForumTopicsC : JLNimbusTableViewController 12 | 13 | // 根据类型初始化,无其他参数:热门帖子、精华帖等 14 | - (id)initWithTopicsType:(RCForumTopicsType)topicsType; 15 | 16 | // 分类节点帖子列表 17 | - (id)initWithNodeName:(NSString*)nodeName nodeId:(NSUInteger)nodeId; 18 | 19 | // 用户的帖子列表 20 | - (id)initWithUserLoginId:(NSString*)loginId; 21 | 22 | // 用户收藏的帖子列表 23 | - (id)initForFavoritedWithUserLoginId:(NSString*)loginId; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCLeftMenuC.h: -------------------------------------------------------------------------------- 1 | // 2 | // LeftViewController.h 3 | // EasySample 4 | // 5 | // Created by Marian PAUL on 12/06/12. 6 | // Copyright (c) 2012 Marian PAUL aka ipodishima — iPuP SARL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum 12 | { 13 | LeftMenuType_Home=0, 14 | LeftMenuType_ForumNodes, 15 | LeftMenuType_CoolSites, 16 | LeftMenuType_TopMembers, 17 | LeftMenuType_MyHomePage, 18 | LeftMenuType_Wiki, 19 | LeftMenuType_More 20 | }LeftMenuType; 21 | 22 | @protocol RCLeftMenuDelegate; 23 | @interface RCLeftMenuC : UIViewController 24 | 25 | @property (assign, nonatomic) id delegate; 26 | 27 | - (id)initWithStyle:(UITableViewStyle)style; 28 | - (void)setSelectedMenuType:(LeftMenuType)type; 29 | 30 | @end 31 | 32 | @protocol RCLeftMenuDelegate 33 | 34 | - (void)didSelectLeftMenuType:(LeftMenuType)type; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCLoginC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SNLoginC.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-7-25. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCLoginC : UITableViewController 12 | 13 | @end -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCMoreC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCMoreC.h 3 | // RubyChina 4 | // 5 | // Created by Lee jimney on 10/7/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCMoreC : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCNodesCloudTagC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCForumNodesCloudTagC.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-13. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCNodeEntity.h" 10 | 11 | @protocol RCNodesCloudTagDelegate; 12 | @interface RCNodesCloudTagC : UIViewController 13 | @property (nonatomic, assign) iddelegate; 14 | @end 15 | 16 | @protocol RCNodesCloudTagDelegate 17 | 18 | @optional 19 | - (void)didSelectANode:(RCNodeEntity*)nodeEntity; 20 | 21 | @end -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCNodesCloudTagC.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCForumNodesCloudTagC.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-13. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCNodesCloudTagC.h" 10 | #import "RCForumNodesModel.h" 11 | #import "RCNodeEntity.h" 12 | #import "RTagCloudView.h" 13 | 14 | @interface RCNodesCloudTagC () 15 | @property (nonatomic, strong) RTagCloudView* tagCloudView; 16 | @property (nonatomic, strong) RCForumNodesModel* model; 17 | @property (nonatomic, strong) NSArray* nodesArray; 18 | @end 19 | 20 | @implementation RCNodesCloudTagC 21 | 22 | /////////////////////////////////////////////////////////////////////////////////////////////////// 23 | /////////////////////////////////////////////////////////////////////////////////////////////////// 24 | #pragma mark - UIViewController 25 | 26 | /////////////////////////////////////////////////////////////////////////////////////////////////// 27 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 28 | { 29 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 30 | if (self) { 31 | // Custom initialization 32 | self.model = [[RCForumNodesModel alloc] init]; 33 | self.title = @"请选择分类"; 34 | } 35 | return self; 36 | } 37 | 38 | /////////////////////////////////////////////////////////////////////////////////////////////////// 39 | - (void)viewDidLoad 40 | { 41 | [super viewDidLoad]; 42 | 43 | [self.model loadNodesWithBlock:^(NSArray *nodeSectionsArray, NSError *error) { 44 | self.nodesArray = self.model.nodesArray; 45 | self.tagCloudView = self.tagCloudView; 46 | }]; 47 | } 48 | 49 | /////////////////////////////////////////////////////////////////////////////////////////////////// 50 | - (void)didReceiveMemoryWarning 51 | { 52 | [super didReceiveMemoryWarning]; 53 | // Dispose of any resources that can be recreated. 54 | } 55 | 56 | /////////////////////////////////////////////////////////////////////////////////////////////////// 57 | - (void)viewWillDisappear:(BOOL)animated 58 | { 59 | [super viewWillDisappear:animated]; 60 | if (self.model.isLoading) { 61 | [self.model cancelRequstOperation]; 62 | } 63 | } 64 | 65 | /////////////////////////////////////////////////////////////////////////////////////////////////// 66 | /////////////////////////////////////////////////////////////////////////////////////////////////// 67 | #pragma mark - Private 68 | 69 | /////////////////////////////////////////////////////////////////////////////////////////////////// 70 | - (RTagCloudView*)tagCloudView 71 | { 72 | if (!_tagCloudView) { 73 | _tagCloudView = [[RTagCloudView alloc] initWithFrame:CGRectMake(0, 0, self.view.width, self.view.height)]; 74 | _tagCloudView.backgroundColor = TABLE_VIEW_BG_COLOR; 75 | _tagCloudView.center = CGPointMake(self.view.width /2, self.view.height / 2); 76 | _tagCloudView.dataSource = self; 77 | _tagCloudView.delegate = self; 78 | [self.view addSubview:_tagCloudView]; 79 | } 80 | return _tagCloudView; 81 | } 82 | 83 | /////////////////////////////////////////////////////////////////////////////////////////////////// 84 | /////////////////////////////////////////////////////////////////////////////////////////////////// 85 | #pragma mark - RTagCloudViewDatasource 86 | 87 | /////////////////////////////////////////////////////////////////////////////////////////////////// 88 | - (NSInteger)numberOfTags:(RTagCloudView *)tagCloud 89 | { 90 | return self.nodesArray.count; 91 | } 92 | 93 | /////////////////////////////////////////////////////////////////////////////////////////////////// 94 | - (NSString*)RTagCloudView:(RTagCloudView *)tagCloud 95 | tagNameOfIndex:(NSInteger)index 96 | { 97 | if (index < self.nodesArray.count) { 98 | RCNodeEntity* node = self.nodesArray[index]; 99 | return node.nodeName; 100 | } 101 | return @"未知分类"; 102 | } 103 | 104 | /////////////////////////////////////////////////////////////////////////////////////////////////// 105 | - (UIFont*)RTagCloudView:(RTagCloudView *)tagCloud 106 | tagFontOfIndex:(NSInteger)index 107 | { 108 | CGFloat fontSize = 14.f; 109 | if (index < self.nodesArray.count) { 110 | RCNodeEntity* node = self.nodesArray[index]; 111 | if (node.topicsCount > 2500) { 112 | fontSize = 30.f; 113 | } 114 | else if (node.topicsCount > 2000) { 115 | fontSize = 28.f; 116 | } 117 | else if (node.topicsCount > 1500) { 118 | fontSize = 26.f; 119 | } 120 | else if (node.topicsCount > 1000) { 121 | fontSize = 24.f; 122 | } 123 | else if (node.topicsCount > 500) { 124 | fontSize = 22.f; 125 | } 126 | else if (node.topicsCount > 200) { 127 | fontSize = 20.f; 128 | } 129 | else if (node.topicsCount > 100) { 130 | fontSize = 18.f; 131 | } 132 | else if (node.topicsCount > 50) { 133 | fontSize = 16.f; 134 | } 135 | else { 136 | fontSize = 14.f; 137 | } 138 | } 139 | return [UIFont systemFontOfSize:fontSize]; 140 | } 141 | 142 | /////////////////////////////////////////////////////////////////////////////////////////////////// 143 | - (UIColor*)RTagCloudView:(RTagCloudView *)tagCloud tagColorOfIndex:(NSInteger)index 144 | { 145 | UIColor *colors[] = { 146 | [UIColor redColor], 147 | [UIColor yellowColor], 148 | [UIColor blueColor], 149 | [UIColor orangeColor], 150 | [UIColor blackColor], 151 | [UIColor purpleColor], 152 | [UIColor greenColor] 153 | }; 154 | return colors[index%7]; 155 | } 156 | 157 | /////////////////////////////////////////////////////////////////////////////////////////////////// 158 | /////////////////////////////////////////////////////////////////////////////////////////////////// 159 | #pragma mark - RTagCloudViewDelegate 160 | 161 | /////////////////////////////////////////////////////////////////////////////////////////////////// 162 | - (void)RTagCloudView:(RTagCloudView*)tagCloud didTapOnTagOfIndex:(NSInteger)index 163 | { 164 | if (index < self.nodesArray.count) { 165 | RCNodeEntity* node = self.nodesArray[index]; 166 | self.title = [NSString stringWithFormat:@"已选择 %@", node.nodeName]; 167 | if ([self.delegate respondsToSelector:@selector(didSelectANode:)]) { 168 | [self.delegate didSelectANode:node]; 169 | } 170 | } 171 | } 172 | 173 | @end 174 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCPostC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SNPostC.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-9-9. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol RCPostDelegate; 12 | 13 | // TODO:当前采用tableview实现,除了键盘弹出好处理,其他太过复杂,后面考虑简单化 14 | @interface RCPostC : UITableViewController 15 | 16 | @property (nonatomic, assign) id postDelegate; 17 | 18 | @end 19 | 20 | @protocol RCPostDelegate 21 | 22 | - (void)didPostNewTopic; 23 | 24 | @end -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCQuickReplyC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCQuickReplyC.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/12/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "HPGrowingTextView.h" 11 | #import "TSEmojiView.h" 12 | #import "RCReplyEntity.h" 13 | 14 | @protocol RCQuickReplyDelegate; 15 | @interface RCQuickReplyC : UIViewController 16 | 17 | @property(nonatomic, strong) HPGrowingTextView *textView; 18 | @property (nonatomic, strong) TSEmojiView* emojiView; 19 | @property (nonatomic, assign) id replyDelegate; 20 | 21 | - (id)initWithTopicId:(unsigned long)topicId; 22 | - (void)appendString:(NSString*)string; 23 | 24 | @end 25 | 26 | @protocol RCQuickReplyDelegate 27 | @optional 28 | - (void)didReplySuccessWithMyReply:(RCReplyEntity*)replyEntity; 29 | - (void)didReplyFailure; 30 | - (void)didReplyCancel; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCTopMembersC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopUsersC.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/14/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | #import "NimbusLauncher.h" 9 | @interface RCTopMembersC : NILauncherViewController 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCTopMembersC_list.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopUsersC.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/14/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusTableViewController.h" 10 | 11 | //TODO: use launch view to show top N, more better 12 | @interface RCTopMembersC : JLNimbusTableViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCTopMembersC_list.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopUsersC.m 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/14/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCTopMembersC.h" 10 | #import "RCUserEntity.h" 11 | #import "RCTopMembersModel.h" 12 | 13 | @interface RCTopMembersC () 14 | 15 | @end 16 | 17 | @implementation RCTopMembersC 18 | 19 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 20 | { 21 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 22 | if (self) { 23 | // Custom initialization 24 | self.title = @"TOP活跃会员"; 25 | self.navigationItem.leftBarButtonItem = [RCGlobalConfig createMenuBarButtonItemWithTarget:self 26 | action:@selector(showLeft:)]; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)viewDidLoad 32 | { 33 | [super viewDidLoad]; 34 | // Do any additional setup after loading the view. 35 | self.tableView.separatorColor = [UIColor clearColor]; 36 | self.tableView.backgroundColor = TABLE_VIEW_BG_COLOR; 37 | self.tableView.backgroundView = nil; 38 | } 39 | 40 | - (void)didReceiveMemoryWarning 41 | { 42 | [super didReceiveMemoryWarning]; 43 | // Dispose of any resources that can be recreated. 44 | } 45 | 46 | /////////////////////////////////////////////////////////////////////////////////////////////////// 47 | /////////////////////////////////////////////////////////////////////////////////////////////////// 48 | #pragma mark - Override 49 | 50 | /////////////////////////////////////////////////////////////////////////////////////////////////// 51 | - (id)tableModelClass 52 | { 53 | return [RCTopMembersModel class]; 54 | } 55 | 56 | /////////////////////////////////////////////////////////////////////////////////////////////////// 57 | - (NITableViewActionBlock)tapAction 58 | { 59 | return ^BOOL(id object, id target) { 60 | if (!self.editing) { 61 | if ([object isKindOfClass:[RCUserEntity class]]) { 62 | RCUserEntity* o = (RCUserEntity*)object; 63 | [RCGlobalConfig hudShowMessage:o.username addedToView:self.view]; 64 | } 65 | return YES; 66 | } 67 | else { 68 | return NO; 69 | } 70 | }; 71 | } 72 | 73 | /////////////////////////////////////////////////////////////////////////////////////////////////// 74 | - (void)showMessageForEmpty 75 | { 76 | NSString* msg = @"信息为空"; 77 | [RCGlobalConfig hudShowMessage:msg addedToView:self.view]; 78 | } 79 | 80 | /////////////////////////////////////////////////////////////////////////////////////////////////// 81 | - (void)showMessageForError 82 | { 83 | NSString* msg = @"抱歉,无法获取信息,请稍后再试!"; 84 | [RCGlobalConfig hudShowMessage:msg addedToView:self.view]; 85 | } 86 | 87 | /////////////////////////////////////////////////////////////////////////////////////////////////// 88 | - (void)showMssageForLastPage 89 | { 90 | //NSString* msg = @"已是最后一页"; 91 | //[RCGlobalConfig hudShowMessage:msg addedToView:self.view]; 92 | } 93 | 94 | /////////////////////////////////////////////////////////////////////////////////////////////////// 95 | /////////////////////////////////////////////////////////////////////////////////////////////////// 96 | #pragma mark Side View Controller 97 | 98 | /////////////////////////////////////////////////////////////////////////////////////////////////// 99 | - (void)showLeft:(id)sender 100 | { 101 | // used to push a new controller, but we preloaded it ! 102 | [self.revealSideViewController pushOldViewControllerOnDirection:PPRevealSideDirectionLeft 103 | withOffset:SIDE_DIRECTION_LEFT_OFFSET 104 | animated:YES]; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCTopicDetailC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicDetailC.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusTableViewController.h" 10 | 11 | // TODO:楼层调转 12 | @interface RCTopicDetailC : JLNimbusTableViewController 13 | - (id)initWithTopicId:(unsigned long)topicId; 14 | - (void)replyTopicWithFloorAtSomeone:(NSString*)floorAtsomeoneString; 15 | @end 16 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCUserHomepageC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicDetailC.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusTableViewController.h" 10 | 11 | @interface RCUserHomepageC : JLNimbusTableViewController 12 | 13 | // only me in left side, my home homepage 14 | - (id)initWithMyLoginId:(NSString*)loginId; 15 | 16 | // for anyone include me, can back to privious controller 17 | - (id)initWithUserLoginId:(NSString*)loginId; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCWikiC.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCWikiC.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/14/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "NIWebController.h" 10 | 11 | // TODO: 很奇怪,基于Ruby on rails后台web请求有时不被响应, 12 | // 如:进入wiki页面后,点击一条wiki,webview的delegate没有调用 13 | // - (void)webViewDidStartLoad:(UIWebView*)webView 14 | // 导致底部前进和后退无法操作,疑问是 15 | // 后台处理页面请求方式与php、js等是不是不太一样,小白,待求解 16 | @interface RCWikiC : NIWebController 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /JLRubyChina/Controller/RCWikiC.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCWikiC.m 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/14/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCWikiC.h" 10 | 11 | @interface RCWikiC () 12 | 13 | @end 14 | 15 | @implementation RCWikiC 16 | 17 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 18 | { 19 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 20 | if (self) { 21 | // Custom initialization 22 | self.title = @"Wiki"; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)viewDidLoad 28 | { 29 | [super viewDidLoad]; 30 | // Do any additional setup after loading the view. 31 | } 32 | 33 | - (void)didReceiveMemoryWarning 34 | { 35 | [super didReceiveMemoryWarning]; 36 | // Dispose of any resources that can be recreated. 37 | } 38 | 39 | - (void)viewWillAppear:(BOOL)animated 40 | { 41 | [super viewWillAppear:animated]; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCAccountEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCUserEntity.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusEntity.h" 10 | 11 | @interface RCAccountEntity : JLNimbusEntity 12 | @property (nonatomic, copy) NSString* loginId;// 用户注册时,用户自己输入的ID号,api接口均使用这个id 13 | @property (nonatomic, copy) NSString* privateToken; 14 | 15 | + (RCAccountEntity*)loadStoredUserAccount; 16 | 17 | + (void)storePrivateToken:(NSString*)privateToken forLoginId:(NSString*)loginId; 18 | + (void)deleteLoginedUserDiskData; 19 | 20 | + (void)storeLoginId:(NSString*)loginId; 21 | + (NSString*)readLoginId; 22 | + (void)deleteLoginId; 23 | 24 | + (NSString*)readPrivateToken; 25 | + (void)deletePrivateToken; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCAccountEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCAccountEntity.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCAccountEntity.h" 10 | #import "SSKeychain.h" 11 | 12 | NSString* kRubyChinaService = @"RubyChinaService"; 13 | NSString* kLoginId = @"LoginId"; 14 | 15 | //{ 16 | // avatar = { 17 | // big = { 18 | // url = "https://ruby-china-files.b0.upaiyun.com/user/big_avatar/4988.jpg"; 19 | // }; 20 | // large = { 21 | // url = "https://ruby-china-files.b0.upaiyun.com/user/large_avatar/4988.jpg"; 22 | // }; 23 | // normal = { 24 | // url = "https://ruby-china-files.b0.upaiyun.com/user/normal_avatar/4988.jpg"; 25 | // }; 26 | // small = { 27 | // url = "https://ruby-china-files.b0.upaiyun.com/user/small_avatar/4988.jpg"; 28 | // }; 29 | // url = "https://ruby-china-files.b0.upaiyun.com/user/avatar/4988.jpg"; 30 | // }; 31 | // email = "jimneylee@gmail.com"; 32 | // login = jimneylee; 33 | // "private_token" = "8a67b1e1042c8093f709:4988"; 34 | //} 35 | @implementation RCAccountEntity 36 | 37 | /////////////////////////////////////////////////////////////////////////////////////////////////// 38 | - (id)initWithDictionary:(NSDictionary*)dic 39 | { 40 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 41 | return nil; 42 | } 43 | 44 | self = [super initWithDictionary:dic]; 45 | if (self) { 46 | self.loginId = dic[JSON_LOGIN]; 47 | self.privateToken = dic[JSON_PRIVATE_TOKEN]; 48 | } 49 | return self; 50 | } 51 | 52 | /////////////////////////////////////////////////////////////////////////////////////////////////// 53 | + (id)entityWithDictionary:(NSDictionary*)dic 54 | { 55 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 56 | return nil; 57 | } 58 | 59 | RCAccountEntity* entity = [[RCAccountEntity alloc] initWithDictionary:dic]; 60 | return entity; 61 | } 62 | 63 | /////////////////////////////////////////////////////////////////////////////////////////////////// 64 | /////////////////////////////////////////////////////////////////////////////////////////////////// 65 | #pragma mark - Load & Delete logined user 66 | 67 | /////////////////////////////////////////////////////////////////////////////////////////////////// 68 | + (RCAccountEntity*)loadStoredUserAccount 69 | { 70 | NSString* loginId = [RCAccountEntity readLoginId]; 71 | NSString* privateToken = [RCAccountEntity readPrivateToken]; 72 | if (loginId && privateToken) { 73 | RCAccountEntity* user = [[RCAccountEntity alloc] init]; 74 | user.loginId = loginId; 75 | user.privateToken = privateToken; 76 | return user; 77 | } 78 | return nil; 79 | } 80 | 81 | /////////////////////////////////////////////////////////////////////////////////////////////////// 82 | + (void)deleteLoginedUserDiskData 83 | { 84 | [RCAccountEntity deletePrivateToken]; 85 | [RCAccountEntity deleteLoginId]; 86 | } 87 | 88 | /////////////////////////////////////////////////////////////////////////////////////////////////// 89 | /////////////////////////////////////////////////////////////////////////////////////////////////// 90 | #pragma mark - Store & Read login id 91 | /////////////////////////////////////////////////////////////////////////////////////////////////// 92 | /////////////////////////////////////////////////////////////////////////////////////////////////// 93 | + (void)storeLoginId:(NSString*)loginId 94 | { 95 | [[NSUserDefaults standardUserDefaults] setObject:loginId forKey:kLoginId]; 96 | [[NSUserDefaults standardUserDefaults] synchronize]; 97 | } 98 | 99 | /////////////////////////////////////////////////////////////////////////////////////////////////// 100 | + (NSString*)readLoginId 101 | { 102 | NSString* LoginedLoginId = [[NSUserDefaults standardUserDefaults] objectForKey:kLoginId]; 103 | return LoginedLoginId; 104 | } 105 | 106 | /////////////////////////////////////////////////////////////////////////////////////////////////// 107 | + (void)deleteLoginId 108 | { 109 | [[NSUserDefaults standardUserDefaults] setObject:nil forKey:kLoginId]; 110 | [[NSUserDefaults standardUserDefaults] synchronize]; 111 | } 112 | 113 | /////////////////////////////////////////////////////////////////////////////////////////////////// 114 | /////////////////////////////////////////////////////////////////////////////////////////////////// 115 | #pragma mark - Store & Read private token 116 | 117 | /////////////////////////////////////////////////////////////////////////////////////////////////// 118 | + (void)storePrivateToken:(NSString*)privateToken forLoginId:(NSString*)loginId 119 | { 120 | NSError *error = nil; 121 | BOOL success = [SSKeychain setPassword:privateToken 122 | forService:kRubyChinaService 123 | account:loginId error:&error]; 124 | if (!success || error) { 125 | NSLog(@"can NOT store account"); 126 | } 127 | else { 128 | [RCAccountEntity storeLoginId:loginId]; 129 | } 130 | } 131 | 132 | /////////////////////////////////////////////////////////////////////////////////////////////////// 133 | + (NSString*)readPrivateToken 134 | { 135 | NSString* LoginedLoginId = [RCAccountEntity readLoginId]; 136 | NSString* password = [SSKeychain passwordForService:kRubyChinaService 137 | account:LoginedLoginId]; 138 | return password; 139 | } 140 | 141 | /////////////////////////////////////////////////////////////////////////////////////////////////// 142 | + (void)deletePrivateToken 143 | { 144 | NSString* LoginedLoginId = [RCAccountEntity readLoginId]; 145 | [SSKeychain deletePasswordForService:kRubyChinaService account:LoginedLoginId]; 146 | } 147 | 148 | @end 149 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCKeywordEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCKeywordsEntity.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCKeywordEntity : NSObject 12 | @property (nonatomic, copy) NSString* keyword; 13 | @property (nonatomic, assign) NSRange range; 14 | @end 15 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCKeywordEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCKeywordsEntity.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCKeywordEntity.h" 10 | 11 | @implementation RCKeywordEntity 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCNodeEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCNodeEntity.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusEntity.h" 10 | //{ 11 | // "id": 1, 12 | // "name": "Ruby", 13 | // "topics_count": 1288, 14 | // "summary": "Ruby 鏄竴闂ㄤ紭缇庣殑璇█", 15 | // "section_id": 1, 16 | // "sort": 0, 17 | // "section_name": "Ruby" 18 | //}, 19 | @interface RCNodeEntity : JLNimbusEntity 20 | @property (nonatomic, assign) NSUInteger nodeId; 21 | @property (nonatomic, copy) NSString* nodeName; 22 | @property (nonatomic, copy) NSString* summary; 23 | @property (nonatomic, assign) unsigned long topicsCount; 24 | @property (nonatomic, assign) NSUInteger sectionId; 25 | @property (nonatomic, copy) NSString* sectionName; 26 | @end 27 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCNodeEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCNodeEntity.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCNodeEntity.h" 10 | #import "NSString+stringFromValue.h" 11 | 12 | @implementation RCNodeEntity 13 | 14 | /////////////////////////////////////////////////////////////////////////////////////////////////// 15 | - (id)initWithDictionary:(NSDictionary*)dic 16 | { 17 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 18 | return nil; 19 | } 20 | 21 | self = [super initWithDictionary:dic]; 22 | if (self) { 23 | self.nodeId = [dic[JSON_ID] unsignedIntegerValue]; 24 | 25 | if (ForumBaseAPIType_RubyChina == FORUM_BASE_API_TYPE) { 26 | self.nodeName = dic[JSON_NAME]; 27 | self.topicsCount = [dic[JSON_TOPICS_COUNT] longValue]; 28 | self.summary = dic[JSON_SUMMARY]; 29 | self.sectionId = [dic[JSON_SECTION_ID] unsignedIntegerValue]; 30 | self.sectionName = dic[JSON_SECTION_NAME]; 31 | } 32 | else { 33 | self.nodeName = dic[JSON_TITLE]; 34 | self.topicsCount = [dic[JSON_TOPICS] longValue]; 35 | self.summary = [NSString stringFromValue:dic[JSON_HEADER]]; 36 | // TODO: API need add 37 | self.sectionId = 1; 38 | self.sectionName = @"全部暂未分组"; 39 | //self.sectionId = [dic[JSON_SECTION_ID] unsignedIntegerValue]; 40 | //self.sectionName = dic[JSON_SECTION_NAME]; 41 | } 42 | } 43 | return self; 44 | } 45 | 46 | /////////////////////////////////////////////////////////////////////////////////////////////////// 47 | + (id)entityWithDictionary:(NSDictionary*)dic 48 | { 49 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 50 | return nil; 51 | } 52 | 53 | RCNodeEntity* entity = [[RCNodeEntity alloc] initWithDictionary:dic]; 54 | return entity; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCNodeSectionEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCNodeSectionEntity.h 3 | // JLRubyChina 4 | // 5 | // Created by Ken_lu on 12/26/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusEntity.h" 10 | 11 | @interface RCNodeSectionEntity : JLNimbusEntity 12 | 13 | @property (nonatomic, assign) NSUInteger sectionId; 14 | @property (nonatomic, copy) NSString* name; 15 | @property (nonatomic, strong) NSMutableArray* nodesArray; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCNodeSectionEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCNodeSectionEntity.m 3 | // JLRubyChina 4 | // 5 | // Created by Ken_lu on 12/26/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCNodeSectionEntity.h" 10 | #import "RCNodeEntity.h" 11 | 12 | @implementation RCNodeSectionEntity 13 | 14 | - (id)init 15 | { 16 | self = [super init]; 17 | if (self) { 18 | 19 | } 20 | return self; 21 | } 22 | @end 23 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCReplyEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCReplyEntity.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusEntity.h" 10 | #import "RCUserEntity.h" 11 | 12 | @interface RCReplyEntity : JLNimbusEntity 13 | 14 | @property (nonatomic, strong) RCUserEntity* user; 15 | @property (nonatomic, copy) NSString* replyId; 16 | @property (nonatomic, copy) NSString* body; 17 | @property (nonatomic, strong) NSDate* createdAtDate; 18 | @property (nonatomic, strong) NSDate* updatedAtDate; 19 | @property (nonatomic, assign) NSUInteger floorNumber; 20 | @property (nonatomic, copy) NSString* floorNumberString; 21 | @property (nonatomic, strong) NSArray* atPersonRanges; 22 | @property (nonatomic, strong) NSArray* sharpFloorRanges; 23 | @property (nonatomic, strong) NSArray* emotionRanges; 24 | @property (nonatomic, strong) NSArray* imageUrlsArray; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCReplyEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCReplyEntity.m 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCReplyEntity.h" 10 | #import "NSDate+RubyChina.h" 11 | #import "RCRegularParser.h" 12 | #import "NSString+Emojize.h" 13 | 14 | @implementation RCReplyEntity 15 | 16 | /////////////////////////////////////////////////////////////////////////////////////////////////// 17 | - (id)initWithDictionary:(NSDictionary*)dic 18 | { 19 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 20 | return nil; 21 | } 22 | 23 | self = [super initWithDictionary:dic]; 24 | if (self) { 25 | if (ForumBaseAPIType_RubyChina == FORUM_BASE_API_TYPE) { 26 | self.replyId = dic[JSON_ID]; 27 | self.body = dic[JSON_BODY]; 28 | self.createdAtDate = [NSDate dateFromSourceDateString:dic[JSON_CREATEED_AT]]; 29 | self.updatedAtDate = [NSDate dateFromSourceDateString:dic[JSON_UPDATEED_AT]]; 30 | self.user = [RCUserEntity entityWithDictionary:dic[JSON_USER]]; 31 | 32 | [self parseAllKeywords]; 33 | } 34 | else { 35 | self.replyId = dic[JSON_ID]; 36 | self.body = dic[JSON_CONTENT]; 37 | NSString* createTimestamp = dic[JSON_CREATED]; 38 | if (createTimestamp) { 39 | self.createdAtDate = [NSDate dateWithTimeIntervalSince1970:[createTimestamp doubleValue]]; 40 | } 41 | self.user = [RCUserEntity entityWithDictionary:dic[JSON_MEMBER]]; 42 | 43 | [self parseAllKeywords]; 44 | } 45 | } 46 | return self; 47 | } 48 | 49 | /////////////////////////////////////////////////////////////////////////////////////////////////// 50 | + (id)entityWithDictionary:(NSDictionary*)dic 51 | { 52 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 53 | return nil; 54 | } 55 | 56 | RCReplyEntity* entity = [[RCReplyEntity alloc] initWithDictionary:dic]; 57 | return entity; 58 | } 59 | 60 | /////////////////////////////////////////////////////////////////////////////////////////////////// 61 | // 识别出 表情 at某人 share话题 标签 62 | - (void)parseAllKeywords 63 | { 64 | if (self.body.length) { 65 | // parse emotion first 66 | self.body = [self.body emojizedString]; 67 | 68 | NSString* trimedString = self.body; 69 | self.imageUrlsArray = [RCRegularParser imageUrlsInString:self.body trimedString:&trimedString]; 70 | self.body = trimedString; 71 | 72 | if (!self.atPersonRanges) { 73 | self.atPersonRanges = [RCRegularParser keywordRangesOfAtPersonInString:self.body]; 74 | } 75 | if (!self.sharpFloorRanges) { 76 | self.sharpFloorRanges = [RCRegularParser keywordRangesOfSharpFloorInString:self.body]; 77 | } 78 | } 79 | } 80 | 81 | /////////////////////////////////////////////////////////////////////////////////////////////////// 82 | - (NSString*)floorNumberString 83 | { 84 | if (!_floorNumberString.length) { 85 | NSString* louString = nil; 86 | switch (_floorNumber) { 87 | case 1: 88 | louString = @"沙发"; 89 | break; 90 | case 2: 91 | louString = @"板凳"; 92 | break; 93 | case 3: 94 | louString = @"地板"; 95 | break; 96 | default: 97 | louString = [NSString stringWithFormat:@"%u楼", _floorNumber]; 98 | } 99 | _floorNumberString = [louString copy]; 100 | } 101 | return _floorNumberString; 102 | } 103 | 104 | /////////////////////////////////////////////////////////////////////////////////////////////////// 105 | // inline sort by reply id, remove it when api return sorted array 106 | - (NSComparisonResult)compare:(RCReplyEntity*)other 107 | { 108 | return [self.replyId compare:other.replyId]; 109 | } 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCSiteEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCSiteEntity.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-12. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusEntity.h" 10 | 11 | @interface RCSiteEntity : JLNimbusEntity 12 | @property (nonatomic, copy) NSString* name; 13 | @property (nonatomic, copy) NSString* url; 14 | @property (nonatomic, copy) NSString* iconUrl; 15 | @property (nonatomic, copy) NSString* description; 16 | @end 17 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCSiteEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCSiteEntity.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-12. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCSiteEntity.h" 10 | 11 | @implementation RCSiteEntity 12 | 13 | /////////////////////////////////////////////////////////////////////////////////////////////////// 14 | - (id)initWithDictionary:(NSDictionary*)dic 15 | { 16 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 17 | return nil; 18 | } 19 | 20 | self = [super initWithDictionary:dic]; 21 | if (self) { 22 | self.name = dic[JSON_NAME]; 23 | self.url = dic[JSON_URL]; 24 | self.iconUrl = dic[JSON_FAV_ICON]; 25 | self.description = dic[JSON_DESCRIPTION]; 26 | } 27 | return self; 28 | } 29 | 30 | /////////////////////////////////////////////////////////////////////////////////////////////////// 31 | + (id)entityWithDictionary:(NSDictionary*)dic 32 | { 33 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 34 | return nil; 35 | } 36 | 37 | RCSiteEntity* entity = [[RCSiteEntity alloc] initWithDictionary:dic]; 38 | return entity; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCSiteSectionEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCSiteSectionEntity.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-12. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusEntity.h" 10 | 11 | @interface RCSiteSectionEntity : JLNimbusEntity 12 | @property (nonatomic, assign) NSUInteger sectionId; 13 | @property (nonatomic, copy) NSString* name; 14 | @property (nonatomic, strong) NSArray* sitesArray; 15 | @end 16 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCSiteSectionEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCSiteSectionEntity.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-12. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCSiteSectionEntity.h" 10 | #import "RCSiteEntity.h" 11 | 12 | @implementation RCSiteSectionEntity 13 | 14 | /////////////////////////////////////////////////////////////////////////////////////////////////// 15 | - (id)initWithDictionary:(NSDictionary*)dic 16 | { 17 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 18 | return nil; 19 | } 20 | 21 | self = [super initWithDictionary:dic]; 22 | if (self) { 23 | self.sectionId = [dic[JSON_SITE_SECTION_ID] unsignedIntegerValue]; 24 | self.name = dic[JSON_NAME]; 25 | NSArray* sourceSitesArray = dic[JSON_SITES_LIST]; 26 | if (sourceSitesArray.count) { 27 | NSMutableArray* sitesArray = [NSMutableArray arrayWithCapacity:sourceSitesArray.count]; 28 | RCSiteEntity* s = nil; 29 | for (NSDictionary* dic in sourceSitesArray) { 30 | s = [RCSiteEntity entityWithDictionary:dic]; 31 | [sitesArray addObject:s]; 32 | } 33 | self.sitesArray = sitesArray; 34 | } 35 | } 36 | return self; 37 | } 38 | 39 | /////////////////////////////////////////////////////////////////////////////////////////////////// 40 | + (id)entityWithDictionary:(NSDictionary*)dic 41 | { 42 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 43 | return nil; 44 | } 45 | 46 | RCSiteSectionEntity* entity = [[RCSiteSectionEntity alloc] initWithDictionary:dic]; 47 | return entity; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCTopicDetailEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicDetailEntity.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCTopicEntity.h" 10 | 11 | @interface RCTopicDetailEntity : RCTopicEntity 12 | 13 | @property (nonatomic, assign) unsigned long hitsCount; 14 | @property (nonatomic, copy) NSString* body; 15 | @property (nonatomic, copy) NSString* bodyHTML; 16 | @property (nonatomic, copy) NSAttributedString* attributedBody; 17 | @property (nonatomic, strong) NSArray* atPersonRanges; 18 | @property (nonatomic, strong) NSArray* sharpFloorRanges; 19 | @property (nonatomic, strong) NSArray* emotionRanges; 20 | @property (nonatomic, strong) NSArray* imageUrlsArray; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCTopicDetailEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicDetailEntity.m 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCTopicDetailEntity.h" 10 | #import "RCRegularParser.h" 11 | #import "NSString+Emojize.h" 12 | 13 | #define CONTENT_FONT_SIZE [UIFont fontWithName:@"STHeitiSC-Light" size:18.f] 14 | 15 | @implementation RCTopicDetailEntity 16 | 17 | /////////////////////////////////////////////////////////////////////////////////////////////////// 18 | - (id)initWithDictionary:(NSDictionary*)dic 19 | { 20 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 21 | return nil; 22 | } 23 | 24 | self = [super initWithDictionary:dic]; 25 | if (self) { 26 | if (ForumBaseAPIType_RubyChina == FORUM_BASE_API_TYPE) { 27 | self.body = dic[JSON_BODY]; 28 | 29 | // 需要注意的是第一行需要指明编码格式 否则的话 中文会显示乱码 30 | // http://hufeng825.github.io/2014/01/21/ios37/ 31 | self.bodyHTML = [NSString stringWithFormat:@"%@", dic[JSON_BODY_HTML]]; 32 | self.hitsCount = [dic[JSON_HITS_COUNT] unsignedLongValue]; 33 | // [self parseAllKeywords]; 34 | 35 | // learn from here http://initwithfunk.com/blog/2013/09/29/easy-markdown-rendering-with-nsattributedstring-on-ios-7/ 36 | NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}; 37 | 38 | NSMutableAttributedString *mAttributedString = [[NSMutableAttributedString alloc] initWithData:[self.bodyHTML dataUsingEncoding:NSUTF8StringEncoding] 39 | options:options documentAttributes:nil error:nil]; 40 | // set line height 41 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy]; 42 | NSDictionary *defaultAttributes = @{NSFontAttributeName : CONTENT_FONT_SIZE}; 43 | 44 | paragraphStyle.minimumLineHeight = 21.f; 45 | [mAttributedString addAttribute:NSParagraphStyleAttributeName 46 | value:paragraphStyle 47 | range:NSMakeRange(0, mAttributedString.length)]; 48 | [mAttributedString addAttributes:defaultAttributes 49 | range:NSMakeRange(0, mAttributedString.length)]; 50 | self.attributedBody = mAttributedString; 51 | } 52 | else { 53 | self.body = dic[JSON_CONTENT]; 54 | self.attributedBody = [[NSAttributedString alloc] initWithString:self.body]; 55 | [self parseAllKeywords]; 56 | } 57 | } 58 | return self; 59 | } 60 | 61 | /////////////////////////////////////////////////////////////////////////////////////////////////// 62 | + (id)entityWithDictionary:(NSDictionary*)dic 63 | { 64 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 65 | return nil; 66 | } 67 | 68 | RCTopicDetailEntity* entity = [[RCTopicDetailEntity alloc] initWithDictionary:dic]; 69 | return entity; 70 | } 71 | 72 | /////////////////////////////////////////////////////////////////////////////////////////////////// 73 | // 识别出 表情 at某人 share话题 标签 74 | - (void)parseAllKeywords 75 | { 76 | if (self.body.length) { 77 | // parse emotion first 78 | self.body = [self.body emojizedString]; 79 | 80 | NSString* trimedString = self.body; 81 | self.imageUrlsArray = [RCRegularParser imageUrlsInString:self.body trimedString:&trimedString]; 82 | self.body = trimedString; 83 | 84 | if (!self.atPersonRanges) { 85 | self.atPersonRanges = [RCRegularParser keywordRangesOfAtPersonInString:self.body]; 86 | } 87 | if (!self.sharpFloorRanges) { 88 | self.sharpFloorRanges = [RCRegularParser keywordRangesOfSharpFloorInString:self.body]; 89 | } 90 | } 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCTopicEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicEntity.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusEntity.h" 10 | #import "RCUserEntity.h" 11 | 12 | @interface RCTopicEntity : JLNimbusEntity 13 | 14 | @property (nonatomic, strong) RCUserEntity* user; 15 | @property (nonatomic, assign) unsigned long topicId; 16 | @property (nonatomic, copy) NSString* topicTitle; 17 | @property (nonatomic, assign) NSUInteger nodeId; 18 | @property (nonatomic, copy) NSString* nodeName; 19 | @property (nonatomic, strong) NSDate* createdAtDate; 20 | @property (nonatomic, strong) NSDate* updatedAtDate; 21 | @property (nonatomic, strong) NSDate* repliedAtDate; 22 | @property (nonatomic, assign) unsigned long repliesCount; 23 | @property (nonatomic, strong) RCUserEntity* lastRepliedUser; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCTopicEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicEntity.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCTopicEntity.h" 10 | #import "NSDate+RubyChina.h" 11 | #import "RCNodeEntity.h" 12 | 13 | @implementation RCTopicEntity 14 | 15 | /////////////////////////////////////////////////////////////////////////////////////////////////// 16 | - (id)initWithDictionary:(NSDictionary*)dic 17 | { 18 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 19 | return nil; 20 | } 21 | 22 | self = [super initWithDictionary:dic]; 23 | if (self) { 24 | 25 | self.topicId = [dic[JSON_ID] unsignedLongValue]; 26 | self.topicTitle = dic[JSON_TITLE]; 27 | 28 | if (ForumBaseAPIType_RubyChina == FORUM_BASE_API_TYPE) { 29 | self.nodeId = [dic[JSON_NODE_ID] unsignedIntegerValue]; 30 | self.nodeName = dic[JSON_NODE_NAME]; 31 | self.createdAtDate = [NSDate dateFromSourceDateString:dic[JSON_CREATEED_AT]]; 32 | self.updatedAtDate = [NSDate dateFromSourceDateString:dic[JSON_UPDATEED_AT]]; 33 | self.repliedAtDate = [NSDate dateFromSourceDateString:dic[JSON_REPLIED_AT]]; 34 | self.repliesCount = [dic[JSON_REPLIES_COUNT] unsignedLongValue]; 35 | self.user = [RCUserEntity entityWithDictionary:dic[JSON_USER]]; 36 | 37 | NSString* lastRepliedUserLoginId = dic[JSON_LAST_REPLY_USER_LOGIN]; 38 | if (lastRepliedUserLoginId && [lastRepliedUserLoginId isKindOfClass:[NSString class]] && lastRepliedUserLoginId.length) { 39 | self.lastRepliedUser = [[RCUserEntity alloc] init]; 40 | self.lastRepliedUser.hashId = [dic[JSON_LAST_REPLY_USER_ID] unsignedLongValue]; 41 | self.lastRepliedUser.loginId = lastRepliedUserLoginId; 42 | } 43 | } 44 | else { 45 | RCNodeEntity* node = [RCNodeEntity entityWithDictionary:dic[JSON_NODE]]; 46 | self.nodeId = node.nodeId; 47 | self.nodeName = node.nodeName; 48 | NSString* createTimestamp = dic[JSON_CREATED]; 49 | if (createTimestamp) { 50 | self.createdAtDate = [NSDate dateWithTimeIntervalSince1970:[createTimestamp doubleValue]]; 51 | } 52 | self.repliesCount = [dic[JSON_REPLIES] unsignedLongValue]; 53 | self.user = [RCUserEntity entityWithDictionary:dic[JSON_MEMBER]]; 54 | 55 | //TODO: for v2ex no replied user info 56 | } 57 | } 58 | return self; 59 | } 60 | 61 | /////////////////////////////////////////////////////////////////////////////////////////////////// 62 | + (id)entityWithDictionary:(NSDictionary*)dic 63 | { 64 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 65 | return nil; 66 | } 67 | 68 | RCTopicEntity* entity = [[RCTopicEntity alloc] initWithDictionary:dic]; 69 | return entity; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCUserEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCUserEntity.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusEntity.h" 10 | 11 | @interface RCUserEntity : JLNimbusEntity 12 | @property (nonatomic, assign) unsigned long hashId;//注册后,服务器后台自动分配的hash值 13 | @property (nonatomic, copy) NSString* loginId;// 用户注册时,用户自己输入的ID号,api接口均使用这个id 14 | @property (nonatomic, copy) NSString* avatarUrl; 15 | @end 16 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCUserEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCUserEntity.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCUserEntity.h" 10 | 11 | //"user": 12 | //{ 13 | //"id": 2596, 14 | //"login": "fengzhilian818", 15 | //"avatar_url": "http://ruby-china.org/avatar/e351cfb6c0fa7e761e5287952f292a16.png?s=120" 16 | //} 17 | @implementation RCUserEntity 18 | 19 | /////////////////////////////////////////////////////////////////////////////////////////////////// 20 | - (id)initWithDictionary:(NSDictionary*)dic 21 | { 22 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 23 | return nil; 24 | } 25 | 26 | self = [super initWithDictionary:dic]; 27 | if (self) { 28 | if (ForumBaseAPIType_RubyChina == FORUM_BASE_API_TYPE) { 29 | self.hashId = [dic[JSON_ID] unsignedLongValue]; 30 | self.loginId = dic[JSON_LOGIN]; 31 | self.avatarUrl = dic[JSON_AVATAR_URL]; 32 | 33 | if (![self.avatarUrl hasPrefix:@"http"]) { 34 | self.avatarUrl = [NSString stringWithFormat:@"%@%@", HOST_URL, self.avatarUrl]; 35 | } 36 | } 37 | else { 38 | self.hashId = [dic[JSON_ID] unsignedLongValue]; 39 | self.loginId = dic[JSON_USERNAME]; 40 | self.avatarUrl = dic[JSON_AVATAR_MINI]; 41 | } 42 | } 43 | return self; 44 | } 45 | 46 | /////////////////////////////////////////////////////////////////////////////////////////////////// 47 | + (id)entityWithDictionary:(NSDictionary*)dic 48 | { 49 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 50 | return nil; 51 | } 52 | 53 | RCUserEntity* entity = [[RCUserEntity alloc] initWithDictionary:dic]; 54 | return entity; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCUserFullEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCUserEntity.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCUserEntity.h" 10 | 11 | @interface RCUserFullEntity : RCUserEntity 12 | @property (nonatomic, copy) NSString* name; 13 | @property (nonatomic, copy) NSString* location; 14 | @property (nonatomic, copy) NSString* company; 15 | @property (nonatomic, copy) NSString* twitter; 16 | @property (nonatomic, copy) NSString* website; 17 | @property (nonatomic, copy) NSString* introduce; 18 | @property (nonatomic, copy) NSString* tagline; 19 | @property (nonatomic, copy) NSString* githubUrl; 20 | @property (nonatomic, copy) NSString* email; 21 | @end 22 | -------------------------------------------------------------------------------- /JLRubyChina/Entities/RCUserFullEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCUserEntity.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCUserFullEntity.h" 10 | #import "NSString+stringFromValue.h" 11 | 12 | //"user": 13 | //"location": "鍖椾含", 14 | //"company": "", 15 | //"twitter": "chloerei", 16 | //"website": "http://chloerei.com", 17 | //"bio": "Twitter @chloerei\r\n\r\n鎴戝啓浜嗚繖浜涚綉绔欙細\r\n\r\nhttp://writings.io\r\nhttp://codecampo.com ", 18 | //"tagline": "涓笅姘村钩 Rails 绋嬪簭鍛�", 19 | //"github_url": "https://github.com/chloerei", 20 | //"email": "chloerei@gmail.com", 21 | //"gravatar_hash": "5aec84cd0b5479a0d1d89b6ffa2a9a20", 22 | //"avatar_url": "http://ruby-china.org/avatar/5aec84cd0b5479a0d1d89b6ffa2a9a20.png?s=120", 23 | @implementation RCUserFullEntity 24 | 25 | /////////////////////////////////////////////////////////////////////////////////////////////////// 26 | - (id)initWithDictionary:(NSDictionary*)dic 27 | { 28 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 29 | return nil; 30 | } 31 | 32 | self = [super initWithDictionary:dic]; 33 | if (self) { 34 | self.name = [NSString stringFromValue:dic[@"name"]]; 35 | self.location = [NSString stringFromValue:dic[@"location"]]; 36 | self.company = [NSString stringFromValue:dic[@"company"]]; 37 | self.twitter = [NSString stringFromValue:dic[@"twitter"]]; 38 | self.website = [NSString stringFromValue:dic[@"website"]]; 39 | self.introduce = [NSString stringFromValue:dic[@"bio"]]; 40 | self.tagline = [NSString stringFromValue:dic[@"tagline"]]; 41 | self.githubUrl = [NSString stringFromValue:dic[@"github_url"]]; 42 | self.email = [NSString stringFromValue:dic[@"email"]]; 43 | } 44 | return self; 45 | } 46 | 47 | /////////////////////////////////////////////////////////////////////////////////////////////////// 48 | + (id)entityWithDictionary:(NSDictionary*)dic 49 | { 50 | if (!dic || ![dic isKindOfClass:[NSDictionary class]]) { 51 | return nil; 52 | } 53 | 54 | RCUserFullEntity* entity = [[RCUserFullEntity alloc] initWithDictionary:dic]; 55 | return entity; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /JLRubyChina/JLRubyChina-Dis-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | APP_STORE_ID 6 | 789643801 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleDisplayName 10 | Ruby China 11 | CFBundleExecutable 12 | ${EXECUTABLE_NAME} 13 | CFBundleIcons 14 | 15 | CFBundlePrimaryIcon 16 | 17 | CFBundleIconFiles 18 | 19 | icon 20 | icon58 21 | icon80 22 | icon120 23 | 24 | 25 | 26 | CFBundleIdentifier 27 | cn.rafood.rubychina 28 | CFBundleInfoDictionaryVersion 29 | 6.0 30 | CFBundleName 31 | ${PRODUCT_NAME} 32 | CFBundlePackageType 33 | APPL 34 | CFBundleShortVersionString 35 | 1.3 36 | CFBundleSignature 37 | ???? 38 | CFBundleVersion 39 | 1.3 40 | HOST_API_URL 41 | https://ruby-china.org/api/v2/ 42 | HOST_BASE_API_TYPE 43 | rubychina 44 | HOST_INTRO 45 | Ruby China,对!没错!这里就是 Ruby 社区,目前这里已经是国内最权威的 Ruby 社区,拥有国内所有资深的 Ruby 工程师。 46 | HOST_URL 47 | https://ruby-china.org 48 | LSRequiresIPhoneOS 49 | 50 | UILaunchImages 51 | 52 | 53 | UILaunchImageMinimumOSVersion 54 | 7.0 55 | UILaunchImageName 56 | Default 57 | UILaunchImageOrientation 58 | Portrait 59 | UILaunchImageSize 60 | {320, 568} 61 | 62 | 63 | UILaunchImageMinimumOSVersion 64 | 7.0 65 | UILaunchImageName 66 | Default-568 67 | UILaunchImageOrientation 68 | Portrait 69 | UILaunchImageSize 70 | {320, 568} 71 | 72 | 73 | UILaunchImageMinimumOSVersion 74 | 7.0 75 | UILaunchImageName 76 | Default-568 77 | UILaunchImageOrientation 78 | Portrait 79 | UILaunchImageSize 80 | {320, 568} 81 | 82 | 83 | UILaunchImageMinimumOSVersion 84 | 7.0 85 | UILaunchImageName 86 | Default-568 87 | UILaunchImageOrientation 88 | Portrait 89 | UILaunchImageSize 90 | {320, 568} 91 | 92 | 93 | UILaunchImageMinimumOSVersion 94 | 7.0 95 | UILaunchImageName 96 | Default 97 | UILaunchImageOrientation 98 | Portrait 99 | UILaunchImageSize 100 | {320, 480} 101 | 102 | 103 | UILaunchImageMinimumOSVersion 104 | 7.0 105 | UILaunchImageName 106 | Default-568 107 | UILaunchImageOrientation 108 | Portrait 109 | UILaunchImageSize 110 | {320, 568} 111 | 112 | 113 | UIRequiredDeviceCapabilities 114 | 115 | armv7 116 | 117 | UISupportedInterfaceOrientations 118 | 119 | UIInterfaceOrientationPortrait 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /JLRubyChina/JLRubyChina-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | APP_STORE_ID 6 | 789643801 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleDisplayName 10 | Ruby China 11 | CFBundleExecutable 12 | ${EXECUTABLE_NAME} 13 | CFBundleIcons 14 | 15 | CFBundlePrimaryIcon 16 | 17 | CFBundleIconFiles 18 | 19 | icon 20 | icon58 21 | icon80 22 | icon120 23 | 24 | 25 | 26 | CFBundleIdentifier 27 | cn.rafood.rubychina 28 | CFBundleInfoDictionaryVersion 29 | 6.0 30 | CFBundleName 31 | ${PRODUCT_NAME} 32 | CFBundlePackageType 33 | APPL 34 | CFBundleShortVersionString 35 | 1.3 36 | CFBundleSignature 37 | ???? 38 | CFBundleVersion 39 | 1.3 40 | HOST_API_URL 41 | https://ruby-china.org/api/v2/ 42 | HOST_BASE_API_TYPE 43 | rubychina 44 | HOST_INTRO 45 | Ruby China,对!没错!这里就是 Ruby 社区,目前这里已经是国内最权威的 Ruby 社区,拥有国内所有资深的 Ruby 工程师。 46 | HOST_URL 47 | https://ruby-china.org 48 | LSRequiresIPhoneOS 49 | 50 | UILaunchImages 51 | 52 | 53 | UILaunchImageMinimumOSVersion 54 | 7.0 55 | UILaunchImageName 56 | Default 57 | UILaunchImageOrientation 58 | Portrait 59 | UILaunchImageSize 60 | {320, 568} 61 | 62 | 63 | UILaunchImageMinimumOSVersion 64 | 7.0 65 | UILaunchImageName 66 | Default-568 67 | UILaunchImageOrientation 68 | Portrait 69 | UILaunchImageSize 70 | {320, 568} 71 | 72 | 73 | UILaunchImageMinimumOSVersion 74 | 7.0 75 | UILaunchImageName 76 | Default-568 77 | UILaunchImageOrientation 78 | Portrait 79 | UILaunchImageSize 80 | {320, 568} 81 | 82 | 83 | UILaunchImageMinimumOSVersion 84 | 7.0 85 | UILaunchImageName 86 | Default-568 87 | UILaunchImageOrientation 88 | Portrait 89 | UILaunchImageSize 90 | {320, 568} 91 | 92 | 93 | UILaunchImageMinimumOSVersion 94 | 7.0 95 | UILaunchImageName 96 | Default 97 | UILaunchImageOrientation 98 | Portrait 99 | UILaunchImageSize 100 | {320, 480} 101 | 102 | 103 | UILaunchImageMinimumOSVersion 104 | 7.0 105 | UILaunchImageName 106 | Default-568 107 | UILaunchImageOrientation 108 | Portrait 109 | UILaunchImageSize 110 | {320, 568} 111 | 112 | 113 | UIRequiredDeviceCapabilities 114 | 115 | armv7 116 | 117 | UISupportedInterfaceOrientations 118 | 119 | UIInterfaceOrientationPortrait 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /JLRubyChina/JLRubyChina-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | 17 | // Nimbus addtional header 18 | #import "NimbusPagingScrollView.h" 19 | 20 | #import "JLNimbusTimeline.h" 21 | #import "TTCategoryHeader.h" 22 | #import "MBProgressHUD.h" 23 | 24 | #import "RCJSONKeys.h" 25 | #import "RCGlobalConfig.h" 26 | #import "MacroDefines.h" 27 | #import "UIImage+nimbusImageNamed.h" 28 | 29 | #endif 30 | 31 | // debug log switch 32 | #ifdef DEBUG 33 | # define NSLog(...) NSLog(__VA_ARGS__) 34 | #else 35 | # define NSLog(...) {} 36 | #endif 37 | -------------------------------------------------------------------------------- /JLRubyChina/JLTesterHome-Dis-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | APP_STORE_ID 6 | 803942891 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleDisplayName 10 | Tester Home 11 | CFBundleExecutable 12 | ${EXECUTABLE_NAME} 13 | CFBundleIcons 14 | 15 | CFBundlePrimaryIcon 16 | 17 | CFBundleIconFiles 18 | 19 | icon 20 | icon58 21 | icon80 22 | icon120 23 | 24 | 25 | 26 | CFBundleIdentifier 27 | com.toyaca.testerhome 28 | CFBundleInfoDictionaryVersion 29 | 6.0 30 | CFBundleName 31 | ${PRODUCT_NAME} 32 | CFBundlePackageType 33 | APPL 34 | CFBundleShortVersionString 35 | 1.0 36 | CFBundleSignature 37 | ???? 38 | CFBundleVersion 39 | 1.0 40 | LSRequiresIPhoneOS 41 | 42 | UILaunchImages 43 | 44 | 45 | UILaunchImageMinimumOSVersion 46 | 7.0 47 | UILaunchImageName 48 | Default 49 | UILaunchImageOrientation 50 | Portrait 51 | UILaunchImageSize 52 | {320, 568} 53 | 54 | 55 | UILaunchImageMinimumOSVersion 56 | 7.0 57 | UILaunchImageName 58 | Default-568 59 | UILaunchImageOrientation 60 | Portrait 61 | UILaunchImageSize 62 | {320, 568} 63 | 64 | 65 | UILaunchImageMinimumOSVersion 66 | 7.0 67 | UILaunchImageName 68 | Default-568 69 | UILaunchImageOrientation 70 | Portrait 71 | UILaunchImageSize 72 | {320, 568} 73 | 74 | 75 | UILaunchImageMinimumOSVersion 76 | 7.0 77 | UILaunchImageName 78 | Default-568 79 | UILaunchImageOrientation 80 | Portrait 81 | UILaunchImageSize 82 | {320, 568} 83 | 84 | 85 | UILaunchImageMinimumOSVersion 86 | 7.0 87 | UILaunchImageName 88 | Default 89 | UILaunchImageOrientation 90 | Portrait 91 | UILaunchImageSize 92 | {320, 480} 93 | 94 | 95 | UILaunchImageMinimumOSVersion 96 | 7.0 97 | UILaunchImageName 98 | Default-568 99 | UILaunchImageOrientation 100 | Portrait 101 | UILaunchImageSize 102 | {320, 568} 103 | 104 | 105 | UIRequiredDeviceCapabilities 106 | 107 | armv7 108 | 109 | UISupportedInterfaceOrientations 110 | 111 | UIInterfaceOrientationPortrait 112 | 113 | HOST_URL 114 | http://testerhome.com 115 | HOST_API_URL 116 | http://testerhome.com/api/v2/ 117 | HOST_INTRO 118 | 国内首个移动测试交流社区,专注于Web测试,移动测试,测试产品与云测服务,一个技术驱动的组织,一个活跃而温馨的测试大家庭。 119 | HOST_BASE_API_TYPE 120 | rubychina 121 | UIViewControllerBasedStatusBarAppearance 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /JLRubyChina/JLTesterHome-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | APP_STORE_ID 6 | 803942891 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleDisplayName 10 | Tester Home 11 | CFBundleExecutable 12 | ${EXECUTABLE_NAME} 13 | CFBundleIcons 14 | 15 | CFBundlePrimaryIcon 16 | 17 | CFBundleIconFiles 18 | 19 | icon 20 | icon58 21 | icon80 22 | icon120 23 | 24 | 25 | 26 | CFBundleIdentifier 27 | com.toyaca.testerhome 28 | CFBundleInfoDictionaryVersion 29 | 6.0 30 | CFBundleName 31 | ${PRODUCT_NAME} 32 | CFBundlePackageType 33 | APPL 34 | CFBundleShortVersionString 35 | 1.0 36 | CFBundleSignature 37 | ???? 38 | CFBundleVersion 39 | 1.0 40 | LSRequiresIPhoneOS 41 | 42 | UILaunchImages 43 | 44 | 45 | UILaunchImageMinimumOSVersion 46 | 7.0 47 | UILaunchImageName 48 | Default 49 | UILaunchImageOrientation 50 | Portrait 51 | UILaunchImageSize 52 | {320, 568} 53 | 54 | 55 | UILaunchImageMinimumOSVersion 56 | 7.0 57 | UILaunchImageName 58 | Default-568 59 | UILaunchImageOrientation 60 | Portrait 61 | UILaunchImageSize 62 | {320, 568} 63 | 64 | 65 | UILaunchImageMinimumOSVersion 66 | 7.0 67 | UILaunchImageName 68 | Default-568 69 | UILaunchImageOrientation 70 | Portrait 71 | UILaunchImageSize 72 | {320, 568} 73 | 74 | 75 | UILaunchImageMinimumOSVersion 76 | 7.0 77 | UILaunchImageName 78 | Default-568 79 | UILaunchImageOrientation 80 | Portrait 81 | UILaunchImageSize 82 | {320, 568} 83 | 84 | 85 | UILaunchImageMinimumOSVersion 86 | 7.0 87 | UILaunchImageName 88 | Default 89 | UILaunchImageOrientation 90 | Portrait 91 | UILaunchImageSize 92 | {320, 480} 93 | 94 | 95 | UILaunchImageMinimumOSVersion 96 | 7.0 97 | UILaunchImageName 98 | Default-568 99 | UILaunchImageOrientation 100 | Portrait 101 | UILaunchImageSize 102 | {320, 568} 103 | 104 | 105 | UIRequiredDeviceCapabilities 106 | 107 | armv7 108 | 109 | UISupportedInterfaceOrientations 110 | 111 | UIInterfaceOrientationPortrait 112 | 113 | HOST_URL 114 | http://testerhome.com 115 | HOST_API_URL 116 | http://testerhome.com/api/v2/ 117 | HOST_INTRO 118 | 国内首个移动测试交流社区,专注于Web测试,移动测试,测试产品与云测服务,一个技术驱动的组织,一个活跃而温馨的测试大家庭。 119 | HOST_BASE_API_TYPE 120 | rubychina 121 | UIViewControllerBasedStatusBarAppearance 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /JLRubyChina/JLV2EX-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | APP_STORE_ID 6 | 1 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleDisplayName 10 | Livid V2EX 11 | CFBundleExecutable 12 | ${EXECUTABLE_NAME} 13 | CFBundleIcons 14 | 15 | CFBundlePrimaryIcon 16 | 17 | CFBundleIconFiles 18 | 19 | icon 20 | icon58 21 | icon80 22 | icon120 23 | 24 | 25 | 26 | CFBundleIdentifier 27 | cn.rafood.v2ex 28 | CFBundleInfoDictionaryVersion 29 | 6.0 30 | CFBundleName 31 | ${PRODUCT_NAME} 32 | CFBundlePackageType 33 | APPL 34 | CFBundleShortVersionString 35 | 1.0 36 | CFBundleSignature 37 | ???? 38 | CFBundleVersion 39 | 1.0 40 | LSRequiresIPhoneOS 41 | 42 | UILaunchImages 43 | 44 | 45 | UILaunchImageMinimumOSVersion 46 | 7.0 47 | UILaunchImageName 48 | Default 49 | UILaunchImageOrientation 50 | Portrait 51 | UILaunchImageSize 52 | {320, 568} 53 | 54 | 55 | UILaunchImageMinimumOSVersion 56 | 7.0 57 | UILaunchImageName 58 | Default-568 59 | UILaunchImageOrientation 60 | Portrait 61 | UILaunchImageSize 62 | {320, 568} 63 | 64 | 65 | UILaunchImageMinimumOSVersion 66 | 7.0 67 | UILaunchImageName 68 | Default-568 69 | UILaunchImageOrientation 70 | Portrait 71 | UILaunchImageSize 72 | {320, 568} 73 | 74 | 75 | UILaunchImageMinimumOSVersion 76 | 7.0 77 | UILaunchImageName 78 | Default-568 79 | UILaunchImageOrientation 80 | Portrait 81 | UILaunchImageSize 82 | {320, 568} 83 | 84 | 85 | UILaunchImageMinimumOSVersion 86 | 7.0 87 | UILaunchImageName 88 | Default 89 | UILaunchImageOrientation 90 | Portrait 91 | UILaunchImageSize 92 | {320, 480} 93 | 94 | 95 | UILaunchImageMinimumOSVersion 96 | 7.0 97 | UILaunchImageName 98 | Default-568 99 | UILaunchImageOrientation 100 | Portrait 101 | UILaunchImageSize 102 | {320, 568} 103 | 104 | 105 | UIRequiredDeviceCapabilities 106 | 107 | armv7 108 | 109 | UISupportedInterfaceOrientations 110 | 111 | UIInterfaceOrientationPortrait 112 | 113 | HOST_URL 114 | http://www.v2ex.com 115 | HOST_API_URL 116 | http://www.v2ex.com/api/ 117 | HOST_INTRO 118 | V2EX 是创意工作者们的社区。这里目前汇聚了超过 50000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。 119 | HOST_BASE_API_TYPE 120 | v2ex 121 | UIViewControllerBasedStatusBarAppearance 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /JLRubyChina/MacroDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // MacroDefines.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/16/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #ifndef JLRubyChina_MacroDefines_h 10 | #define JLRubyChina_MacroDefines_h 11 | 12 | // APP 基本信息 13 | #define APP_NAME [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"] 14 | #define APP_VERSION [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] 15 | #define APP_ID [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"APP_STORE_ID"] longValue] 16 | #define HOST_URL [[NSBundle mainBundle] objectForInfoDictionaryKey:@"HOST_URL"] 17 | //#define HOST_API_URL [NSString stringWithFormat:@"%@/api/v2", HOST_URL] 18 | #define HOST_API_URL [[NSBundle mainBundle] objectForInfoDictionaryKey:@"HOST_API_URL"] 19 | #define HOST_WIKI_URL [NSString stringWithFormat:@"%@/wiki", HOST_URL] 20 | #define HOST_INTRO [[NSBundle mainBundle] objectForInfoDictionaryKey:@"HOST_INTRO"] 21 | #define FORUM_BASE_API_TYPE [RCGlobalConfig forumBaseAPIType] 22 | 23 | // 是否是iphone5的判断 24 | #define IS_WIDESCREEN ([[UIScreen mainScreen] bounds].size.height > 500) 25 | #define IS_IPHONE ([[[UIDevice currentDevice] model] isEqualToString:@"iPhone"] \ 26 | ||[[[UIDevice currentDevice] model] isEqualToString:@"iPhone Simulator"]) 27 | #define IS_IPHONE5 (IS_IPHONE && IS_WIDESCREEN) 28 | 29 | // Cell布局 30 | #define CELL_PADDING_10 10 31 | #define CELL_PADDING_8 8 32 | #define CELL_PADDING_6 6 33 | #define CELL_PADDING_4 4 34 | #define CELL_PADDING_2 2 35 | 36 | // Color配色 37 | #define APP_THEME_COLOR RGBCOLOR(41, 41, 41) 38 | #define APP_NAME_RED_COLOR RGBCOLOR(177, 9, 0) 39 | #define APP_NAME_WHITE_COLOR RGBCOLOR(200, 200, 200) 40 | #define TABLE_VIEW_BG_COLOR RGBCOLOR(237, 234, 234) 41 | #define CELL_CONTENT_VIEW_BG_COLOR RGBCOLOR(247, 247, 247) 42 | #define CELL_CONTENT_VIEW_BORDER_COLOR RGBCOLOR(234, 234, 234) 43 | 44 | // 左侧菜单栏可视宽度比 45 | #define LEFT_GAP_PERCENTAGE 0.55f 46 | 47 | // 自定义链接协议 48 | #define PROTOCOL_AT_SOMEONE @"atsomeone://" 49 | #define PROTOCOL_SHARP_FLOOR @"sharpfloor://" 50 | #define PROTOCOL_NODE @"node://" 51 | 52 | // Notification通知 53 | #define DID_LOGIN_NOTIFICATION @"DID_LOGIN_NOTIFICATION" 54 | #define DID_LOGOUT_NOTIFICATION @"DID_LOGOUT_NOTIFICATION" 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCBaseTableModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // NITimelineTableModel.h 3 | // NimbusTimeline 4 | // 5 | // Created by Lee jimney on 7/27/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "JLNimbusTableModel.h" 10 | #import "RCAPIClient.h" 11 | 12 | @interface RCBaseTableModel : JLNimbusTableModel 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCBaseTableModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // NITimelineTableModel.m 3 | // NimbusTimeline 4 | // 5 | // Created by Lee jimney on 7/27/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCBaseTableModel.h" 10 | 11 | /////////////////////////////////////////////////////////////////////////////////////////////////// 12 | /////////////////////////////////////////////////////////////////////////////////////////////////// 13 | /////////////////////////////////////////////////////////////////////////////////////////////////// 14 | @implementation RCBaseTableModel 15 | 16 | /////////////////////////////////////////////////////////////////////////////////////////////////// 17 | - (id)initWithDelegate:(id)delegate 18 | { 19 | self = [super initWithDelegate:delegate]; 20 | if (self) 21 | { 22 | } 23 | return self; 24 | } 25 | 26 | /////////////////////////////////////////////////////////////////////////////////////////////////// 27 | /////////////////////////////////////////////////////////////////////////////////////////////////// 28 | #pragma mark - Override 29 | 30 | /////////////////////////////////////////////////////////////////////////////////////////////////// 31 | - (NSString*)listKey 32 | { 33 | return nil; 34 | } 35 | 36 | /////////////////////////////////////////////////////////////////////////////////////////////////// 37 | /////////////////////////////////////////////////////////////////////////////////////////////////// 38 | #pragma mark - Public 39 | 40 | /////////////////////////////////////////////////////////////////////////////////////////////////// 41 | - (id)apiSharedClient 42 | { 43 | return [RCAPIClient sharedClient]; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCCoolSitesModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCCoolSitesModel.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-12. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | @interface RCCoolSitesModel : NIMutableTableViewModel 10 | @property (nonatomic, strong) NSMutableArray* siteSectionsArray; 11 | @property (nonatomic, assign) BOOL isLoading; 12 | - (Class)objectClass; 13 | - (Class)cellClass; 14 | - (void)loadCoolSitesWithBlock:(void(^)(NSArray* siteSectionsArray, NSError* error))block; 15 | - (void)cancelRequstOperation; 16 | @end 17 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCCoolSitesModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCCoolSitesModel.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-12. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCCoolSitesModel.h" 10 | #import "RCAPIClient.h" 11 | #import "RCSiteSectionEntity.h" 12 | #import "RCSiteEntity.h" 13 | #import "RCSiteCell.h" 14 | 15 | @implementation RCCoolSitesModel 16 | 17 | /////////////////////////////////////////////////////////////////////////////////////////////////// 18 | - (id)initWithDelegate:(id)delegate 19 | { 20 | self = [super initWithDelegate:delegate]; 21 | if (self) 22 | { 23 | if (delegate && [delegate isKindOfClass:[NICellFactory class]]) { 24 | NICellFactory* factory = (NICellFactory*)delegate; 25 | NIDASSERT([self objectClass]); 26 | NIDASSERT([self cellClass]); 27 | [factory mapObjectClass:[self objectClass] 28 | toCellClass:[self cellClass]]; 29 | } 30 | } 31 | return self; 32 | } 33 | 34 | /////////////////////////////////////////////////////////////////////////////////////////////////// 35 | - (NSString*)relativePath 36 | { 37 | return [RCAPIClient relativePathForCoolSites];//tid = @"111837" 38 | } 39 | 40 | /////////////////////////////////////////////////////////////////////////////////////////////////// 41 | - (Class)objectClass 42 | { 43 | return [RCSiteEntity class]; 44 | } 45 | 46 | /////////////////////////////////////////////////////////////////////////////////////////////////// 47 | - (Class)cellClass 48 | { 49 | return [RCSiteCell class]; 50 | } 51 | 52 | /////////////////////////////////////////////////////////////////////////////////////////////////// 53 | - (void)loadCoolSitesWithBlock:(void(^)(NSArray* siteSectionsArray, NSError* error))block 54 | { 55 | if (self.isLoading) { 56 | return; 57 | } 58 | else { 59 | self.isLoading = YES; 60 | } 61 | [[RCAPIClient sharedClient] GET:[self relativePath] parameters:nil 62 | success:^(AFHTTPRequestOperation *operation, id responseObject) { 63 | self.isLoading = NO; 64 | if ([responseObject isKindOfClass:[NSArray class]]) { 65 | NSArray* sourceArray = (NSArray*)responseObject; 66 | if (sourceArray.count) { 67 | RCSiteSectionEntity* sectionEntity = nil; 68 | NSMutableArray* siteSectionsArray = [NSMutableArray arrayWithCapacity:sourceArray.count]; 69 | for (NSDictionary* dic in sourceArray) { 70 | sectionEntity = [RCSiteSectionEntity entityWithDictionary:dic]; 71 | [siteSectionsArray addObject:sectionEntity]; 72 | } 73 | self.siteSectionsArray = siteSectionsArray; 74 | if (block) { 75 | block(siteSectionsArray, nil); 76 | return; 77 | } 78 | } 79 | } 80 | if (block) { 81 | NSError* error = [[NSError alloc] init]; 82 | block(nil, error); 83 | } 84 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 85 | self.isLoading = NO; 86 | if (block) { 87 | block(nil, error); 88 | } 89 | }]; 90 | } 91 | 92 | /////////////////////////////////////////////////////////////////////////////////////////////////// 93 | - (void)cancelRequstOperation 94 | { 95 | if (self.isLoading) { 96 | [[RCAPIClient sharedClient] cancelAllHTTPOperationsWithPath:[self relativePath]]; 97 | self.isLoading = NO; 98 | } 99 | } 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCForumNodesModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCForumNodesModel.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCBaseTableModel.h" 10 | 11 | @interface RCForumNodesModel : NIMutableTableViewModel 12 | 13 | @property (nonatomic, assign) BOOL isLoading; 14 | @property (nonatomic, strong) NSArray* nodesArray; 15 | 16 | @property (nonatomic, strong) NSMutableArray* nodeSectionsArray; 17 | - (Class)objectClass; 18 | - (Class)cellClass; 19 | - (void)loadNodesWithBlock:(void(^)(NSArray* nodeSectionsArray, NSError *error))block; 20 | - (void)cancelRequstOperation; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCForumNodesModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCForumNodesModel.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCForumNodesModel.h" 10 | #import "RCNodeCell.h" 11 | #import "RCNodeEntity.h" 12 | #import "RCNodeSectionEntity.h" 13 | #import "RCAPIClient.h" 14 | 15 | @implementation RCForumNodesModel 16 | 17 | /////////////////////////////////////////////////////////////////////////////////////////////////// 18 | - (id)initWithDelegate:(id)delegate 19 | { 20 | self = [super initWithDelegate:delegate]; 21 | if (self) { 22 | // TODO:数据一次性获取过来,没有分页,这边逻辑有点别扭,待修改 23 | if (delegate && [delegate isKindOfClass:[NICellFactory class]]) { 24 | NICellFactory* factory = (NICellFactory*)delegate; 25 | NIDASSERT([self objectClass]); 26 | NIDASSERT([self cellClass]); 27 | [factory mapObjectClass:[self objectClass] 28 | toCellClass:[self cellClass]]; 29 | } 30 | self.nodeSectionsArray = [[NSMutableArray alloc] init]; 31 | } 32 | return self; 33 | } 34 | 35 | /////////////////////////////////////////////////////////////////////////////////////////////////// 36 | - (NSString*)relativePath 37 | { 38 | return [RCAPIClient relativePathForForumNodes]; 39 | } 40 | /////////////////////////////////////////////////////////////////////////////////////////////////// 41 | - (id)apiSharedClient 42 | { 43 | return [RCAPIClient sharedClient]; 44 | } 45 | 46 | /////////////////////////////////////////////////////////////////////////////////////////////////// 47 | - (Class)objectClass 48 | { 49 | return [RCNodeEntity class]; 50 | } 51 | 52 | /////////////////////////////////////////////////////////////////////////////////////////////////// 53 | - (Class)cellClass 54 | { 55 | return [RCNodeCell class]; 56 | } 57 | 58 | /////////////////////////////////////////////////////////////////////////////////////////////////// 59 | - (NSArray*)entitiesParsedFromResponseObject:(id)responseObject 60 | { 61 | NSArray* sourceArray = (NSArray*)responseObject; 62 | RCNodeEntity* entity = nil; 63 | NSMutableArray* entities = [[NSMutableArray alloc] init]; 64 | for (NSDictionary* dic in sourceArray) { 65 | entity = [RCNodeEntity entityWithDictionary:dic]; 66 | [entities addObject:entity]; 67 | } 68 | self.nodesArray = entities; 69 | for (RCNodeEntity* o in entities) { 70 | 71 | BOOL hasExist = NO; 72 | for (RCNodeSectionEntity* s in _nodeSectionsArray) { 73 | if (s.sectionId == o.sectionId) { 74 | hasExist = YES; 75 | break; 76 | } 77 | } 78 | if (!hasExist) { 79 | RCNodeSectionEntity* s = [[RCNodeSectionEntity alloc] init]; 80 | s.sectionId = o.sectionId; 81 | s.name = o.sectionName; 82 | s.nodesArray = [[NSMutableArray alloc] init]; 83 | [_nodeSectionsArray addObject:s]; 84 | } 85 | } 86 | for (RCNodeEntity* o in entities) { 87 | for (RCNodeSectionEntity* s in _nodeSectionsArray) { 88 | if (s.sectionId == o.sectionId) { 89 | [s.nodesArray addObject:o]; 90 | break; 91 | } 92 | } 93 | } 94 | return _nodeSectionsArray; 95 | } 96 | 97 | - (void)loadNodesWithBlock:(void(^)(NSArray* nodeSectionsArray, NSError *error))block 98 | { 99 | if (self.isLoading) { 100 | return; 101 | } 102 | else { 103 | self.isLoading = YES; 104 | } 105 | 106 | NSString* relativePath = [self relativePath]; 107 | [[self apiSharedClient] GET:relativePath parameters:nil 108 | success:^(AFHTTPRequestOperation *operation, id responseObject) { 109 | self.isLoading = NO; 110 | if ([responseObject isKindOfClass:[NSArray class]]) { 111 | NSArray* sectionsArray = [self entitiesParsedFromResponseObject:responseObject]; 112 | if (block) { 113 | block(sectionsArray, nil); 114 | } 115 | } 116 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 117 | self.isLoading = NO; 118 | if (block) { 119 | block(nil, error); 120 | } 121 | }]; 122 | } 123 | 124 | /////////////////////////////////////////////////////////////////////////////////////////////////// 125 | - (void)cancelRequstOperation 126 | { 127 | if (self.isLoading) { 128 | [[RCAPIClient sharedClient] cancelAllHTTPOperationsWithPath:[self relativePath]]; 129 | self.isLoading = NO; 130 | } 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCForumTopicsModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCForumTopicsModel.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCBaseTableModel.h" 10 | 11 | @interface RCForumTopicsModel : RCBaseTableModel 12 | @property (nonatomic, assign) RCForumTopicsType topicsType; 13 | @property (nonatomic, copy) NSString* nodeName; 14 | @property (nonatomic, assign) NSUInteger nodeId; 15 | @property (nonatomic, copy) NSString* loginId; 16 | @end 17 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCForumTopicsModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCForumTopicsModel.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCForumTopicsModel.h" 10 | #import "RCAPIClient.h" 11 | #import "RCTopicCell.h" 12 | #import "RCTopicEntity.h" 13 | 14 | @interface RCForumTopicsModel() 15 | 16 | @end 17 | 18 | @implementation RCForumTopicsModel 19 | 20 | /////////////////////////////////////////////////////////////////////////////////////////////////// 21 | - (id)initWithDelegate:(id)delegate 22 | { 23 | self = [super initWithDelegate:delegate]; 24 | if (self) { 25 | 26 | } 27 | return self; 28 | } 29 | 30 | /////////////////////////////////////////////////////////////////////////////////////////////////// 31 | - (NSString*)relativePath 32 | { 33 | NSString* path = nil; 34 | switch (self.topicsType) { 35 | case RCForumTopicsType_LatestActivity: 36 | path = [RCAPIClient relativePathForTopicsWithPageIndex:self.pageIndex 37 | pageSize:self.pageSize]; 38 | break; 39 | case RCForumTopicsType_NodeList: 40 | path = [RCAPIClient relativePathForTopicsWithNodeId:self.nodeId 41 | pageIndex:self.pageIndex 42 | pageSize:self.pageSize]; 43 | break; 44 | 45 | case RCForumTopicsType_UserPosted: 46 | path = [RCAPIClient relativePathForPostedTopicsWithUserLoginId:self.loginId 47 | pageIndex:self.pageIndex 48 | pageSize:self.pageSize]; 49 | break; 50 | 51 | case RCForumTopicsType_UserFavorited: 52 | path = [RCAPIClient relativePathForFavoritedTopicsWithUserLoginId:self.loginId 53 | pageIndex:self.pageIndex 54 | pageSize:self.pageSize]; 55 | break; 56 | 57 | default: 58 | break; 59 | } 60 | return path; 61 | } 62 | 63 | /////////////////////////////////////////////////////////////////////////////////////////////////// 64 | - (Class)objectClass 65 | { 66 | return [RCTopicEntity class]; 67 | } 68 | 69 | /////////////////////////////////////////////////////////////////////////////////////////////////// 70 | - (Class)cellClass 71 | { 72 | return [RCTopicCell class]; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCLoginModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCSignModel.h 3 | // RubyChina 4 | // 5 | // Created by jimneylee on 13-7-25. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RCAccountEntity.h" 11 | 12 | @interface RCLoginModel : NSObject 13 | 14 | - (void)loginWithUsername:(NSString*)username password:(NSString*)password 15 | block:(void(^)(RCAccountEntity* user, NSError *error))block; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCLoginModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCLoginModel.m 3 | // RubyChina 4 | // 5 | // Created by jimneylee on 13-7-25. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCLoginModel.h" 10 | #import "RCAPIClient.h" 11 | //#import "AFJSONRequestOperation.h" 12 | #import "NSDataAdditions.h" 13 | 14 | /////////////////////////////////////////////////////////////////////////////////////////////////// 15 | /////////////////////////////////////////////////////////////////////////////////////////////////// 16 | /////////////////////////////////////////////////////////////////////////////////////////////////// 17 | @implementation RCLoginModel 18 | 19 | /////////////////////////////////////////////////////////////////////////////////////////////////// 20 | - (void)loginWithUsername:(NSString*)username password:(NSString*)password 21 | block:(void(^)(RCAccountEntity* user, NSError *error))block 22 | { 23 | NSString* path = [RCAPIClient relativePathForSignIn]; 24 | #if 1 25 | // 由于登录的接口与其他接口base_url不太一样,后台没有放到api路径下,故单独处理 26 | // ruby-china.org/account/sign_in.json 27 | AFHTTPRequestOperationManager *httpClient = [[AFHTTPRequestOperationManager alloc] initWithBaseURL: 28 | [NSURL URLWithString:HOST_URL]]; 29 | [httpClient.requestSerializer setAuthorizationHeaderFieldWithUsername:username password:password]; 30 | [httpClient POST:path parameters:nil 31 | success:^(AFHTTPRequestOperation *operation, id responseObject) { 32 | if ([responseObject isKindOfClass:[NSDictionary class]]) { 33 | RCAccountEntity* account = [RCAccountEntity entityWithDictionary:responseObject]; 34 | [RCGlobalConfig setMyLoginId:account.loginId]; 35 | [RCGlobalConfig setMyToken:account.privateToken]; 36 | [RCAccountEntity storePrivateToken:account.privateToken forLoginId:account.loginId]; 37 | if (block) { 38 | block(account, nil); 39 | } 40 | } 41 | else { 42 | if (block) { 43 | NSError* error = [[NSError alloc] init]; 44 | block(nil, error); 45 | } 46 | } 47 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 48 | //NSDictionary* info = [error.userInfo objectForKey:@"NSLocalizedRecoverySuggestion"]; 49 | //NSLog(@"error: %@", [info objectForKey:@"error"]); 50 | //NSLog(@"error: %@", error); 51 | if (block) { 52 | block(nil, error); 53 | } 54 | }]; 55 | #endif 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCPostModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCReplyModel.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/11/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RCTopicEntity.h" 11 | 12 | @interface RCPostModel : NSObject 13 | - (void)postNewTopicWithTitle:(NSString*)title 14 | body:(NSString*)body 15 | nodeId:(NSUInteger)nodeId 16 | success:(void(^)(RCTopicEntity* topicEntity))success 17 | failure:(void(^)(NSError *error))failure; 18 | @end 19 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCPostModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCReplyModel.m 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/11/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCPostModel.h" 10 | #import "RCAPIClient.h" 11 | #import "AFHTTPRequestOperation.h" 12 | 13 | @implementation RCPostModel 14 | 15 | /////////////////////////////////////////////////////////////////////////////////////////////////// 16 | - (void)postNewTopicWithTitle:(NSString*)title 17 | body:(NSString*)body 18 | nodeId:(NSUInteger)nodeId 19 | success:(void(^)(RCTopicEntity* topicEntity))success 20 | failure:(void(^)(NSError *error))failure 21 | { 22 | if (title.length && body.length && nodeId > 0) { 23 | NSMutableDictionary* parameters = [NSMutableDictionary dictionary]; 24 | [parameters setObject:title forKey:@"title"]; 25 | [parameters setObject:body forKey:@"body"]; 26 | [parameters setObject:[NSNumber numberWithUnsignedInt:nodeId] forKey:@"node_id"]; 27 | [parameters setObject:[RCGlobalConfig myToken] forKey:@"token"]; 28 | 29 | NSString* path = [RCAPIClient relativePathForPostNewTopic]; 30 | [[RCAPIClient sharedClient] POST:path parameters:parameters 31 | success:^(AFHTTPRequestOperation *operation, id responseObject) { 32 | 33 | BOOL successFlag = NO; 34 | if ([responseObject isKindOfClass:[NSDictionary class]]) { 35 | RCTopicEntity* topicEntity = [RCTopicEntity entityWithDictionary:responseObject]; 36 | if (topicEntity) { 37 | success(topicEntity); 38 | successFlag = YES; 39 | } 40 | } 41 | 42 | if (!successFlag) { 43 | failure(nil); 44 | } 45 | } 46 | failure:^(AFHTTPRequestOperation *operation, NSError *error) { 47 | NSLog(@"%@", error); 48 | failure(error); 49 | }]; 50 | } 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCReplyModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCReplyModel.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/11/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RCReplyEntity.h" 11 | 12 | @interface RCReplyModel : NSObject 13 | - (void)replyTopicId:(unsigned long)topicId 14 | body:(NSString*)body 15 | success:(void(^)(RCReplyEntity* replyEntity))success 16 | failure:(void(^)(NSError *error))failure; 17 | @end 18 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCReplyModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCReplyModel.m 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/11/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCReplyModel.h" 10 | #import "RCAPIClient.h" 11 | #import "AFHTTPRequestOperation.h" 12 | 13 | @implementation RCReplyModel 14 | 15 | /////////////////////////////////////////////////////////////////////////////////////////////////// 16 | - (void)replyTopicId:(unsigned long)topicId 17 | body:(NSString*)body 18 | success:(void(^)(RCReplyEntity* replyEntity))success 19 | failure:(void(^)(NSError *error))failure 20 | { 21 | if (body.length) { 22 | NSMutableDictionary* parameters = [NSMutableDictionary dictionary]; 23 | [parameters setObject:body forKey:@"body"]; 24 | [parameters setObject:[RCGlobalConfig myToken] forKey:@"token"]; 25 | 26 | NSString* path = [RCAPIClient relativePathForReplyTopicId:topicId]; 27 | [[RCAPIClient sharedClient] POST:path parameters:parameters 28 | success:^(AFHTTPRequestOperation *operation, id responseObject) { 29 | BOOL successFlag = NO; 30 | if ([responseObject isKindOfClass:[NSDictionary class]]) { 31 | RCReplyEntity* replyEntity = [RCReplyEntity entityWithDictionary:responseObject]; 32 | if (replyEntity) { 33 | success(replyEntity); 34 | successFlag = YES; 35 | } 36 | } 37 | 38 | if (!successFlag) { 39 | failure(nil); 40 | } 41 | } 42 | failure:^(AFHTTPRequestOperation *operation, NSError *error) { 43 | failure(error); 44 | }]; 45 | } 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCTopMembersModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCCoolSitesModel.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-12. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | @interface RCTopMembersModel : NIMutableTableViewModel 10 | 11 | @property (nonatomic, strong) NSMutableArray* topMembersArray; 12 | @property (nonatomic, assign) BOOL isLoading; 13 | 14 | - (void)loadTopMembersWithBlock:(void(^)(NSArray* topMembersArray, NSError* error))block; 15 | - (void)cancelRequstOperation; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCTopMembersModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCCoolSitesModel.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-12. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCTopMembersModel.h" 10 | #import "RCAPIClient.h" 11 | #import "RCUserEntity.h" 12 | 13 | @implementation RCTopMembersModel 14 | 15 | /////////////////////////////////////////////////////////////////////////////////////////////////// 16 | - (NSString*)relativePath 17 | { 18 | // 暂时未分页 19 | return [RCAPIClient relativePathForTopMembersWithPageIndex:0 pageSize:0]; 20 | } 21 | 22 | /////////////////////////////////////////////////////////////////////////////////////////////////// 23 | - (void)loadTopMembersWithBlock:(void(^)(NSArray* siteSectionsArray, NSError* error))block 24 | { 25 | if (self.isLoading) { 26 | return; 27 | } 28 | else { 29 | self.isLoading = YES; 30 | } 31 | [[RCAPIClient sharedClient] GET:[self relativePath] parameters:nil 32 | success:^(AFHTTPRequestOperation *operation, id responseObject) { 33 | self.isLoading = NO; 34 | if ([responseObject isKindOfClass:[NSArray class]]) { 35 | NSArray* sourceArray = (NSArray*)responseObject; 36 | if (sourceArray.count) { 37 | RCUserEntity* user = nil; 38 | NSMutableArray* topMembersArray = [NSMutableArray arrayWithCapacity:sourceArray.count]; 39 | for (NSDictionary* dic in sourceArray) { 40 | user = [RCUserEntity entityWithDictionary:dic]; 41 | [topMembersArray addObject:user]; 42 | } 43 | self.topMembersArray = topMembersArray; 44 | if (block) { 45 | block(topMembersArray, nil); 46 | return; 47 | } 48 | } 49 | } 50 | if (block) { 51 | NSError* error = [[NSError alloc] init]; 52 | block(nil, error); 53 | } 54 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 55 | self.isLoading = NO; 56 | if (block) { 57 | block(nil, error); 58 | } 59 | }]; 60 | } 61 | 62 | /////////////////////////////////////////////////////////////////////////////////////////////////// 63 | - (void)cancelRequstOperation 64 | { 65 | if (self.isLoading) { 66 | [[RCAPIClient sharedClient] cancelAllHTTPOperationsWithPath:[self relativePath]]; 67 | self.isLoading = NO; 68 | } 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCTopMembersModel_list.h: -------------------------------------------------------------------------------- 1 | // 2 | // SMPublicTimelineModel.h 3 | // SinaMBlogNimbus 4 | // 5 | // Created by Lee jimney on 10/30/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCBaseTableModel.h" 10 | 11 | @interface RCTopMembersModel : RCBaseTableModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCTopMembersModel_list.m: -------------------------------------------------------------------------------- 1 | // 2 | // SMPublicTimelineModel.m 3 | // SinaMBlogNimbus 4 | // 5 | // Created by Lee jimney on 10/30/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCTopMembersModel.h" 10 | #import "RCUserEntity.h" 11 | #import "RCUserCell.h" 12 | 13 | @implementation RCTopMembersModel 14 | 15 | /////////////////////////////////////////////////////////////////////////////////////////////////// 16 | - (id)initWithDelegate:(id)delegate 17 | { 18 | self = [super initWithDelegate:delegate]; 19 | if (self) { 20 | // TODO:数据一次性获取过来,没有分页,后面建议后台做分页 21 | self.perpageCount = NSIntegerMax; 22 | } 23 | return self; 24 | } 25 | 26 | /////////////////////////////////////////////////////////////////////////////////////////////////// 27 | - (NSString*)relativePath 28 | { 29 | return [RCAPIClient relativePathForTopMembersWithPageCounter:self.pageCounter 30 | perpageCount:self.perpageCount]; 31 | } 32 | 33 | /////////////////////////////////////////////////////////////////////////////////////////////////// 34 | - (Class)objectClass 35 | { 36 | return [RCUserEntity class]; 37 | } 38 | 39 | /////////////////////////////////////////////////////////////////////////////////////////////////// 40 | - (Class)cellClass 41 | { 42 | return [RCUserCell class]; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCTopicActionModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicActionModel.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/11/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, RCTopicActionType) { 12 | RCTopicActionType_Follow, 13 | RCTopicActionType_Unfollow, 14 | RCTopicActionType_Favorite 15 | }; 16 | 17 | @interface RCTopicActionModel : NSObject 18 | 19 | - (void)followTopicId:(unsigned long)topicId 20 | success:(void(^)())success 21 | failure:(void(^)(NSError *error))failure; 22 | 23 | - (void)unfollowTopicId:(unsigned long)topicId 24 | success:(void(^)())success 25 | failure:(void(^)(NSError *error))failure; 26 | 27 | - (void)favoriteTopicId:(unsigned long)topicId 28 | success:(void(^)())success 29 | failure:(void(^)(NSError *error))failure; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCTopicActionModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicActionModel.m 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/11/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCTopicActionModel.h" 10 | #import "RCAPIClient.h" 11 | #import "AFHTTPRequestOperation.h" 12 | 13 | @implementation RCTopicActionModel 14 | 15 | /////////////////////////////////////////////////////////////////////////////////////////////////// 16 | - (NSString*)relativePathWithTopicId:(unsigned long)topicId actionType:(RCTopicActionType)actionType 17 | { 18 | NSString* path = nil; 19 | switch (actionType) { 20 | case RCTopicActionType_Follow: 21 | path = [RCAPIClient relativePathForFollowTopicId:topicId]; 22 | break; 23 | 24 | case RCTopicActionType_Unfollow: 25 | path = [RCAPIClient relativePathForUnfollowTopicId:topicId]; 26 | break; 27 | 28 | case RCTopicActionType_Favorite: 29 | path = [RCAPIClient relativePathForFavoriteTopicId:topicId]; 30 | break; 31 | 32 | default: 33 | break; 34 | } 35 | return path; 36 | } 37 | 38 | /////////////////////////////////////////////////////////////////////////////////////////////////// 39 | - (void)followTopicId:(unsigned long)topicId 40 | success:(void(^)())success 41 | failure:(void(^)(NSError *error))failure 42 | { 43 | [self doActionWithTopicId_json_response:topicId actionType:RCTopicActionType_Follow 44 | success:success failure:failure]; 45 | } 46 | 47 | /////////////////////////////////////////////////////////////////////////////////////////////////// 48 | - (void)unfollowTopicId:(unsigned long)topicId 49 | success:(void(^)())success 50 | failure:(void(^)(NSError *error))failure 51 | { 52 | [self doActionWithTopicId_json_response:topicId actionType:RCTopicActionType_Unfollow 53 | success:success failure:failure]; 54 | } 55 | 56 | /////////////////////////////////////////////////////////////////////////////////////////////////// 57 | - (void)favoriteTopicId:(unsigned long)topicId 58 | success:(void(^)())success 59 | failure:(void(^)(NSError *error))failure 60 | { 61 | [self doActionWithTopicId:topicId actionType:RCTopicActionType_Favorite 62 | success:success failure:failure]; 63 | } 64 | 65 | /////////////////////////////////////////////////////////////////////////////////////////////////// 66 | // 返回的是json数据 => follow unfollow,不同于favorite,DT!:( 67 | - (void)doActionWithTopicId_json_response:(unsigned long)topicId 68 | actionType:(RCTopicActionType)actionType 69 | success:(void(^)())success 70 | failure:(void(^)(NSError *error))failure 71 | { 72 | if (topicId > 0) { 73 | NSMutableDictionary* parameters = [NSMutableDictionary dictionary]; 74 | [parameters setObject:[RCGlobalConfig myToken] forKey:@"token"]; 75 | 76 | NSString* path = [self relativePathWithTopicId:topicId actionType:actionType]; 77 | [[RCAPIClient sharedClient] POST:path parameters:parameters 78 | success:^(AFHTTPRequestOperation *operation, id responseObject) { 79 | NSLog(@"%@", responseObject); 80 | success(); 81 | } 82 | failure:^(AFHTTPRequestOperation *operation, NSError *error) { 83 | // TODO: 已关注,返回不是json,建议后台统一处理 84 | // (JSON text did not start with array or object and option to allow fragments not set.) 85 | NSLog(@"%@", error); 86 | failure(error); 87 | }]; 88 | } 89 | } 90 | 91 | /////////////////////////////////////////////////////////////////////////////////////////////////// 92 | // 返回是ture or false => favorite 93 | - (void)doActionWithTopicId:(unsigned long)topicId 94 | actionType:(RCTopicActionType)actionType 95 | success:(void(^)())success 96 | failure:(void(^)(NSError *error))failure 97 | { 98 | #warning "to use af2.0" 99 | #if 0 100 | // 参考:http://stackoverflow.com/questions/9562459/afnetworking-posting-malformed-json-single-quotes-and-object-refs 101 | if (topicId > 0) { 102 | NSMutableDictionary* parameters = [NSMutableDictionary dictionary]; 103 | [parameters setObject:[RCGlobalConfig myToken] forKey:@"token"]; 104 | 105 | NSString* path = [self relativePathWithTopicId:topicId actionType:actionType]; 106 | NSError *error = nil; 107 | NSData* jsonData = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:&error]; 108 | 109 | AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:HOST_API_URL]]; 110 | [httpClient setParameterEncoding:AFFormURLParameterEncoding]; 111 | NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" 112 | path:path 113 | parameters:nil]; 114 | NSMutableData *body = [NSMutableData data]; 115 | [body appendData:jsonData]; 116 | [request setHTTPBody:body]; 117 | [request setHTTPMethod:@"POST"]; 118 | [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 119 | [request setValue:@"application/json" forHTTPHeaderField:@"content-type"]; 120 | 121 | AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 122 | [httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]]; 123 | [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 124 | NSString* resultString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; 125 | NSLog(@"Response: %@", resultString); 126 | if ([resultString isEqualToString:@"true"]) { 127 | success(); 128 | } 129 | else { 130 | failure(nil); 131 | } 132 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 133 | NSLog(@"Error: %@", error); 134 | failure(nil); 135 | }]; 136 | [operation start]; 137 | } 138 | #endif 139 | } 140 | @end 141 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCTopicDetailModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicDetailModel.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCBaseTableModel.h" 10 | #import "RCTopicDetailEntity.h" 11 | 12 | @interface RCTopicDetailModel : RCBaseTableModel 13 | @property (nonatomic, assign) unsigned long topicId; 14 | @property (nonatomic, strong) RCTopicDetailEntity* topicDetailEntity; 15 | @end 16 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCTopicDetailModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicDetailModel.m 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCTopicDetailModel.h" 10 | #import "RCReplyCell.h" 11 | #import "RCReplyEntity.h" 12 | 13 | @implementation RCTopicDetailModel 14 | 15 | /////////////////////////////////////////////////////////////////////////////////////////////////// 16 | - (id)initWithDelegate:(id)delegate 17 | { 18 | self = [super initWithDelegate:delegate]; 19 | if (self) { 20 | 21 | // TODO:数据一次性获取过来,没有分页,后面建议后台做分页 22 | if (ForumBaseAPIType_RubyChina == FORUM_BASE_API_TYPE) { 23 | self.pageSize = NSIntegerMax; 24 | } 25 | 26 | //TOPIC_PAGE_SIZE=100 see v2ex https://github.com/livid/v2ex/blob/5d8764c8ec0d138a308b5c90003261c5673124a6/topic.py 27 | else if (ForumBaseAPIType_V2EX == FORUM_BASE_API_TYPE) { 28 | self.pageSize = 100; 29 | } 30 | } 31 | return self; 32 | } 33 | 34 | /////////////////////////////////////////////////////////////////////////////////////////////////// 35 | /////////////////////////////////////////////////////////////////////////////////////////////////// 36 | #pragma mark - Override 37 | 38 | /////////////////////////////////////////////////////////////////////////////////////////////////// 39 | - (NSString*)relativePath 40 | { 41 | // TODO: set type 42 | if (ForumBaseAPIType_RubyChina == FORUM_BASE_API_TYPE) { 43 | return [RCAPIClient relativePathForTopicDetailWithTopicId:self.topicId]; 44 | } 45 | else if (ForumBaseAPIType_V2EX == FORUM_BASE_API_TYPE) { 46 | return [RCAPIClient relativePathForTopicRepliesWithTopicId:self.topicId 47 | pageIndex:self.pageIndex 48 | pageSize:self.pageSize]; 49 | } 50 | return nil; 51 | } 52 | 53 | /////////////////////////////////////////////////////////////////////////////////////////////////// 54 | - (NSString*)listKey 55 | { 56 | return JSON_REPLIES_LIST; 57 | } 58 | 59 | /////////////////////////////////////////////////////////////////////////////////////////////////// 60 | - (Class)objectClass 61 | { 62 | return [RCReplyEntity class]; 63 | } 64 | 65 | /////////////////////////////////////////////////////////////////////////////////////////////////// 66 | - (Class)cellClass 67 | { 68 | return [RCReplyCell class]; 69 | } 70 | 71 | /////////////////////////////////////////////////////////////////////////////////////////////////// 72 | - (NSArray*)entitiesParsedFromResponseObject:(id)responseObject 73 | { 74 | // 1、parse topic detail body 75 | self.topicDetailEntity = [RCTopicDetailEntity entityWithDictionary:responseObject]; 76 | 77 | // 2、parse replies list with key: JSON_REPLIES_LIST 78 | NSArray* entities = [super entitiesParsedFromResponseObject:responseObject]; 79 | RCReplyEntity* o = nil; 80 | for (NSUInteger i = 0; i < entities.count; i++) { 81 | o = entities[i]; 82 | o.floorNumber = i+1; 83 | } 84 | 85 | // 3、call inline sort 86 | //entities = [entities sortedArrayUsingSelector:@selector(compare:)]; 87 | 88 | return entities; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCUserHomepageModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicDetailModel.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCBaseTableModel.h" 10 | #import "RCUserFullEntity.h" 11 | 12 | @interface RCUserHomepageModel : RCBaseTableModel 13 | @property (nonatomic, copy) NSString* loginId; 14 | @property (nonatomic, strong) RCUserFullEntity* userEntity;//TODO:replace with RCUserFullEntity 15 | @end 16 | -------------------------------------------------------------------------------- /JLRubyChina/Models/RCUserHomepageModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicDetailModel.m 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCUserHomepageModel.h" 10 | #import "RCTopicCell.h" 11 | #import "RCTopicEntity.h" 12 | 13 | @implementation RCUserHomepageModel 14 | 15 | /////////////////////////////////////////////////////////////////////////////////////////////////// 16 | - (id)initWithDelegate:(id)delegate 17 | { 18 | self = [super initWithDelegate:delegate]; 19 | if (self) { 20 | // TODO:数据一次性获取过来,没有分页,后面建议后台做分页 21 | self.pageSize = NSIntegerMax; 22 | } 23 | return self; 24 | } 25 | 26 | /////////////////////////////////////////////////////////////////////////////////////////////////// 27 | /////////////////////////////////////////////////////////////////////////////////////////////////// 28 | #pragma mark - Override 29 | 30 | /////////////////////////////////////////////////////////////////////////////////////////////////// 31 | - (NSString*)relativePath 32 | { 33 | if (self.loginId.length) { 34 | return [RCAPIClient relativePathForVisitUserHomepageWithLoginId:self.loginId]; 35 | } 36 | return nil; 37 | } 38 | 39 | /////////////////////////////////////////////////////////////////////////////////////////////////// 40 | - (NSString*)listKey 41 | { 42 | return JSON_TOPICS_LIST; 43 | } 44 | 45 | /////////////////////////////////////////////////////////////////////////////////////////////////// 46 | - (Class)objectClass 47 | { 48 | return [RCTopicEntity class]; 49 | } 50 | 51 | /////////////////////////////////////////////////////////////////////////////////////////////////// 52 | - (Class)cellClass 53 | { 54 | return [RCTopicCell class]; 55 | } 56 | 57 | /////////////////////////////////////////////////////////////////////////////////////////////////// 58 | - (NSArray*)entitiesParsedFromResponseObject:(id)responseObject 59 | { 60 | // 1、parse topic detail body 61 | self.userEntity = [RCUserFullEntity entityWithDictionary:responseObject]; 62 | 63 | // 2、parse replies list with key: JSON_REPLIES_LIST 64 | NSArray* entities = [super entitiesParsedFromResponseObject:responseObject]; 65 | return entities; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /JLRubyChina/RCAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // JLAppDelegate.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "JASidePanelController.h" 11 | 12 | @interface RCAppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | @property (strong, nonatomic) JASidePanelController *sidePanelController; 16 | @end 17 | -------------------------------------------------------------------------------- /JLRubyChina/RCGlobalConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCGlobalConfig.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // API 接口类型:ruby-china、v2ex 12 | typedef enum { 13 | ForumBaseAPIType_RubyChina, 14 | ForumBaseAPIType_V2EX 15 | }ForumBaseAPIType; 16 | 17 | // 帖子类型 18 | typedef enum { 19 | RCForumTopicsType_LatestActivity,//当前活跃帖子 20 | RCForumTopicsType_HighQuality,//优质帖子 21 | RCForumTopicsType_NeverReviewed,//无人问津 22 | RCForumTopicsType_LatestCreate,//最新创建 23 | RCForumTopicsType_NodeList,//某一分类帖子 24 | RCForumTopicsType_UserPosted,//某个用户发的 25 | RCForumTopicsType_UserFavorited//某个用户收藏 26 | }RCForumTopicsType; 27 | 28 | @interface RCGlobalConfig : NSObject 29 | 30 | //Global Data 31 | + (NSString*)myToken; 32 | + (void)setMyToken:(NSString*)token; 33 | + (NSString*)myLoginId; 34 | + (void)setMyLoginId:(NSString*)loginId; 35 | + (void)parseAppConfig; 36 | + (ForumBaseAPIType)forumBaseAPIType; 37 | 38 | // Global UI 39 | + (MBProgressHUD*)HUDShowMessage:(NSString*)msg addedToView:(UIView*)view; 40 | + (UIBarButtonItem*)createBarButtonItemWithTitle:(NSString*)buttonTitle Target:(id)target action:(SEL)action; 41 | + (UIBarButtonItem*)createMenuBarButtonItemWithTarget:(id)target action:(SEL)action; 42 | + (UIBarButtonItem*)createRefreshBarButtonItemWithTarget:(id)target action:(SEL)action; 43 | + (void)showLoginControllerFromNavigationController:(UINavigationController*)navigationController; 44 | 45 | // emoji reverse code 46 | + (NSDictionary *)emojiReverseAliases; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /JLRubyChina/RCGlobalConfig.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCGlobalConfig.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCGlobalConfig.h" 10 | #import "RCLoginC.h" 11 | 12 | static NSString* myToken = nil; 13 | static NSString* myLoginId = nil; 14 | static ForumBaseAPIType forumBaseAPIType = ForumBaseAPIType_RubyChina; 15 | 16 | @implementation RCGlobalConfig 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////// 19 | /////////////////////////////////////////////////////////////////////////////////////////////////// 20 | #pragma mark - Global Data 21 | 22 | /////////////////////////////////////////////////////////////////////////////////////////////////// 23 | + (NSString*)myToken 24 | { 25 | return myToken; 26 | } 27 | 28 | /////////////////////////////////////////////////////////////////////////////////////////////////// 29 | + (void)setMyToken:(NSString*)token 30 | { 31 | myToken = [token copy]; 32 | } 33 | 34 | /////////////////////////////////////////////////////////////////////////////////////////////////// 35 | + (NSString*)myLoginId 36 | { 37 | return myLoginId; 38 | } 39 | 40 | /////////////////////////////////////////////////////////////////////////////////////////////////// 41 | + (void)setMyLoginId:(NSString*)loginId 42 | { 43 | myLoginId = [loginId copy]; 44 | } 45 | 46 | /////////////////////////////////////////////////////////////////////////////////////////////////// 47 | /////////////////////////////////////////////////////////////////////////////////////////////////// 48 | #pragma mark - App Config 49 | 50 | /////////////////////////////////////////////////////////////////////////////////////////////////// 51 | + (void)parseAppConfig 52 | { 53 | NSString* apiTypeString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"HOST_BASE_API_TYPE"]; 54 | if (NSOrderedSame == [apiTypeString caseInsensitiveCompare:@"rubychina"]) { 55 | forumBaseAPIType = ForumBaseAPIType_RubyChina; 56 | } 57 | else if (NSOrderedSame == [apiTypeString caseInsensitiveCompare:@"v2ex"]) { 58 | forumBaseAPIType = ForumBaseAPIType_V2EX; 59 | } 60 | else { 61 | forumBaseAPIType = ForumBaseAPIType_RubyChina; 62 | } 63 | } 64 | 65 | /////////////////////////////////////////////////////////////////////////////////////////////////// 66 | + (ForumBaseAPIType)forumBaseAPIType 67 | { 68 | return forumBaseAPIType; 69 | } 70 | 71 | /////////////////////////////////////////////////////////////////////////////////////////////////// 72 | /////////////////////////////////////////////////////////////////////////////////////////////////// 73 | #pragma mark - Global UI 74 | 75 | /////////////////////////////////////////////////////////////////////////////////////////////////// 76 | + (MBProgressHUD*)HUDShowMessage:(NSString*)msg addedToView:(UIView*)view 77 | { 78 | static MBProgressHUD* hud = nil; 79 | if (!hud) { 80 | hud = [MBProgressHUD showHUDAddedTo:view animated:YES]; 81 | } 82 | hud.mode = MBProgressHUDModeText; 83 | hud.labelText = msg; 84 | hud.hidden = NO; 85 | hud.alpha = 1.0f; 86 | [hud hide:YES afterDelay:1.0f]; 87 | return hud; 88 | } 89 | 90 | /////////////////////////////////////////////////////////////////////////////////////////////////// 91 | + (UIBarButtonItem*)createBarButtonItemWithTitle:(NSString*)buttonTitle Target:(id)target action:(SEL)action 92 | { 93 | UIBarButtonItem* item = nil; 94 | item = [[UIBarButtonItem alloc] initWithTitle:buttonTitle 95 | style:UIBarButtonItemStylePlain 96 | target:target 97 | action:action]; 98 | return item; 99 | } 100 | 101 | /////////////////////////////////////////////////////////////////////////////////////////////////// 102 | + (UIBarButtonItem*)createMenuBarButtonItemWithTarget:(id)target action:(SEL)action 103 | { 104 | return [[UIBarButtonItem alloc] initWithImage:[UIImage nimbusImageNamed:@"icon_menu.png"] 105 | style:UIBarButtonItemStylePlain 106 | target:target action:action]; 107 | } 108 | 109 | /////////////////////////////////////////////////////////////////////////////////////////////////// 110 | + (UIBarButtonItem*)createRefreshBarButtonItemWithTarget:(id)target action:(SEL)action 111 | { 112 | UIBarButtonItem* item = nil; 113 | item = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh 114 | target:target action:action]; 115 | return item; 116 | } 117 | 118 | /////////////////////////////////////////////////////////////////////////////////////////////////// 119 | + (void)showLoginControllerFromNavigationController:(UINavigationController*)navigationController 120 | { 121 | RCLoginC* loginC = [[RCLoginC alloc] initWithStyle:UITableViewStyleGrouped]; 122 | [navigationController pushViewController:loginC animated:YES]; 123 | } 124 | 125 | /////////////////////////////////////////////////////////////////////////////////////////////////// 126 | // emoji -> code 127 | + (NSDictionary *)emojiReverseAliases { 128 | static NSDictionary *_emojiReverseAliases; 129 | static dispatch_once_t onceToken; 130 | dispatch_once(&onceToken, ^{ 131 | _emojiReverseAliases = @{ 132 | @"\U0001F604" : @":smile:", 133 | @"\U0001F60A" : @":blush:", 134 | @"\U0001F603" : @":smiley:", 135 | @"\U0000263A" : @":relaxed:", 136 | @"\U0001F609" : @":wink:", 137 | @"\U0001F60D" : @":heart_eyes:", 138 | @"\U0001F618" : @":kissing_heart:", 139 | @"\U0001F61A" : @":kissing_closed_eyes:", 140 | @"\U0001F633" : @":flushed:", 141 | @"\U0001F60C" : @":relieved:", 142 | @"\U0001F601" : @":grin:", 143 | @"\U0001F61C" : @":stuck_out_tongue_winking_eye:", 144 | @"\U0001F61D" : @":stuck_out_tongue_closed_eyes:", 145 | @"\U0001F612" : @":unamused:", 146 | @"\U0001F60F" : @":smirk:", 147 | @"\U0001F613" : @":sweat:", 148 | @"\U0001F614" : @":pensive:", 149 | @"\U0001F61E" : @":disappointed:", 150 | @"\U0001F616" : @":confounded:", 151 | @"\U0001F625" : @":disappointed_relieved:", 152 | @"\U0001F630" : @":cold_sweat:", 153 | @"\U0001F628" : @":fearful:", 154 | @"\U0001F623" : @":persevere:", 155 | @"\U0001F622" : @":cry:", 156 | @"\U0001F62D" : @":sob:", 157 | @"\U0001F602" : @":joy:", 158 | @"\U0001F632" : @":astonished:", 159 | @"\U0001F631" : @":scream:", 160 | }; 161 | }); 162 | return _emojiReverseAliases; 163 | } 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /JLRubyChina/Util/RCRegularParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // SMRegularParser.h 3 | // SinaMBlog 4 | // 5 | // Created by jimneylee on 13-2-18. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCRegularParser : NSObject 12 | 13 | // 返回所有at某人的range数组 14 | + (NSArray *)keywordRangesOfAtPersonInString:(NSString *)string; 15 | 16 | // 返回所有#楼的range数组 17 | + (NSArray *)keywordRangesOfSharpFloorInString:(NSString *)string; 18 | 19 | // 返回表情的range数组 20 | + (NSArray *)keywordRangesOfEmotionInString:(NSString *)string; 21 | 22 | // 返回图片的string数组,和去掉图片链接的trimed字符串 23 | + (NSArray *)imageUrlsInString:(NSString *)string trimedString:(NSString **)trimedString; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCHomepageHeaderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCReplyCell.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | @class RCUserFullEntity; 10 | @interface RCHomepageHeaderView : UIView 11 | - (void)updateViewWithHomepageUser:(RCUserFullEntity*)user; 12 | @end 13 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCNodeCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCNodeCell.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "NICellCatalog.h" 10 | 11 | @interface RCNodeCell : NITextCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCNodeCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCNodeCell.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCNodeCell.h" 10 | #import "RCNodeEntity.h" 11 | 12 | #define TITLE_FONT_SIZE [UIFont boldSystemFontOfSize:17.f] 13 | #define SUBTITLE_FONT_SIZE [UIFont systemFontOfSize:15.f] 14 | 15 | @interface RCNodeCell() 16 | @property (nonatomic, strong) UILabel* topicsCountLabel; 17 | @end 18 | @implementation RCNodeCell 19 | 20 | /////////////////////////////////////////////////////////////////////////////////////////////////// 21 | + (CGFloat)heightForObject:(id)object atIndexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView 22 | { 23 | CGFloat height = 0.f; 24 | CGFloat contentViewMarin = CELL_PADDING_6; 25 | 26 | height = height + contentViewMarin; 27 | height = height + TITLE_FONT_SIZE.lineHeight; 28 | 29 | height = height + CELL_PADDING_2; 30 | 31 | RCNodeEntity* o = (RCNodeEntity*)object; 32 | CGFloat kContentLength = tableView.width - contentViewMarin * 2; 33 | #if 1 34 | NSAttributedString *attributedText = 35 | [[NSAttributedString alloc] initWithString:o.summary 36 | attributes:@{NSFontAttributeName:SUBTITLE_FONT_SIZE}]; 37 | CGRect rect = [attributedText boundingRectWithSize:(CGSize){kContentLength, CGFLOAT_MAX} 38 | options:NSStringDrawingUsesLineFragmentOrigin 39 | context:nil]; 40 | CGSize size = rect.size; 41 | #else 42 | CGSize size = [o.summary sizeWithFont:SUBTITLE_FONT_SIZE 43 | constrainedToSize:CGSizeMake(kContentLength, FLT_MAX) 44 | lineBreakMode:NSLineBreakByWordWrapping]; 45 | #endif 46 | height = height + size.height; 47 | height = height + contentViewMarin; 48 | 49 | return height; 50 | } 51 | 52 | /////////////////////////////////////////////////////////////////////////////////////////////////// 53 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 54 | { 55 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 56 | if (self) { 57 | self.selectionStyle = UITableViewCellSelectionStyleBlue; 58 | self.textLabel.font = TITLE_FONT_SIZE; 59 | self.detailTextLabel.font = SUBTITLE_FONT_SIZE; 60 | self.detailTextLabel.textColor = [UIColor darkGrayColor]; 61 | self.detailTextLabel.numberOfLines = 0; 62 | 63 | // lou 64 | self.topicsCountLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 65 | self.topicsCountLabel.font = SUBTITLE_FONT_SIZE; 66 | self.topicsCountLabel.textColor = [UIColor blackColor]; 67 | self.topicsCountLabel.textAlignment = NSTextAlignmentRight; 68 | [self.contentView addSubview:self.topicsCountLabel]; 69 | 70 | 71 | } 72 | return self; 73 | } 74 | 75 | 76 | /////////////////////////////////////////////////////////////////////////////////////////////////// 77 | - (void)prepareForReuse 78 | { 79 | [super prepareForReuse]; 80 | } 81 | 82 | /////////////////////////////////////////////////////////////////////////////////////////////////// 83 | - (void)layoutSubviews 84 | { 85 | [super layoutSubviews]; 86 | 87 | CGFloat contentViewMarin = CELL_PADDING_6; 88 | CGFloat kContentLength = self.contentView.width - contentViewMarin * 2; 89 | self.textLabel.frame = CGRectMake(contentViewMarin, contentViewMarin, kContentLength / 2, self.textLabel.font.lineHeight); 90 | self.topicsCountLabel.frame = CGRectMake(self.textLabel.right, self.textLabel.top, 91 | kContentLength / 2, self.topicsCountLabel.font.lineHeight); 92 | #if 1 93 | NSAttributedString *attributedText = 94 | [[NSAttributedString alloc] initWithString:self.detailTextLabel.text 95 | attributes:@{NSFontAttributeName:SUBTITLE_FONT_SIZE}]; 96 | CGRect rect = [attributedText boundingRectWithSize:(CGSize){kContentLength, CGFLOAT_MAX} 97 | options:NSStringDrawingUsesLineFragmentOrigin 98 | context:nil]; 99 | CGSize size = rect.size; 100 | #else 101 | CGSize size = [self.detailTextLabel.text sizeWithFont:SUBTITLE_FONT_SIZE 102 | constrainedToSize:CGSizeMake(kContentLength, FLT_MAX) 103 | lineBreakMode:NSLineBreakByWordWrapping]; 104 | #endif 105 | self.detailTextLabel.frame = CGRectMake(self.textLabel.left, self.textLabel.bottom + CELL_PADDING_2, 106 | kContentLength, size.height); 107 | } 108 | 109 | /////////////////////////////////////////////////////////////////////////////////////////////////// 110 | - (BOOL)shouldUpdateCellWithObject:(id)object 111 | { 112 | [super shouldUpdateCellWithObject:object]; 113 | if ([object isKindOfClass:[RCNodeEntity class]]) { 114 | RCNodeEntity* o = (RCNodeEntity*)object; 115 | self.textLabel.text = o.nodeName; 116 | self.detailTextLabel.text = o.summary; 117 | self.topicsCountLabel.text = [NSString stringWithFormat:@"共有 %lu 个主题", o.topicsCount]; 118 | } 119 | return YES; 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCReplyCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCReplyCell.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "NICellCatalog.h" 10 | 11 | // TODO: 12 | // 评论太长,收起和放下 13 | @interface RCReplyCell : NITextCell 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCSiteCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCNodeCell.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "NICellCatalog.h" 10 | 11 | @interface RCSiteCell : NITextCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCSiteCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCNodeCell.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCSiteCell.h" 10 | #import "RCSiteEntity.h" 11 | 12 | #define TITLE_FONT_SIZE [UIFont boldSystemFontOfSize:17.f] 13 | #define SUBTITLE_FONT_SIZE [UIFont systemFontOfSize:15.f] 14 | 15 | @interface RCSiteCell() 16 | @end 17 | @implementation RCSiteCell 18 | 19 | /////////////////////////////////////////////////////////////////////////////////////////////////// 20 | + (CGFloat)heightForObject:(id)object atIndexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView 21 | { 22 | CGFloat height = 0.f; 23 | CGFloat contentViewMarin = CELL_PADDING_6; 24 | 25 | height = height + contentViewMarin; 26 | height = height + TITLE_FONT_SIZE.lineHeight; 27 | 28 | height = height + CELL_PADDING_2; 29 | 30 | RCSiteEntity* o = (RCSiteEntity*)object; 31 | CGFloat kContentLength = tableView.width - contentViewMarin * 2; 32 | #if 1 33 | NSAttributedString *attributedText = 34 | [[NSAttributedString alloc] initWithString:o.description 35 | attributes:@{NSFontAttributeName:SUBTITLE_FONT_SIZE}]; 36 | CGRect rect = [attributedText boundingRectWithSize:(CGSize){kContentLength, CGFLOAT_MAX} 37 | options:NSStringDrawingUsesLineFragmentOrigin 38 | context:nil]; 39 | CGSize size = rect.size; 40 | #else 41 | CGSize size = [o.description sizeWithFont:SUBTITLE_FONT_SIZE 42 | constrainedToSize:CGSizeMake(kContentLength, FLT_MAX) 43 | lineBreakMode:NSLineBreakByWordWrapping]; 44 | #endif 45 | height = height + size.height; 46 | height = height + contentViewMarin; 47 | 48 | return height; 49 | } 50 | 51 | /////////////////////////////////////////////////////////////////////////////////////////////////// 52 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 53 | { 54 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 55 | if (self) { 56 | self.selectionStyle = UITableViewCellSelectionStyleBlue; 57 | self.textLabel.font = TITLE_FONT_SIZE; 58 | self.detailTextLabel.font = SUBTITLE_FONT_SIZE; 59 | self.detailTextLabel.textColor = [UIColor darkGrayColor]; 60 | self.detailTextLabel.numberOfLines = 0; 61 | } 62 | return self; 63 | } 64 | 65 | 66 | /////////////////////////////////////////////////////////////////////////////////////////////////// 67 | - (void)prepareForReuse 68 | { 69 | [super prepareForReuse]; 70 | } 71 | 72 | /////////////////////////////////////////////////////////////////////////////////////////////////// 73 | - (void)layoutSubviews 74 | { 75 | [super layoutSubviews]; 76 | 77 | CGFloat contentViewMarin = CELL_PADDING_6; 78 | CGFloat kContentLength = self.contentView.width - contentViewMarin * 2; 79 | self.textLabel.frame = CGRectMake(contentViewMarin, contentViewMarin, 80 | kContentLength / 2, self.textLabel.font.lineHeight); 81 | #if 1 82 | NSAttributedString *attributedText = 83 | [[NSAttributedString alloc] initWithString:self.detailTextLabel.text 84 | attributes:@{NSFontAttributeName:SUBTITLE_FONT_SIZE}]; 85 | CGRect rect = [attributedText boundingRectWithSize:(CGSize){kContentLength, CGFLOAT_MAX} 86 | options:NSStringDrawingUsesLineFragmentOrigin 87 | context:nil]; 88 | CGSize size = rect.size; 89 | #else 90 | CGSize size = [self.detailTextLabel.text sizeWithFont:SUBTITLE_FONT_SIZE 91 | constrainedToSize:CGSizeMake(kContentLength, FLT_MAX) 92 | lineBreakMode:NSLineBreakByWordWrapping]; 93 | #endif 94 | self.detailTextLabel.frame = CGRectMake(self.textLabel.left, self.textLabel.bottom + CELL_PADDING_2, 95 | kContentLength, size.height); 96 | } 97 | 98 | /////////////////////////////////////////////////////////////////////////////////////////////////// 99 | - (BOOL)shouldUpdateCellWithObject:(id)object 100 | { 101 | [super shouldUpdateCellWithObject:object]; 102 | if ([object isKindOfClass:[RCSiteEntity class]]) { 103 | RCSiteEntity* o = (RCSiteEntity*)object; 104 | self.textLabel.text = o.name; 105 | self.detailTextLabel.text = o.description; 106 | } 107 | return YES; 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCTopicBodyView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTopicDetailHeaderView.h 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-11. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RCTopicDetailEntity.h" 11 | 12 | @interface RCTopicBodyView : UIView 13 | - (void)updateViewWithTopicDetailEntity:(RCTopicDetailEntity*)topicDetailEntity; 14 | @end 15 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCTopicCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // SMStatusCell.h 3 | // SinaMBlogNimbus 4 | // 5 | // Created by Lee jimney on 10/30/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "NICellCatalog.h" 10 | 11 | @interface RCTopicCell : NITextCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCUserCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCReplyCell.h 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "NICellCatalog.h" 10 | 11 | @interface RCUserCell : NITextCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCUserCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCReplyCell.m 3 | // JLRubyChina 4 | // 5 | // Created by Lee jimney on 12/10/13. 6 | // Copyright (c) 2013 jimneylee. All rights reserved. 7 | // 8 | 9 | #import "RCUserCell.h" 10 | #import 11 | #import "UIImage+nimbusImageNamed.h" 12 | #import "RCUserEntity.h" 13 | #import "UIView+findViewController.h" 14 | #import "RCUserHomepageC.h" 15 | 16 | #define NAME_FONT_SIZE [UIFont systemFontOfSize:15.f] 17 | #define DATE_FONT_SIZE [UIFont systemFontOfSize:12.f] 18 | 19 | #define HEAD_IAMGE_HEIGHT 34 20 | 21 | @interface RCUserCell() 22 | @property (nonatomic, strong) NINetworkImageView* headView; 23 | @property (nonatomic, strong) RCUserEntity* user; 24 | @end 25 | 26 | @implementation RCUserCell 27 | 28 | /////////////////////////////////////////////////////////////////////////////////////////////////// 29 | + (CGFloat)heightForObject:(id)object atIndexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView 30 | { 31 | if ([object isKindOfClass:[RCUserEntity class]]) { 32 | CGFloat cellMargin = CELL_PADDING_4; 33 | CGFloat contentViewMarin = CELL_PADDING_6; 34 | CGFloat sideMargin = cellMargin + contentViewMarin; 35 | 36 | CGFloat height = sideMargin; 37 | 38 | // head image 39 | height = height + HEAD_IAMGE_HEIGHT; 40 | 41 | height = height + sideMargin; 42 | 43 | return height; 44 | } 45 | 46 | return 0.0f; 47 | } 48 | 49 | /////////////////////////////////////////////////////////////////////////////////////////////////// 50 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 51 | { 52 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 53 | if (self) { 54 | self.selectionStyle = UITableViewCellSelectionStyleNone; 55 | 56 | // head 57 | self.headView = [[NINetworkImageView alloc] initWithFrame:CGRectMake(0, 0, HEAD_IAMGE_HEIGHT, 58 | HEAD_IAMGE_HEIGHT)]; 59 | self.headView.initialImage = [UIImage nimbusImageNamed:@"head_s.png"]; 60 | [self.contentView addSubview:self.headView]; 61 | UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self 62 | action:@selector(visitUserHomepage)]; 63 | self.headView.userInteractionEnabled = YES; 64 | [self.headView addGestureRecognizer:tap]; 65 | 66 | // name 67 | self.textLabel.font = NAME_FONT_SIZE; 68 | self.textLabel.textColor = [UIColor blackColor]; 69 | self.textLabel.highlightedTextColor = self.textLabel.textColor; 70 | 71 | // date 72 | self.detailTextLabel.font = DATE_FONT_SIZE; 73 | self.detailTextLabel.textColor = [UIColor grayColor]; 74 | self.detailTextLabel.highlightedTextColor = self.detailTextLabel.textColor; 75 | 76 | self.contentView.layer.borderColor = CELL_CONTENT_VIEW_BORDER_COLOR.CGColor; 77 | self.contentView.layer.borderWidth = 1.0f; 78 | 79 | self.backgroundColor = [UIColor clearColor]; 80 | self.contentView.backgroundColor = CELL_CONTENT_VIEW_BG_COLOR; 81 | self.textLabel.backgroundColor = [UIColor clearColor]; 82 | self.detailTextLabel.backgroundColor = [UIColor clearColor]; 83 | } 84 | return self; 85 | } 86 | 87 | /////////////////////////////////////////////////////////////////////////////////////////////////// 88 | - (void)prepareForReuse 89 | { 90 | [super prepareForReuse]; 91 | self.headView.image = [UIImage nimbusImageNamed:@"head_s.png"]; 92 | } 93 | 94 | /////////////////////////////////////////////////////////////////////////////////////////////////// 95 | - (void)layoutSubviews 96 | { 97 | [super layoutSubviews]; 98 | 99 | CGFloat cellMargin = CELL_PADDING_4; 100 | CGFloat contentViewMarin = CELL_PADDING_6; 101 | //CGFloat sideMargin = cellMargin + contentViewMarin; 102 | 103 | self.contentView.frame = CGRectMake(cellMargin, cellMargin, 104 | self.width - cellMargin * 2, 105 | self.height - cellMargin * 2); 106 | 107 | self.headView.left = contentViewMarin; 108 | self.headView.top = contentViewMarin; 109 | 110 | // name 111 | CGFloat topWidth = self.contentView.width - contentViewMarin * 2 - (self.headView.right + CELL_PADDING_10); 112 | self.textLabel.frame = CGRectMake(self.headView.right + CELL_PADDING_10, self.headView.top, 113 | topWidth / 2, 114 | self.textLabel.font.lineHeight); 115 | 116 | // date 117 | self.detailTextLabel.frame = CGRectMake(self.textLabel.left, self.textLabel.bottom, 118 | topWidth, self.detailTextLabel.font.lineHeight); 119 | } 120 | 121 | /////////////////////////////////////////////////////////////////////////////////////////////////// 122 | - (BOOL)shouldUpdateCellWithObject:(id)object 123 | { 124 | [super shouldUpdateCellWithObject:object]; 125 | if ([object isKindOfClass:[RCUserEntity class]]) { 126 | RCUserEntity* o = (RCUserEntity*)object; 127 | self.user = o; 128 | if (o.avatarUrl.length) { 129 | [self.headView setPathToNetworkImage:o.avatarUrl]; 130 | } 131 | else { 132 | self.headView.image = [UIImage nimbusImageNamed:@"head_s.png"]; 133 | } 134 | self.textLabel.text = o.loginId; 135 | } 136 | return YES; 137 | } 138 | 139 | /////////////////////////////////////////////////////////////////////////////////////////////////// 140 | - (void)visitUserHomepage 141 | { 142 | UIViewController* superviewC = self.viewController; 143 | [RCGlobalConfig HUDShowMessage:self.user.loginId 144 | addedToView:[UIApplication sharedApplication].keyWindow]; 145 | if (superviewC) { 146 | RCUserHomepageC* c = [[RCUserHomepageC alloc] initWithUserLoginId:self.user.loginId]; 147 | [superviewC.navigationController pushViewController:c animated:YES]; 148 | } 149 | } 150 | 151 | @end 152 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCUserLauncherButtonView.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2011-2012 Jeff Verkoeyen 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import "NimbusLauncher.h" 18 | 19 | @interface RCUserLauncherViewObject : NILauncherViewObject 20 | 21 | @property (nonatomic, copy) NSString* imageUrl; 22 | 23 | - (id)initWithTitle:(NSString *)title defaultImage:(UIImage *)image imageUrl:(NSString*)imageUrl; 24 | + (id)objectWithTitle:(NSString *)title defaultImage:(UIImage *)image imageUrl:(NSString*)imageUrl; 25 | 26 | @end 27 | 28 | @interface RCUserLauncherButtonView : NILauncherButtonView 29 | @end 30 | -------------------------------------------------------------------------------- /JLRubyChina/Views/RCUserLauncherButtonView.m: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2011-2012 Jeff Verkoeyen 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | #import "RCUserLauncherButtonView.h" 18 | #import 19 | #import "NimbusBadge.h" 20 | 21 | 22 | /////////////////////////////////////////////////////////////////////////////////////////////////// 23 | /////////////////////////////////////////////////////////////////////////////////////////////////// 24 | /////////////////////////////////////////////////////////////////////////////////////////////////// 25 | @implementation RCUserLauncherViewObject 26 | 27 | /////////////////////////////////////////////////////////////////////////////////////////////////// 28 | - (id)initWithTitle:(NSString *)title defaultImage:(UIImage *)image imageUrl:(NSString*)imageUrl { 29 | if ((self = [super initWithTitle:title image:image])) { 30 | _imageUrl = imageUrl; 31 | } 32 | return self; 33 | } 34 | 35 | 36 | /////////////////////////////////////////////////////////////////////////////////////////////////// 37 | + (id)objectWithTitle:(NSString *)title defaultImage:(UIImage *)image imageUrl:(NSString*)imageUrl { 38 | return [[self alloc] initWithTitle:title defaultImage:image imageUrl:imageUrl]; 39 | } 40 | 41 | /////////////////////////////////////////////////////////////////////////////////////////////////// 42 | - (Class)buttonViewClass 43 | { 44 | return [RCUserLauncherButtonView class]; 45 | } 46 | 47 | @end 48 | 49 | /////////////////////////////////////////////////////////////////////////////////////////////////// 50 | /////////////////////////////////////////////////////////////////////////////////////////////////// 51 | /////////////////////////////////////////////////////////////////////////////////////////////////// 52 | @interface RCUserLauncherButtonView() 53 | @property (nonatomic, strong) NINetworkImageView* networkImageview; 54 | @end 55 | 56 | /////////////////////////////////////////////////////////////////////////////////////////////////// 57 | @implementation RCUserLauncherButtonView 58 | 59 | /////////////////////////////////////////////////////////////////////////////////////////////////// 60 | - (id)initWithReuseIdentifier:(NSString *)reuseIdentifier 61 | { 62 | if ((self = [super initWithReuseIdentifier:reuseIdentifier])) { 63 | 64 | _networkImageview = [[NINetworkImageView alloc] init]; 65 | _networkImageview.delegate = self; 66 | // 不需要显示,只需要负责下载图片,实现的有点恶心,但是目前没有更简单的方法,如TTImageView 67 | //[self.button addSubview:_networkImageview]; 68 | } 69 | return self; 70 | } 71 | 72 | /////////////////////////////////////////////////////////////////////////////////////////////////// 73 | - (void)shouldUpdateViewWithObject:(RCUserLauncherViewObject *)object 74 | { 75 | [super shouldUpdateViewWithObject:object]; 76 | 77 | if (object.imageUrl.length) { 78 | // download image to set in button's imageview 79 | [self.networkImageview setPathToNetworkImage:object.imageUrl]; 80 | } 81 | } 82 | 83 | /////////////////////////////////////////////////////////////////////////////////////////////////// 84 | /////////////////////////////////////////////////////////////////////////////////////////////////// 85 | #pragma mark - NINetworkImageViewDelegate 86 | 87 | /////////////////////////////////////////////////////////////////////////////////////////////////// 88 | - (void)networkImageView:(NINetworkImageView *)imageView didLoadImage:(UIImage *)image 89 | { 90 | if (image) { 91 | [self.button setImage:image forState:UIControlStateNormal]; 92 | [self.button.imageView setContentMode:UIViewContentModeScaleAspectFit]; 93 | } 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /JLRubyChina/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /JLRubyChina/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // JLRubyChina 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "RCAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([RCAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /JLRubyChinaTests/JLRubyChinaTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | jimneylee.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /JLRubyChinaTests/JLRubyChinaTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // JLRubyChinaTests.m 3 | // JLRubyChinaTests 4 | // 5 | // Created by jimneylee on 13-12-10. 6 | // Copyright (c) 2013年 jimneylee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JLRubyChinaTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation JLRubyChinaTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /JLRubyChinaTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios,'6.0' 2 | pod 'Nimbus', '~> 1.2.0' 3 | pod 'AFNetworking', '~> 2.2.3' 4 | pod 'MBProgressHUD' 5 | pod 'MTStatusBarOverlay' 6 | pod 'SSKeychain' 7 | pod 'HPGrowingTextView' 8 | pod 'SDSegmentedControl' 9 | pod 'NSStringEmojize' 10 | pod 'LTUpdate', '~> 0.0.2' 11 | pod 'RTagCloudView' 12 | pod 'NSAttributedStringMarkdownParser', '~> 0.0.1' 13 | pod 'ReactiveCocoa', '~> 2.3.1' 14 | pod 'Mantle', '~> 1.5.1' -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (2.2.3): 3 | - AFNetworking/NSURLConnection 4 | - AFNetworking/NSURLSession 5 | - AFNetworking/Reachability 6 | - AFNetworking/Security 7 | - AFNetworking/Serialization 8 | - AFNetworking/UIKit 9 | - AFNetworking/NSURLConnection (2.2.3): 10 | - AFNetworking/Reachability 11 | - AFNetworking/Security 12 | - AFNetworking/Serialization 13 | - AFNetworking/NSURLSession (2.2.3): 14 | - AFNetworking/NSURLConnection 15 | - AFNetworking/Reachability (2.2.3) 16 | - AFNetworking/Security (2.2.3) 17 | - AFNetworking/Serialization (2.2.3) 18 | - AFNetworking/UIKit (2.2.3): 19 | - AFNetworking/NSURLConnection 20 | - AFNetworking/NSURLSession 21 | - fmemopen (0.0.1) 22 | - HPGrowingTextView (1.1) 23 | - LTUpdate (0.0.2) 24 | - MBProgressHUD (0.8) 25 | - MTStatusBarOverlay (0.9.1) 26 | - Nimbus (1.2.0): 27 | - Nimbus/AttributedLabel 28 | - Nimbus/Badge 29 | - Nimbus/Collections 30 | - Nimbus/Collections 31 | - Nimbus/Core 32 | - Nimbus/CSS 33 | - Nimbus/Interapp 34 | - Nimbus/Launcher 35 | - Nimbus/Models 36 | - Nimbus/NetworkControllers 37 | - Nimbus/NetworkImage 38 | - Nimbus/Overview 39 | - Nimbus/PagingScrollView 40 | - Nimbus/Photos 41 | - Nimbus/Textfield 42 | - Nimbus/WebController 43 | - Nimbus/AttributedLabel (1.2.0): 44 | - Nimbus/Core 45 | - Nimbus/Badge (1.2.0): 46 | - Nimbus/Core 47 | - Nimbus/Collections (1.2.0): 48 | - Nimbus/Core 49 | - Nimbus/Core (1.2.0) 50 | - Nimbus/CSS (1.2.0): 51 | - AFNetworking (~> 2.1) 52 | - Nimbus/Core 53 | - Nimbus/Textfield 54 | - Nimbus/Interapp (1.2.0): 55 | - Nimbus/Core 56 | - Nimbus/Launcher (1.2.0): 57 | - Nimbus/Core 58 | - Nimbus/PagingScrollView 59 | - Nimbus/Models (1.2.0): 60 | - Nimbus/Core 61 | - Nimbus/NetworkControllers (1.2.0): 62 | - Nimbus/Core 63 | - Nimbus/NetworkImage (1.2.0): 64 | - AFNetworking (~> 2.1) 65 | - Nimbus/Core 66 | - Nimbus/Overview (1.2.0): 67 | - Nimbus/Core 68 | - Nimbus/Models 69 | - Nimbus/PagingScrollView (1.2.0): 70 | - Nimbus/Core 71 | - Nimbus/Photos (1.2.0): 72 | - Nimbus/Core 73 | - Nimbus/PagingScrollView 74 | - Nimbus/Textfield (1.2.0): 75 | - Nimbus/Core 76 | - Nimbus/WebController (1.2.0): 77 | - Nimbus/Core 78 | - NSAttributedStringMarkdownParser (0.0.1): 79 | - fmemopen 80 | - NSStringEmojize (0.2.0) 81 | - RTagCloudView (1.0.0) 82 | - SDSegmentedControl (1.0.2) 83 | - SSKeychain (1.2.2) 84 | 85 | DEPENDENCIES: 86 | - AFNetworking (~> 2.2.3) 87 | - HPGrowingTextView 88 | - LTUpdate (~> 0.0.2) 89 | - MBProgressHUD 90 | - MTStatusBarOverlay 91 | - Nimbus (~> 1.2.0) 92 | - NSAttributedStringMarkdownParser (~> 0.0.1) 93 | - NSStringEmojize 94 | - RTagCloudView 95 | - SDSegmentedControl 96 | - SSKeychain 97 | 98 | SPEC CHECKSUMS: 99 | AFNetworking: ae513199cca79e9d7af2708ccabe2ed075550c42 100 | fmemopen: 0c47f38f28a59216152d51fa80672c1549f80ea0 101 | HPGrowingTextView: 4318f557b33c19def1c53ec275d6e2a2d6589cd0 102 | LTUpdate: ee58a30f73e6dcbc47ce1e5c617b024212a2dd98 103 | MBProgressHUD: 2bbc6f470111daf7f3eaa4eb12b8cbf01c4c0622 104 | MTStatusBarOverlay: 2cee705996e4e307191d423bf49e583b9b2c14ac 105 | Nimbus: bbde56c7e845d3c38c1f484018ef1bb3259c0507 106 | NSAttributedStringMarkdownParser: fb93a47c4be94a80f4bd5e81dd8067cce5f7f5eb 107 | NSStringEmojize: ea303101d9174142813454c4f3616a1a569c1052 108 | RTagCloudView: 2c190afd8b633d908aba80b8f741403c004431be 109 | SDSegmentedControl: 165956a426f1fd7ff1eb486c4931241f12e0867e 110 | SSKeychain: 3d0b76c87e7b062a7ad1631a825fddec84367d44 111 | 112 | COCOAPODS: 0.32.1 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Ruby China社区和V2EX社区接口通用客户端 2 | 3 | [Ruby China](http://ruby-china.org/)社区接口,社区有:[Ruby China](http://ruby-china.org/)、[Tester Home](http://testerhome.com/) 4 | 5 | [V2EX](http://www.v2ex.com/)社区接口:[V2EX](http://www.v2ex.com/) 6 | 7 | ## 强烈提醒,勿随意发帖测试 8 | 请把玩这个客户端源码的同学,不要在上面几个社区上随意发帖测试,谢谢配合。 9 | 10 | ## THKS To Contributors 11 | [**luzhiyongGit**](https://github.com/luzhiyongGit) [**bachue**](https://github.com/bachue) [**gbammc**](https://github.com/gbammc) 12 | 13 | ##JLRubyChina-iPhone 14 | 希望能给上面几个社区活跃的同学带来一点帮助,节省一点时间。欢迎大家在使用过程中,提出改进建议和意见。同时期望更多的同学参与学习交流,维护和优化APP。 15 | 16 | ## 开发环境 17 | XCode5 iOS7.x & iOS6.x 18 | 19 | ## 编译安装 20 | 1、下载[最近的Release版本](https://github.com/jimneylee/JLRubyChina-iPhone/releases),直接编译即可安装。 21 | 22 | 2、fork后clone到本地,手工添加依赖库安装方法 23 | * 1、git submodule 24 | 25 | ``` bash 26 | $ git submodule init 27 | $ git submodule update 28 | ``` 29 | 30 | * 2、[CocoaPods](http://cocoapods.org) 31 | 32 | ``` bash 33 | $ pod install 34 | ``` 35 | 36 | 3、通过'JLRubyChina.xcworkspace'打开项目,也可以[自定义xopen命令](http://jimneylee.github.io/2014/01/09/add-xopen-command-to-open-xcode-workspace/)便捷打开 37 | 38 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/ErrorResolve/open_xcworkspace.jpg) 39 | 40 | # ERROR解决方法 41 | 42 | 1、若出现这个问题:'vendor/JLNimbusTimeline' already exists in the index 43 | ``` bash 44 | $ git rm --cached vendor/JLNimbusTimeline 45 | ``` 46 | 47 | 2、如果JLNimbusTimeline里面编译出错,`git submodule update`无法更新时,请删除JLNimbusTimeline重新添加,步骤如下: 48 | 49 | * 1、`.git/config`删除依赖JLNimbusTimeline相关,`vi .git/config` 50 | * 2、删除`.git/modules/vendor`下JLNimbusTimeline目录,`rm -rf .git/modules/vendor/JLNimbusTimeline` 51 | * 3、到工程vendor目录,删除JLNimbusTimeline,`rm -rf vendor/JLNimbusTimeline` 52 | * 4、删除`git submodule add`对应的cache,`git rm --cached vendor/JLNimbusTimeline` 53 | * 5、重新添加submodule, 54 | `git submodule add https://github.com/jimneylee/JLNimbusTimeline.git vendor/JLNimbusTimeline` 55 | 56 | 5、若出现这个问题:diff: /../Podfile.lock: No such file or directory 57 | diff: /Manifest.lock: No such file or directory 58 | error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation. 59 | ``` bash 60 | $ [sudo]pod install 61 | ``` 62 | 63 | 6、若出现这个问题:library not found for -lPods 64 | 65 | 解决方法1、没有通过pod update生成的JLRubyChina.xcworkspace来打开工程 66 | 67 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/ErrorResolve/open_xcworkspace.jpg) 68 | 69 | 解决方法2、Pods工程中,试着如下修改TARGETS的Pods,今天搞了一上午才解决这个错误问题 70 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/ErrorResolve/not_found_pods.png) 71 | 72 | # 多个git server仓库同步 73 | 今天研究了多个git server仓库同步,把项目同步到[osc](http://git.oschina.net)和[gitcafe](https://gitcafe.com),不熟悉如何同步到多个git server,可以参考我的[这篇blog](http://jimneylee.github.io/2013/12/20/git-push-multi-server/),仓库地址分别如下 74 | 75 | github:https://github.com/jimneylee/JLRubyChina-iPhone 76 | 77 | gitcafe:https://gitcafe.com/jimneylee/JLRubyChina-iPhone 78 | 79 | oschina:http://git.oschina.net/jimneylee/JLRubyChina-iPhone 80 | 81 | csdn:https://code.csdn.net/jimney_ljj/JLRubyChina-iPhone 82 | 83 | 使用相同的ssh key,同步还是很方便的,后面考虑进一步精简步骤,自动化发布到各个git server 84 | 85 | ### DONE 86 | 1、首页热门帖子显示 87 | 88 | 2、帖子详细浏览、帖子回复列表 89 | 90 | 3、帖子关注、收藏、@某人 91 | 92 | 4、回复帖子支持表情选择 93 | 94 | 5、发帖到指定分类,支持markdown语法 95 | 96 | 6、分类节点列表查看 97 | 98 | 7、酷站分组显示 99 | 100 | 8、会员TOP N查看 101 | 102 | 9、我的主页,已发帖子、收藏帖子查看 103 | 104 | 10、Ruby China Wiki 105 | 106 | 11、更多功能包含:清空缓存、更新检测、给我评分、关于APP 107 | 108 | 12、帖子列表支持markdown语法解析显示(仅使用于7.x),效果不是太好 109 | 110 | 13、网络2G/3G/WIFI切换提示 111 | 112 | ## LICENSE 113 | 本项目基于MIT协议发布 114 | MIT: [http://rem.mit-license.org](http://rem.mit-license.org) 115 | 116 | # Screenshots 117 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/default.png) 118 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/home_activity_topics.png) 119 | 120 | 121 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/left_menu_side.png) 122 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/node_select.png) 123 | 124 | 125 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/topic_reply.png) 126 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/home_page.png) 127 | 128 | 129 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/nodes.png) 130 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/outside_link_sites.png) 131 | 132 | 133 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/top_members.png) 134 | ![image](https://github.com/jimneylee/JLRubyChina-iPhone/raw/master/Resource/Screenshots/more.png) 135 | -------------------------------------------------------------------------------- /Resource/Images/Common/37x-Checkmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/37x-Checkmark.png -------------------------------------------------------------------------------- /Resource/Images/Common/37x-Checkmark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/37x-Checkmark@2x.png -------------------------------------------------------------------------------- /Resource/Images/Common/QuickReply/MessageEntryBackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/QuickReply/MessageEntryBackground.png -------------------------------------------------------------------------------- /Resource/Images/Common/QuickReply/MessageEntryBackground@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/QuickReply/MessageEntryBackground@2x.png -------------------------------------------------------------------------------- /Resource/Images/Common/QuickReply/MessageEntryInputField.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/QuickReply/MessageEntryInputField.png -------------------------------------------------------------------------------- /Resource/Images/Common/QuickReply/MessageEntryInputField@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/QuickReply/MessageEntryInputField@2x.png -------------------------------------------------------------------------------- /Resource/Images/Common/QuickReply/MessageEntrySendButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/QuickReply/MessageEntrySendButton.png -------------------------------------------------------------------------------- /Resource/Images/Common/QuickReply/MessageEntrySendButton@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/QuickReply/MessageEntrySendButton@2x.png -------------------------------------------------------------------------------- /Resource/Images/Common/QuickReply/MessageEntrySendButtonPressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/QuickReply/MessageEntrySendButtonPressed.png -------------------------------------------------------------------------------- /Resource/Images/Common/QuickReply/MessageEntrySendButtonPressed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/QuickReply/MessageEntrySendButtonPressed@2x.png -------------------------------------------------------------------------------- /Resource/Images/Common/head_b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/head_b.png -------------------------------------------------------------------------------- /Resource/Images/Common/head_b@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/head_b@2x.png -------------------------------------------------------------------------------- /Resource/Images/Common/head_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/head_s.png -------------------------------------------------------------------------------- /Resource/Images/Common/head_s@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/head_s@2x.png -------------------------------------------------------------------------------- /Resource/Images/Common/icon_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/icon_menu.png -------------------------------------------------------------------------------- /Resource/Images/Common/icon_menu@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/icon_menu@2x.png -------------------------------------------------------------------------------- /Resource/Images/Common/more_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/more_photo.png -------------------------------------------------------------------------------- /Resource/Images/Common/more_photo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Common/more_photo@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/Default-375w-667h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/Default-375w-667h@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/Default-414w-736h@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/Default-414w-736h@3x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/Default-568h@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/Default.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/Default@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon/icon.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon/icon120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon/icon120.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon/icon58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon/icon58.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon/icon80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon/icon80.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon/icon@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon/logo512.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon120.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon512.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon58.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon80.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/icon@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/pure_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/pure_icon@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/ruby-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/ruby-logo.png -------------------------------------------------------------------------------- /Resource/Images/Forums/RubyChina/IconDefault/ruby-logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/RubyChina/IconDefault/ruby-logo@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/TesterHome/IconDefault/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/TesterHome/IconDefault/Default-568h@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/TesterHome/IconDefault/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/TesterHome/IconDefault/Default.png -------------------------------------------------------------------------------- /Resource/Images/Forums/TesterHome/IconDefault/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/TesterHome/IconDefault/Default@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/TesterHome/IconDefault/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/TesterHome/IconDefault/icon.png -------------------------------------------------------------------------------- /Resource/Images/Forums/TesterHome/IconDefault/icon120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/TesterHome/IconDefault/icon120.png -------------------------------------------------------------------------------- /Resource/Images/Forums/TesterHome/IconDefault/icon58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/TesterHome/IconDefault/icon58.png -------------------------------------------------------------------------------- /Resource/Images/Forums/TesterHome/IconDefault/icon80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/TesterHome/IconDefault/icon80.png -------------------------------------------------------------------------------- /Resource/Images/Forums/TesterHome/IconDefault/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/TesterHome/IconDefault/icon@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/TesterHome/IconDefault/ruby-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/TesterHome/IconDefault/ruby-logo.png -------------------------------------------------------------------------------- /Resource/Images/Forums/TesterHome/IconDefault/ruby-logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/TesterHome/IconDefault/ruby-logo@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/IconDefault/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/IconDefault/Default-568h@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/IconDefault/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/IconDefault/Default.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/IconDefault/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/IconDefault/Default@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/IconDefault/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/IconDefault/icon.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/IconDefault/icon120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/IconDefault/icon120.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/IconDefault/icon58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/IconDefault/icon58.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/IconDefault/icon80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/IconDefault/icon80.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/IconDefault/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/IconDefault/icon@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/IconDefault/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/IconDefault/logo.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/IconDefault/ruby-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/IconDefault/ruby-logo.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/IconDefault/ruby-logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/IconDefault/ruby-logo@2x.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/Screenshots/0110_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/Screenshots/0110_1.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/Screenshots/0110_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/Screenshots/0110_2.png -------------------------------------------------------------------------------- /Resource/Images/Forums/V2EX/Screenshots/0110_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Images/Forums/V2EX/Screenshots/0110_3.png -------------------------------------------------------------------------------- /Resource/Screenshots/ErrorResolve/not_found_pods.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/ErrorResolve/not_found_pods.png -------------------------------------------------------------------------------- /Resource/Screenshots/ErrorResolve/open_xcworkspace.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/ErrorResolve/open_xcworkspace.jpg -------------------------------------------------------------------------------- /Resource/Screenshots/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/default.png -------------------------------------------------------------------------------- /Resource/Screenshots/home_activity_topics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/home_activity_topics.png -------------------------------------------------------------------------------- /Resource/Screenshots/home_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/home_page.png -------------------------------------------------------------------------------- /Resource/Screenshots/left_menu_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/left_menu_side.png -------------------------------------------------------------------------------- /Resource/Screenshots/more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/more.png -------------------------------------------------------------------------------- /Resource/Screenshots/node_select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/node_select.png -------------------------------------------------------------------------------- /Resource/Screenshots/nodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/nodes.png -------------------------------------------------------------------------------- /Resource/Screenshots/outside_link_sites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/outside_link_sites.png -------------------------------------------------------------------------------- /Resource/Screenshots/top_members.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/top_members.png -------------------------------------------------------------------------------- /Resource/Screenshots/topic_reply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimneylee/JLRubyChina-iPhone/bd60977fd3212e3f3713e9f0152cb4e94bcfb594/Resource/Screenshots/topic_reply.png -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | 2 | #TODO 3 | 1、与后台API接口修改确认,参见API Problem文档说明 4 | 2、网络2G/3G/WIFI切换提示 5 | 3、发布模式下需屏蔽No Point分类 6 | 4、增加社交组件分享 7 | 5、经公测稳定,提交AppStore审核,方便大家下载使用 8 | 6、如果需要的话,添加友盟统计 9 | 10 | // Other 11 | pod push command: 12 | pod spec lint libname.podspec 13 | pod push libname.podspec 14 | 15 | git submodule add https://github.com/jimneylee/RTagCloudView.git vendor/RTagCloudView 16 | git rm -r --cached vendor/RTagCloudView 17 | --------------------------------------------------------------------------------