├── README.md ├── PHPHub ├── Images.xcassets │ ├── Contents.json │ ├── Base │ │ ├── Contents.json │ │ ├── back.imageset │ │ │ ├── back.png │ │ │ └── Contents.json │ │ ├── cancel.imageset │ │ │ ├── cancel.png │ │ │ └── Contents.json │ │ ├── logo.imageset │ │ │ ├── icon_180.png │ │ │ └── Contents.json │ │ ├── more.imageset │ │ │ ├── more_icon.png │ │ │ └── Contents.json │ │ ├── pure_icon.imageset │ │ │ ├── pure_icon.png │ │ │ └── Contents.json │ │ └── estgroup_short_intro.imageset │ │ │ ├── estgroup_short_intro.png │ │ │ └── Contents.json │ ├── Me │ │ ├── Contents.json │ │ ├── ring_icon.imageset │ │ │ ├── ring_icon.png │ │ │ └── Contents.json │ │ ├── topic_icon.imageset │ │ │ ├── topic_icon.png │ │ │ └── Contents.json │ │ ├── watch_icon.imageset │ │ │ ├── watch_icon.png │ │ │ └── Contents.json │ │ ├── comment_icon.imageset │ │ │ ├── comment_icon.png │ │ │ └── Contents.json │ │ ├── favorite_icon.imageset │ │ │ ├── favorite_icon.png │ │ │ └── Contents.json │ │ └── settings_icon.imageset │ │ │ ├── settings_icon.png │ │ │ └── Contents.json │ ├── User │ │ ├── Contents.json │ │ ├── blog_icon.imageset │ │ │ ├── blog_icon.png │ │ │ └── Contents.json │ │ ├── tick_icon.imageset │ │ │ ├── tick_icon.png │ │ │ └── Contents.json │ │ ├── local_icon.imageset │ │ │ ├── local_icon.png │ │ │ └── Contents.json │ │ ├── github_icon.imageset │ │ │ ├── github_icon.png │ │ │ └── Contents.json │ │ ├── twitter_icon.imageset │ │ │ ├── twitter_icon.png │ │ │ └── Contents.json │ │ └── edit_profile_icon.imageset │ │ │ ├── edit_profile_icon.png │ │ │ └── Contents.json │ ├── TabBar │ │ ├── Contents.json │ │ ├── me_icon.imageset │ │ │ ├── me_icon.png │ │ │ └── Contents.json │ │ ├── wiki_icon.imageset │ │ │ ├── wiki_icon.png │ │ │ └── Contents.json │ │ ├── forum_icon.imageset │ │ │ ├── forum_icon.png │ │ │ └── Contents.json │ │ ├── reply_icon.imageset │ │ │ ├── reply_icon.png │ │ │ └── Contents.json │ │ ├── comments_icon.imageset │ │ │ ├── comments_icon.png │ │ │ └── Contents.json │ │ ├── essential_icon.imageset │ │ │ ├── essential_icon.png │ │ │ └── Contents.json │ │ ├── me_selected_icon.imageset │ │ │ ├── me_selected_icon.png │ │ │ └── Contents.json │ │ ├── tabbar_backgroud.imageset │ │ │ ├── tabbar_background@2x.png │ │ │ └── Contents.json │ │ ├── wiki_selected_icon.imageset │ │ │ ├── wiki_selected_icon.png │ │ │ └── Contents.json │ │ ├── forum_selected_icon.imageset │ │ │ ├── forum_selected_icon.png │ │ │ └── Contents.json │ │ └── essential_selected_icon.imageset │ │ │ ├── essential_selected_icon.png │ │ │ └── Contents.json │ ├── Topic │ │ ├── Contents.json │ │ ├── sad_face.imageset │ │ │ ├── sad_face.png │ │ │ └── Contents.json │ │ ├── send_icon.imageset │ │ │ ├── send_icon.png │ │ │ └── Contents.json │ │ ├── vote_icon.imageset │ │ │ ├── vote_icon.png │ │ │ └── Contents.json │ │ ├── pencil_icon.imageset │ │ │ ├── pencil_icon.png │ │ │ └── Contents.json │ │ ├── upvote_icon.imageset │ │ │ ├── upvote_icon.png │ │ │ └── Contents.json │ │ ├── corner_circle.imageset │ │ │ ├── corner_circle.png │ │ │ └── Contents.json │ │ ├── downvote_icon.imageset │ │ │ ├── downvote_icon.png │ │ │ └── Contents.json │ │ ├── big_upvote_icon.imageset │ │ │ ├── big_upvote_icon.png │ │ │ └── Contents.json │ │ ├── watch_blue_icon.imageset │ │ │ ├── watch_blue_icon.png │ │ │ └── Contents.json │ │ ├── big_downvote_icon.imageset │ │ │ ├── big_downvote_icon.png │ │ │ └── Contents.json │ │ ├── avatar_placeholder.imageset │ │ │ ├── avatar_placeholder.png │ │ │ └── Contents.json │ │ ├── favorite_blue_icon.imageset │ │ │ ├── favorite_blue_icon.png │ │ │ └── Contents.json │ │ ├── pencil_square_icon.imageset │ │ │ ├── pencil_square_icon.png │ │ │ └── Contents.json │ │ ├── big_upvote_selected_icon.imageset │ │ │ ├── big_upvote_selected_icon.png │ │ │ └── Contents.json │ │ └── big_downvote_selected_icon.imageset │ │ │ ├── big_downvote__selected_icon.png │ │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── icon_100.png │ │ ├── icon_114.png │ │ ├── icon_120.png │ │ ├── icon_144.png │ │ ├── icon_152.png │ │ ├── icon_180.png │ │ ├── icon_29-1.png │ │ ├── icon_29.png │ │ ├── icon_40.png │ │ ├── icon_50.png │ │ ├── icon_57.png │ │ ├── icon_58-1.png │ │ ├── icon_58.png │ │ ├── icon_72.png │ │ ├── icon_76.png │ │ ├── icon_80-1.png │ │ ├── icon_80.png │ │ ├── icon_87.png │ │ ├── icon_120-1.png │ │ └── Contents.json │ ├── Passport │ │ └── anonymous_logo.imageset │ │ │ ├── anonymous_logo.png │ │ │ └── Contents.json │ └── ViewPager │ │ └── pager_title_indicator.imageset │ │ ├── pager_title_indicator.png │ │ └── Contents.json ├── ThirdParty │ ├── JPush │ │ └── lib │ │ │ └── libPushSDK-1.8.5.a │ ├── GoogleAnalytics │ │ ├── libGoogleAnalyticsServices.a │ │ └── Library │ │ │ ├── GAITrackedViewController.h │ │ │ ├── GAILogger.h │ │ │ ├── GAITracker.h │ │ │ ├── GAIEcommercePromotion.h │ │ │ └── GAIEcommerceProduct.h │ ├── TPKeyboardAvoiding │ │ ├── TPKeyboardAvoidingTableView.h │ │ ├── TPKeyboardAvoidingCollectionView.h │ │ ├── TPKeyboardAvoidingScrollView.h │ │ ├── UIScrollView+TPKeyboardAvoidingAdditions.h │ │ └── TPKeyboardAvoidingScrollView.m │ ├── TitlePagerView │ │ └── TitlePagerView.h │ ├── TOWebViewController │ │ ├── TOActivityChrome.h │ │ ├── TOActivitySafari.h │ │ └── UIImage+TOWebViewControllerIcons.h │ └── ViewPagerController │ │ └── ViewPagerController.h ├── Views │ ├── Base │ │ ├── BaseView.h │ │ ├── SkipButton.h │ │ ├── BubbleButton.h │ │ ├── BaseWebView.h │ │ ├── BaseView.m │ │ ├── SkipButton.m │ │ └── BubbleButton.m │ ├── Topic │ │ ├── EmptyTopicView.h │ │ ├── TopicSearchBar.h │ │ ├── TopicListCell.h │ │ ├── TopicVoteView.h │ │ ├── TopicSearchBar.m │ │ ├── TopicListTableView.h │ │ └── EmptyTopicView.m │ ├── Comment │ │ ├── CommentListViewController.h │ │ └── CommentListViewController.m │ ├── Notification │ │ ├── NotificationListTableView.h │ │ └── NotificationListCell.h │ └── LaunchAd │ │ └── LaunchScreenAdView.h ├── Apis │ ├── AdApi.h │ ├── NodeApi.h │ ├── NotificationApi.h │ ├── UserApi.h │ ├── NodeApi.m │ ├── AdApi.m │ ├── TopicApi.h │ └── NotificationApi.m ├── Handlers │ ├── ExceptionHandler.h │ ├── APIRequestHandler.h │ ├── JpushHandler.h │ ├── LaunchScreenAdHandler.h │ ├── AccessTokenHandler.h │ ├── UMengSocialHandler.h │ ├── JumpToOtherVCHandler.h │ ├── AnalyticsHandler.h │ ├── ExceptionHandler.m │ ├── UMengSocialHandler.m │ ├── AccessTokenHandler.m │ └── JumpToOtherVCHandler.m ├── Controllers │ ├── Topic │ │ ├── PostTopicViewController.h │ │ ├── TopicDetailViewController.h │ │ ├── ReplyTopicViewController.h │ │ └── ReplyTopicViewController.m │ ├── WiKi │ │ ├── WiKiListViewController.h │ │ └── WiKiListViewController.m │ ├── Settings │ │ ├── SettingsViewController.h │ │ └── SettingsViewController.m │ ├── Essential │ │ └── EssentialListViewController.h │ ├── Forum │ │ ├── TopicListContainerViewController.h │ │ └── TopicListViewController.h │ ├── User │ │ ├── UserProfileViewController.h │ │ └── EditUserProfileViewController.h │ ├── Notification │ │ ├── NotificationListViewController.h │ │ └── NotificationListViewController.m │ ├── Me │ │ └── MeViewController.h │ ├── TabBar │ │ └── BaseTabBarViewController.h │ └── Passport │ │ └── LoginViewController.h ├── Utils │ ├── Categories │ │ ├── UIViewController │ │ │ ├── UIViewController+Custom.h │ │ │ └── UIViewController+Custom.m │ │ ├── UIResponder │ │ │ ├── UIResponder+Router.h │ │ │ └── UIResponder+Router.m │ │ ├── NSString │ │ │ ├── NSString+Additions.h │ │ │ └── NSString+Additions.m │ │ ├── GVUserDefaults │ │ │ ├── GVUserDefaults+Properties.m │ │ │ └── GVUserDefaults+Properties.h │ │ ├── AFOAuth2Manager │ │ │ ├── AFOAuth2Manager+Addtions.h │ │ │ └── AFOAuth2Manager+Addtions.m │ │ ├── UIView │ │ │ ├── UIView+Additions.h │ │ │ └── UIView+Additions.m │ │ └── NSURL+QueryDictionary │ │ │ └── NSURL+QueryDictionary.h │ ├── DBManager │ │ ├── UserDBManager.h │ │ ├── LaunchScreenAdDBManager.h │ │ ├── UserDBManager.m │ │ └── LaunchScreenAdDBManager.m │ ├── Entities │ │ ├── NodeEntity.h │ │ ├── PaginationEntity.h │ │ ├── NodeEntity.m │ │ ├── CommentEntity.h │ │ ├── PaginationEntity.m │ │ ├── CommentEntity.m │ │ ├── NotificationEntity.h │ │ ├── NotificationEntity.m │ │ ├── LaunchScreenAdEntity.h │ │ ├── TopicEntity.h │ │ ├── UserEntity.h │ │ ├── TopicEntity.m │ │ ├── LaunchScreenAdEntity.m │ │ └── UserEntity.m │ └── Helper │ │ ├── BaseHelper.h │ │ └── BaseHelper.m ├── Models │ ├── AdModel.h │ ├── NodeModel.h │ ├── NotificationModel.h │ ├── NodeModel.m │ ├── UserModel.h │ ├── NotificationModel.m │ ├── TopicModel.h │ ├── AdModel.m │ ├── UserModel.m │ └── TopicModel.m ├── main.m ├── PushConfig.example.plist ├── AppDelegate.h ├── BaseClasses │ ├── BaseModel.h │ ├── CurrentUser.h │ ├── BaseEntity.h │ ├── BaseModel.m │ ├── BaseApi.h │ ├── BaseDBManager.h │ ├── CurrentUser.m │ └── BaseEntity.m ├── Constants │ ├── DebugConstant.h │ ├── SecretConstant.example.h │ ├── UIConstant.h │ └── APIConstant.h ├── Resources │ └── Migrations.bundle │ │ ├── 20151019093301120_create_launchScreenAds_table.sql │ │ └── 20151002095034729_create_users_table.sql └── PHPHub-Prefix.pch ├── PHPHub.xcodeproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── PHPHub.xcworkspace └── contents.xcworkspacedata ├── PHPHubTests ├── Info.plist └── PHPHubTests.m ├── Podfile └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | Move to [Aufree's PHPHub-iOS](https://github.com/Aufree/phphub-ios) 2 | -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /PHPHub/ThirdParty/JPush/lib/libPushSDK-1.8.5.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/ThirdParty/JPush/lib/libPushSDK-1.8.5.a -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/back.imageset/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Base/back.imageset/back.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_100.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_114.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_120.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_144.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_152.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_180.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_29-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_29-1.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_29.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_40.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_50.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_57.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_58-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_58-1.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_58.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_72.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_76.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_80-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_80-1.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_80.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_87.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/cancel.imageset/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Base/cancel.imageset/cancel.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/logo.imageset/icon_180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Base/logo.imageset/icon_180.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/more.imageset/more_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Base/more.imageset/more_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/icon_120-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/AppIcon.appiconset/icon_120-1.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/pure_icon.imageset/pure_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Base/pure_icon.imageset/pure_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/ring_icon.imageset/ring_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Me/ring_icon.imageset/ring_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/topic_icon.imageset/topic_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Me/topic_icon.imageset/topic_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/watch_icon.imageset/watch_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Me/watch_icon.imageset/watch_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/me_icon.imageset/me_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/TabBar/me_icon.imageset/me_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/sad_face.imageset/sad_face.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/sad_face.imageset/sad_face.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/blog_icon.imageset/blog_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/User/blog_icon.imageset/blog_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/tick_icon.imageset/tick_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/User/tick_icon.imageset/tick_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/wiki_icon.imageset/wiki_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/TabBar/wiki_icon.imageset/wiki_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/send_icon.imageset/send_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/send_icon.imageset/send_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/vote_icon.imageset/vote_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/vote_icon.imageset/vote_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/local_icon.imageset/local_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/User/local_icon.imageset/local_icon.png -------------------------------------------------------------------------------- /PHPHub/ThirdParty/GoogleAnalytics/libGoogleAnalyticsServices.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/ThirdParty/GoogleAnalytics/libGoogleAnalyticsServices.a -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/comment_icon.imageset/comment_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Me/comment_icon.imageset/comment_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/forum_icon.imageset/forum_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/TabBar/forum_icon.imageset/forum_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/reply_icon.imageset/reply_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/TabBar/reply_icon.imageset/reply_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/pencil_icon.imageset/pencil_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/pencil_icon.imageset/pencil_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/upvote_icon.imageset/upvote_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/upvote_icon.imageset/upvote_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/github_icon.imageset/github_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/User/github_icon.imageset/github_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/favorite_icon.imageset/favorite_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Me/favorite_icon.imageset/favorite_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/settings_icon.imageset/settings_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Me/settings_icon.imageset/settings_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/twitter_icon.imageset/twitter_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/User/twitter_icon.imageset/twitter_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/comments_icon.imageset/comments_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/TabBar/comments_icon.imageset/comments_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/corner_circle.imageset/corner_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/corner_circle.imageset/corner_circle.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/downvote_icon.imageset/downvote_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/downvote_icon.imageset/downvote_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/essential_icon.imageset/essential_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/TabBar/essential_icon.imageset/essential_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Passport/anonymous_logo.imageset/anonymous_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Passport/anonymous_logo.imageset/anonymous_logo.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/big_upvote_icon.imageset/big_upvote_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/big_upvote_icon.imageset/big_upvote_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/watch_blue_icon.imageset/watch_blue_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/watch_blue_icon.imageset/watch_blue_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/me_selected_icon.imageset/me_selected_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/TabBar/me_selected_icon.imageset/me_selected_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/big_downvote_icon.imageset/big_downvote_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/big_downvote_icon.imageset/big_downvote_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/edit_profile_icon.imageset/edit_profile_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/User/edit_profile_icon.imageset/edit_profile_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/tabbar_backgroud.imageset/tabbar_background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/TabBar/tabbar_backgroud.imageset/tabbar_background@2x.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/wiki_selected_icon.imageset/wiki_selected_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/TabBar/wiki_selected_icon.imageset/wiki_selected_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/avatar_placeholder.imageset/avatar_placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/avatar_placeholder.imageset/avatar_placeholder.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/favorite_blue_icon.imageset/favorite_blue_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/favorite_blue_icon.imageset/favorite_blue_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/pencil_square_icon.imageset/pencil_square_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/pencil_square_icon.imageset/pencil_square_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/estgroup_short_intro.imageset/estgroup_short_intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Base/estgroup_short_intro.imageset/estgroup_short_intro.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/forum_selected_icon.imageset/forum_selected_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/TabBar/forum_selected_icon.imageset/forum_selected_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/essential_selected_icon.imageset/essential_selected_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/TabBar/essential_selected_icon.imageset/essential_selected_icon.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/ViewPager/pager_title_indicator.imageset/pager_title_indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/ViewPager/pager_title_indicator.imageset/pager_title_indicator.png -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/big_upvote_selected_icon.imageset/big_upvote_selected_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/big_upvote_selected_icon.imageset/big_upvote_selected_icon.png -------------------------------------------------------------------------------- /PHPHub.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/big_downvote_selected_icon.imageset/big_downvote__selected_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phphub/phphub-ios/HEAD/PHPHub/Images.xcassets/Topic/big_downvote_selected_icon.imageset/big_downvote__selected_icon.png -------------------------------------------------------------------------------- /PHPHub/Views/Base/BaseView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseView.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/26/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BaseView : UIView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Views/Base/SkipButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // SkipButton.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SkipButton : UIButton 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Views/Base/BubbleButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // BubbleButton.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/9/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BubbleButton : UIButton 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Views/Topic/EmptyTopicView.h: -------------------------------------------------------------------------------- 1 | // 2 | // EmptyTopicView.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/23/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface EmptyTopicView : UIView 12 | @end 13 | -------------------------------------------------------------------------------- /PHPHub/Apis/AdApi.h: -------------------------------------------------------------------------------- 1 | // 2 | // AdApi.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseApi.h" 10 | 11 | @interface AdApi : BaseApi 12 | - (id)getAdvertsLaunchScreen:(BaseResultBlock)block; 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /PHPHub/Handlers/ExceptionHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // ExceptionHandler.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/21/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ExceptionHandler : NSObject 12 | + (void)bootup; 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Apis/NodeApi.h: -------------------------------------------------------------------------------- 1 | // 2 | // NodeApi.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/10/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseApi.h" 10 | #import "NodeEntity.h" 11 | 12 | @interface NodeApi : BaseApi 13 | - (id)getAllTopicNode:(BaseResultBlock)block; 14 | @end 15 | -------------------------------------------------------------------------------- /PHPHub/Controllers/Topic/PostTopicViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PostTopicViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/9/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PostTopicViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Controllers/WiKi/WiKiListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // WiKiListViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface WiKiListViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/UIViewController/UIViewController+Custom.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Custom.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/3/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIViewController (Custom) 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Controllers/Settings/SettingsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/4/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SettingsViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Views/Topic/TopicSearchBar.h: -------------------------------------------------------------------------------- 1 | // 2 | // TopicSearchBar.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/12/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TopicSearchBar : UISearchBar 12 | - (instancetype)initWithFrame:(CGRect)frame; 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Controllers/Essential/EssentialListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // EssentialListViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface EssentialListViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Utils/DBManager/UserDBManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // UserDBManager.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/2/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseDBManager.h" 10 | #import "UserEntity.h" 11 | 12 | @interface UserDBManager : BaseDBManager 13 | + (UserEntity *)findByUserId:(NSNumber *)userId; 14 | @end -------------------------------------------------------------------------------- /PHPHub/Views/Topic/TopicListCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TopicListCell.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TopicEntity.h" 11 | 12 | @interface TopicListCell : UITableViewCell 13 | @property (nonatomic, strong) TopicEntity *topicEntity; 14 | @end 15 | -------------------------------------------------------------------------------- /PHPHub/Models/AdModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // AdModel.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseModel.h" 10 | #import "AdApi.h" 11 | 12 | @interface AdModel : BaseModel 13 | @property (nonatomic, strong) AdApi *api; 14 | - (id)getAdvertsLaunchScreen:(BaseResultBlock)block; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Views/Comment/CommentListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CommentListViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/26/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CommentListViewController : UIViewController 12 | @property (nonatomic, strong) TopicEntity *topic; 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Handlers/APIRequestHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // APIRequestHandler.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface APIRequestHandler : NSObject 12 | @property(nonatomic, copy) NSString *grantType; 13 | - (void)registerNotifications; 14 | @end 15 | -------------------------------------------------------------------------------- /PHPHub/Models/NodeModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // NodeModel.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/10/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseModel.h" 10 | #import "NodeApi.h" 11 | 12 | @interface NodeModel : BaseModel 13 | @property (nonatomic, strong) NodeApi *api; 14 | - (id)getAllTopicNode:(BaseResultBlock)block; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Controllers/Forum/TopicListContainerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TopicListContainerViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "ViewPagerController.h" 12 | 13 | @interface TopicListContainerViewController : ViewPagerController 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Views/Notification/NotificationListTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationListTableView.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/26/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NotificationListTableView : UITableView 12 | @property (nonatomic, strong) NSMutableArray *notificationEntities; 13 | @end 14 | -------------------------------------------------------------------------------- /PHPHub/Controllers/Topic/TopicDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TopicDetailViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/8/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TopicEntity.h" 11 | 12 | @interface TopicDetailViewController : UIViewController 13 | @property (nonatomic, strong) TopicEntity *topic; 14 | @end 15 | -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/UIResponder/UIResponder+Router.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIResponder+Router.h 3 | // PHPHub 4 | // 5 | // Created by zhengjinghua on 9/24/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIResponder (Router) 12 | 13 | - (void)routerEventWithName:(NSString *)eventName userInfo:(NSDictionary *)userInfo; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Views/Base/BaseWebView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseWebView.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/27/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BaseWebView : UIWebView 12 | @property (nonatomic, copy) NSString *urlString; 13 | - (instancetype)initWithFrame:(CGRect)frame urlString:(NSString *)urlString; 14 | @end 15 | -------------------------------------------------------------------------------- /PHPHub/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PHPHub/PushConfig.example.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | APS_FOR_PRODUCTION 6 | 0 7 | CHANNEL 8 | Apple App Store 9 | APP_KEY 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/NSString/NSString+Additions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Additions.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/1/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (Additions) 12 | + (BOOL)isStringEmpty:(NSString *)string; 13 | + (NSNumber *)covertToNumber:(NSString *)numberString; 14 | @end 15 | -------------------------------------------------------------------------------- /PHPHub/Controllers/User/UserProfileViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // UserProfileViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/2/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UserEntity.h" 11 | 12 | @interface UserProfileViewController : UITableViewController 13 | @property (nonatomic, strong) UserEntity *userEntity; 14 | @end 15 | -------------------------------------------------------------------------------- /PHPHub/Views/Notification/NotificationListCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationListCell.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/26/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NotificationEntity.h" 11 | 12 | @interface NotificationListCell : UITableViewCell 13 | @property (nonatomic, strong) NotificationEntity *notificationEntity; 14 | @end 15 | -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/NodeEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // NodeEntity.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/23/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseEntity.h" 10 | 11 | @interface NodeEntity : BaseEntity 12 | @property (nonatomic, strong) NSNumber *nodeId; 13 | @property (nonatomic, copy) NSString *nodeName; 14 | @property (nonatomic, strong) NSNumber *parentNode; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Utils/DBManager/LaunchScreenAdDBManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // LaunchScreenAdDBManager.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseDBManager.h" 10 | 11 | @interface LaunchScreenAdDBManager : BaseDBManager 12 | + (id)findLaunchScreenAdByExpries; 13 | + (id)getLaunchScreenAdByExpriesInLocal; 14 | + (id)eraseLaunchScreenAdData; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/back.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "back.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/GVUserDefaults/GVUserDefaults+Properties.m: -------------------------------------------------------------------------------- 1 | // 2 | // GVUserDefaults+Properties.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "GVUserDefaults+Properties.h" 10 | 11 | @implementation GVUserDefaults (Properties) 12 | @dynamic userClientToken; 13 | @dynamic currentUserId; 14 | @dynamic lastTimeShowLaunchScreenAd; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/cancel.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "cancel.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_180.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/more.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "more_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Apis/NotificationApi.h: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationApi.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/13/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseApi.h" 10 | #import "NotificationEntity.h" 11 | 12 | @interface NotificationApi : BaseApi 13 | - (id)getNotificationList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 14 | - (id)getUnreadNotificationCount:(BaseResultBlock)block; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/pure_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "pure_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/ring_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "ring_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/topic_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "topic_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/watch_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "watch_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/me_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "me_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/sad_face.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "sad_face.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/send_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "send_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/vote_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "vote_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/blog_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "blog_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/tick_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "tick_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/comment_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "comment_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/favorite_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "favorite_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Me/settings_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "settings_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/forum_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "forum_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/reply_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "reply_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/wiki_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "wiki_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/pencil_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "pencil_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/upvote_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "upvote_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/github_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "github_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/local_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "local_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/twitter_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "twitter_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Controllers/Notification/NotificationListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationListViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/26/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NotificationListTableView.h" 11 | 12 | @interface NotificationListViewController : UIViewController 13 | @property (nonatomic, strong) NotificationListTableView *tableView; 14 | @end 15 | -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/comments_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "comments_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/corner_circle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "corner_circle.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/downvote_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "downvote_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/PaginationEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // PaginationEntity.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseEntity.h" 10 | 11 | @interface PaginationEntity : BaseEntity 12 | @property (nonatomic, assign) NSUInteger totalPages; 13 | @property (nonatomic, assign) NSUInteger currentPage; 14 | @property (nonatomic, assign) NSUInteger perPage; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Passport/anonymous_logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "anonymous_logo.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/essential_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "essential_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/me_selected_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "me_selected_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/big_upvote_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "big_upvote_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/watch_blue_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "watch_blue_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/User/edit_profile_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "edit_profile_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/tabbar_backgroud.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "tabbar_background@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/wiki_selected_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "wiki_selected_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/avatar_placeholder.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "avatar_placeholder.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/big_downvote_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "big_downvote_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/favorite_blue_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "favorite_blue_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/pencil_square_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "pencil_square_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BaseTabBarViewController.h" 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | @property (strong, nonatomic) BaseTabBarViewController *tabBarViewController; 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Base/estgroup_short_intro.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "estgroup_short_intro.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/forum_selected_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "forum_selected_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Views/Topic/TopicVoteView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TopicVoteView.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/10/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TopicVoteView : UIView 12 | @property (nonatomic, strong) UIButton *upVoteButton; 13 | @property (nonatomic, strong) UIButton *downVoteButton; 14 | - (instancetype)initWithFrame:(CGRect)frame topicEntity:(TopicEntity *)topic; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/TabBar/essential_selected_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "essential_selected_icon.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/big_upvote_selected_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "big_upvote_selected_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/ViewPager/pager_title_indicator.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "pager_title_indicator.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/Topic/big_downvote_selected_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "big_downvote__selected_icon.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/NodeEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // NodeEntity.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/23/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "NodeEntity.h" 10 | 11 | @implementation NodeEntity 12 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 13 | return @{ 14 | @"nodeId" : @"id", 15 | @"nodeName" : @"name", 16 | @"parentNode" : @"parent_node", 17 | }; 18 | } 19 | @end 20 | -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/CommentEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // CommentEntity.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/9/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseEntity.h" 10 | 11 | @interface CommentEntity : BaseEntity 12 | @property (nonatomic, copy) NSNumber *commentId; 13 | @property (nonatomic, copy) NSNumber *topicId; 14 | @property (nonatomic, copy) NSNumber *userId; 15 | @property (nonatomic, copy) NSString *commentBody; 16 | @end 17 | -------------------------------------------------------------------------------- /PHPHub/BaseClasses/BaseModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseModel.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BaseModel : NSObject 12 | + (instancetype)Instance; 13 | 14 | - (id)create:(id)entity withBlock:(BaseResultBlock)block; 15 | - (id)update:(id)entity withBlock:(BaseResultBlock)block; 16 | - (id)upvote:(id)entity withBlock:(BaseResultBlock)block; 17 | @end 18 | -------------------------------------------------------------------------------- /PHPHub/Controllers/Me/MeViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MeViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/23/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MeViewController : UITableViewController 12 | @property (weak, nonatomic) IBOutlet UIImageView *avatarImageView; 13 | @property (weak, nonatomic) IBOutlet UILabel *usernameLabel; 14 | @property (weak, nonatomic) IBOutlet UILabel *userIntroLabel; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/UIResponder/UIResponder+Router.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIResponder+Router.m 3 | // PHPHub 4 | // 5 | // Created by zhengjinghua on 9/24/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "UIResponder+Router.h" 10 | 11 | @implementation UIResponder (Router) 12 | 13 | - (void)routerEventWithName:(NSString *)eventName userInfo:(NSDictionary *)userInfo { 14 | [[self nextResponder] routerEventWithName:eventName userInfo:userInfo]; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /PHPHub/Utils/DBManager/UserDBManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // UserDBManager.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/2/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "UserDBManager.h" 10 | 11 | @implementation UserDBManager 12 | 13 | + (UserEntity *)findByUserId:(NSNumber *)userId { 14 | UserEntity *tmpEntity = [[UserEntity alloc] init]; 15 | tmpEntity.userId = userId; 16 | return [UserDBManager findUsingPrimaryKeys:tmpEntity]; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /PHPHub/Models/NotificationModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationModel.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/13/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseModel.h" 10 | #import "NotificationApi.h" 11 | 12 | @interface NotificationModel : BaseModel 13 | @property (nonatomic, strong) NotificationApi *api; 14 | - (id)getNotificationList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 15 | - (id)getUnreadNotificationCount:(BaseResultBlock)block; 16 | @end 17 | -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/GVUserDefaults/GVUserDefaults+Properties.h: -------------------------------------------------------------------------------- 1 | // 2 | // GVUserDefaults+Properties.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "GVUserDefaults.h" 10 | 11 | @interface GVUserDefaults (Properties) 12 | @property (nonatomic, copy) NSString *userClientToken; 13 | @property (nonatomic, copy) NSNumber *currentUserId; 14 | @property (nonatomic, strong) NSDate *lastTimeShowLaunchScreenAd; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Constants/DebugConstant.h: -------------------------------------------------------------------------------- 1 | // 2 | // DebugConstant.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | 10 | #define DEBUG_HTTP NO 11 | #define DEBUG_ANALYTICS NO 12 | 13 | 14 | #ifdef DEBUG 15 | #define debugLog(...) NSLog(__VA_ARGS__) 16 | #define debugMethod() NSLog(@"%s", __func__) 17 | #define NSLog(...) NSLog(__VA_ARGS__) 18 | #else 19 | #define debugLog(...) 20 | #define debugMethod() 21 | #define NSLog(...) 22 | #endif 23 | -------------------------------------------------------------------------------- /PHPHub/Models/NodeModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // NodeModel.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/10/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "NodeModel.h" 10 | 11 | @implementation NodeModel 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | if (self) { 16 | _api = [[NodeApi alloc] init]; 17 | } 18 | return self; 19 | } 20 | 21 | - (id)getAllTopicNode:(BaseResultBlock)block { 22 | return [_api getAllTopicNode:block]; 23 | } 24 | @end 25 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/TPKeyboardAvoiding/TPKeyboardAvoidingTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TPKeyboardAvoidingTableView.h 3 | // TPKeyboardAvoiding 4 | // 5 | // Created by Michael Tyson on 30/09/2013. 6 | // Copyright 2015 A Tasty Pixel. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UIScrollView+TPKeyboardAvoidingAdditions.h" 11 | 12 | @interface TPKeyboardAvoidingTableView : UITableView 13 | - (BOOL)focusNextTextField; 14 | - (void)scrollToActiveTextField; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Controllers/User/EditUserProfileViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // EditUserProfileViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/4/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol EditUserProfileViewControllerDelegate 12 | - (void)refreshUserProfileView; 13 | @end 14 | 15 | @interface EditUserProfileViewController : UITableViewController 16 | @property (nonatomic, weak) id delegate; 17 | @end 18 | -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/PaginationEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // PaginationEntity.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "PaginationEntity.h" 10 | 11 | @implementation PaginationEntity 12 | 13 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 14 | return @{ 15 | @"totalPages" : @"total_pages", 16 | @"currentPage" : @"current_page", 17 | @"perPage" : @"per_page" 18 | }; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/CommentEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // CommentEntity.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/9/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "CommentEntity.h" 10 | 11 | 12 | @implementation CommentEntity 13 | 14 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 15 | return @{ 16 | @"commentId" : @"id", 17 | @"topicId" : @"topic_id", 18 | @"userId" : @"user_id", 19 | @"commentBody" : @"body", 20 | }; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/TPKeyboardAvoiding/TPKeyboardAvoidingCollectionView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TPKeyboardAvoidingCollectionView.h 3 | // TPKeyboardAvoiding 4 | // 5 | // Created by Michael Tyson on 30/09/2013. 6 | // Copyright 2015 A Tasty Pixel & The CocoaBots. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UIScrollView+TPKeyboardAvoidingAdditions.h" 11 | 12 | @interface TPKeyboardAvoidingCollectionView : UICollectionView 13 | - (BOOL)focusNextTextField; 14 | - (void)scrollToActiveTextField; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/TPKeyboardAvoiding/TPKeyboardAvoidingScrollView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TPKeyboardAvoidingScrollView.h 3 | // TPKeyboardAvoiding 4 | // 5 | // Created by Michael Tyson on 30/09/2013. 6 | // Copyright 2015 A Tasty Pixel. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UIScrollView+TPKeyboardAvoidingAdditions.h" 11 | 12 | @interface TPKeyboardAvoidingScrollView : UIScrollView 13 | - (void)contentSizeToFit; 14 | - (BOOL)focusNextTextField; 15 | - (void)scrollToActiveTextField; 16 | @end 17 | -------------------------------------------------------------------------------- /PHPHub/Apis/UserApi.h: -------------------------------------------------------------------------------- 1 | // 2 | // UserApi.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseApi.h" 10 | #import "UserEntity.h" 11 | 12 | @interface UserApi : BaseApi 13 | - (id)getCurrentUserData:(BaseResultBlock)block; 14 | - (id)getUserById:(NSNumber *)userId callback:(BaseResultBlock)block; 15 | - (id)loginWithUserName:(NSString *)username loginToken:(NSString *)loginToken block:(BaseResultBlock)block; 16 | - (id)updateUserProfile:(UserEntity *)user withBlock:(BaseResultBlock)block; 17 | @end 18 | -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/NotificationEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationEntity.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/26/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseEntity.h" 10 | #import "UserEntity.h" 11 | 12 | @interface NotificationEntity : BaseEntity 13 | @property (nonatomic, strong) NSNumber *notificationId; 14 | @property (nonatomic, copy) NSString *message; 15 | @property (nonatomic, strong) UserEntity *fromUser; 16 | @property (nonatomic, strong) TopicEntity *topic; 17 | @property (nonatomic, strong) NSDate *createdAt; 18 | @end 19 | -------------------------------------------------------------------------------- /PHPHub/Handlers/JpushHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // JpushHandler.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/16/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "APService.h" 11 | 12 | @interface JpushHandler : NSObject 13 | + (void)setupJpush:(NSDictionary *)launchOptions; 14 | + (void)tagsAliasCallback:(int)iResCode tags:(NSSet *)tags alias:(NSString *)alias; 15 | + (NSString *)logSet:(NSSet *)dic; 16 | + (void)sendUserIdToAlias; 17 | + (void)sendEmptyAlias; 18 | + (void)handleUserInfo:(NSDictionary *)userInfo; 19 | @end 20 | -------------------------------------------------------------------------------- /PHPHub/Controllers/Topic/ReplyTopicViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ReplyTopicViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/9/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol ReplyTopicViewControllerDelegate 12 | @optional 13 | - (void)jumpToCommentsView; 14 | - (void)reloadCommentListView; 15 | @end 16 | 17 | @interface ReplyTopicViewController : UIViewController 18 | @property (nonatomic, copy) NSNumber *topicId; 19 | @property (nonatomic, weak) id delegate; 20 | @end 21 | -------------------------------------------------------------------------------- /PHPHub/Controllers/TabBar/BaseTabBarViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTabBarViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BaseTabBarViewController : UITabBarController 12 | - (void)setupTabBarItems; 13 | - (void)pushToViewController:(UIViewController *)viewController animated:(BOOL)animated; 14 | - (void)presentToViewController:(UIViewController *)viewController animated:(BOOL)animated completion:(void (^)(void))completion; 15 | @end 16 | -------------------------------------------------------------------------------- /PHPHub/Views/Topic/TopicSearchBar.m: -------------------------------------------------------------------------------- 1 | // 2 | // TopicSearchBar.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/12/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "TopicSearchBar.h" 10 | 11 | @implementation TopicSearchBar 12 | 13 | - (instancetype)initWithFrame:(CGRect)frame { 14 | self = [super initWithFrame:frame]; 15 | if (self) { 16 | self.placeholder = @"搜索"; 17 | self.backgroundColor = [UIColor groupTableViewBackgroundColor]; 18 | self.backgroundImage = [[UIImage alloc] init]; 19 | } 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /PHPHub/Controllers/Passport/LoginViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "QRCodeReaderDelegate.h" 12 | #import "QRCodeReaderViewController.h" 13 | 14 | @protocol LoginViewControllerDelegate 15 | - (void)updateMeView; 16 | @end 17 | 18 | @interface LoginViewController : UIViewController 19 | @property (nonatomic, weak) id delegate; 20 | @property (nonatomic, copy) void (^completeLoginBlock)(void); 21 | @end 22 | -------------------------------------------------------------------------------- /PHPHub/Utils/Helper/BaseHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseHelper.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BaseHelper : NSObject 12 | 13 | + (NSURL *)qiniuImageCenter:(NSString *)link 14 | withWidth:(NSString *)width 15 | withHeight:(NSString *)height; 16 | 17 | + (NSURL *)qiniuImageCenter:(NSString *)link 18 | withWidth:(NSString *)width 19 | withHeight:(NSString *)height 20 | mode:(NSInteger)model; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /PHPHub/Handlers/LaunchScreenAdHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // LaunchScreenAdHandler.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LaunchScreenAdEntity.h" 11 | 12 | @interface LaunchScreenAdHandler : NSObject 13 | @property (nonatomic, strong) LaunchScreenAdEntity *launchScreenAdEntity; 14 | + (void)checkShouldShowLaunchScreenAd; 15 | + (void)showLaunchScreenAd; 16 | + (void)createLaunchScreenAdWithAdEntity:(LaunchScreenAdEntity *)launchScreenAdEntity; 17 | + (void)removeLaunchScreenAd:(BOOL)shouldJumpToOtherVC; 18 | @end 19 | -------------------------------------------------------------------------------- /PHPHub/Views/Topic/TopicListTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TopicListTableView.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/23/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol TopicListTableViewDelegate 12 | - (void)headerRefreshing; 13 | - (void)footerRereshing; 14 | @end 15 | 16 | @interface TopicListTableView : UITableView 17 | @property (nonatomic, assign) BOOL shouldRemoveHeaderView; 18 | @property (nonatomic, strong) NSMutableArray *topicEntites; 19 | @property (nonatomic, weak) id topicListTableViewDelegate; 20 | - (void)setupFooterView; 21 | @end 22 | -------------------------------------------------------------------------------- /PHPHub/Views/LaunchAd/LaunchScreenAdView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LaunchScreenAdView.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SkipButton.h" 11 | 12 | @interface LaunchScreenAdView : UIView 13 | @property (nonatomic, assign) NSTimeInterval timePerImage; 14 | @property (nonatomic, strong) UIImageView *imageView; 15 | @property (nonatomic, assign) NSTimeInterval transitionDuration; 16 | @property (nonatomic, strong) UILabel *durationTimeLabel; 17 | @property (nonatomic) NSTimer *updateDurationLabelTimer; 18 | - (void)startAnimateWithImageLink:(NSURL *)url; 19 | @end -------------------------------------------------------------------------------- /PHPHub/Models/UserModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // UserModel.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseModel.h" 10 | #import "UserApi.h" 11 | #import "UserDBManager.h" 12 | 13 | @interface UserModel : BaseModel 14 | @property (nonatomic, strong) UserApi *api; 15 | - (id)getCurrentUserData:(BaseResultBlock)block; 16 | - (id)getUserById:(NSNumber *)userId callback:(BaseResultBlock)block; 17 | - (id)loginWithUserName:(NSString *)username loginToken:(NSString *)loginToken block:(BaseResultBlock)block; 18 | - (id)updateUserProfile:(UserEntity *)user withBlock:(BaseResultBlock)block; 19 | @end 20 | -------------------------------------------------------------------------------- /PHPHub/Views/Base/BaseView.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseView.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/26/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseView.h" 10 | 11 | @implementation BaseView 12 | 13 | - (instancetype)initWithFrame:(CGRect)frame { 14 | self = [super initWithFrame:frame]; 15 | if (self) { 16 | self.backgroundColor = [UIColor clearColor]; 17 | self.layer.backgroundColor = [UIColor whiteColor].CGColor; 18 | self.layer.cornerRadius = 2; 19 | self.layer.borderColor = [UIColor colorWithRed:0.871 green:0.875 blue:0.878 alpha:1.000].CGColor; 20 | self.layer.borderWidth = 0.5; 21 | } 22 | return self; 23 | } 24 | @end 25 | -------------------------------------------------------------------------------- /PHPHub/Handlers/AccessTokenHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // AccessTokenHandler.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AFOAuth2Manager.h" 11 | 12 | @interface AccessTokenHandler : NSObject 13 | 14 | + (void)fetchClientGrantToken; 15 | 16 | + (NSString *)getClientGrantAccessTokenFromLocal; 17 | + (NSString *)getLoginTokenGrantAccessToken; 18 | 19 | + (void)storeClientGrantAccessToken:(NSString *)token; 20 | + (void)storeLoginTokenGrantAccessToken:(NSString *)token; 21 | 22 | + (void)clearToken; 23 | 24 | + (void)fetchClientGrantTokenWithRetryTimes:(NSInteger)times callback:(BaseResultBlock)block; 25 | @end 26 | -------------------------------------------------------------------------------- /PHPHub/Handlers/UMengSocialHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // UMengSocialHandler.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/15/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "UMSocial.h" 10 | #import "UMSocialQQHandler.h" 11 | #import "UMSocialWechatHandler.h" 12 | #import "UMSocialSinaHandler.h" 13 | 14 | @interface UMengSocialHandler : NSObject 15 | + (void)setup; 16 | + (void)shareWithShareURL:(NSString *)shareURL 17 | shareImageUrl:(NSString *)shareImageUrl 18 | shareTitle:(NSString *)shareTitle 19 | shareText:(NSString *)shareText 20 | presentVC:(UIViewController *)vc 21 | delegate:(id )delegate; 22 | @end 23 | -------------------------------------------------------------------------------- /PHPHub/Models/NotificationModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationModel.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/13/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "NotificationModel.h" 10 | 11 | @implementation NotificationModel 12 | - (instancetype)init { 13 | self = [super init]; 14 | if (self) { 15 | _api = [[NotificationApi alloc] init]; 16 | } 17 | return self; 18 | } 19 | 20 | - (id)getNotificationList:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 21 | return [_api getNotificationList:block atPage:pageIndex]; 22 | } 23 | 24 | - (id)getUnreadNotificationCount:(BaseResultBlock)block { 25 | return [_api getUnreadNotificationCount:block]; 26 | } 27 | @end 28 | -------------------------------------------------------------------------------- /PHPHub/Resources/Migrations.bundle/20151019093301120_create_launchScreenAds_table.sql: -------------------------------------------------------------------------------- 1 | -- ---------------------------- 2 | -- Table structure for launchScreenAds 3 | -- ---------------------------- 4 | DROP TABLE IF EXISTS "launchScreenAds"; 5 | CREATE TABLE "launchScreenAds" ( 6 | "id" integer not null primary key, 7 | "image_small" varchar not null, 8 | "image_large" varchar not null, 9 | "type" varchar null, 10 | "payload" varchar not null, 11 | "display_time" integer not null default '0', 12 | "start_at" datetime not null, 13 | "expires_at" datetime not null 14 | ); 15 | -- ---------------------------- 16 | -- Indexes structure for table launchScreenAds 17 | -- ---------------------------- 18 | CREATE INDEX launchScreenAds_expiresAt_index on "launchScreenAds" ("expires_at"); -------------------------------------------------------------------------------- /PHPHub/BaseClasses/CurrentUser.h: -------------------------------------------------------------------------------- 1 | // 2 | // CurrentUser.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "UserEntity.h" 11 | #import "UserModel.h" 12 | #import "UserDBManager.h" 13 | 14 | @interface CurrentUser : NSObject 15 | 16 | @property (nonatomic, copy) NSNumber *userId; 17 | @property (nonatomic, strong) UserEntity *userInfo; 18 | + (CurrentUser *)Instance; 19 | - (BOOL)isLogin; 20 | - (BOOL)hasClientToken; 21 | - (void)updateCurrentUserInfoIfNeeded; 22 | - (void)saveUser:(UserEntity *)user; 23 | - (void)setupClientRequestState:(BaseResultBlock)block; 24 | - (void)checkNoticeCount; 25 | - (void)logOut; 26 | - (NSString *)userLabel; 27 | @end 28 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/TitlePagerView/TitlePagerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // TitlePagerView.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol TitlePagerViewDelegate 12 | @optional 13 | - (void)didTouchBWTitle:(NSUInteger)index; 14 | @end 15 | 16 | @interface TitlePagerView : UIView 17 | 18 | @property (nonatomic, strong) UIFont *font; 19 | @property (nonatomic, weak) id delegate; 20 | 21 | - (void)addObjects:(NSArray *)images; 22 | - (void)adjustTitleViewByIndex:(CGFloat)index; 23 | + (CGFloat)calculateTitleWidth:(NSArray *)titleArray withFont:(UIFont *)titleFont; 24 | - (void)updatePageIndicatorPosition:(CGFloat)xPosition; 25 | @end 26 | -------------------------------------------------------------------------------- /PHPHub/BaseClasses/BaseEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseEntity.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "MTLModel.h" 10 | #import "MTLJSONAdapter.h" 11 | #import "MTLValueTransformer.h" 12 | #import "NSValueTransformer+MTLPredefinedTransformerAdditions.h" 13 | #import "MTLFMDBAdapter.h" 14 | 15 | @interface BaseEntity : MTLModel 16 | #pragma mark - Class Methods to create Entity 17 | 18 | + (NSDateFormatter *)dateFormatter; 19 | 20 | + (id)entityFromDictionary:(NSDictionary *)data; 21 | + (NSArray *)arrayOfEntitiesFromArray:(NSArray *)array; 22 | 23 | #pragma mark - Instance Method 24 | 25 | - (NSDictionary *)transformToDictionary; 26 | + (NSArray *)transformToArray:(NSArray *)array; 27 | @end 28 | -------------------------------------------------------------------------------- /PHPHub/Resources/Migrations.bundle/20151002095034729_create_users_table.sql: -------------------------------------------------------------------------------- 1 | -- ---------------------------- 2 | -- Table structure for users 3 | -- ---------------------------- 4 | DROP TABLE IF EXISTS "users"; 5 | CREATE TABLE "users" ( 6 | "id" integer not null primary key, 7 | "name" varchar not null, 8 | "avatar" varchar null, 9 | "github_url" varchar null, 10 | "topic_count" integer not null default '0', 11 | "reply_count" integer not null default '0', 12 | "twitter_account" varchar null, 13 | "personal_website" varchar null, 14 | "company" varchar null, 15 | "city" varchar null, 16 | "email" varchar null, 17 | "signature" varchar null, 18 | "github_name" varchar null, 19 | "real_name" varchar null, 20 | "replies_web_view" varchar null, 21 | "created_at" datetime not null, 22 | "updated_at" datetime null 23 | ); -------------------------------------------------------------------------------- /PHPHubTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /PHPHub/Controllers/Forum/TopicListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TopicListViewController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TopicListTableView.h" 11 | 12 | typedef NS_ENUM(NSInteger, TopicListType) { 13 | TopicListTypeNewest = 0, 14 | TopicListTypeHots = 1, 15 | TopicListTypeNoReply = 2, 16 | TopicListTypeJob = 3, 17 | TopicListTypeFavorite = 4, 18 | TopicListTypeAttention = 5, 19 | TopicListTypeNormal = 6, 20 | }; 21 | 22 | @interface TopicListViewController : UIViewController 23 | @property (nonatomic) TopicListType topicListType; 24 | @property (nonatomic, assign) NSInteger userId; 25 | @property (nonatomic, strong) TopicListTableView *tableView; 26 | @property (nonatomic, assign) BOOL isFromTopicContainer; 27 | @end 28 | -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/AFOAuth2Manager/AFOAuth2Manager+Addtions.h: -------------------------------------------------------------------------------- 1 | // 2 | // AFOAuth2Manager+Addtions.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "AFOAuth2Manager.h" 10 | 11 | @interface AFOAuth2Manager (Addtions) 12 | - (AFHTTPRequestOperation *)authenticateUsingOAuthWithURLString:(NSString *)URLString 13 | username:(NSString *)username 14 | loginToken:(NSString *)loginToken 15 | scope:(NSString *)scope 16 | success:(void (^)(AFOAuthCredential *credential))success 17 | failure:(void (^)(NSError *error))failure; 18 | @end 19 | -------------------------------------------------------------------------------- /PHPHub/Constants/SecretConstant.example.h: -------------------------------------------------------------------------------- 1 | // 2 | // SecretConstant.example.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #if DEBUG 10 | #define Client_id @"kHOugsx4dmcXwvVbmLkd" 11 | #define Client_secret @"PuuFCrF94MloSbSkxpwS" 12 | #else 13 | #define Client_id @"" // Set up a client id for production environment 14 | #define Client_secret @"" // Set up a client secret for production environment 15 | #endif 16 | 17 | #define UMENG_APPKEY @"" // Set up UMEng App Key 18 | #define UMENG_QQ_ID @"" // Set up QQ id 19 | #define UMENG_QQ_APPKEY @"" // Set up QQ appkey 20 | #define WX_APP_ID @"" // Set up wechat app id 21 | #define WX_APP_SECRET @"" // Set up wechat app secret 22 | #define JPush_APP_KEY @"" // Set up Jpush App Key 23 | #define TRACKING_ID @"" // Set up google anlytics tracking id -------------------------------------------------------------------------------- /PHPHub/Handlers/JumpToOtherVCHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // JumpToOtherVCHandler.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/8/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "TopicEntity.h" 11 | 12 | @interface JumpToOtherVCHandler : NSObject 13 | + (UIViewController *)getTabbarViewController; 14 | + (void)pushToOtherView:(UIViewController *)vc animated:(BOOL)animated; 15 | + (void)presentToOtherView:(UIViewController *)vc animated:(BOOL)animated completion:(void (^)(void))completion; 16 | + (void)jumpToTopicDetailWithTopic:(TopicEntity *)topic; 17 | + (void)jumpToLoginVC:(void (^)(void))completion; 18 | + (void)jumpToTopicDetailWithTopicId:(NSNumber *)topicId; 19 | + (void)jumpToUserProfileWithUserId:(NSNumber *)userId; 20 | + (void)jumpToCommentListVCWithTopic:(TopicEntity *)topic; 21 | + (void)jumpToWebVCWithUrlString:(NSString *)url; 22 | @end 23 | -------------------------------------------------------------------------------- /PHPHub/PHPHub-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // PHPHub-Prefix.pch 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #if DEBUG 10 | #define IS_IN_DEVELOPMENT TRUE 11 | #else 12 | #define IS_IN_DEVELOPMENT FALSE 13 | #endif 14 | 15 | #import "BaseApi.h" 16 | #import "APIConstant.h" 17 | #import "SecretConstant.h" 18 | #import "UIConstant.h" 19 | #import "DebugConstant.h" 20 | #import "UIView+Additions.h" 21 | #import "BaseHelper.h" 22 | #import "UIImageView+WebCache.h" 23 | #import "MJRefresh.h" 24 | #import "PaginationEntity.h" 25 | #import "AFOAuth2Manager+Addtions.h" 26 | #import "GVUserDefaults+Properties.h" 27 | #import "CurrentUser.h" 28 | #import "NSString+Additions.h" 29 | #import "UIViewController+Custom.h" 30 | #import "JumpToOtherVCHandler.h" 31 | #import "SVProgressHUD.h" 32 | #import "AnalyticsHandler.h" 33 | 34 | #define DidTapStatusBar @"DidTapStatusBar" -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/NotificationEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationEntity.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/26/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "NotificationEntity.h" 10 | 11 | @implementation NotificationEntity 12 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 13 | return @{ 14 | @"notificationId" : @"id", 15 | @"message" : @"message", 16 | @"fromUser" : @"from_user.data", 17 | @"topic" : @"topic.data", 18 | @"createdAt" : @"created_at", 19 | }; 20 | } 21 | 22 | + (NSValueTransformer *)fromUserJSONTransformer { 23 | return [NSValueTransformer mtl_JSONDictionaryTransformerWithModelClass:[UserEntity class]]; 24 | } 25 | 26 | + (NSValueTransformer *)topicJSONTransformer { 27 | return [NSValueTransformer mtl_JSONDictionaryTransformerWithModelClass:[TopicEntity class]]; 28 | } 29 | @end -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/NSString/NSString+Additions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Additions.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/1/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "NSString+Additions.h" 10 | 11 | @implementation NSString (Additions) 12 | + (BOOL)isStringEmpty:(NSString *)string { 13 | if([string length] == 0) { //string is empty or nil 14 | return YES; 15 | } 16 | 17 | if(![[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]) { 18 | //string is all whitespace 19 | return YES; 20 | } 21 | 22 | return NO; 23 | } 24 | 25 | + (NSNumber *)covertToNumber:(NSString *)numberString { 26 | NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; 27 | formatter.numberStyle = NSNumberFormatterDecimalStyle; 28 | return [formatter numberFromString:numberString]; 29 | } 30 | @end 31 | -------------------------------------------------------------------------------- /PHPHub/Handlers/AnalyticsHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // AnalyticsHandler.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/21/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #define kShare @"用户分享" 12 | #define kUserAction @"用户行为" 13 | #define kTopicAction @"帖子操作" 14 | 15 | @interface AnalyticsHandler : NSObject 16 | + (void)bootup; 17 | + (void)logEvent:(NSString *)event; 18 | + (void)logEvent:(NSString *)event withProperties:(NSDictionary *)dict; 19 | + (void)logEvent:(NSString *)event withCategory:(NSString *)category label:(NSString *)lable; 20 | + (void)logScreen:(NSString *)screenName; 21 | 22 | // Log Time 23 | + (void)startTimeEvent:(NSString *)event; 24 | + (void)endTimedEventForHttp:(NSString *)event; 25 | + (void)endTimedEventForDatabase:(NSString *)event; 26 | + (void)endTimedEvent:(NSString *)event withCategory:(NSString *)category label:(NSString *)label; 27 | @end 28 | -------------------------------------------------------------------------------- /PHPHub/Views/Base/SkipButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // SkipButton.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "SkipButton.h" 10 | 11 | @implementation SkipButton 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | 16 | if (self) { 17 | [self setupSkipButton]; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)setupSkipButton { 23 | self.width = 56; 24 | self.height = 30; 25 | 26 | self.backgroundColor = [UIColor colorWithWhite:0.000 alpha:0.150]; 27 | [self setTitle:@"Skip" forState:UIControlStateNormal]; 28 | self.titleLabel.font = [UIFont fontWithName:FontName size:14]; 29 | 30 | self.layer.masksToBounds = YES; 31 | self.layer.cornerRadius = 7.5; 32 | self.layer.borderColor = [UIColor colorWithWhite:1.000 alpha:0.150].CGColor; 33 | self.layer.borderWidth = 1.5f; 34 | 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /PHPHub/BaseClasses/BaseModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseModel.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseModel.h" 10 | 11 | @implementation BaseModel 12 | + (instancetype)Instance { 13 | return [[self alloc] init]; 14 | } 15 | 16 | - (id)create:(id)entity withBlock:(BaseResultBlock)block { 17 | NSLog(@"You must override %@ in a subclass",NSStringFromSelector(_cmd)); 18 | [self doesNotRecognizeSelector:_cmd]; 19 | return nil; 20 | } 21 | 22 | - (id)update:(id)entity withBlock:(BaseResultBlock)block { 23 | NSLog(@"You must override %@ in a subclass",NSStringFromSelector(_cmd)); 24 | [self doesNotRecognizeSelector:_cmd]; 25 | return nil; 26 | } 27 | 28 | - (id)upvote:(id)entity withBlock:(BaseResultBlock)block { 29 | NSLog(@"You must override %@ in a subclass",NSStringFromSelector(_cmd)); 30 | [self doesNotRecognizeSelector:_cmd]; 31 | return nil; 32 | } 33 | @end 34 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/TPKeyboardAvoiding/UIScrollView+TPKeyboardAvoidingAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollView+TPKeyboardAvoidingAdditions.h 3 | // TPKeyboardAvoiding 4 | // 5 | // Created by Michael Tyson on 30/09/2013. 6 | // Copyright 2015 A Tasty Pixel. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIScrollView (TPKeyboardAvoidingAdditions) 12 | - (BOOL)TPKeyboardAvoiding_focusNextTextField; 13 | - (void)TPKeyboardAvoiding_scrollToActiveTextField; 14 | 15 | - (void)TPKeyboardAvoiding_keyboardWillShow:(NSNotification*)notification; 16 | - (void)TPKeyboardAvoiding_keyboardWillHide:(NSNotification*)notification; 17 | - (void)TPKeyboardAvoiding_updateContentInset; 18 | - (void)TPKeyboardAvoiding_updateFromContentSizeChange; 19 | - (void)TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:(UIView*)view; 20 | - (UIView*)TPKeyboardAvoiding_findFirstResponderBeneathView:(UIView*)view; 21 | -(CGSize)TPKeyboardAvoiding_calculatedContentSizeFromSubviewFrames; 22 | @end 23 | -------------------------------------------------------------------------------- /PHPHubTests/PHPHubTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // PHPHubTests.m 3 | // PHPHubTests 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface PHPHubTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation PHPHubTests 17 | 18 | - (void)setUp { 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 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/UIView/UIView+Additions.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Additions.h 3 | // 4 | // Created by Jin on 15/3/25. 5 | // Copyright (c) 2015年 Jin. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @interface UIView (Additions) 11 | 12 | - (id) initWithParent:(UIView *)parent; 13 | + (id) viewWithParent:(UIView *)parent; 14 | - (void)removeAllSubViews; 15 | - (UIViewController*)viewController; 16 | 17 | 18 | // Position of the top-left corner in superview's coordinates 19 | @property CGPoint position; 20 | @property CGFloat x; 21 | @property CGFloat y; 22 | @property CGFloat top; 23 | @property CGFloat bottom; 24 | @property CGFloat left; 25 | @property CGFloat right; 26 | 27 | 28 | // makes hiding more logical 29 | @property BOOL visible; 30 | 31 | 32 | // Setting size keeps the position (top-left corner) constant 33 | @property CGSize size; 34 | @property CGFloat width; 35 | @property CGFloat height; 36 | 37 | @end 38 | 39 | @interface UIImageView (MFAdditions) 40 | 41 | - (void) setImageWithName:(NSString *)name; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/LaunchScreenAdEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // LaunchScreenAdEntity.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseEntity.h" 10 | 11 | typedef NS_ENUM(NSInteger, LaunchScreenType) { 12 | LaunchScreenTypeByTopic = 0, 13 | LaunchScreenTypeByUser = 1, 14 | LaunchScreenTypeByWeb = 2, 15 | LaunchScreenTypeUnknow = 3, 16 | }; 17 | 18 | @interface LaunchScreenAdEntity : BaseEntity 19 | @property (nonatomic, copy) NSNumber *launchScreenAdId; 20 | @property (nonatomic, copy) NSString *launchDescription; 21 | @property (nonatomic, copy) NSString *smallImage; 22 | @property (nonatomic, copy) NSString *bigImage; 23 | @property (nonatomic, assign) LaunchScreenType type; 24 | @property (nonatomic, strong) NSString *launchScreenType; 25 | @property (nonatomic, copy) NSString *payload; 26 | @property (nonatomic, strong) NSDate *startAt; 27 | @property (nonatomic, strong) NSDate *expiresAt; 28 | @property (nonatomic, copy) NSNumber *displayTime; 29 | @end 30 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | 3 | platform :ios, "8.0" 4 | 5 | pod 'AFNetworking', '~> 2.0' 6 | pod 'AFOAuth2Manager' 7 | pod 'Qiniu' 8 | pod 'SDWebImage' 9 | pod 'Reachability' 10 | pod 'MBProgressHUD' 11 | pod 'DateTools' 12 | pod 'UIActivityIndicator-for-SDWebImage' 13 | pod 'CTAssetsPickerController' 14 | pod 'QBPopupMenu' 15 | pod 'Mantle', '1.5.5' 16 | pod 'FMDB', '~> 2.3' 17 | pod 'MTLFMDBAdapter', :git => 'https://github.com/summerblue/MTLFMDBAdapter' 18 | pod 'FMDBMigrationManager', '~> 1.3' 19 | pod 'GVUserDefaults' 20 | pod 'Masonry' 21 | pod 'SVProgressHUD', :head 22 | pod 'MJRefresh' 23 | pod 'UMengFeedback', '~> 2.3.4' 24 | pod 'UMengSocial', '4.2.3' 25 | pod 'QRCodeReaderViewController', :git => 'https://github.com/zhengjinghua/MQRCodeReaderViewController.git' 26 | pod 'UITextView+Placeholder' 27 | pod 'pop', '~> 1.0' 28 | pod 'FDFullscreenPopGesture', '1.1' 29 | pod 'UITableView+FDTemplateLayoutCell' 30 | pod 'UIActionSheet+Blocks' 31 | pod 'Fabric' 32 | pod 'Crashlytics' 33 | pod 'DZNEmptyDataSet' 34 | pod 'WebViewJavascriptBridge' 35 | pod 'JTSImageViewController' 36 | pod 'SSKeychain' -------------------------------------------------------------------------------- /PHPHub/Apis/NodeApi.m: -------------------------------------------------------------------------------- 1 | // 2 | // NodeApi.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/10/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "NodeApi.h" 10 | 11 | @implementation NodeApi 12 | 13 | - (id)getAllTopicNode:(BaseResultBlock)block { 14 | NSString *urlPath = @"nodes"; 15 | 16 | BaseRequestSuccessBlock successBlock = ^(NSURLSessionDataTask * __unused task, id rawData) { 17 | NSMutableDictionary *data = [(NSDictionary *)rawData mutableCopy]; 18 | if (data[@"data"]) { 19 | data[@"entities"] = [NodeEntity arrayOfEntitiesFromArray:data[@"data"]]; 20 | } 21 | if (block) block(data, nil); 22 | }; 23 | 24 | BaseRequestFailureBlock failureBlock = ^(NSURLSessionDataTask *__unused task, NSError *error) { 25 | if (block) block(nil, error); 26 | }; 27 | 28 | return [[BaseApi clientGrantInstance] GET:urlPath 29 | parameters:nil 30 | success:successBlock 31 | failure:failureBlock]; 32 | } 33 | @end 34 | -------------------------------------------------------------------------------- /PHPHub/Apis/AdApi.m: -------------------------------------------------------------------------------- 1 | // 2 | // AdApi.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "AdApi.h" 10 | #import "LaunchScreenAdEntity.h" 11 | 12 | @implementation AdApi 13 | 14 | - (id)getAdvertsLaunchScreen:(BaseResultBlock)block { 15 | NSString *urlPath = @"adverts/launch_screen"; 16 | 17 | BaseRequestSuccessBlock successBlock = ^(NSURLSessionDataTask * __unused task, id rawData) { 18 | NSMutableDictionary *data = [(NSDictionary *)rawData mutableCopy]; 19 | data[@"entities"] = [LaunchScreenAdEntity arrayOfEntitiesFromArray:data[@"data"]]; 20 | if (block) block(data, nil); 21 | }; 22 | 23 | BaseRequestFailureBlock failureBlock = ^(NSURLSessionDataTask *__unused task, NSError *error) { 24 | if (block) block(nil, error); 25 | }; 26 | 27 | return [[BaseApi clientGrantInstance] GET:urlPath 28 | parameters:nil 29 | success:successBlock 30 | failure:failureBlock]; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # Ignore secret constant file 46 | PHPHub/Constants/SecretConstant.h 47 | 48 | # Ignore Config Plist File 49 | PHPHub/PushConfig.plist -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/TopicEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // TopicEntity.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseEntity.h" 10 | #import "UserEntity.h" 11 | #import "NodeEntity.h" 12 | 13 | @interface TopicEntity : BaseEntity 14 | @property (nonatomic, strong) NSNumber *topicId; 15 | @property (nonatomic, strong) NSNumber *nodeId; 16 | @property (nonatomic, copy) NSString *topicTitle; 17 | @property (nonatomic, copy) NSString *topicBody; 18 | @property (nonatomic, strong) NSNumber *topicRepliesCount; 19 | @property (nonatomic, strong) NSNumber *voteCount; 20 | @property (nonatomic, strong) UserEntity *user; 21 | @property (nonatomic, strong) UserEntity *lastReplyUser; 22 | @property (nonatomic, strong) NodeEntity *node; 23 | @property (nonatomic, copy) NSString *topicContentUrl; 24 | @property (nonatomic, copy) NSString *topicRepliesUrl; 25 | @property (nonatomic, assign) BOOL favorite; 26 | @property (nonatomic, assign) BOOL attention; 27 | @property (nonatomic, assign) BOOL voteUp; 28 | @property (nonatomic, assign) BOOL voteDown; 29 | @property (nonatomic, strong) NSDate *updatedAt; 30 | @end 31 | -------------------------------------------------------------------------------- /PHPHub/Utils/Helper/BaseHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseHelper.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseHelper.h" 10 | 11 | @implementation BaseHelper 12 | 13 | // Center Square Image 14 | + (NSURL *)qiniuImageCenter:(NSString *)link 15 | withWidth:(NSString *)width 16 | withHeight:(NSString *)height { 17 | NSString *url = [[NSString alloc] init]; 18 | if([height isEqualToString:@"0"]) { 19 | url = [NSString stringWithFormat:@"%@?imageView2/2/w/%@/", link, width]; 20 | } else { 21 | url = [NSString stringWithFormat:@"%@?imageView/1/w/%@/h/%@", link, width, height]; 22 | } 23 | return [NSURL URLWithString:url]; 24 | } 25 | 26 | + (NSURL *)qiniuImageCenter:(NSString *)link 27 | withWidth:(NSString *)width 28 | withHeight:(NSString *)height 29 | mode:(NSInteger)model { 30 | NSString *url = [[NSString alloc] init]; 31 | url = [NSString stringWithFormat:@"%@?imageView/%ld/w/%@/h/%@", link, (long)model, width, height]; 32 | return [NSURL URLWithString:url]; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /PHPHub/BaseClasses/BaseApi.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseApi.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "AFHTTPSessionManager.h" 10 | #import "APIRequestHandler.h" 11 | 12 | typedef void (^ BaseResultBlock)(id data, NSError *error); 13 | typedef void (^ BaseRequestSuccessBlock)(NSURLSessionDataTask *task, id responseObject); 14 | typedef void (^ BaseRequestFailureBlock)(NSURLSessionDataTask *task, NSError *error); 15 | typedef void (^ BaseRequestConstructingBodyBlock)(id formData); 16 | 17 | @interface BaseApi : AFHTTPSessionManager 18 | 19 | @property(strong,nonatomic) APIRequestHandler* handler; 20 | 21 | #pragma mark - Share Instance 22 | 23 | + (instancetype)loginTokenGrantInstance; 24 | + (instancetype)clientGrantInstance; 25 | 26 | #pragma mark - Public Method 27 | 28 | - (void)setUpLoginTokenGrantRequest; 29 | - (void)setUpClientGrantRequest; 30 | 31 | #pragma mark - Shared/Inherit Method 32 | 33 | - (id)create:(id)entity withBlock:(BaseResultBlock)block; 34 | - (id)update:(id)entity withBlock:(BaseResultBlock)block; 35 | - (id)upvote:(id)entity withBlock:(BaseResultBlock)block; 36 | @end 37 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/GoogleAnalytics/Library/GAITrackedViewController.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @header GAITrackedViewController.h 3 | @abstract Google Analytics for iOS Tracked View Controller Header 4 | @copyright Copyright 2012 Google Inc. All rights reserved. 5 | */ 6 | 7 | #import 8 | #import 9 | 10 | @protocol GAITracker; 11 | 12 | /*! 13 | Extends UIViewController to generate Google Analytics screenview calls 14 | whenever the view appears; this is done by overriding the `viewDidAppear:` 15 | method. The screen name must be set for any tracking calls to be made. 16 | 17 | By default, this will use [GAI defaultTracker] for tracking calls, but one can 18 | override this by setting the tracker property. 19 | */ 20 | @interface GAITrackedViewController : UIViewController 21 | 22 | /*! 23 | The tracker on which view tracking calls are be made, or `nil`, in which case 24 | [GAI defaultTracker] will be used. 25 | */ 26 | @property(nonatomic, assign) id tracker; 27 | /*! 28 | The screen name, for purposes of Google Analytics tracking. If this is `nil`, 29 | no tracking calls will be made. 30 | */ 31 | @property(nonatomic, copy) NSString *screenName; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/UserEntity.h: -------------------------------------------------------------------------------- 1 | // 2 | // UserEntity.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseEntity.h" 10 | 11 | @interface UserEntity : BaseEntity 12 | @property (nonatomic, copy) NSNumber *userId; 13 | @property (nonatomic, copy) NSString *githubURL; 14 | @property (nonatomic, copy) NSString *username; 15 | @property (nonatomic, copy) NSString *avatar; 16 | @property (nonatomic, copy) NSNumber *topicCount; 17 | @property (nonatomic, copy) NSNumber *replyCount; 18 | @property (nonatomic, copy) NSNumber *notificationCount; 19 | @property (nonatomic, copy) NSString *twitterAccount; 20 | @property (nonatomic, copy) NSString *blogURL; 21 | @property (nonatomic, copy) NSString *company; 22 | @property (nonatomic, copy) NSString *city; 23 | @property (nonatomic, copy) NSString *email; 24 | @property (nonatomic, copy) NSString *signature; 25 | @property (nonatomic, copy) NSString *githubName; 26 | @property (nonatomic, copy) NSString *realName; 27 | @property (nonatomic, copy) NSString *repliesUrl; 28 | @property (nonatomic, strong) NSDate *createdAtDate; 29 | @property (nonatomic, strong) NSDate *updatedAtDate; 30 | @end 31 | -------------------------------------------------------------------------------- /PHPHub/Constants/UIConstant.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIConstant.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #define FontName @"Helvetica Neue" 10 | #define BoldFontName @"Helvetica-Bold" 11 | 12 | // Main Screen 13 | #define SCREEN_HEIGHT [[UIScreen mainScreen]bounds].size.height 14 | #define SCREEN_WIDTH [[UIScreen mainScreen]bounds].size.width 15 | #define ORIGINAL_MAX_WIDTH 640.0f 16 | 17 | // RGB Color 18 | #define RGBA(r,g,b,a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a] 19 | #define RGB(r,g,b) RGBA(r,g,b,1.0f) 20 | 21 | #define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 22 | #define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) 23 | #define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0) 24 | 25 | #define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT)) 26 | #define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT)) 27 | 28 | #define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0) 29 | #define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0) 30 | #define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0) 31 | #define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0) -------------------------------------------------------------------------------- /PHPHub/Constants/APIConstant.h: -------------------------------------------------------------------------------- 1 | // 2 | // APIConstant.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #define APIAccessTokenURL [NSString stringWithFormat:@"%@%@", APIBaseURL, @"/oauth/access_token"] 10 | #define QiniuUploadTokenIdentifier @"QiniuUploadTokenIdentifier" 11 | 12 | #if DEBUG 13 | #define APIBaseURL @"https://staging_api.phphub.org/v1" 14 | #else 15 | #define APIBaseURL @"https://api.phphub.org/v1" 16 | #endif 17 | 18 | #define PHPHubHost @"phphub.org" 19 | #define PHPHubUrl @"https://phphub.org/" 20 | #define GitHubURL @"https://github.com/" 21 | #define TwitterURL @"https://twitter.com/" 22 | #define ProjectURL @"https://github.com/aufree/phphub-ios" 23 | #define AboutPageURL @"https://phphub.org/about" 24 | #define ESTGroupURL @"http://est-group.org" 25 | #define AboutTheAuthorURL @"https://github.com/aufree" 26 | #define PHPHubGuide @"http://7xnqwn.com1.z0.glb.clouddn.com/index.html" 27 | #define PHPHubTopicURL @"https://phphub.org/topics/" 28 | #define SinaRedirectURL @"http://sns.whalecloud.com/sina2/callback" 29 | 30 | #define UpdateNoticeCount @"UpdateNoticeCount" 31 | #define KeyChainService @"PHPHubService" 32 | #define KeyChainAccount @"com.PHPHub.keychain" -------------------------------------------------------------------------------- /PHPHub/BaseClasses/BaseDBManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // BaseDBManager.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "FMDatabase.h" 12 | #import "FMDatabaseAdditions.h" 13 | #import "MTLModel.h" 14 | #import "FMDBMigrationManager.h" 15 | 16 | #define DefaultDatabaseFileName @"MainDataBase.sqlite" 17 | 18 | @interface BaseDBManager : NSObject 19 | @property(strong, nonatomic)FMDatabase *db; 20 | 21 | + (instancetype)sharedInstance; 22 | 23 | + (NSArray *)columnValuesForUpdate:(MTLModel *)model; 24 | + (BOOL)isExists:(MTLModel *)model; 25 | + (NSNumber *)getDataCount:(Class)objectClass; 26 | 27 | + (void)insertOnDuplicateUpdate:(MTLModel *)model; 28 | + (id)findById:(NSString *)primary_id withClass:(Class)objectClass; 29 | 30 | + (id)findUsingPrimaryKeys:(MTLModel *)model; 31 | + (NSArray *)findByColumn:(NSString *)column columnValue:(NSString *)value withClass:(Class)objectClass; 32 | + (NSArray *)findRandomByDictionary:(NSDictionary *)columnDictionary withClass:(Class)objectClass; 33 | + (id)updateDate:(NSDictionary *)columnDictionary withClass:(Class)objectClass; 34 | + (NSNumber *)getMaxColumnIdWithClass:(Class)objectClass column:(NSString *)column; 35 | @end 36 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/GoogleAnalytics/Library/GAILogger.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @header GAILogger.h 3 | @abstract Google Analytics iOS SDK Source 4 | @copyright Copyright 2011 Google Inc. All rights reserved. 5 | */ 6 | 7 | #import 8 | 9 | typedef NS_ENUM(NSUInteger, GAILogLevel) { 10 | kGAILogLevelNone = 0, 11 | kGAILogLevelError = 1, 12 | kGAILogLevelWarning = 2, 13 | kGAILogLevelInfo = 3, 14 | kGAILogLevelVerbose = 4 15 | }; 16 | 17 | /*! 18 | Protocol to be used for logging debug and informational messages from the SDK. 19 | Implementations of this protocol can be provided to the |GAI| class, 20 | to be used as the logger by the SDK. See the |logger| property in GAI.h. 21 | */ 22 | @protocol GAILogger 23 | @required 24 | 25 | /*! 26 | Only messages of |logLevel| and below are logged. 27 | */ 28 | @property (nonatomic, assign) GAILogLevel logLevel; 29 | 30 | /*! 31 | Logs message with log level |kGAILogLevelVerbose|. 32 | */ 33 | - (void)verbose:(NSString *)message; 34 | 35 | /*! 36 | Logs message with log level |kGAILogLevelInfo|. 37 | */ 38 | - (void)info:(NSString *)message; 39 | 40 | /*! 41 | Logs message with log level |kGAILogLevelWarning|. 42 | */ 43 | - (void)warning:(NSString *)message; 44 | 45 | /*! 46 | Logs message with log level |kGAILogLevelError|. 47 | */ 48 | - (void)error:(NSString *)message; 49 | @end 50 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/TOWebViewController/TOActivityChrome.h: -------------------------------------------------------------------------------- 1 | // 2 | // TOActivityChrome.h 3 | // 4 | // Copyright 2013-2015 Timothy Oliver. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to 8 | // deal in the Software without restriction, including without limitation the 9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | // sell copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | extern NSString *const TOActivityTypeChrome; 26 | 27 | @interface TOActivityChrome : UIActivity 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/TOWebViewController/TOActivitySafari.h: -------------------------------------------------------------------------------- 1 | // 2 | // TOActivitySafari.h 3 | // 4 | // Copyright 2013-2015 Timothy Oliver. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to 8 | // deal in the Software without restriction, including without limitation the 9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | // sell copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | extern NSString *const TOActivityTypeSafari; 26 | 27 | @interface TOActivitySafari : UIActivity 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/AFOAuth2Manager/AFOAuth2Manager+Addtions.m: -------------------------------------------------------------------------------- 1 | // 2 | // AFOAuth2Manager+Addtions.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | NSString * const kAFOAuthLoginTokenCredentialsGrantType = @"login_token"; 10 | 11 | #import "AFOAuth2Manager+Addtions.h" 12 | 13 | @implementation AFOAuth2Manager (Addtions) 14 | - (AFHTTPRequestOperation *)authenticateUsingOAuthWithURLString:(NSString *)URLString 15 | username:(NSString *)username 16 | loginToken:(NSString *)loginToken 17 | scope:(NSString *)scope 18 | success:(void (^)(AFOAuthCredential *credential))success 19 | failure:(void (^)(NSError *error))failure { 20 | NSParameterAssert(username); 21 | NSParameterAssert(scope); 22 | 23 | NSDictionary *parameters = @{ 24 | @"grant_type": kAFOAuthLoginTokenCredentialsGrantType, 25 | @"username": username, 26 | @"login_token": loginToken, 27 | @"scope": scope 28 | }; 29 | 30 | return [self authenticateUsingOAuthWithURLString:URLString parameters:parameters success:success failure:failure]; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /PHPHub/Handlers/ExceptionHandler.m: -------------------------------------------------------------------------------- 1 | // 2 | // ExceptionHandler.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/21/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "ExceptionHandler.h" 10 | #import 11 | #import 12 | 13 | @implementation ExceptionHandler 14 | 15 | + (void)bootup { 16 | 17 | // Init Crashlitics 18 | [Fabric with:@[[Crashlytics class]]]; 19 | 20 | if ([[CurrentUser Instance] isLogin]) { 21 | [CrashlyticsKit setUserIdentifier:[[CurrentUser Instance].userId stringValue]]; 22 | [CrashlyticsKit setUserName:[[CurrentUser Instance] userInfo].username]; 23 | } 24 | } 25 | 26 | + (void)logEvent:(NSString *)eventName { 27 | [Answers logCustomEventWithName:eventName customAttributes:@{}]; 28 | } 29 | 30 | + (void)logEvent:(NSString *)eventName attributes:(NSDictionary * )attributes { 31 | [Answers logCustomEventWithName:eventName customAttributes:attributes]; 32 | } 33 | 34 | + (void)setObjectValue:(id)value forKey:(NSString *)key { 35 | [[Crashlytics sharedInstance] setObjectValue:value forKey:key]; 36 | } 37 | 38 | + (void)setIntValue:(int)value forKey:(NSString *)key { 39 | [[Crashlytics sharedInstance] setIntValue:value forKey:key]; 40 | } 41 | 42 | + (void)setBoolValue:(BOOL)value forKey:(NSString *)key { 43 | [[Crashlytics sharedInstance] setBoolValue:value forKey:key]; 44 | } 45 | 46 | + (void)setFloatValue:(float)value forKey:(NSString *)key { 47 | [[Crashlytics sharedInstance] setFloatValue:value forKey:key]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/TopicEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // TopicEntity.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "TopicEntity.h" 10 | 11 | @implementation TopicEntity 12 | 13 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 14 | return @{ 15 | @"topicId" : @"id", 16 | @"nodeId" : @"node_id", 17 | @"topicTitle" : @"title", 18 | @"topicBody" : @"body", 19 | @"topicRepliesCount" : @"reply_count", 20 | @"voteCount" : @"vote_count", 21 | @"user" : @"user.data", 22 | @"lastReplyUser" : @"last_reply_user.data", 23 | @"node" : @"node.data", 24 | @"topicContentUrl" : @"links.details_web_view", 25 | @"topicRepliesUrl" : @"links.replies_web_view", 26 | @"favorite" : @"favorite", 27 | @"attention" : @"attention", 28 | @"voteUp" : @"vote_up", 29 | @"voteDown" : @"vote_down", 30 | @"updatedAt" : @"updated_at", 31 | }; 32 | } 33 | 34 | + (NSValueTransformer *)userJSONTransformer { 35 | return [NSValueTransformer mtl_JSONDictionaryTransformerWithModelClass:[UserEntity class]]; 36 | } 37 | 38 | + (NSValueTransformer *)lastReplyUserJSONTransformer { 39 | return [NSValueTransformer mtl_JSONDictionaryTransformerWithModelClass:[UserEntity class]]; 40 | } 41 | 42 | + (NSValueTransformer *)nodeJSONTransformer { 43 | return [NSValueTransformer mtl_JSONDictionaryTransformerWithModelClass:[NodeEntity class]]; 44 | } 45 | @end 46 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/GoogleAnalytics/Library/GAITracker.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @header GAITracker.h 3 | @abstract Google Analytics iOS SDK Tracker Header 4 | @copyright Copyright 2013 Google Inc. All rights reserved. 5 | */ 6 | 7 | #import 8 | 9 | /*! 10 | Google Analytics tracking interface. Obtain instances of this interface from 11 | [GAI trackerWithTrackingId:] to track screens, events, transactions, timing, 12 | and exceptions. The implementation of this interface is thread-safe, and no 13 | calls are expected to block or take a long time. All network and disk activity 14 | will take place in the background. 15 | */ 16 | @protocol GAITracker 17 | 18 | /*! 19 | Name of this tracker. 20 | */ 21 | @property(nonatomic, readonly) NSString *name; 22 | 23 | /*! 24 | Allow collection of IDFA and related fields if set to true. Default is false. 25 | */ 26 | @property(nonatomic) BOOL allowIDFACollection; 27 | 28 | /*! 29 | Set a tracking parameter. 30 | 31 | @param parameterName The parameter name. 32 | 33 | @param value The value to set for the parameter. If this is nil, the 34 | value for the parameter will be cleared. 35 | */ 36 | - (void)set:(NSString *)parameterName 37 | value:(NSString *)value; 38 | 39 | /*! 40 | Get a tracking parameter. 41 | 42 | @param parameterName The parameter name. 43 | 44 | @returns The parameter value, or nil if no value for the given parameter is 45 | set. 46 | */ 47 | - (NSString *)get:(NSString *)parameterName; 48 | 49 | /*! 50 | Queue tracking information with the given parameter values. 51 | 52 | @param parameters A map from parameter names to parameter values which will be 53 | set just for this piece of tracking information, or nil for none. 54 | */ 55 | - (void)send:(NSDictionary *)parameters; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/GoogleAnalytics/Library/GAIEcommercePromotion.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @header GAIEcommercePromotion.h 3 | @abstract Google Analytics iOS SDK Hit Format Header 4 | @copyright Copyright 2014 Google Inc. All rights reserved. 5 | */ 6 | 7 | #import 8 | 9 | /*! 10 | * Class to construct promotion related fields for Google Analytics hits. The fields from this class 11 | * can be used to represent internal promotions that run within an app, such as banners, banner ads 12 | * etc. 13 | * 14 | * Typical usage: 15 | * 16 | * GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createScreenView]; 17 | * GAIEcommercePromotion *promotion = [[GAIEcommercePromotion alloc] init]; 18 | * [promotion setId:@"PROMO-ID1234"]; 19 | * [promotion setName:@"Home screen banner"]; 20 | * [builder set:kGAIPromotionClick forKey:kGAIPromotionAction]; 21 | * [builder addPromotion:promotion]; 22 | * [tracker send:builder.build]]; 23 | * 24 | */ 25 | @interface GAIEcommercePromotion : NSObject 26 | 27 | /*! 28 | Sets the id that is used to identify a promotion in GA reports. 29 | */ 30 | - (GAIEcommercePromotion *)setId:(NSString *)pid; 31 | 32 | /*! 33 | Sets the name that is used to identify a promotion in GA reports. 34 | */ 35 | - (GAIEcommercePromotion *)setName:(NSString *)name; 36 | 37 | /*! 38 | Sets the name of the creative associated with the promotion. 39 | */ 40 | - (GAIEcommercePromotion *)setCreative:(NSString *)creative; 41 | 42 | /*! 43 | Sets the position of the promotion. 44 | */ 45 | - (GAIEcommercePromotion *)setPosition:(NSString *)position; 46 | 47 | /*! 48 | Builds an NSDictionary of fields stored in this instance. The index parameter is the 49 | index of this promotion in that promotion list. 50 |
51 | Normally, users will have no need to call this method. 52 | */ 53 | - (NSDictionary *)buildWithIndex:(NSUInteger)index; 54 | @end 55 | -------------------------------------------------------------------------------- /PHPHub/Apis/TopicApi.h: -------------------------------------------------------------------------------- 1 | // 2 | // TopicApi.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseApi.h" 10 | #import "TopicEntity.h" 11 | #import "CommentEntity.h" 12 | 13 | @interface TopicApi : BaseApi 14 | 15 | - (id)getAll:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 16 | - (id)getExcellentTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 17 | - (id)getNewestTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 18 | - (id)getHotsTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 19 | - (id)getNoReplyTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 20 | - (id)getJobTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 21 | - (id)getWiKiList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 22 | - (id)getTopicListByUser:(NSInteger)userId callback:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 23 | - (id)getFavoriteTopicListByUser:(NSInteger)userId callback:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 24 | - (id)getAttentionTopicListByUser:(NSInteger)userId callback:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 25 | - (id)getTopicById:(NSInteger)topicId callback:(BaseResultBlock)block; 26 | - (id)addCommentToTopic:(CommentEntity *)comment withBlock:(BaseResultBlock)block; 27 | - (id)favoriteTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 28 | - (id)cancelFavoriteTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 29 | - (id)attentionTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 30 | - (id)cancelAttentionTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 31 | - (id)createTopic:(TopicEntity *)entity withBlock:(BaseResultBlock)block; 32 | - (id)voteUpTopic:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 33 | - (id)voteDownTopic:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 34 | @end 35 | -------------------------------------------------------------------------------- /PHPHub/Models/TopicModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TopicModel.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseModel.h" 10 | #import "TopicApi.h" 11 | 12 | @interface TopicModel : BaseModel 13 | @property TopicApi *api; 14 | - (id)getAllTopic:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 15 | - (id)getExcellentTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 16 | - (id)getNewestTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 17 | - (id)getHotsTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 18 | - (id)getNoReplyTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 19 | - (id)getJobTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 20 | - (id)getWiKiList:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 21 | - (id)getTopicListByUser:(NSInteger)userId callback:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 22 | - (id)getFavoriteTopicListByUser:(NSInteger)userId callback:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 23 | - (id)getAttentionTopicListByUser:(NSInteger)userId callback:(BaseResultBlock)block atPage:(NSInteger)pageIndex; 24 | - (id)getTopicById:(NSInteger)topicId callback:(BaseResultBlock)block; 25 | - (id)addCommentToTopic:(CommentEntity *)comment withBlock:(BaseResultBlock)block; 26 | - (id)favoriteTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 27 | - (id)cancelFavoriteTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 28 | - (id)attentionTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 29 | - (id)cancelAttentionTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 30 | - (id)createTopic:(TopicEntity *)entity withBlock:(BaseResultBlock)block; 31 | - (id)voteUpTopic:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 32 | - (id)voteDownTopic:(NSNumber *)topicId withBlock:(BaseResultBlock)block; 33 | @end -------------------------------------------------------------------------------- /PHPHub/Utils/DBManager/LaunchScreenAdDBManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // LaunchScreenAdDBManager.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "LaunchScreenAdDBManager.h" 10 | #import "LaunchScreenAdEntity.h" 11 | 12 | @implementation LaunchScreenAdDBManager 13 | 14 | + (id)findLaunchScreenAdByExpries { 15 | LaunchScreenAdEntity *entity = [self getLaunchScreenAdByExpriesInLocal]; 16 | 17 | if (entity) { 18 | return entity; 19 | } 20 | 21 | return nil; 22 | } 23 | 24 | + (id)getLaunchScreenAdByExpriesInLocal { 25 | NSError *error = nil; 26 | MTLModel *model = [[LaunchScreenAdEntity alloc] init]; 27 | NSString *query = [NSString stringWithFormat:@"select * from %@ where expires_at > datetime(CURRENT_TIMESTAMP,'localtime') order by datetime(expires_at) asc limit 1", [model.class FMDBTableName]]; 28 | NSArray *params = [MTLFMDBAdapter primaryKeysValues:model]; 29 | FMResultSet *resultSet = [[BaseDBManager sharedInstance].db executeQuery:query withArgumentsInArray:params]; 30 | if ([resultSet next]) { 31 | return [MTLFMDBAdapter modelOfClass:model.class fromFMResultSet:resultSet error:&error]; 32 | } 33 | return nil; 34 | } 35 | 36 | + (id)eraseLaunchScreenAdData { 37 | NSError *error = nil; 38 | MTLModel *model = [[LaunchScreenAdEntity alloc] init]; 39 | NSString *query = [NSString stringWithFormat:@"DELETE FROM %@", [model.class FMDBTableName]]; 40 | NSArray *params = [MTLFMDBAdapter primaryKeysValues:model]; 41 | FMResultSet *resultSet = [[BaseDBManager sharedInstance].db executeQuery:query withArgumentsInArray:params]; 42 | if ([resultSet next]) { 43 | return [MTLFMDBAdapter modelOfClass:model.class fromFMResultSet:resultSet error:&error]; 44 | } 45 | return nil; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/TOWebViewController/UIImage+TOWebViewControllerIcons.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+TOWebViewControllerIcons.h 3 | // 4 | // Copyright 2013-2015 Timothy Oliver. All rights reserved. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to 8 | // deal in the Software without restriction, including without limitation the 9 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 | // sell copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 21 | // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | /* Keys for each of the theming properties */ 26 | extern const NSString *TOWebViewControllerButtonTintColor; 27 | extern const NSString *TOWebViewControllerButtonBevelOpacity; 28 | 29 | @interface UIImage (TOWebViewControllerIcons) 30 | 31 | /* Navigtion Buttons */ 32 | + (instancetype)TOWebViewControllerIcon_backButtonWithAttributes:(NSDictionary *)attributes; 33 | + (instancetype)TOWebViewControllerIcon_forwardButtonWithAttributes:(NSDictionary *)attributes; 34 | + (instancetype)TOWebViewControllerIcon_refreshButtonWithAttributes:(NSDictionary *)attributes; 35 | + (instancetype)TOWebViewControllerIcon_stopButtonWithAttributes:(NSDictionary *)attributes; 36 | + (instancetype)TOWebViewControllerIcon_actionButtonWithAttributes:(NSDictionary *)attributes; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/LaunchScreenAdEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // LaunchScreenAdEntity.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "LaunchScreenAdEntity.h" 10 | 11 | @implementation LaunchScreenAdEntity 12 | 13 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 14 | return @{ 15 | @"launchScreenAdId" : @"id", 16 | @"launchDescription" : @"description", 17 | @"smallImage" : @"image_small", 18 | @"bigImage" : @"image_large", 19 | @"launchScreenType" : @"type", 20 | @"payload" : @"payload", 21 | @"displayTime" : @"display_time", 22 | @"startAt" : @"start_at", 23 | @"expiresAt" : @"expires_at", 24 | }; 25 | } 26 | 27 | #pragma mark - MTLFMDBAdapter Stuff 28 | 29 | + (NSDictionary *)FMDBColumnsByPropertyKey { 30 | return @{ 31 | @"launchScreenAdId" : @"id", 32 | @"launchDescription" : [NSNull null], 33 | @"smallImage" : @"image_small", 34 | @"bigImage" : @"image_large", 35 | @"launchScreenType" : @"type", 36 | @"payload" : @"payload", 37 | @"displayTime" : @"display_time", 38 | @"startAt" : @"start_at", 39 | @"expiresAt" : @"expires_at", 40 | @"type" : [NSNull null] 41 | }; 42 | } 43 | 44 | - (LaunchScreenType)type { 45 | if (!_type) { 46 | if ([self.launchScreenType isEqualToString:@"topic"]) { 47 | _type = LaunchScreenTypeByTopic; 48 | } else if ([self.launchScreenType isEqualToString:@"user"]) { 49 | _type = LaunchScreenTypeByUser; 50 | } else if ([self.launchScreenType isEqualToString:@"web"]) { 51 | _type = LaunchScreenTypeByWeb; 52 | } else { 53 | _type = LaunchScreenTypeUnknow; 54 | } 55 | } 56 | return _type; 57 | } 58 | 59 | + (NSArray *)FMDBPrimaryKeys { 60 | return @[@"id"]; 61 | } 62 | 63 | + (NSString *)FMDBTableName { 64 | return @"launchScreenAds"; 65 | } 66 | @end 67 | -------------------------------------------------------------------------------- /PHPHub/Apis/NotificationApi.m: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationApi.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/13/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "NotificationApi.h" 10 | 11 | @implementation NotificationApi 12 | - (id)getNotificationList:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 13 | NSString *urlPath = [NSString stringWithFormat:@"me/notifications?include=from_user,topic&per_page=20&page=%ld", (long)pageIndex]; 14 | 15 | BaseRequestSuccessBlock successBlock = ^(NSURLSessionDataTask * __unused task, id rawData) { 16 | NSMutableDictionary *data = [(NSDictionary *)rawData mutableCopy]; 17 | data[@"entities"] = [NotificationEntity arrayOfEntitiesFromArray:data[@"data"]]; 18 | data[@"pagination"] = [PaginationEntity entityFromDictionary:data[@"meta"][@"pagination"]]; 19 | if (block) block(data, nil); 20 | }; 21 | 22 | BaseRequestFailureBlock failureBlock = ^(NSURLSessionDataTask *__unused task, NSError *error) { 23 | if (block) block(nil, error); 24 | }; 25 | 26 | return [[BaseApi loginTokenGrantInstance] GET:urlPath 27 | parameters:nil 28 | success:successBlock 29 | failure:failureBlock]; 30 | } 31 | 32 | - (id)getUnreadNotificationCount:(BaseResultBlock)block { 33 | NSString *urlPath = [NSString stringWithFormat:@"me/notifications/count"]; 34 | 35 | BaseRequestSuccessBlock successBlock = ^(NSURLSessionDataTask * __unused task, id rawData) { 36 | NSMutableDictionary *data = [(NSDictionary *)rawData mutableCopy]; 37 | if (block) block(data, nil); 38 | }; 39 | 40 | BaseRequestFailureBlock failureBlock = ^(NSURLSessionDataTask *__unused task, NSError *error) { 41 | if (block) block(nil, error); 42 | }; 43 | 44 | return [[BaseApi loginTokenGrantInstance] GET:urlPath 45 | parameters:nil 46 | success:successBlock 47 | failure:failureBlock]; 48 | } 49 | @end 50 | -------------------------------------------------------------------------------- /PHPHub/Handlers/UMengSocialHandler.m: -------------------------------------------------------------------------------- 1 | // 2 | // UMengSocialHandler.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/15/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "UMengSocialHandler.h" 10 | 11 | @interface UMengSocialHandler () 12 | @end 13 | 14 | @implementation UMengSocialHandler 15 | 16 | + (void)setup { 17 | [UMSocialData setAppKey:UMENG_APPKEY]; 18 | [UMSocialQQHandler setQQWithAppId:UMENG_QQ_ID appKey:UMENG_QQ_APPKEY url:PHPHubUrl]; 19 | [UMSocialWechatHandler setWXAppId:WX_APP_ID appSecret:WX_APP_SECRET url:PHPHubUrl]; 20 | [UMSocialSinaHandler openSSOWithRedirectURL:SinaRedirectURL]; 21 | } 22 | 23 | + (void)shareWithShareURL:(NSString *)shareURL 24 | shareImageUrl:(NSString *)shareImageUrl 25 | shareTitle:(NSString *)shareTitle 26 | shareText:(NSString *)shareText 27 | presentVC:(UIViewController *)vc 28 | delegate:(id )delegate { 29 | 30 | [UMSocialData defaultData].extConfig.title = shareTitle; 31 | // Global share link 32 | [[UMSocialData defaultData].urlResource setResourceType:UMSocialUrlResourceTypeImage url:shareImageUrl]; 33 | // WeChat Timeline Custom 34 | [UMSocialData defaultData].extConfig.wechatTimelineData.url = shareURL; 35 | [UMSocialData defaultData].extConfig.wechatSessionData.url = shareURL; 36 | [UMSocialData defaultData].extConfig.qqData.url = shareURL; 37 | 38 | [UMSocialSnsService presentSnsIconSheetView:vc 39 | appKey:UMENG_APPKEY 40 | shareText:shareText 41 | shareImage:[UIImage imageNamed:@"logo"] 42 | shareToSnsNames:[NSArray arrayWithObjects: 43 | UMShareToWechatSession, 44 | UMShareToWechatTimeline, 45 | UMShareToQQ, 46 | UMShareToSina, 47 | nil] 48 | delegate:delegate]; 49 | } 50 | @end -------------------------------------------------------------------------------- /PHPHub/Utils/Entities/UserEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // UserEntity.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "UserEntity.h" 10 | 11 | @implementation UserEntity 12 | 13 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 14 | return @{ 15 | @"userId" : @"id", 16 | @"username" : @"name", 17 | @"avatar" : @"avatar", 18 | @"topicCount" : @"topic_count", 19 | @"replyCount" : @"reply_count", 20 | @"notificationCount" : @"notification_count", 21 | @"twitterAccount" : @"twitter_account", 22 | @"company" : @"company", 23 | @"city" : @"city", 24 | @"email" : @"email", 25 | @"signature" : @"signature", 26 | @"githubName" : @"github_name", 27 | @"githubURL" : @"github_url", 28 | @"realName" : @"real_name", 29 | @"blogURL" : @"personal_website", 30 | @"repliesUrl" : @"links.replies_web_view", 31 | @"createdAtDate" : @"created_at", 32 | @"updatedAtDate" : @"updated_at", 33 | }; 34 | } 35 | 36 | + (NSArray *)FMDBPrimaryKeys { 37 | return @[@"id"]; 38 | } 39 | 40 | + (NSString *)FMDBTableName { 41 | return @"users"; 42 | } 43 | 44 | #pragma mark - MTLFMDBAdapter 45 | 46 | + (NSDictionary *)FMDBColumnsByPropertyKey { 47 | return @{ 48 | @"userId" : @"id", 49 | @"username" : @"name", 50 | @"avatar" : @"avatar", 51 | @"topicCount" : @"topic_count", 52 | @"replyCount" : @"reply_count", 53 | @"notificationCount" : [NSNull null], 54 | @"twitterAccount" : @"twitter_account", 55 | @"company" : @"company", 56 | @"city" : @"city", 57 | @"email" : @"email", 58 | @"signature" : @"signature", 59 | @"githubName" : @"github_name", 60 | @"githubURL" : @"github_url", 61 | @"realName" : @"real_name", 62 | @"blogURL" : @"personal_website", 63 | @"repliesUrl" : @"replies_web_view", 64 | @"createdAtDate" : @"created_at", 65 | @"updatedAtDate" : @"updated_at", 66 | }; 67 | } 68 | @end 69 | -------------------------------------------------------------------------------- /PHPHub/Views/Comment/CommentListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CommentListViewController.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/26/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "CommentListViewController.h" 10 | #import "ReplyTopicViewController.h" 11 | #import "TOWebViewController.h" 12 | #import "BaseWebView.h" 13 | 14 | #import "AccessTokenHandler.h" 15 | 16 | @interface CommentListViewController () 17 | @property (nonatomic, strong) BaseWebView *commentsWebView; 18 | @end 19 | 20 | @implementation CommentListViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | self.navigationItem.title = @"评论列表"; 25 | 26 | [self.view addSubview:self.commentsWebView]; 27 | 28 | if (_topic.topicId > 0) { 29 | [self createRightBarButtonItem]; 30 | } 31 | } 32 | 33 | - (UIWebView *)commentsWebView { 34 | if (!_commentsWebView) { 35 | _commentsWebView = [[BaseWebView alloc] initWithFrame:self.view.bounds urlString:_topic.topicRepliesUrl]; 36 | } 37 | return _commentsWebView; 38 | } 39 | 40 | - (void)createRightBarButtonItem { 41 | if ([[CurrentUser Instance] isLogin]) { 42 | UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"edit_profile_icon"] 43 | style:UIBarButtonItemStylePlain 44 | target:self 45 | action:@selector(jumpToReplyTopicVC)]; 46 | rightBarButtonItem.tintColor = [UIColor colorWithRed:0.502 green:0.776 blue:0.200 alpha:1.000]; 47 | self.navigationItem.rightBarButtonItem = rightBarButtonItem; 48 | } 49 | } 50 | 51 | - (void)jumpToReplyTopicVC { 52 | ReplyTopicViewController *replyTopicVC = [[UIStoryboard storyboardWithName:@"Topic" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"replyTopic"]; 53 | replyTopicVC.topicId = _topic.topicId; 54 | replyTopicVC.delegate = self; 55 | [self.navigationController pushViewController:replyTopicVC animated:YES]; 56 | } 57 | 58 | #pragma mark Load WebView 59 | 60 | - (void)reloadCommentListView { 61 | [_commentsWebView reload]; 62 | } 63 | @end 64 | -------------------------------------------------------------------------------- /PHPHub/Models/AdModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // AdModel.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/19/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "AdModel.h" 10 | #import "LaunchScreenAdDBManager.h" 11 | #import "LaunchScreenAdEntity.h" 12 | 13 | @implementation AdModel 14 | 15 | - (instancetype)init { 16 | self = [super init]; 17 | if (self) { 18 | _api = [[AdApi alloc] init]; 19 | } 20 | return self; 21 | } 22 | 23 | - (id)getAdvertsLaunchScreen:(BaseResultBlock)block { 24 | BaseResultBlock callback = ^(NSDictionary *data, NSError *error) { 25 | if (!error) { 26 | NSArray *adEntities = [data objectForKey:@"entities"]; 27 | [self insertAdEntitiesToLocalDataBase:adEntities]; 28 | } 29 | if (block) block(data, error); 30 | }; 31 | 32 | return [_api getAdvertsLaunchScreen:callback]; 33 | } 34 | 35 | - (void)insertAdEntitiesToLocalDataBase:(NSArray *)adEntities { 36 | [LaunchScreenAdDBManager eraseLaunchScreenAdData]; 37 | 38 | if (adEntities.count > 0) { 39 | [[BaseDBManager sharedInstance].db beginTransaction]; 40 | for (int i = 0; i < adEntities.count; i++) { 41 | LaunchScreenAdEntity *entity = [adEntities objectAtIndex:i]; 42 | [LaunchScreenAdDBManager insertOnDuplicateUpdate:entity]; 43 | } 44 | [[BaseDBManager sharedInstance].db commit]; 45 | 46 | [self checkLaunchScreenAdImageHasCached:adEntities]; 47 | } 48 | } 49 | 50 | - (void)checkLaunchScreenAdImageHasCached:(NSArray *)adEntities { 51 | for (int i = 0; i < adEntities.count; i++) { 52 | LaunchScreenAdEntity *launchScreenAdEntity = [adEntities objectAtIndex:i]; 53 | NSString *screenImageUrl = IS_IPHONE_4_OR_LESS ? launchScreenAdEntity.smallImage : launchScreenAdEntity.bigImage; 54 | NSString *imageWidth = [NSString stringWithFormat:@"%.f", SCREEN_WIDTH * 2]; 55 | NSString *imageHeight = [NSString stringWithFormat:@"%.f", SCREEN_HEIGHT * 2]; 56 | NSURL *imageLink = [BaseHelper qiniuImageCenter:screenImageUrl withWidth:imageWidth withHeight:imageHeight]; 57 | BOOL imageIsCache = [SDWebImageManager.sharedManager cachedImageExistsForURL:imageLink]; 58 | if (!imageIsCache) { 59 | [[[UIImageView alloc] init] sd_setImageWithURL:imageLink]; 60 | } 61 | } 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /PHPHub/Views/Base/BubbleButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // BubbleButton.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/9/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BubbleButton.h" 10 | #import 11 | 12 | @implementation BubbleButton 13 | 14 | - (instancetype)initWithFrame:(CGRect)frame { 15 | self = [super initWithFrame:frame]; 16 | if (self) { 17 | [self setup]; 18 | } 19 | return self; 20 | } 21 | 22 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 23 | self = [super initWithCoder:aDecoder]; 24 | if (self) { 25 | [self setup]; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)setup { 31 | [self addTarget:self action:@selector(scaleToSmall) forControlEvents:UIControlEventTouchDown | UIControlEventTouchDragEnter]; 32 | [self addTarget:self action:@selector(scaleAnimation) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside]; 33 | } 34 | 35 | - (void)scaleToSmall { 36 | POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; 37 | scaleAnimation.velocity = [NSValue valueWithCGSize:CGSizeMake(3.f, 3.f)]; 38 | scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(0.7f, 0.7f)]; 39 | [self.layer pop_addAnimation:scaleAnimation forKey:@"layerScaleSmallAnimation"]; 40 | } 41 | 42 | - (void)scaleAnimation { 43 | POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; 44 | scaleAnimation.velocity = [NSValue valueWithCGSize:CGSizeMake(3.f, 3.f)]; 45 | scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.f, 1.f)]; 46 | scaleAnimation.springBounciness = 18.0f; 47 | 48 | __weak typeof(self) weakself = self; 49 | scaleAnimation.completionBlock = ^(POPAnimation *anim, BOOL finished) { 50 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.3f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 51 | [weakself scaleToDefault]; 52 | }); 53 | }; 54 | 55 | [self.layer pop_addAnimation:scaleAnimation forKey:@"layerScaleSpringAnimation"]; 56 | } 57 | 58 | - (void)scaleToDefault { 59 | POPBasicAnimation *scaleAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; 60 | scaleAnimation.toValue = [NSValue valueWithCGSize:CGSizeMake(1.f, 1.f)]; 61 | [self.layer pop_addAnimation:scaleAnimation forKey:@"layerScaleDefaultAnimation"]; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/NSURL+QueryDictionary/NSURL+QueryDictionary.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSURL+Query.h 3 | // NSURL+Query 4 | // 5 | // Created by Jon Crooke on 10/12/2013. 6 | // Copyright (c) 2013 Jonathan Crooke. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSURL (UQ_URLQuery) 12 | 13 | /** 14 | * @return URL's query component as keys/values 15 | * Returns nil for an empty query 16 | */ 17 | - (NSDictionary*) uq_queryDictionary; 18 | 19 | /** 20 | * @return URL with keys values appending to query string 21 | * @param queryDictionary Query keys/values 22 | * @param sortedKeys Sorted the keys alphabetically? 23 | * @warning If keys overlap in receiver and query dictionary, 24 | * behaviour is undefined. 25 | */ 26 | - (NSURL*) uq_URLByAppendingQueryDictionary:(NSDictionary*) queryDictionary 27 | withSortedKeys:(BOOL) sortedKeys; 28 | 29 | /** As above, but `sortedKeys=NO` */ 30 | - (NSURL*) uq_URLByAppendingQueryDictionary:(NSDictionary*) queryDictionary; 31 | 32 | /** 33 | * @return Copy of URL with its query component replaced with 34 | * the specified dictionary. 35 | * @param queryDictionary A new query dictionary 36 | * @param sortedKeys Whether or not to sort the query keys 37 | */ 38 | - (NSURL*) uq_URLByReplacingQueryWithDictionary:(NSDictionary*) queryDictionary 39 | withSortedKeys:(BOOL) sortedKeys; 40 | 41 | /** As above, but `sortedKeys=NO` */ 42 | - (NSURL*) uq_URLByReplacingQueryWithDictionary:(NSDictionary*) queryDictionary; 43 | 44 | /** @return Receiver with query component completely removed */ 45 | - (NSURL*) uq_URLByRemovingQuery; 46 | 47 | @end 48 | 49 | #pragma mark - 50 | 51 | @interface NSString (UQ_URLQuery) 52 | 53 | /** 54 | * @return If the receiver is a valid URL query component, returns 55 | * components as key/value pairs. If couldn't split into *any* pairs, 56 | * returns nil. 57 | */ 58 | - (NSDictionary*) uq_URLQueryDictionary; 59 | 60 | @end 61 | 62 | #pragma mark - 63 | 64 | @interface NSDictionary (UQ_URLQuery) 65 | 66 | /** 67 | * @return URL query string component created from the keys and values in 68 | * the dictionary. Returns nil for an empty dictionary. 69 | * @param sortedKeys Sorted the keys alphabetically? 70 | * @see cavetas from the main `NSURL` category as well. 71 | */ 72 | - (NSString*) uq_URLQueryStringWithSortedKeys:(BOOL) sortedKeys; 73 | 74 | /** As above, but `sortedKeys=NO` */ 75 | - (NSString*) uq_URLQueryString; 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /PHPHub/Views/Topic/EmptyTopicView.m: -------------------------------------------------------------------------------- 1 | // 2 | // EmptyTopicView.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/23/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "EmptyTopicView.h" 10 | #import "Masonry.h" 11 | 12 | @interface EmptyTopicView () 13 | @property (nonatomic) UIView *containerView; 14 | @property (nonatomic) UIImageView *emptyDataImage; 15 | @property (nonatomic) UILabel *hintLabel; 16 | @end 17 | 18 | @implementation EmptyTopicView 19 | - (instancetype)initWithFrame:(CGRect)frame { 20 | self = [super initWithFrame:frame]; 21 | 22 | if (self) { 23 | [self setUp]; 24 | [self addAutoLayout]; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | - (void)setUp { 31 | [self addSubview:self.containerView]; 32 | } 33 | 34 | - (UIView *)containerView { 35 | if (_containerView == nil) { 36 | _containerView = [[UIView alloc] init]; 37 | [_containerView addSubview:self.emptyDataImage]; 38 | [_containerView addSubview:self.hintLabel]; 39 | } 40 | return _containerView; 41 | } 42 | 43 | - (UIImageView *)emptyDataImage { 44 | if (_emptyDataImage == nil) { 45 | _emptyDataImage = [[UIImageView alloc] init]; 46 | _emptyDataImage.image = [UIImage imageNamed:@"sad_face"]; 47 | } 48 | return _emptyDataImage; 49 | } 50 | 51 | - (UILabel *)hintLabel { 52 | if (_hintLabel == nil) { 53 | _hintLabel = [[UILabel alloc] init]; 54 | _hintLabel.font = [UIFont fontWithName:FontName size:18]; 55 | _hintLabel.textColor = [UIColor colorWithWhite:0.620 alpha:1.000]; 56 | _hintLabel.textAlignment = NSTextAlignmentCenter; 57 | _hintLabel.text = @"暂无数据"; 58 | } 59 | return _hintLabel; 60 | } 61 | 62 | - (void)addAutoLayout { 63 | [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) { 64 | make.centerX.equalTo(self); 65 | make.centerY.equalTo(self); 66 | make.size.mas_equalTo(CGSizeMake(SCREEN_WIDTH, 230)); 67 | }]; 68 | 69 | [self.emptyDataImage mas_makeConstraints:^(MASConstraintMaker *make) { 70 | make.top.offset(0); 71 | make.centerX.equalTo(self); 72 | make.size.mas_equalTo(CGSizeMake(140, 140)); 73 | }]; 74 | 75 | [self.hintLabel mas_makeConstraints:^(MASConstraintMaker *make) { 76 | make.top.equalTo(self.emptyDataImage.mas_bottom).offset(30); 77 | make.centerX.equalTo(self); 78 | make.size.mas_equalTo(CGSizeMake(SCREEN_WIDTH, 20)); 79 | }]; 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /PHPHub/BaseClasses/CurrentUser.m: -------------------------------------------------------------------------------- 1 | // 2 | // CurrentUser.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "CurrentUser.h" 10 | #import "AccessTokenHandler.h" 11 | #import "JpushHandler.h" 12 | #import "NotificationModel.h" 13 | #import "SSKeychain.h" 14 | 15 | @implementation CurrentUser 16 | + (CurrentUser *)Instance { 17 | static dispatch_once_t once; 18 | static CurrentUser *sharedInstance; 19 | dispatch_once(&once, ^{ 20 | sharedInstance = [[CurrentUser alloc] init]; 21 | }); 22 | return sharedInstance; 23 | } 24 | 25 | - (BOOL)isLogin { 26 | return (self.userId && self.userId.intValue > 0); 27 | } 28 | 29 | - (BOOL)hasClientToken { 30 | return [NSString isStringEmpty:[GVUserDefaults standardUserDefaults].userClientToken]; 31 | } 32 | 33 | - (void)saveUser:(UserEntity *)user { 34 | [UserDBManager insertOnDuplicateUpdate:user]; 35 | [JpushHandler sendUserIdToAlias]; 36 | } 37 | 38 | - (void)updateCurrentUserInfoIfNeeded { 39 | if ([[CurrentUser Instance] isLogin]) { 40 | [[UserModel Instance] getCurrentUserData:nil]; 41 | } 42 | } 43 | 44 | - (NSNumber *)userId { 45 | return [GVUserDefaults standardUserDefaults].currentUserId; 46 | } 47 | 48 | - (UserEntity *)userInfo { 49 | if (!self.userId) return nil; 50 | 51 | return [UserDBManager findByUserId:self.userId]; 52 | } 53 | 54 | - (void)setupClientRequestState:(BaseResultBlock)block { 55 | [AccessTokenHandler fetchClientGrantTokenWithRetryTimes:3 callback:block]; 56 | } 57 | 58 | - (void)checkNoticeCount { 59 | if ([[CurrentUser Instance] isLogin]) { 60 | [[NotificationModel Instance] getUnreadNotificationCount:^(id data, NSError *error) { 61 | if (!error) { 62 | NSNumber *unreadCount = data[@"count"]; 63 | [[UIApplication sharedApplication] setApplicationIconBadgeNumber:unreadCount.integerValue]; 64 | [[NSNotificationCenter defaultCenter] postNotificationName:UpdateNoticeCount object:nil userInfo:@{@"unreadCount":unreadCount}]; 65 | } 66 | }]; 67 | } 68 | } 69 | 70 | - (void)logOut { 71 | [SSKeychain deletePasswordForService:KeyChainService account:KeyChainAccount]; 72 | [GVUserDefaults standardUserDefaults].currentUserId = nil; 73 | [JpushHandler sendEmptyAlias]; 74 | } 75 | 76 | - (NSString *)userLabel { 77 | return self.isLogin ? [NSString stringWithFormat:@"user_%@_%@", [CurrentUser Instance].userId, [[CurrentUser Instance] userInfo].username] : @"non-logged-in"; 78 | } 79 | @end 80 | -------------------------------------------------------------------------------- /PHPHub/Models/UserModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // UserModel.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/30/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "UserModel.h" 10 | #import "AccessTokenHandler.h" 11 | 12 | @implementation UserModel 13 | 14 | - (instancetype)init { 15 | self = [super init]; 16 | if (self) { 17 | _api = [[UserApi alloc] init]; 18 | } 19 | return self; 20 | } 21 | 22 | - (id)getCurrentUserData:(BaseResultBlock)block { 23 | BaseResultBlock callback =^ (NSDictionary *data, NSError *error) { 24 | if (data) { 25 | UserEntity *user = data[@"entity"]; 26 | if (user) { 27 | [GVUserDefaults standardUserDefaults].currentUserId = user.userId; 28 | [[CurrentUser Instance] saveUser:user]; 29 | } 30 | if (block) block(data, nil); 31 | } else { 32 | if (block) block(nil, error); 33 | } 34 | }; 35 | 36 | return [_api getCurrentUserData:callback]; 37 | } 38 | 39 | - (id)getUserById:(NSNumber *)userId callback:(BaseResultBlock)block { 40 | return [_api getUserById:userId callback:block]; 41 | } 42 | 43 | - (id)loginWithUserName:(NSString *)username loginToken:(NSString *)loginToken block:(BaseResultBlock)block { 44 | BaseResultBlock callback =^ (NSDictionary *data, NSError *error) { 45 | if (data) { 46 | [self completeLoginAction:data]; 47 | [self getCurrentUserData:^(NSDictionary *userdata, NSError *error) { 48 | if (block) block(data, nil); 49 | }]; 50 | } else { 51 | if (block) block(nil, error); 52 | } 53 | }; 54 | 55 | return [_api loginWithUserName:username loginToken:loginToken block:callback]; 56 | } 57 | 58 | - (void)completeLoginAction:(NSDictionary *)data { 59 | [AccessTokenHandler storeLoginTokenGrantAccessToken:data[@"access_token"]]; 60 | [[BaseApi loginTokenGrantInstance] setUpLoginTokenGrantRequest]; 61 | [[CurrentUser Instance] setupClientRequestState:nil]; 62 | } 63 | 64 | - (id)updateUserProfile:(UserEntity *)user withBlock:(BaseResultBlock)block { 65 | BaseResultBlock callback =^ (NSDictionary *data, NSError *error) { 66 | if (!error) { 67 | UserEntity *userEntity = data[@"entity"]; 68 | [[CurrentUser Instance] saveUser:userEntity]; 69 | if (block) block(data, nil); 70 | } else { 71 | if (block) block(nil, error); 72 | } 73 | }; 74 | return [_api updateUserProfile:user withBlock:callback]; 75 | } 76 | @end 77 | -------------------------------------------------------------------------------- /PHPHub/Controllers/WiKi/WiKiListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // WiKiListViewController.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "WiKiListViewController.h" 10 | #import "TopicListTableView.h" 11 | #import "TopicEntity.h" 12 | #import "TopicModel.h" 13 | 14 | @interface WiKiListViewController () 15 | @property (nonatomic, strong) TopicListTableView *tableView; 16 | @property (nonatomic, strong) NSMutableArray *topicEntites; 17 | @property (nonatomic, strong) PaginationEntity *pagination; 18 | @end 19 | 20 | @implementation WiKiListViewController 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | self.tableView = [[TopicListTableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; 25 | self.tableView.topicListTableViewDelegate = self; 26 | [self.view addSubview:self.tableView]; 27 | 28 | self.navigationItem.title = @"社区 WiKi"; 29 | 30 | [self.tableView.mj_header beginRefreshing]; 31 | } 32 | 33 | - (void)headerRefreshing { 34 | __weak typeof(self) weakself = self; 35 | BaseResultBlock callback =^ (NSDictionary *data, NSError *error) { 36 | if (!error) { 37 | weakself.topicEntites = data[@"entities"]; 38 | weakself.pagination = data[@"pagination"]; 39 | [weakself.tableView reloadData]; 40 | } 41 | 42 | [weakself.tableView.mj_header endRefreshing]; 43 | if (weakself.pagination.totalPages > 1) { 44 | [weakself.tableView setupFooterView]; 45 | } 46 | }; 47 | 48 | [self fetchDataSource:callback atPage:1]; 49 | } 50 | 51 | - (void)footerRereshing { 52 | NSUInteger maxPage = self.pagination.totalPages; 53 | NSUInteger nextPage = self.pagination.currentPage + 1; 54 | 55 | if (nextPage <= maxPage) { 56 | __weak typeof(self) weakself = self; 57 | BaseResultBlock callback = ^(NSDictionary *data, NSError *error) { 58 | if (!error) { 59 | NSArray *newData = [data objectForKey:@"entities"]; 60 | 61 | [weakself.topicEntites addObjectsFromArray:newData]; 62 | weakself.pagination = data[@"pagination"]; 63 | [weakself.tableView reloadData]; 64 | } 65 | [weakself.tableView.mj_footer endRefreshing]; 66 | }; 67 | 68 | [self fetchDataSource:callback atPage:nextPage]; 69 | } else { 70 | [self.tableView.mj_footer endRefreshingWithNoMoreData]; 71 | } 72 | 73 | } 74 | 75 | - (void)setTopicEntites:(NSMutableArray *)topicEntites { 76 | _topicEntites = topicEntites; 77 | self.tableView.topicEntites = _topicEntites; 78 | } 79 | 80 | - (void)fetchDataSource:(BaseResultBlock)callback atPage:(NSUInteger)atPage { 81 | [[TopicModel Instance] getWiKiList:callback atPage:atPage]; 82 | } 83 | @end 84 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/ViewPagerController/ViewPagerController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewPagerController.h 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, ViewPagerOption) { 12 | ViewPagerOptionTabHeight, 13 | ViewPagerOptionTabOffset, 14 | ViewPagerOptionTabWidth, 15 | ViewPagerOptionTabLocation, 16 | ViewPagerOptionStartFromSecondTab, 17 | ViewPagerOptionCenterCurrentTab 18 | }; 19 | 20 | typedef NS_ENUM(NSUInteger, ViewPagerComponent) { 21 | ViewPagerIndicator, 22 | ViewPagerTabsView, 23 | ViewPagerContent 24 | }; 25 | 26 | @protocol ViewPagerDataSource; 27 | @protocol ViewPagerDelegate; 28 | 29 | @interface ViewPagerController : UIViewController 30 | 31 | @property (nonatomic, weak) id dataSource; 32 | @property (nonatomic, weak) id delegate; 33 | 34 | @property UIPageViewController *pageViewController; 35 | 36 | - (UIViewController *)viewControllerAtIndex:(NSUInteger)index; 37 | 38 | #pragma mark ViewPagerOptions 39 | 40 | // 1.0: YES, 0.0: NO, defines if view should appear with the second or the first tab 41 | // Defaults to NO 42 | @property CGFloat startFromSecondTab; 43 | 44 | // 1.0: YES, 0.0: NO, defines if tabs should be centered, with the given tabWidth 45 | // Defaults to NO 46 | @property CGFloat centerCurrentTab; 47 | 48 | #pragma mark Colors 49 | @property UIColor *contentViewBackgroundColor; 50 | 51 | @property (nonatomic) BOOL manualLoadData; 52 | @property (nonatomic) BOOL scrollingLocked; 53 | #pragma mark Methods 54 | // Reload all tabs and contents 55 | - (void)reloadData; 56 | 57 | @end 58 | 59 | #pragma mark dataSource 60 | @protocol ViewPagerDataSource 61 | 62 | // Asks dataSource how many tabs will be 63 | - (NSUInteger)numberOfTabsForViewPager:(ViewPagerController *)viewPager; 64 | 65 | @optional 66 | // The content for any tab. Return a view controller and ViewPager will use its view to show as content 67 | - (UIViewController *)viewPager:(ViewPagerController *)viewPager contentViewControllerForTabAtIndex:(NSUInteger)index; 68 | - (UIView *)viewPager:(ViewPagerController *)viewPager contentViewForTabAtIndex:(NSUInteger)index; 69 | 70 | @end 71 | 72 | #pragma mark delegate 73 | @protocol ViewPagerDelegate 74 | 75 | @optional 76 | // delegate object must implement this method if wants to be informed when a tab changes 77 | - (void)viewPager:(ViewPagerController *)viewPager didChangeTabToIndex:(NSUInteger)index; 78 | // Every time - reloadData called, ViewPager will ask its delegate for option values 79 | // So you don't have to set options from ViewPager itself 80 | - (CGFloat)viewPager:(ViewPagerController *)viewPager valueForOption:(ViewPagerOption)option withDefault:(CGFloat)value; 81 | 82 | - (void)setSubViewScrollStatus:(BOOL)enabled; 83 | @end -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/UIViewController/UIViewController+Custom.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Custom.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/3/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "UIViewController+Custom.h" 10 | 11 | @implementation UIViewController (Custom) 12 | 13 | + (void)load { 14 | 15 | Method viewWillAppear = class_getInstanceMethod(self, @selector(customViewWillAppear:)); 16 | 17 | Method customViewWillAppear = class_getInstanceMethod(self, @selector(viewWillAppear:)); 18 | method_exchangeImplementations(viewWillAppear, customViewWillAppear); 19 | } 20 | 21 | - (void)customViewWillAppear:(BOOL)animated { 22 | [self customViewWillAppear:animated]; 23 | [self analyticsScreenView]; 24 | 25 | BOOL modalPresent = (BOOL)(self.presentingViewController); 26 | 27 | if (modalPresent) { 28 | [self createCancelButton]; 29 | return; 30 | } 31 | 32 | if ([self.navigationController.viewControllers indexOfObject:self] != 0 && !self.navigationItem.hidesBackButton) { 33 | [self createBackButton]; 34 | } 35 | } 36 | 37 | - (void)analyticsScreenView { 38 | NSString *title = self.navigationItem.title; 39 | if (title) { 40 | [AnalyticsHandler logScreen:title]; 41 | } 42 | } 43 | 44 | - (void)createBackButton { 45 | UIImage *backImage = [UIImage imageNamed:@"back"]; 46 | UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:backImage 47 | style:UIBarButtonItemStylePlain 48 | target:self 49 | action:@selector(closeView)]; 50 | self.navigationItem.leftBarButtonItem = backButton; 51 | self.navigationController.interactivePopGestureRecognizer.delegate = (id)self; 52 | self.navigationItem.backBarButtonItem = nil; 53 | } 54 | 55 | - (void)createCancelButton { 56 | UIBarButtonItem *cancelBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"cancel"] 57 | style:UIBarButtonItemStylePlain 58 | target:self 59 | action:@selector(closeView)]; 60 | cancelBarButtonItem.tintColor = [UIColor colorWithRed:0.502 green:0.776 blue:0.200 alpha:1.000]; 61 | self.navigationItem.leftBarButtonItem = cancelBarButtonItem; 62 | } 63 | 64 | - (void)closeView { 65 | BOOL modalPresent = (BOOL)(self.presentingViewController); 66 | if (modalPresent) { 67 | [self.navigationController dismissViewControllerAnimated:YES completion:nil]; 68 | } else { 69 | [self.navigationController popViewControllerAnimated:YES]; 70 | } 71 | } 72 | @end 73 | -------------------------------------------------------------------------------- /PHPHub/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "icon_29.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "icon_58.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "icon_87.png", 19 | "scale" : "3x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "icon_80.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "icon_120.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "57x57", 35 | "idiom" : "iphone", 36 | "filename" : "icon_57.png", 37 | "scale" : "1x" 38 | }, 39 | { 40 | "size" : "57x57", 41 | "idiom" : "iphone", 42 | "filename" : "icon_114.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "icon_120-1.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "icon_180.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "29x29", 59 | "idiom" : "ipad", 60 | "filename" : "icon_29-1.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "icon_58-1.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "40x40", 71 | "idiom" : "ipad", 72 | "filename" : "icon_40.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "icon_80-1.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "50x50", 83 | "idiom" : "ipad", 84 | "filename" : "icon_50.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "50x50", 89 | "idiom" : "ipad", 90 | "filename" : "icon_100.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "72x72", 95 | "idiom" : "ipad", 96 | "filename" : "icon_72.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "72x72", 101 | "idiom" : "ipad", 102 | "filename" : "icon_144.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "76x76", 107 | "idiom" : "ipad", 108 | "filename" : "icon_76.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "76x76", 113 | "idiom" : "ipad", 114 | "filename" : "icon_152.png", 115 | "scale" : "2x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } -------------------------------------------------------------------------------- /PHPHub/Controllers/Topic/ReplyTopicViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ReplyTopicViewController.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/9/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "ReplyTopicViewController.h" 10 | #import "UITextView+Placeholder.h" 11 | #import "TopicModel.h" 12 | 13 | @interface ReplyTopicViewController () 14 | @property (weak, nonatomic) IBOutlet UITextView *commentTextView; 15 | @end 16 | 17 | @implementation ReplyTopicViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | self.navigationItem.title = @"发表回复"; 23 | 24 | [self createRightButtonItem]; 25 | _commentTextView.layer.cornerRadius = 5.0f; 26 | _commentTextView.placeholder = @"请使用 Markdown 格式书写 ;-)"; 27 | [_commentTextView becomeFirstResponder]; 28 | } 29 | 30 | # pragma mark Post Comment 31 | 32 | - (void)createRightButtonItem { 33 | UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"send_icon"] 34 | style:UIBarButtonItemStylePlain 35 | target:self 36 | action:@selector(postTopicCommentToServer)]; 37 | rightBarButtonItem.tintColor = [UIColor colorWithRed:0.502 green:0.776 blue:0.200 alpha:1.000]; 38 | self.navigationItem.rightBarButtonItem = rightBarButtonItem; 39 | } 40 | 41 | - (void)postTopicCommentToServer { 42 | 43 | CommentEntity *comment = [[CommentEntity alloc] init]; 44 | comment.topicId = _topicId; 45 | comment.commentBody = _commentTextView.text; 46 | [AnalyticsHandler logEvent:@"回复帖子" withCategory:kTopicAction label:[NSString stringWithFormat:@"%@ topicId:%@", [CurrentUser Instance].userLabel, _topicId]]; 47 | 48 | [SVProgressHUD show]; 49 | 50 | __weak typeof(self) weakself = self; 51 | BaseResultBlock callback =^(NSDictionary *data, NSError *error) { 52 | if (!error) { 53 | [SVProgressHUD dismiss]; 54 | [weakself.navigationController popViewControllerAnimated:YES]; 55 | if (weakself.delegate) { 56 | if ([weakself.delegate respondsToSelector:@selector(reloadCommentListView)]) { 57 | [weakself.delegate reloadCommentListView]; 58 | } else if ([weakself.delegate respondsToSelector:@selector(jumpToCommentsView)]) { 59 | [weakself.delegate jumpToCommentsView]; 60 | } 61 | } 62 | } else { 63 | [SVProgressHUD showErrorWithStatus:@"回复失败, 请重试"]; 64 | } 65 | self.navigationItem.rightBarButtonItem.enabled = YES; 66 | }; 67 | 68 | if (_commentTextView.text.length > 1) { 69 | self.navigationItem.rightBarButtonItem.enabled = NO; 70 | [[TopicModel Instance] addCommentToTopic:comment withBlock:callback]; 71 | } else { 72 | [SVProgressHUD showErrorWithStatus:@"评论字数至少为两个"]; 73 | } 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /PHPHub/BaseClasses/BaseEntity.m: -------------------------------------------------------------------------------- 1 | // 2 | // BaseEntity.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "BaseEntity.h" 10 | 11 | @implementation BaseEntity 12 | + (NSDictionary *)JSONKeyPathsByPropertyKey { 13 | NSLog(@"You must override %@ in a subclass",NSStringFromSelector(_cmd)); 14 | [self doesNotRecognizeSelector:_cmd]; 15 | return nil; 16 | } 17 | 18 | #pragma mark - Common Public Methods 19 | 20 | - (NSDictionary *)transformToDictionary { 21 | return [MTLJSONAdapter JSONDictionaryFromModel:self]; 22 | } 23 | 24 | + (NSArray *)transformToArray:(NSArray *)array { 25 | return [MTLJSONAdapter JSONArrayFromModels:array]; 26 | } 27 | 28 | + (id)entityFromDictionary:(NSDictionary *)data { 29 | NSError *error; 30 | id entity = [MTLJSONAdapter modelOfClass:self.class fromJSONDictionary:data error:&error]; 31 | 32 | if (error) { 33 | NSLog(@"Couldn't convert JSON to Entity: %@", error); 34 | return nil; 35 | } 36 | return entity; 37 | } 38 | 39 | + (NSArray *)arrayOfEntitiesFromArray:(NSArray *)array { 40 | NSError *error; 41 | NSArray *arrayOfEntities = [MTLJSONAdapter modelsOfClass:[self class] 42 | fromJSONArray:array 43 | error:&error]; 44 | if (error) { 45 | NSLog(@"Couldn't convert app infos JSON to ChoosyAppInfo models: %@", error); 46 | return nil; 47 | } 48 | return arrayOfEntities; 49 | } 50 | 51 | #pragma mark - Share Property convertor 52 | 53 | + (NSValueTransformer *)createdAtJSONTransformer { 54 | return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString *str) { 55 | return [self.dateFormatter dateFromString:str]; 56 | } reverseBlock:^(NSDate *date) { 57 | return [self.dateFormatter stringFromDate:date]; 58 | }]; 59 | } 60 | 61 | + (NSValueTransformer *)updatedAtJSONTransformer { 62 | return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString *str) { 63 | return [self.dateFormatter dateFromString:str];; 64 | } reverseBlock:^(NSDate *date) { 65 | return [self.dateFormatter stringFromDate:date]; 66 | }]; 67 | } 68 | 69 | #pragma mark - MTLModel Overwrite 70 | 71 | - (NSDictionary *)dictionaryValue { 72 | NSMutableDictionary *modifiedDictionaryValue = [[super dictionaryValue] mutableCopy]; 73 | 74 | for (NSString *originalKey in [super dictionaryValue]) { 75 | if ([self valueForKey:originalKey] == nil ) { 76 | 77 | if ([[self valueForKey:originalKey] isKindOfClass:[NSString class]]) { 78 | [modifiedDictionaryValue setObject:@"" forKey:originalKey]; 79 | } 80 | } 81 | } 82 | 83 | return [modifiedDictionaryValue copy]; 84 | } 85 | 86 | #pragma mark - Helpers 87 | 88 | + (NSDateFormatter *)dateFormatter { 89 | static NSDateFormatter *_formatter; 90 | 91 | if (!_formatter) { 92 | _formatter = [NSDateFormatter new]; 93 | _formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss"; 94 | } 95 | return _formatter; 96 | } 97 | 98 | @end -------------------------------------------------------------------------------- /PHPHub/ThirdParty/TPKeyboardAvoiding/TPKeyboardAvoidingScrollView.m: -------------------------------------------------------------------------------- 1 | // 2 | // TPKeyboardAvoidingScrollView.m 3 | // TPKeyboardAvoiding 4 | // 5 | // Created by Michael Tyson on 30/09/2013. 6 | // Copyright 2015 A Tasty Pixel. All rights reserved. 7 | // 8 | 9 | #import "TPKeyboardAvoidingScrollView.h" 10 | 11 | @interface TPKeyboardAvoidingScrollView () 12 | @end 13 | 14 | @implementation TPKeyboardAvoidingScrollView 15 | 16 | #pragma mark - Setup/Teardown 17 | 18 | - (void)setup { 19 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TPKeyboardAvoiding_keyboardWillShow:) name:UIKeyboardWillChangeFrameNotification object:nil]; 20 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TPKeyboardAvoiding_keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; 21 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scrollToActiveTextField) name:UITextViewTextDidBeginEditingNotification object:nil]; 22 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scrollToActiveTextField) name:UITextFieldTextDidBeginEditingNotification object:nil]; 23 | } 24 | 25 | -(id)initWithFrame:(CGRect)frame { 26 | if ( !(self = [super initWithFrame:frame]) ) return nil; 27 | [self setup]; 28 | return self; 29 | } 30 | 31 | -(void)awakeFromNib { 32 | [self setup]; 33 | } 34 | 35 | -(void)dealloc { 36 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 37 | #if !__has_feature(objc_arc) 38 | [super dealloc]; 39 | #endif 40 | } 41 | 42 | -(void)setFrame:(CGRect)frame { 43 | [super setFrame:frame]; 44 | [self TPKeyboardAvoiding_updateContentInset]; 45 | } 46 | 47 | -(void)setContentSize:(CGSize)contentSize { 48 | [super setContentSize:contentSize]; 49 | [self TPKeyboardAvoiding_updateFromContentSizeChange]; 50 | } 51 | 52 | - (void)contentSizeToFit { 53 | self.contentSize = [self TPKeyboardAvoiding_calculatedContentSizeFromSubviewFrames]; 54 | } 55 | 56 | - (BOOL)focusNextTextField { 57 | return [self TPKeyboardAvoiding_focusNextTextField]; 58 | 59 | } 60 | - (void)scrollToActiveTextField { 61 | return [self TPKeyboardAvoiding_scrollToActiveTextField]; 62 | } 63 | 64 | #pragma mark - Responders, events 65 | 66 | -(void)willMoveToSuperview:(UIView *)newSuperview { 67 | [super willMoveToSuperview:newSuperview]; 68 | if ( !newSuperview ) { 69 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:) object:self]; 70 | } 71 | } 72 | 73 | - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 74 | [[self TPKeyboardAvoiding_findFirstResponderBeneathView:self] resignFirstResponder]; 75 | [super touchesEnded:touches withEvent:event]; 76 | } 77 | 78 | -(BOOL)textFieldShouldReturn:(UITextField *)textField { 79 | if ( ![self focusNextTextField] ) { 80 | [textField resignFirstResponder]; 81 | } 82 | return YES; 83 | } 84 | 85 | -(void)layoutSubviews { 86 | [super layoutSubviews]; 87 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:) object:self]; 88 | [self performSelector:@selector(TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:) withObject:self afterDelay:0.1]; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /PHPHub/Models/TopicModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TopicModel.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/22/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "TopicModel.h" 10 | 11 | @implementation TopicModel 12 | 13 | - (instancetype)init { 14 | self = [super init]; 15 | if (self) { 16 | _api = [[TopicApi alloc] init]; 17 | } 18 | return self; 19 | } 20 | 21 | - (id)getAllTopic:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 22 | return [_api getAll:block atPage:pageIndex]; 23 | } 24 | 25 | - (id)getExcellentTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 26 | return [_api getExcellentTopicList:block atPage:pageIndex]; 27 | } 28 | 29 | - (id)getNewestTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 30 | return [_api getNewestTopicList:block atPage:pageIndex]; 31 | } 32 | 33 | - (id)getHotsTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 34 | return [_api getHotsTopicList:block atPage:pageIndex]; 35 | } 36 | 37 | - (id)getNoReplyTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 38 | return [_api getNoReplyTopicList:block atPage:pageIndex]; 39 | } 40 | 41 | - (id)getJobTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 42 | return [_api getJobTopicList:block atPage:pageIndex]; 43 | } 44 | 45 | - (id)getWiKiList:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 46 | return [_api getWiKiList:block atPage:pageIndex]; 47 | } 48 | 49 | - (id)getTopicListByUser:(NSInteger)userId callback:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 50 | return [_api getTopicListByUser:userId callback:block atPage:pageIndex]; 51 | } 52 | 53 | - (id)getFavoriteTopicListByUser:(NSInteger)userId callback:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 54 | return [_api getFavoriteTopicListByUser:userId callback:block atPage:pageIndex]; 55 | } 56 | 57 | - (id)getAttentionTopicListByUser:(NSInteger)userId callback:(BaseResultBlock)block atPage:(NSInteger)pageIndex { 58 | return [_api getAttentionTopicListByUser:userId callback:block atPage:pageIndex]; 59 | } 60 | 61 | - (id)getTopicById:(NSInteger)topicId callback:(BaseResultBlock)block { 62 | return [_api getTopicById:topicId callback:block]; 63 | } 64 | 65 | - (id)addCommentToTopic:(CommentEntity *)comment withBlock:(BaseResultBlock)block { 66 | return [_api addCommentToTopic:comment withBlock:block]; 67 | } 68 | 69 | - (id)favoriteTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block { 70 | return [_api favoriteTopicById:topicId withBlock:block]; 71 | } 72 | 73 | - (id)cancelFavoriteTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block { 74 | return [_api cancelFavoriteTopicById:topicId withBlock:block]; 75 | } 76 | 77 | - (id)attentionTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block { 78 | return [_api attentionTopicById:topicId withBlock:block]; 79 | } 80 | 81 | - (id)cancelAttentionTopicById:(NSNumber *)topicId withBlock:(BaseResultBlock)block { 82 | return [_api cancelAttentionTopicById:topicId withBlock:block]; 83 | } 84 | 85 | - (id)voteUpTopic:(NSNumber *)topicId withBlock:(BaseResultBlock)block { 86 | return [_api voteUpTopic:topicId withBlock:block]; 87 | } 88 | 89 | - (id)voteDownTopic:(NSNumber *)topicId withBlock:(BaseResultBlock)block { 90 | return [_api voteDownTopic:topicId withBlock:block]; 91 | } 92 | 93 | - (id)createTopic:(TopicEntity *)entity withBlock:(BaseResultBlock)block { 94 | return [_api createTopic:entity withBlock:block]; 95 | } 96 | @end 97 | -------------------------------------------------------------------------------- /PHPHub/Controllers/Settings/SettingsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsViewController.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/4/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "SettingsViewController.h" 10 | #import "TOWebViewController.h" 11 | 12 | #import "UMFeedback.h" 13 | #import "WCAlertView.h" 14 | 15 | @interface SettingsViewController () 16 | 17 | @end 18 | 19 | @implementation SettingsViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | self.navigationItem.title = @"设置"; 25 | } 26 | 27 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { 28 | return 12.0f; 29 | } 30 | 31 | - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { 32 | return section == 2 ? 100.0f : 0.1f; 33 | } 34 | 35 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 36 | NSInteger section = indexPath.section; 37 | NSInteger row = indexPath.row; 38 | UIViewController *vc; 39 | 40 | if (section == 0) { 41 | [self jumpToUMFeedBack]; 42 | } else if (section == 1) { 43 | switch (row) { 44 | case 0: 45 | vc = [[TOWebViewController alloc] initWithURLString:ProjectURL]; 46 | break; 47 | case 1: 48 | vc = [[TOWebViewController alloc] initWithURLString:AboutTheAuthorURL]; 49 | break; 50 | case 2: 51 | vc = [[TOWebViewController alloc] initWithURLString:AboutPageURL]; 52 | break; 53 | case 3: 54 | vc = [[TOWebViewController alloc] initWithURLString:ESTGroupURL]; 55 | break; 56 | } 57 | } else if (section == 2) { 58 | [self showLogoutAlertView]; 59 | } 60 | 61 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 62 | 63 | if (vc) { 64 | [self.navigationController pushViewController:vc animated:YES]; 65 | } 66 | } 67 | 68 | - (void)jumpToUMFeedBack { 69 | UserEntity *currentUser = [[CurrentUser Instance] userInfo]; 70 | NSString *plain = [NSString stringWithFormat:@"uid:%@ - uname:%@", currentUser.userId, currentUser.username]; 71 | [[UMFeedback sharedInstance] updateUserInfo:@{@"contact": 72 | @{ 73 | @"email": currentUser.email, 74 | @"phone": @"", 75 | @"qq": @"", 76 | @"plain": plain 77 | } 78 | }]; 79 | [self presentViewController:[UMFeedback feedbackModalViewController] animated:YES completion:nil]; 80 | } 81 | 82 | - (void)showLogoutAlertView { 83 | __weak typeof(self) weakSelf = self; 84 | [WCAlertView showAlertWithTitle:@"提示" message:@"您确定要退出当前账号吗?" customizationBlock:nil completionBlock: 85 | ^(NSUInteger buttonIndex, WCAlertView *alertView) { 86 | if (buttonIndex == 1) { 87 | [AnalyticsHandler logEvent:@"退出登录" withCategory:kUserAction label:[CurrentUser Instance].userLabel]; 88 | [weakSelf logout]; 89 | } 90 | } cancelButtonTitle:@"取消" otherButtonTitles:@"退出", nil]; 91 | } 92 | 93 | - (void)logout { 94 | [[CurrentUser Instance] logOut]; 95 | [self.navigationController popViewControllerAnimated:YES]; 96 | } 97 | 98 | @end -------------------------------------------------------------------------------- /PHPHub/Handlers/AccessTokenHandler.m: -------------------------------------------------------------------------------- 1 | // 2 | // AccessTokenHandler.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/21/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "AccessTokenHandler.h" 10 | #import "SSKeychain.h" 11 | 12 | @implementation AccessTokenHandler 13 | #pragma mark - Client Grant 14 | 15 | + (NSString *)getClientGrantAccessTokenFromLocal { 16 | NSString *token = [GVUserDefaults standardUserDefaults].userClientToken; 17 | return [NSString stringWithFormat:@"Bearer %@", token]; 18 | } 19 | 20 | + (void)storeClientGrantAccessToken:(NSString *)token { 21 | [GVUserDefaults standardUserDefaults].userClientToken = token; 22 | [[BaseApi clientGrantInstance] setUpClientGrantRequest]; 23 | } 24 | 25 | + (void)fetchClientGrantToken { 26 | NSURL *url = [NSURL URLWithString:APIBaseURL]; 27 | AFOAuth2Client *oauthClient = [AFOAuth2Client clientWithBaseURL:url clientID:Client_id secret:Client_secret]; 28 | 29 | [oauthClient authenticateUsingOAuthWithURLString:APIAccessTokenURL 30 | scope:@"" 31 | success: ^(AFOAuthCredential *credential) { 32 | NSLog(@"oauthClient -- > I have a CLIENT GRANT token! %@", credential.accessToken); 33 | [AccessTokenHandler storeClientGrantAccessToken:credential.accessToken]; 34 | } 35 | failure: ^(NSError *error) { 36 | NSLog(@" oauthClient --> Error: %@", error); 37 | }]; 38 | } 39 | 40 | + (void)fetchClientGrantTokenWithRetryTimes:(NSInteger)times callback:(BaseResultBlock)block { 41 | NSURL *url = [NSURL URLWithString:APIBaseURL]; 42 | AFOAuth2Client *oauthClient = [AFOAuth2Client clientWithBaseURL:url clientID:Client_id secret:Client_secret]; 43 | 44 | [oauthClient authenticateUsingOAuthWithURLString:APIAccessTokenURL 45 | scope:@"" 46 | success: ^(AFOAuthCredential *credential) { 47 | NSLog(@"oauthClient -- > I have a CLIENT GRANT token! %@", credential.accessToken); 48 | [AccessTokenHandler storeClientGrantAccessToken:credential.accessToken]; 49 | if (block) block(@{@"access_token": credential.accessToken}, nil); 50 | } 51 | failure: ^(NSError *error) { 52 | if (times > 0) { 53 | NSInteger newRetryTime = times - 1; 54 | [self fetchClientGrantTokenWithRetryTimes:newRetryTime callback:block]; 55 | } else { 56 | if (block) block(nil, error); 57 | } 58 | NSLog(@" oauthClient --> Error: %@", error); 59 | }]; 60 | } 61 | 62 | #pragma mark - Password Grant 63 | 64 | + (NSString *)getLoginTokenGrantAccessToken { 65 | NSString *token = [SSKeychain passwordForService:KeyChainService account:KeyChainAccount]; 66 | return [NSString stringWithFormat:@"Bearer %@", token]; 67 | } 68 | 69 | + (void)storeLoginTokenGrantAccessToken:(NSString *)token { 70 | [SSKeychain setPassword:token forService:KeyChainService account:KeyChainAccount]; 71 | [[BaseApi loginTokenGrantInstance] setUpLoginTokenGrantRequest]; 72 | } 73 | 74 | + (void)clearToken { 75 | [SSKeychain deletePasswordForService:KeyChainService account:KeyChainAccount]; 76 | [GVUserDefaults standardUserDefaults].userClientToken = nil; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /PHPHub/Controllers/Notification/NotificationListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationListViewController.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 9/26/15. 6 | // Copyright (c) 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "NotificationListViewController.h" 10 | #import "NotificationListCell.h" 11 | #import "NotificationEntity.h" 12 | #import "NotificationModel.h" 13 | 14 | @interface NotificationListViewController () 15 | @property (nonatomic, strong) NSMutableArray *notificationEntities; 16 | @property (nonatomic, strong) PaginationEntity *pagination; 17 | @end 18 | 19 | @implementation NotificationListViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | 24 | self.tableView = [[NotificationListTableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; 25 | [self.view addSubview:self.tableView]; 26 | self.navigationItem.title = @"我的消息"; 27 | [self setupHeaderView]; 28 | [self.tableView.mj_header beginRefreshing]; 29 | } 30 | 31 | - (void)setupHeaderView { 32 | MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(headerRefreshing)]; 33 | header.lastUpdatedTimeLabel.hidden = YES; 34 | header.stateLabel.font = [UIFont fontWithName:FontName size:13]; 35 | self.self.tableView.mj_header = header; 36 | } 37 | 38 | #pragma mark Get Topic Data 39 | 40 | - (void)headerRefreshing { 41 | __weak typeof(self) weakself = self; 42 | BaseResultBlock callback =^ (NSDictionary *data, NSError *error) { 43 | if (!error) { 44 | weakself.notificationEntities = data[@"entities"]; 45 | weakself.pagination = data[@"pagination"]; 46 | [weakself.tableView reloadData]; 47 | [[CurrentUser Instance] checkNoticeCount]; 48 | } 49 | 50 | [weakself.self.tableView.mj_header endRefreshing]; 51 | if (weakself.pagination.totalPages > 1) { 52 | MJRefreshAutoNormalFooter *footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(footerRereshing)]; 53 | footer.stateLabel.font = [UIFont fontWithName:FontName size:13]; 54 | self.tableView.mj_footer = footer; 55 | } 56 | }; 57 | 58 | [self fetchDataSource:callback atPage:1]; 59 | } 60 | 61 | - (void)footerRereshing { 62 | NSUInteger maxPage = self.pagination.totalPages; 63 | NSUInteger nextPage = self.pagination.currentPage + 1; 64 | 65 | if (nextPage <= maxPage) { 66 | __weak typeof(self) weakself = self; 67 | BaseResultBlock callback = ^(NSDictionary *data, NSError *error) { 68 | if (!error) { 69 | NSArray *newData = [data objectForKey:@"entities"]; 70 | 71 | [weakself.notificationEntities addObjectsFromArray:newData]; 72 | weakself.pagination = data[@"pagination"]; 73 | [weakself.tableView reloadData]; 74 | } 75 | [weakself.tableView.mj_footer endRefreshing]; 76 | }; 77 | 78 | [self fetchDataSource:callback atPage:nextPage]; 79 | } else { 80 | [self.tableView.mj_footer endRefreshingWithNoMoreData]; 81 | } 82 | 83 | } 84 | 85 | - (void)setNotificationEntities:(NSMutableArray *)notificationEntities { 86 | _notificationEntities = notificationEntities; 87 | self.tableView.notificationEntities = _notificationEntities; 88 | } 89 | 90 | - (void)fetchDataSource:(BaseResultBlock)callback atPage:(NSUInteger)atPage { 91 | [[NotificationModel Instance] getNotificationList:callback atPage:atPage]; 92 | } 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /PHPHub/ThirdParty/GoogleAnalytics/Library/GAIEcommerceProduct.h: -------------------------------------------------------------------------------- 1 | /*! 2 | @header GAIEcommerceProduct.h 3 | @abstract Google Analytics iOS SDK Hit Format Header 4 | @copyright Copyright 2014 Google Inc. All rights reserved. 5 | */ 6 | 7 | #import 8 | 9 | /*! 10 | * Class to construct product related information for a Google Analytics beacon. Use this class to 11 | * report information about products sold by merchants or impressions of products seen by users. 12 | * Instances of this class can be associated with both Product Actions and Product 13 | * Impression Lists. 14 | *
15 | * Typical usage: 16 | * 17 | * [tracker set:kGAIScreenName value:@"MyScreen"]; 18 | * GAIDictionaryBuilder *builder = [GAIDictionaryBuilder createScreenView]; 19 | * GAIEcommerceProduct *product = [[GAIEcommerceProduct alloc] init]; 20 | * [product setId:@""PID-1234""]; 21 | * [product setName:@"Space Monkeys!"]; 22 | * [product setPrice:@100]; 23 | * [product setQuantity:@2]; 24 | * [builder addProductImpression:product impressionList:@"listName"]; 25 | * [tracker send:[builder build]]; 26 | * 27 | */ 28 | @interface GAIEcommerceProduct : NSObject 29 | 30 | /*! 31 | Sets the id that is used to identify a product in GA reports. 32 | */ 33 | - (GAIEcommerceProduct *)setId:(NSString *)productId; 34 | 35 | /*! 36 | Sets the name that is used to indentify the product in GA reports. 37 | */ 38 | - (GAIEcommerceProduct *)setName:(NSString *)productName; 39 | 40 | /*! 41 | Sets the brand associated with the product in GA reports. 42 | */ 43 | - (GAIEcommerceProduct *)setBrand:(NSString *)productBrand; 44 | 45 | /*! 46 | Sets the category associated with the product in GA reports. 47 | */ 48 | - (GAIEcommerceProduct *)setCategory:(NSString *)productCategory; 49 | 50 | /*! 51 | Sets the variant of the product. 52 | */ 53 | - (GAIEcommerceProduct *)setVariant:(NSString *)productVariant; 54 | 55 | /*! 56 | Sets the price of the product. 57 | */ 58 | - (GAIEcommerceProduct *)setPrice:(NSNumber *)productPrice; 59 | 60 | /*! 61 | Sets the quantity of the product. This field is usually not used with product impressions. 62 | */ 63 | - (GAIEcommerceProduct *)setQuantity:(NSNumber *)productQuantity; 64 | 65 | /*! 66 | Sets the coupon code associated with the product. This field is usually not used with product 67 | impressions. 68 | */ 69 | - (GAIEcommerceProduct *)setCouponCode:(NSString *)productCouponCode; 70 | 71 | /*! 72 | Sets the position of the product on the screen/product impression list, etc. 73 | */ 74 | - (GAIEcommerceProduct *)setPosition:(NSNumber *)productPosition; 75 | 76 | /*! 77 | Sets the custom dimension associated with this product. 78 | */ 79 | - (GAIEcommerceProduct *)setCustomDimension:(NSUInteger)index value:(NSString *)value; 80 | 81 | /*! 82 | Sets the custom metric associated with this product. 83 | */ 84 | - (GAIEcommerceProduct *)setCustomMetric:(NSUInteger)index value:(NSNumber *)value; 85 | 86 | /*! 87 | Builds an NSDictionary of fields stored in this instance suitable for a product action. The 88 | index parameter is the index of this product in the product action list. 89 |
90 | Normally, users will have no need to call this method. 91 | */ 92 | - (NSDictionary *)buildWithIndex:(NSUInteger)index; 93 | 94 | /*! 95 | Builds an NSDictionary of fields stored in this instance suitable for an impression list. The 96 | lIndex parameter is the index of the product impression list while the index parameter is the 97 | index of this product in that impression list. 98 |
99 | Normally, users will have no need to call this method. 100 | */ 101 | - (NSDictionary *)buildWithListIndex:(NSUInteger)lIndex index:(NSUInteger)index; 102 | @end 103 | -------------------------------------------------------------------------------- /PHPHub/Handlers/JumpToOtherVCHandler.m: -------------------------------------------------------------------------------- 1 | // 2 | // JumpToOtherVCHandler.m 3 | // PHPHub 4 | // 5 | // Created by Aufree on 10/8/15. 6 | // Copyright © 2015 ESTGroup. All rights reserved. 7 | // 8 | 9 | #import "JumpToOtherVCHandler.h" 10 | 11 | #import "BaseTabBarViewController.h" 12 | #import "TopicDetailViewController.h" 13 | #import "LoginViewController.h" 14 | #import "UserProfileViewController.h" 15 | #import "TOWebViewController.h" 16 | #import "CommentListViewController.h" 17 | 18 | #import "AppDelegate.h" 19 | 20 | @implementation JumpToOtherVCHandler 21 | 22 | + (UIViewController *)getTabbarViewController { 23 | BaseTabBarViewController *tabbar = [(AppDelegate *)[[UIApplication sharedApplication] delegate] tabBarViewController]; 24 | return tabbar; 25 | } 26 | 27 | + (void)pushToOtherView:(UIViewController *)vc animated:(BOOL)animated { 28 | BaseTabBarViewController *tabbar = [(AppDelegate *)[[UIApplication sharedApplication] delegate] tabBarViewController]; 29 | [tabbar pushToViewController:vc animated:YES]; 30 | } 31 | 32 | + (void)presentToOtherView:(UIViewController *)vc animated:(BOOL)animated completion:(void (^ __nullable)(void))completion { 33 | BaseTabBarViewController *tabbar = [(AppDelegate *)[[UIApplication sharedApplication] delegate] tabBarViewController]; 34 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:vc]; 35 | [tabbar presentViewController:navigationController animated:animated completion:completion]; 36 | } 37 | 38 | + (void)jumpToTopicDetailWithTopic:(TopicEntity *)topic { 39 | TopicDetailViewController *topicDetailVC = [[UIStoryboard storyboardWithName:@"Topic" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"topic"]; 40 | topicDetailVC.topic = topic; 41 | [self pushToOtherView:topicDetailVC animated:YES]; 42 | } 43 | 44 | + (void)jumpToTopicDetailWithTopicId:(NSNumber *)topicId { 45 | TopicDetailViewController *topicDetailVC = [[UIStoryboard storyboardWithName:@"Topic" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"topic"]; 46 | TopicEntity *topic = [TopicEntity new]; 47 | topic.topicId = topicId; 48 | topicDetailVC.topic = topic; 49 | [self pushToOtherView:topicDetailVC animated:YES]; 50 | } 51 | 52 | + (void)jumpToUserProfileWithUserId:(NSNumber *)userId { 53 | UserProfileViewController *userProfileVC = [[UIStoryboard storyboardWithName:@"UserProfile" 54 | bundle:[NSBundle mainBundle]] 55 | instantiateViewControllerWithIdentifier:@"userprofile"]; 56 | UserEntity *user = [UserEntity new]; 57 | user.userId = userId; 58 | userProfileVC.userEntity = user; 59 | [self pushToOtherView:userProfileVC animated:YES]; 60 | } 61 | 62 | + (void)jumpToCommentListVCWithTopic:(TopicEntity *)topic { 63 | CommentListViewController *commentListVC = [[CommentListViewController alloc] init]; 64 | commentListVC.hidesBottomBarWhenPushed = YES; 65 | commentListVC.topic = topic; 66 | [self pushToOtherView:commentListVC animated:YES]; 67 | } 68 | 69 | + (void)jumpToWebVCWithUrlString:(NSString *)url { 70 | TOWebViewController *webVC = [[TOWebViewController alloc] initWithURLString:url]; 71 | webVC.hidesBottomBarWhenPushed = YES; 72 | [self pushToOtherView:webVC animated:YES]; 73 | } 74 | 75 | + (void)jumpToLoginVC:(void (^)(void))completion { 76 | LoginViewController *loginVC = [[UIStoryboard storyboardWithName:@"Passport" 77 | bundle:[NSBundle mainBundle]] 78 | instantiateViewControllerWithIdentifier:@"login"]; 79 | loginVC.completeLoginBlock = completion; 80 | [self presentToOtherView:loginVC animated:YES completion:nil]; 81 | } 82 | @end 83 | -------------------------------------------------------------------------------- /PHPHub/Utils/Categories/UIView/UIView+Additions.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Additions.m 3 | // 4 | // Created by Jin on 15/3/25. 5 | // Copyright (c) 2015年 Jin. All rights reserved. 6 | // 7 | 8 | #import "UIView+Additions.h" 9 | 10 | @implementation UIView (Additions) 11 | 12 | - (id)initWithParent:(UIView *)parent { 13 | self = [self initWithFrame:CGRectZero]; 14 | 15 | if (!self) 16 | return nil; 17 | 18 | [parent addSubview:self]; 19 | 20 | return self; 21 | } 22 | 23 | + (id) viewWithParent:(UIView *)parent { 24 | return [[self alloc] initWithParent:parent]; 25 | } 26 | 27 | - (CGPoint)position { 28 | return self.frame.origin; 29 | } 30 | 31 | - (void)setPosition:(CGPoint)position { 32 | CGRect rect = self.frame; 33 | rect.origin = position; 34 | [self setFrame:rect]; 35 | } 36 | 37 | - (CGFloat)x { 38 | return self.frame.origin.x; 39 | } 40 | 41 | - (void)setX:(CGFloat)x { 42 | CGRect rect = self.frame; 43 | rect.origin.x = x; 44 | [self setFrame:rect]; 45 | } 46 | 47 | - (CGFloat)y { 48 | return self.frame.origin.y; 49 | } 50 | 51 | - (void)setY:(CGFloat)y { 52 | CGRect rect = self.frame; 53 | rect.origin.y = y; 54 | [self setFrame:rect]; 55 | } 56 | 57 | 58 | - (CGFloat)left { 59 | return self.frame.origin.x; 60 | } 61 | 62 | - (void)setLeft:(CGFloat)x { 63 | CGRect frame = self.frame; 64 | frame.origin.x = x; 65 | self.frame = frame; 66 | } 67 | 68 | - (CGFloat)top { 69 | return self.frame.origin.y; 70 | } 71 | 72 | - (void)setTop:(CGFloat)y { 73 | CGRect frame = self.frame; 74 | frame.origin.y = y; 75 | self.frame = frame; 76 | } 77 | 78 | - (CGFloat)right { 79 | return self.frame.origin.x + self.frame.size.width; 80 | } 81 | 82 | - (void)setRight:(CGFloat)right { 83 | CGRect frame = self.frame; 84 | frame.origin.x = right - frame.size.width; 85 | self.frame = frame; 86 | } 87 | 88 | - (CGFloat)bottom { 89 | return self.frame.origin.y + self.frame.size.height; 90 | } 91 | 92 | - (void)setBottom:(CGFloat)bottom { 93 | CGRect frame = self.frame; 94 | frame.origin.y = bottom - frame.size.height; 95 | self.frame = frame; 96 | } 97 | 98 | 99 | 100 | 101 | 102 | - (BOOL)visible { 103 | return !self.hidden; 104 | } 105 | 106 | - (void)setVisible:(BOOL)visible { 107 | self.hidden=!visible; 108 | } 109 | 110 | 111 | -(void)removeAllSubViews{ 112 | 113 | for (UIView *subview in self.subviews){ 114 | [subview removeFromSuperview]; 115 | } 116 | 117 | } 118 | 119 | 120 | - (CGSize)size { 121 | return [self frame].size; 122 | } 123 | 124 | - (void)setSize:(CGSize)size { 125 | CGRect rect = self.frame; 126 | rect.size = size; 127 | [self setFrame:rect]; 128 | } 129 | 130 | - (CGFloat)width { 131 | return self.frame.size.width; 132 | } 133 | 134 | - (void)setWidth:(CGFloat)width { 135 | CGRect rect = self.frame; 136 | rect.size.width = width; 137 | [self setFrame:rect]; 138 | } 139 | 140 | - (CGFloat)height { 141 | return self.frame.size.height; 142 | } 143 | 144 | - (void)setHeight:(CGFloat)height { 145 | CGRect rect = self.frame; 146 | rect.size.height = height; 147 | [self setFrame:rect]; 148 | } 149 | 150 | - (UIViewController*)viewController { 151 | for (UIView* next = [self superview]; next; next = next.superview) 152 | { 153 | UIResponder* nextResponder = [next nextResponder]; 154 | 155 | if ([nextResponder isKindOfClass:[UIViewController class]]) 156 | { 157 | return (UIViewController*)nextResponder; 158 | } 159 | } 160 | 161 | return nil; 162 | } 163 | 164 | @end 165 | 166 | @implementation UIImageView (MFAdditions) 167 | 168 | - (void) setImageWithName:(NSString *)name { 169 | 170 | [self setImage:[UIImage imageNamed:name]]; 171 | [self sizeToFit]; 172 | } 173 | 174 | @end 175 | --------------------------------------------------------------------------------