├── .gitignore ├── .gitmodules ├── .swift-version ├── .swiftlint.yml ├── .travis.yml ├── Cartfile ├── LICENSE ├── README.md ├── application ├── AccountListViewController.swift ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── account.imageset │ │ ├── Contents.json │ │ ├── account.png │ │ ├── account@2x.png │ │ └── account@3x.png │ ├── action.imageset │ │ ├── Contents.json │ │ ├── action.png │ │ ├── action@2x.png │ │ └── action@3x.png │ ├── back.imageset │ │ ├── Contents.json │ │ ├── back.png │ │ ├── back@2x.png │ │ └── back@3x.png │ ├── backOnBarButton.imageset │ │ ├── Contents.json │ │ ├── backOnBarButton.png │ │ ├── backOnBarButton@2x.png │ │ └── backOnBarButton@3x.png │ ├── bookmark.imageset │ │ ├── Contents.json │ │ ├── bookmark.png │ │ ├── bookmark@2x.png │ │ └── bookmark@3x.png │ ├── categoryList.imageset │ │ ├── Contents.json │ │ ├── categoryList.png │ │ ├── categoryList@2x.png │ │ └── categoryList@3x.png │ ├── comments.imageset │ │ ├── Contents.json │ │ ├── comments.png │ │ ├── comments@2x.png │ │ └── comments@3x.png │ ├── commentsFill.imageset │ │ ├── Contents.json │ │ ├── commentsFill.png │ │ ├── commentsFill@2x.png │ │ └── commentsFill@3x.png │ ├── compose.imageset │ │ ├── Contents.json │ │ ├── compose.png │ │ ├── compose@2x.png │ │ └── compose@3x.png │ ├── crown.imageset │ │ ├── Contents.json │ │ ├── crown.png │ │ ├── crown@2x.png │ │ └── crown@3x.png │ ├── downVote.imageset │ │ ├── Contents.json │ │ ├── downVote.png │ │ ├── downVote@2x.png │ │ └── downVote@3x.png │ ├── downVoteFill.imageset │ │ ├── Contents.json │ │ ├── downVoteFill.png │ │ ├── downVoteFill@2x.png │ │ └── downVoteFill@3x.png │ ├── error.imageset │ │ ├── Contents.json │ │ ├── error.png │ │ ├── error@2x.png │ │ └── error@3x.png │ ├── expand.imageset │ │ ├── Contents.json │ │ ├── expand.png │ │ ├── expand@2x.png │ │ └── expand@3x.png │ ├── fold.imageset │ │ ├── Contents.json │ │ ├── fold.png │ │ ├── fold@2x.png │ │ └── fold@3x.png │ ├── folder.imageset │ │ ├── Contents.json │ │ ├── folder.png │ │ ├── folder@2x.png │ │ └── folder@3x.png │ ├── forward.imageset │ │ ├── Contents.json │ │ ├── forward.png │ │ ├── forward@2x.png │ │ └── forward@3x.png │ ├── link.imageset │ │ ├── Contents.json │ │ ├── link.png │ │ ├── link@2x.png │ │ └── link@3x.png │ ├── mailbox.imageset │ │ ├── Contents.json │ │ ├── mailbox.png │ │ ├── mailbox@2x.png │ │ └── mailbox@3x.png │ ├── newsokurFolder.imageset │ │ ├── Contents.json │ │ ├── newsokurFolder.png │ │ ├── newsokurFolder@2x.png │ │ └── newsokurFolder@3x.png │ ├── playButton.imageset │ │ ├── Contents.json │ │ ├── playButton.png │ │ ├── playButton@2x.png │ │ └── playButton@3x.png │ ├── ranking.imageset │ │ ├── Contents.json │ │ ├── ranking.png │ │ ├── ranking@2x.png │ │ └── ranking@3x.png │ ├── reply.imageset │ │ ├── Contents.json │ │ ├── reply.png │ │ ├── reply@2x.png │ │ └── reply@3x.png │ ├── report.imageset │ │ ├── Contents.json │ │ ├── report.png │ │ ├── report@2x.png │ │ └── report@3x.png │ ├── sample.imageset │ │ ├── Contents.json │ │ └── sample.jpg │ ├── save.imageset │ │ ├── Contents.json │ │ ├── save.png │ │ ├── save@2x.png │ │ └── save@3x.png │ ├── saveFill.imageset │ │ ├── Contents.json │ │ ├── saveFill.png │ │ ├── saveFill@2x.png │ │ └── saveFill@3x.png │ ├── send.imageset │ │ ├── Contents.json │ │ ├── send.png │ │ ├── send@2x.png │ │ └── send@3x.png │ ├── setting.imageset │ │ ├── Contents.json │ │ ├── setting.png │ │ ├── setting@2x.png │ │ └── setting@3x.png │ ├── subredditList.imageset │ │ ├── Contents.json │ │ ├── subredditList.png │ │ ├── subredditList@2x.png │ │ └── subredditList@3x.png │ ├── tab.imageset │ │ ├── Contents.json │ │ ├── tab.png │ │ ├── tab@2x.png │ │ └── tab@3x.png │ ├── tabbarFolder.imageset │ │ ├── Contents.json │ │ ├── tabbarFolder.png │ │ ├── tabbarFolder@2x.png │ │ └── tabbarFolder@3x.png │ ├── tabbarList.imageset │ │ ├── Contents.json │ │ ├── tabbarList.png │ │ ├── tabbarList@2x.png │ │ └── tabbarList@3x.png │ ├── tabbarNewsokur.imageset │ │ ├── Contents.json │ │ ├── tabbarNewsokur.png │ │ ├── tabbarNewsokur@2x.png │ │ └── tabbarNewsokur@3x.png │ ├── tabbarRanking.imageset │ │ ├── Contents.json │ │ ├── tabbarRanking.png │ │ ├── tabbarRanking@2x.png │ │ └── tabbarRanking@3x.png │ ├── trend.imageset │ │ ├── Contents.json │ │ ├── trend.png │ │ ├── trend@2x.png │ │ └── trend@3x.png │ ├── upVote.imageset │ │ ├── Contents.json │ │ ├── upVote.png │ │ ├── upVote@2x.png │ │ └── upVote@3x.png │ ├── upVoteFill.imageset │ │ ├── Contents.json │ │ ├── upVoteFill.png │ │ ├── upVoteFill@2x.png │ │ └── upVoteFill@3x.png │ ├── update.imageset │ │ ├── Contents.json │ │ ├── update.png │ │ ├── update@2x.png │ │ └── update@3x.png │ └── vote.imageset │ │ ├── Contents.json │ │ ├── vote.png │ │ ├── vote@2x.png │ │ └── vote@3x.png ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── BaseCommentCell.swift ├── CloseCommentCell.swift ├── CommentCell.swift ├── CommentContainable.swift ├── CommentContainer.swift ├── CommentContainerCellar.swift ├── CommentThumbnailView.swift ├── CommentViewController.swift ├── ContentInfoView.swift ├── ContentToolbar.swift ├── FromFieldView.swift ├── FrontViewController.swift ├── ImageDownloader.swift ├── ImageLinkThumbnailView.swift ├── ImageURLContainer.swift ├── ImageViewController.swift ├── ImageViewPageController.swift ├── ImageViewPageDismissAnimator.swift ├── ImageViewPageModalAnimator.swift ├── ImgurLinkContainer.swift ├── Info.plist ├── InvisibleCell.swift ├── LinkCell.swift ├── LinkContainable.swift ├── LinkContainer.swift ├── LinkContainerCellar.swift ├── LoadingCommentCell.swift ├── LoadingCommentCell.xib ├── MediaLinkCell.swift ├── MediaLinkContainer.swift ├── MoreCommentCell.swift ├── MoreCommentCell.xib ├── MoreContainer.swift ├── MoviePlayView.swift ├── MoviePlayerController.swift ├── MoviePlayerViewToolbar.swift ├── NewsokurCategoryViewController.swift ├── PostCommentViewController.swift ├── PostFieldView.swift ├── ReddiftAPPError.swift ├── ReddiftTextView.h ├── ReddiftTextView.m ├── SearchController.swift ├── SearchLinkCellar.swift ├── String+reddift.swift ├── SubredditCellar.swift ├── SubredditListCategoryTargetType.swift ├── SubredditListCategoryViewController.swift ├── SubredditListItem.swift ├── SubredditListRankingOrderType.swift ├── SubredditListRankingTargetType.swift ├── SubredditListRankingViewController.swift ├── SubredditListViewCell.swift ├── SubredditListViewController.swift ├── SubredditSelectTabBarController.swift ├── SubredditSelectViewController.storyboard ├── TabSelectViewController.swift ├── TabViewCell.swift ├── TabViewCell.xib ├── ThingContainable.swift ├── Thumbnail.swift ├── ThumbnailLinkCell.swift ├── ThumbnailLinkContainer.swift ├── TitleFieldView.swift ├── UIViewController+reddift.swift ├── URL+reddift.swift ├── URLFieldView.swift ├── UZTextViewCell.swift ├── UserViewController.swift ├── ViewController.swift ├── WebViewController.swift ├── application-Bridging-Header.h ├── application.entitlements ├── mona.ttf ├── reddift-Bridging-Header.h ├── reddift.entitlements └── reddift_config.json.sample ├── framework ├── Extension │ ├── Dictionary+reddift.swift │ ├── HttpStatusWithBody.swift │ ├── NSAttributedString+reddift.swift │ ├── NSBundle+reddift.swift │ ├── NSMutableURLRequest+reddift.swift │ ├── NSURLComponents+reddift.swift │ ├── NSURLRequest+reddift.swift │ └── ReddiftError.swift ├── Info.plist ├── Model │ ├── Account.swift │ ├── CAPTCHA.swift │ ├── Comment.swift │ ├── Config.swift │ ├── Created.swift │ ├── Enum.swift │ ├── Link.swift │ ├── Listing.swift │ ├── Media.swift │ ├── MediaEmbed.swift │ ├── Message.swift │ ├── More.swift │ ├── Multireddit.swift │ ├── MultiredditDescription.swift │ ├── Oembed.swift │ ├── Paginator.swift │ ├── Preference.swift │ ├── Response.swift │ ├── Subreddit.swift │ ├── SubredditKarma.swift │ ├── Thing.swift │ ├── Trophy.swift │ ├── User.swift │ ├── Votable.swift │ ├── generator.rb │ └── source.html ├── Network │ ├── BackgroundFetch.swift │ ├── HttpStatus.swift │ ├── Session+CAPTCHA.swift │ ├── Session+Token.swift │ ├── Session+account.swift │ ├── Session+flair.swift │ ├── Session+gold.swift │ ├── Session+helper.swift │ ├── Session+links.swift │ ├── Session+listings.swift │ ├── Session+liveThreads.swift │ ├── Session+messages.swift │ ├── Session+misc.swift │ ├── Session+moderation.swift │ ├── Session+multireddit.swift │ ├── Session+search.swift │ ├── Session+subreddits.swift │ ├── Session+users.swift │ ├── Session+wiki.swift │ └── Session.swift ├── OAuth │ ├── OAuth2AppOnlyToken.swift │ ├── OAuth2Authorizer.swift │ ├── OAuth2Token.swift │ ├── OAuth2TokenRepository.swift │ └── Token.swift ├── Utility │ ├── Parser.swift │ ├── Result.swift │ └── helper.swift └── reddift.h ├── playground ├── data.playground │ ├── Contents.swift │ ├── Resources │ │ └── test_config.json.sample │ ├── Sources │ │ └── SupportCode.swift │ └── contents.xcplayground └── reddift.playground │ ├── Contents.swift │ ├── Resources │ └── test_config.json.sample │ ├── Sources │ └── SupportCode.swift │ └── contents.xcplayground ├── reddift.podspec ├── reddift.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ ├── application.xcscheme │ ├── reddift-iOS.xcscheme │ ├── reddift-macOS.xcscheme │ └── reddift-tvOS.xcscheme └── test ├── AccountTest.swift ├── CAPTCHATest.swift ├── ExtendCommentsTest.swift ├── Info.plist ├── LinksTest.swift ├── ListingsTest.swift ├── MoreChildrenTest.swift ├── MultiredditTest.swift ├── ParseCommentMarkdownTest.swift ├── ParseResponseObjectTest.swift ├── ParseThingObjectTest.swift ├── ReddiftColorTest.swift ├── SearchTest.swift ├── SessionNoAuthTestSpec.swift ├── SessionTestSpec.swift ├── SubredditsTest.swift ├── UsersTest.swift ├── data ├── comment │ └── comment_parse_data.json ├── other │ ├── create_token.json │ └── refresh_token.json ├── response │ ├── TrophyList.json │ ├── api_comment_response.json │ ├── api_needs_captcha.json │ ├── api_new_captcha.json │ ├── comments.json │ ├── comments_extend.json │ ├── error.json │ ├── links.json │ ├── message.json │ ├── moreChildren.json │ ├── multi.json │ ├── multidesc.json │ └── subreddit.json └── thing │ ├── LabeledMulti.json │ ├── LabeledMultiDescription.json │ ├── UserList.json │ ├── more.json │ ├── t1.json │ ├── t2.json │ ├── t3.json │ ├── t4.json │ └── t5.json ├── objc-header.h ├── test_config.json.enc └── test_config.json.sample /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | *.xcscmblueprint 20 | 21 | # CocoaPods 22 | # 23 | # We recommend against adding the Pods directory to your .gitignore. However 24 | # you should judge for yourself, the pros and cons are mentioned at: 25 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 26 | # 27 | Pods/ 28 | 29 | # Carthage 30 | # 31 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 32 | # Carthage/Checkouts 33 | 34 | /Carthage 35 | /Cartfile.resolved 36 | 37 | # reddift 38 | \#* 39 | *~ 40 | reddift_config.json 41 | test_config.json 42 | .DS_Store 43 | 44 | # jazzy 45 | /docs 46 | 47 | ## Playgrounds 48 | timeline.xctimeline 49 | playground.xcworkspace 50 | 51 | expired_token.json 52 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/.gitmodules -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 4.0 2 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | disabled_rules: 2 | - trailing_whitespace 3 | - valid_docs 4 | - type_name 5 | - variable_name 6 | 7 | excluded: 8 | - reddift/vendor 9 | - playground 10 | - reddiftTests 11 | - reddiftSample 12 | - reddiftSampleTV 13 | 14 | file_length: 15 | warning: 2000 16 | error: 4000 17 | 18 | line_length: 19 | warning: 10000 20 | error: 20000 21 | 22 | type_body_length: 23 | warning: 1000 24 | error: 2000 25 | 26 | variable_name: 27 | max_length: 28 | warning: 50 29 | error: 40 30 | min_length: 31 | warning: 1 32 | error: 0 33 | 34 | function_parameter_count: 35 | warning: 10 36 | error: 20 37 | 38 | function_body_length: 39 | warning: 200 40 | error: 400 41 | 42 | cyclomatic_complexity: 43 | warning: 100 44 | error: 150 45 | 46 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode9.3 3 | 4 | before_install: 5 | - openssl aes-256-cbc -K $encrypted_7f426862c7c1_key -iv $encrypted_7f426862c7c1_iv -in ./test/test_config.json.enc -out ./test/test_config.json -d 6 | 7 | script: 8 | - carthage update HTMLSpecialCharacters MiniKeychain --platform ios --no-use-binaries 9 | - xcodebuild test -project reddift.xcodeproj -scheme reddift-iOS -configuration Debug -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 8" CODE_SIGNING_REQUIRED=NO 10 | 11 | branches: 12 | only: 13 | - master -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "Flipboard/FLAnimatedImage" 2 | github "sonsongithub/UZTextView" 3 | github "sonsongithub/YouTubeGetVideoInfoAPIParser" 4 | github "sonsongithub/HTMLSpecialCharacters" 5 | github "sonsongithub/MiniKeychain" 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 sonson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /application/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | } 43 | ], 44 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/account.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "account.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "account@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "account@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/account.imageset/account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/account.imageset/account.png -------------------------------------------------------------------------------- /application/Assets.xcassets/account.imageset/account@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/account.imageset/account@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/account.imageset/account@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/account.imageset/account@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/action.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "action.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "action@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "action@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/action.imageset/action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/action.imageset/action.png -------------------------------------------------------------------------------- /application/Assets.xcassets/action.imageset/action@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/action.imageset/action@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/action.imageset/action@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/action.imageset/action@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/back.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "back.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "back@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "back@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/back.imageset/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/back.imageset/back.png -------------------------------------------------------------------------------- /application/Assets.xcassets/back.imageset/back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/back.imageset/back@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/back.imageset/back@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/back.imageset/back@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/backOnBarButton.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "backOnBarButton.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "backOnBarButton@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "backOnBarButton@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/backOnBarButton.imageset/backOnBarButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/backOnBarButton.imageset/backOnBarButton.png -------------------------------------------------------------------------------- /application/Assets.xcassets/backOnBarButton.imageset/backOnBarButton@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/backOnBarButton.imageset/backOnBarButton@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/backOnBarButton.imageset/backOnBarButton@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/backOnBarButton.imageset/backOnBarButton@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/bookmark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bookmark.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "bookmark@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "bookmark@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/bookmark.imageset/bookmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/bookmark.imageset/bookmark.png -------------------------------------------------------------------------------- /application/Assets.xcassets/bookmark.imageset/bookmark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/bookmark.imageset/bookmark@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/bookmark.imageset/bookmark@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/bookmark.imageset/bookmark@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/categoryList.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "categoryList.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "categoryList@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "categoryList@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/categoryList.imageset/categoryList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/categoryList.imageset/categoryList.png -------------------------------------------------------------------------------- /application/Assets.xcassets/categoryList.imageset/categoryList@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/categoryList.imageset/categoryList@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/categoryList.imageset/categoryList@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/categoryList.imageset/categoryList@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/comments.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "comments.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "comments@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "comments@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/comments.imageset/comments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/comments.imageset/comments.png -------------------------------------------------------------------------------- /application/Assets.xcassets/comments.imageset/comments@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/comments.imageset/comments@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/comments.imageset/comments@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/comments.imageset/comments@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/commentsFill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "commentsFill.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "commentsFill@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "commentsFill@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/commentsFill.imageset/commentsFill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/commentsFill.imageset/commentsFill.png -------------------------------------------------------------------------------- /application/Assets.xcassets/commentsFill.imageset/commentsFill@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/commentsFill.imageset/commentsFill@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/commentsFill.imageset/commentsFill@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/commentsFill.imageset/commentsFill@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/compose.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "compose.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "compose@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "compose@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/compose.imageset/compose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/compose.imageset/compose.png -------------------------------------------------------------------------------- /application/Assets.xcassets/compose.imageset/compose@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/compose.imageset/compose@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/compose.imageset/compose@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/compose.imageset/compose@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/crown.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "crown.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "crown@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "crown@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/crown.imageset/crown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/crown.imageset/crown.png -------------------------------------------------------------------------------- /application/Assets.xcassets/crown.imageset/crown@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/crown.imageset/crown@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/crown.imageset/crown@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/crown.imageset/crown@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/downVote.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "downVote.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "downVote@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "downVote@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/downVote.imageset/downVote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/downVote.imageset/downVote.png -------------------------------------------------------------------------------- /application/Assets.xcassets/downVote.imageset/downVote@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/downVote.imageset/downVote@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/downVote.imageset/downVote@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/downVote.imageset/downVote@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/downVoteFill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "downVoteFill.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "downVoteFill@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "downVoteFill@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/downVoteFill.imageset/downVoteFill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/downVoteFill.imageset/downVoteFill.png -------------------------------------------------------------------------------- /application/Assets.xcassets/downVoteFill.imageset/downVoteFill@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/downVoteFill.imageset/downVoteFill@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/downVoteFill.imageset/downVoteFill@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/downVoteFill.imageset/downVoteFill@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/error.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "error.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "error@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "error@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/error.imageset/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/error.imageset/error.png -------------------------------------------------------------------------------- /application/Assets.xcassets/error.imageset/error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/error.imageset/error@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/error.imageset/error@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/error.imageset/error@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/expand.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "expand.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "expand@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "expand@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/expand.imageset/expand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/expand.imageset/expand.png -------------------------------------------------------------------------------- /application/Assets.xcassets/expand.imageset/expand@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/expand.imageset/expand@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/expand.imageset/expand@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/expand.imageset/expand@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/fold.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "fold.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "fold@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "fold@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/fold.imageset/fold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/fold.imageset/fold.png -------------------------------------------------------------------------------- /application/Assets.xcassets/fold.imageset/fold@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/fold.imageset/fold@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/fold.imageset/fold@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/fold.imageset/fold@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/folder.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "folder.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "folder@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "folder@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/folder.imageset/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/folder.imageset/folder.png -------------------------------------------------------------------------------- /application/Assets.xcassets/folder.imageset/folder@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/folder.imageset/folder@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/folder.imageset/folder@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/folder.imageset/folder@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/forward.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "forward.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "forward@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "forward@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/forward.imageset/forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/forward.imageset/forward.png -------------------------------------------------------------------------------- /application/Assets.xcassets/forward.imageset/forward@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/forward.imageset/forward@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/forward.imageset/forward@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/forward.imageset/forward@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/link.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "link.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "link@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "link@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/link.imageset/link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/link.imageset/link.png -------------------------------------------------------------------------------- /application/Assets.xcassets/link.imageset/link@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/link.imageset/link@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/link.imageset/link@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/link.imageset/link@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/mailbox.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "mailbox.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "mailbox@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "mailbox@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/mailbox.imageset/mailbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/mailbox.imageset/mailbox.png -------------------------------------------------------------------------------- /application/Assets.xcassets/mailbox.imageset/mailbox@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/mailbox.imageset/mailbox@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/mailbox.imageset/mailbox@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/mailbox.imageset/mailbox@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/newsokurFolder.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "newsokurFolder.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "newsokurFolder@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "newsokurFolder@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/newsokurFolder.imageset/newsokurFolder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/newsokurFolder.imageset/newsokurFolder.png -------------------------------------------------------------------------------- /application/Assets.xcassets/newsokurFolder.imageset/newsokurFolder@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/newsokurFolder.imageset/newsokurFolder@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/newsokurFolder.imageset/newsokurFolder@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/newsokurFolder.imageset/newsokurFolder@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/playButton.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "playButton.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "playButton@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "playButton@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/playButton.imageset/playButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/playButton.imageset/playButton.png -------------------------------------------------------------------------------- /application/Assets.xcassets/playButton.imageset/playButton@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/playButton.imageset/playButton@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/playButton.imageset/playButton@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/playButton.imageset/playButton@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/ranking.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ranking.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ranking@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ranking@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/ranking.imageset/ranking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/ranking.imageset/ranking.png -------------------------------------------------------------------------------- /application/Assets.xcassets/ranking.imageset/ranking@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/ranking.imageset/ranking@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/ranking.imageset/ranking@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/ranking.imageset/ranking@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/reply.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "reply.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "reply@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "reply@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/reply.imageset/reply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/reply.imageset/reply.png -------------------------------------------------------------------------------- /application/Assets.xcassets/reply.imageset/reply@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/reply.imageset/reply@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/reply.imageset/reply@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/reply.imageset/reply@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/report.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "report.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "report@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "report@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/report.imageset/report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/report.imageset/report.png -------------------------------------------------------------------------------- /application/Assets.xcassets/report.imageset/report@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/report.imageset/report@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/report.imageset/report@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/report.imageset/report@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/sample.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "sample.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/sample.imageset/sample.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/sample.imageset/sample.jpg -------------------------------------------------------------------------------- /application/Assets.xcassets/save.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "save.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "save@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "save@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/save.imageset/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/save.imageset/save.png -------------------------------------------------------------------------------- /application/Assets.xcassets/save.imageset/save@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/save.imageset/save@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/save.imageset/save@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/save.imageset/save@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/saveFill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "saveFill.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "saveFill@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "saveFill@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/saveFill.imageset/saveFill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/saveFill.imageset/saveFill.png -------------------------------------------------------------------------------- /application/Assets.xcassets/saveFill.imageset/saveFill@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/saveFill.imageset/saveFill@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/saveFill.imageset/saveFill@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/saveFill.imageset/saveFill@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/send.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "send.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "send@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "send@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/send.imageset/send.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/send.imageset/send.png -------------------------------------------------------------------------------- /application/Assets.xcassets/send.imageset/send@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/send.imageset/send@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/send.imageset/send@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/send.imageset/send@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/setting.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "setting.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "setting@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "setting@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/setting.imageset/setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/setting.imageset/setting.png -------------------------------------------------------------------------------- /application/Assets.xcassets/setting.imageset/setting@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/setting.imageset/setting@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/setting.imageset/setting@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/setting.imageset/setting@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/subredditList.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "subredditList.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "subredditList@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "subredditList@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/subredditList.imageset/subredditList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/subredditList.imageset/subredditList.png -------------------------------------------------------------------------------- /application/Assets.xcassets/subredditList.imageset/subredditList@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/subredditList.imageset/subredditList@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/subredditList.imageset/subredditList@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/subredditList.imageset/subredditList@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tab.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tab.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "tab@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "tab@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/tab.imageset/tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tab.imageset/tab.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tab.imageset/tab@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tab.imageset/tab@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tab.imageset/tab@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tab.imageset/tab@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarFolder.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tabbarFolder.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "tabbarFolder@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "tabbarFolder@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarFolder.imageset/tabbarFolder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarFolder.imageset/tabbarFolder.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarFolder.imageset/tabbarFolder@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarFolder.imageset/tabbarFolder@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarFolder.imageset/tabbarFolder@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarFolder.imageset/tabbarFolder@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarList.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tabbarList.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "tabbarList@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "tabbarList@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarList.imageset/tabbarList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarList.imageset/tabbarList.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarList.imageset/tabbarList@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarList.imageset/tabbarList@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarList.imageset/tabbarList@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarList.imageset/tabbarList@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarNewsokur.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tabbarNewsokur.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "tabbarNewsokur@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "tabbarNewsokur@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarNewsokur.imageset/tabbarNewsokur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarNewsokur.imageset/tabbarNewsokur.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarNewsokur.imageset/tabbarNewsokur@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarNewsokur.imageset/tabbarNewsokur@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarNewsokur.imageset/tabbarNewsokur@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarNewsokur.imageset/tabbarNewsokur@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarRanking.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tabbarRanking.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "tabbarRanking@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "tabbarRanking@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarRanking.imageset/tabbarRanking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarRanking.imageset/tabbarRanking.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarRanking.imageset/tabbarRanking@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarRanking.imageset/tabbarRanking@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/tabbarRanking.imageset/tabbarRanking@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/tabbarRanking.imageset/tabbarRanking@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/trend.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "trend.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "trend@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "trend@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/trend.imageset/trend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/trend.imageset/trend.png -------------------------------------------------------------------------------- /application/Assets.xcassets/trend.imageset/trend@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/trend.imageset/trend@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/trend.imageset/trend@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/trend.imageset/trend@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/upVote.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "upVote.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "upVote@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "upVote@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/upVote.imageset/upVote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/upVote.imageset/upVote.png -------------------------------------------------------------------------------- /application/Assets.xcassets/upVote.imageset/upVote@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/upVote.imageset/upVote@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/upVote.imageset/upVote@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/upVote.imageset/upVote@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/upVoteFill.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "upVoteFill.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "upVoteFill@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "upVoteFill@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/upVoteFill.imageset/upVoteFill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/upVoteFill.imageset/upVoteFill.png -------------------------------------------------------------------------------- /application/Assets.xcassets/upVoteFill.imageset/upVoteFill@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/upVoteFill.imageset/upVoteFill@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/upVoteFill.imageset/upVoteFill@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/upVoteFill.imageset/upVoteFill@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/update.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "update.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "update@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "update@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/update.imageset/update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/update.imageset/update.png -------------------------------------------------------------------------------- /application/Assets.xcassets/update.imageset/update@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/update.imageset/update@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/update.imageset/update@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/update.imageset/update@3x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/vote.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "vote.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "vote@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "vote@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /application/Assets.xcassets/vote.imageset/vote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/vote.imageset/vote.png -------------------------------------------------------------------------------- /application/Assets.xcassets/vote.imageset/vote@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/vote.imageset/vote@2x.png -------------------------------------------------------------------------------- /application/Assets.xcassets/vote.imageset/vote@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/Assets.xcassets/vote.imageset/vote@3x.png -------------------------------------------------------------------------------- /application/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /application/CommentContainable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CommentContainable.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/09/29. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import reddift 10 | import Foundation 11 | 12 | class CommentContainable: ThingContainable, ImageDownloadable { 13 | var depth: Int 14 | var isCollapsed: Bool = false 15 | var isLoading: Bool = false 16 | var numberOfChildren: Int = 0 17 | var isTop = false 18 | 19 | init(with thing: Thing, depth: Int) { 20 | self.depth = depth 21 | super.init(with: thing) 22 | } 23 | 24 | /// Method to download attional contents or images when the cell is updated. 25 | func downloadImages() { 26 | } 27 | 28 | func layout(with width: CGFloat, fontSize: CGFloat) { 29 | } 30 | 31 | static func createContainer(with object: Thing, depth: Int, width: CGFloat, fontSize: CGFloat = 14) throws -> CommentContainable { 32 | if let comment = object as? Comment { 33 | return CommentContainer(with: comment, depth: depth, width: width) 34 | } else if let more = object as? More { 35 | return MoreContainer(with: more, depth: depth) 36 | } else { 37 | throw NSError(domain: "a", code: 0, userInfo: nil) 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /application/FromFieldView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FromFieldView.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/12/12. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol FromFieldViewDelegate { 12 | func didTapFromFieldView(sender: FromFieldView) 13 | } 14 | 15 | class FromFieldView: PostFieldView { 16 | var delegate: FromFieldViewDelegate? 17 | let button = UIButton(type: .custom) 18 | 19 | override func setupSubviews() { 20 | super.setupSubviews() 21 | field.isEnabled = false 22 | let views = ["button": button] 23 | button.translatesAutoresizingMaskIntoConstraints = false 24 | self.addSubview(button) 25 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[button]-0-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)) 26 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[button]-0-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)) 27 | button.addTarget(self, action: #selector(FromFieldView.didTapButton(sender:)), for: .touchUpInside) 28 | 29 | if let name = UIApplication.appDelegate()?.session?.token?.name { 30 | field.text = name 31 | } else { 32 | field.text = "anonymous" 33 | } 34 | 35 | NotificationCenter.default.addObserver(self, selector: #selector(FromFieldView.didUpdateToken(notification:)), name: OAuth2TokenRepositoryDidUpdateTokenName, object: nil) 36 | } 37 | 38 | @objc func didUpdateToken(notification: NSNotification) { 39 | if let name = UIApplication.appDelegate()?.session?.token?.name { 40 | field.text = name 41 | } else { 42 | field.text = "anonymous" 43 | } 44 | } 45 | 46 | @objc func didTapButton(sender: Any) { 47 | if let delegate = delegate { 48 | delegate.didTapFromFieldView(sender: self) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /application/ImageURLContainer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageURLContainer.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/10/09. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol ImageURLContainer { 12 | var sourceURL: URL { get set } 13 | var imageURL: [Thumbnail] { get set } 14 | } 15 | 16 | struct ImageURLInComment: ImageURLContainer { 17 | var sourceURL: URL 18 | var parentID: String 19 | var imageURL: [Thumbnail] = [] 20 | 21 | init(sourceURL: URL, parentID: String) { 22 | self.sourceURL = sourceURL 23 | self.parentID = parentID 24 | imageURL = [Thumbnail.Image(imageURL: sourceURL, parentID: parentID)] 25 | } 26 | } 27 | 28 | struct ImgurURLInComment: ImageURLContainer { 29 | var sourceURL: URL 30 | var parentID: String 31 | var imageURL: [Thumbnail] = [] 32 | 33 | init(sourceURL: URL, parentID: String) { 34 | let removed = sourceURL.deletingPathExtension() 35 | self.parentID = parentID 36 | self.sourceURL = removed 37 | } 38 | } 39 | 40 | struct MovieURLInComment: ImageURLContainer { 41 | var sourceURL: URL 42 | var parentID: String 43 | var imageURL: [Thumbnail] = [] 44 | 45 | init(sourceURL: URL, thumbnailURL: URL, parentID: String) { 46 | self.parentID = parentID 47 | self.sourceURL = sourceURL 48 | self.imageURL = [Thumbnail.Movie(movieURL: sourceURL, thumbnailURL: thumbnailURL, parentID: parentID)] 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /application/ImgurLinkContainer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImgurLinkContainer.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/10/06. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import reddift 10 | import Foundation 11 | 12 | class ImgurLinkContainer: MediaLinkContainer { 13 | 14 | /// Shared session configuration 15 | var sessionConfiguration: URLSessionConfiguration { 16 | get { 17 | let configuration = URLSessionConfiguration.default 18 | configuration.timeoutIntervalForRequest = 30 19 | configuration.timeoutIntervalForResource = 30 20 | return configuration 21 | } 22 | } 23 | 24 | override init(link: Link, width: CGFloat, fontSize: CGFloat = 18, thumbnails: [Thumbnail]) { 25 | super.init(link: link, width: width, fontSize: fontSize, thumbnails: []) 26 | self.thumbnails = thumbnails 27 | let font = UIFont(name: UIFont.systemFont(ofSize: fontSize).fontName, size: fontSize) ?? UIFont.systemFont(ofSize: fontSize) 28 | attributedTitle = NSAttributedString(string: link.title).reconstruct(with: font, color: UIColor.black, linkColor: UIColor.blue) 29 | titleSize = ThumbnailLinkCell.estimateTitleSize(attributedString: attributedTitle, withBountWidth: width, margin: .zero) 30 | pageLoaded = false 31 | } 32 | 33 | override func prefetch(at: IndexPath) { 34 | if pageLoaded { return } 35 | guard let url = URL(string: link.url) else { return } 36 | let https_url = url.httpsSchemaURL 37 | var request = URLRequest(url: https_url) 38 | request.addValue("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/601.1.56 (KHTML, like Gecko) Version/9.0 Safari/601.1.56", forHTTPHeaderField: "User-Agent") 39 | let session: URLSession = URLSession(configuration: sessionConfiguration) 40 | let task = session.dataTask(with: request, completionHandler: { (data, _, error) -> Void in 41 | self.pageLoaded = true 42 | if let error = error { 43 | NotificationCenter.default.post(name: LinkContainerDidLoadImageName, object: nil, userInfo: ["error": error as NSError]) 44 | } 45 | if let data = data, let decoded = String(data: data, encoding: .utf8) { 46 | if !decoded.is404OfImgurcom { 47 | self.thumbnails = decoded.extractImgurImageURL(parentID: self.link.id) 48 | DispatchQueue.main.async(execute: { () -> Void in 49 | NotificationCenter.default.post(name: LinkContainerDidLoadImageName, object: nil, userInfo: [MediaLinkContainerPrefetchAtIndexPathKey: at, MediaLinkContainerPrefetchContentKey: self]) 50 | }) 51 | } 52 | } else { 53 | NotificationCenter.default.post(name: LinkContainerDidLoadImageName, object: nil, userInfo: ["error": "can not decode html"]) 54 | } 55 | }) 56 | task.resume() 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /application/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | reddift 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleURLTypes 22 | 23 | 24 | CFBundleTypeRole 25 | Editor 26 | CFBundleURLName 27 | com.sonson.reddift 28 | CFBundleURLSchemes 29 | 30 | reddift 31 | 32 | 33 | 34 | CFBundleVersion 35 | 1 36 | LSRequiresIPhoneOS 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIMainStoryboardFile 41 | Main 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /application/InvisibleCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InvisibleCell.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/08/28. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class InvisibleCell: UITableViewCell { 12 | } 13 | -------------------------------------------------------------------------------- /application/LinkContainer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LinkContainer.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/09/29. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class LinkContainer: LinkContainable { 12 | 13 | /// Cell identifier for dequeueReusableCellWithIdentifier of FrontViewController class. 14 | override var cellIdentifier: String { 15 | get { 16 | if isHidden { 17 | return "InvisibleCell" 18 | } else { 19 | return "LinkCell" 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /application/LinkContainerCellar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LinkContainerCellar.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/10/05. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public let LinkContainerCellarDidLoadName = Notification.Name(rawValue: "LinkContainerCellarDidLoadName") 12 | 13 | class LinkContainerCellar { 14 | static let reloadIndicesKey = "ReloadIndices" 15 | static let insertIndicesKey = "InsertIndices" 16 | static let deleteIndicesKey = "DeleteIndices" 17 | static let errorKey = "Error" 18 | static let isAtTheBeginningKey = "atTheBeginning" 19 | static let providerKey = "Provider" 20 | 21 | var containers: [LinkContainable] = [] 22 | var thumbnails: [Thumbnail] { 23 | get { 24 | return containers.flatMap({$0.thumbnails}) 25 | } 26 | } 27 | 28 | func updateHidden() { 29 | for i in 0.. String { return "" } 46 | func loadingMessage() -> String { return "" } 47 | } 48 | -------------------------------------------------------------------------------- /application/LoadingCommentCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoadingCommentCell.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/03/14. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class LoadingCommentCell: UITableViewCell { 12 | @IBOutlet var activityIndicator: UIActivityIndicatorView? 13 | 14 | override func awakeFromNib() { 15 | activityIndicator?.startAnimating() 16 | layoutMargins = UIEdgeInsets.zero 17 | separatorInset = UIEdgeInsets.zero 18 | selectionStyle = .none 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /application/LoadingCommentCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /application/MoreCommentCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoreCommentCell.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/03/08. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MoreCommentCell: UITableViewCell { 12 | var moreContainer: MoreContainer? = nil { 13 | didSet { 14 | if let moreContainer = self.moreContainer { 15 | leftMarginVarticalBar?.constant = moreContainer.depth == 1 ? -CommentCell.verticalBarWidth : (CGFloat(moreContainer.depth) - 1) * CommentCell.verticalBarWidth 16 | } 17 | } 18 | } 19 | 20 | @IBOutlet var leftMarginVarticalBar: NSLayoutConstraint? 21 | @IBOutlet var widthOfVerticalBar: NSLayoutConstraint? 22 | 23 | override func awakeFromNib() { 24 | super.awakeFromNib() 25 | // Initialization code 26 | layoutMargins = UIEdgeInsets.zero 27 | separatorInset = UIEdgeInsets.zero 28 | widthOfVerticalBar?.constant = CommentCell.verticalBarWidth 29 | } 30 | 31 | override func setSelected(_ selected: Bool, animated: Bool) { 32 | super.setSelected(selected, animated: animated) 33 | 34 | // Configure the view for the selected state 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /application/MoreContainer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoreContainer.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/09/29. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import reddift 10 | import Foundation 11 | 12 | class MoreContainer: CommentContainable { 13 | internal var intrinsicMore: More 14 | var more: More { 15 | get { 16 | return intrinsicMore 17 | } 18 | } 19 | 20 | init(with more: More, depth: Int) { 21 | self.intrinsicMore = more 22 | super.init(with: more, depth: depth) 23 | } 24 | 25 | override var height: CGFloat { 26 | get { 27 | if isHidden { 28 | return 0 29 | } 30 | return 44 31 | } 32 | } 33 | 34 | override var intrinsicThing: Thing { 35 | didSet { 36 | DispatchQueue.main.async(execute: { () -> Void in 37 | if let more = self.intrinsicThing as? More { 38 | self.intrinsicMore = more 39 | NotificationCenter.default.post(name: ThingContainableDidUpdate, object: nil, userInfo: ["contents": self]) 40 | } 41 | }) 42 | } 43 | } 44 | 45 | override var cellIdentifier: String { 46 | get { 47 | if isHidden { 48 | return "InvisibleCell" 49 | } 50 | if isLoading { 51 | return "LoadingCell" 52 | } 53 | return "MoreCell" 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /application/MoviePlayerController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoviePlayerController.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/10/22. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import AVKit 11 | import AVFoundation 12 | 13 | class MoviePlayerController: ImageViewController { 14 | let movieView: MoviePlayView 15 | let movieURL: URL 16 | 17 | @objc func didChangeStatus(notification: Notification) { 18 | var f = movieView.frame 19 | f.size = movieView.presentationSize 20 | movieView.frame = f 21 | updateImageCenter() 22 | 23 | let boundsSize = self.view.bounds 24 | var frameToCenter = movieView.frame 25 | 26 | let ratio = movieView.presentationSize.width / movieView.presentationSize.height 27 | 28 | var contentSize = CGSize.zero 29 | 30 | if ratio > 1 { 31 | contentSize = CGSize(width: boundsSize.width, height: boundsSize.height / ratio) 32 | } else { 33 | contentSize = CGSize(width: boundsSize.height * ratio, height: boundsSize.height) 34 | } 35 | 36 | frameToCenter.size = contentSize 37 | var f2 = mainImageView.bounds 38 | f2.origin = CGPoint.zero 39 | movieView.frame = f2 40 | 41 | if frameToCenter.size.width < boundsSize.width { 42 | frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2 43 | } else { 44 | frameToCenter.origin.x = 0 45 | } 46 | if frameToCenter.size.height < boundsSize.height { 47 | frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2 48 | } else { 49 | frameToCenter.origin.y = 0 50 | } 51 | movieView.playerLayer.player?.play() 52 | } 53 | 54 | override func viewDidLoad() { 55 | print("MovieViewController - viewDidLoad") 56 | super.viewDidLoad() 57 | mainImageView.addSubview(movieView) 58 | NotificationCenter.default.addObserver(self, selector: #selector(MoviePlayerController.didChangeStatus(notification:)), name: MoviePlayViewDidChangeStatus, object: nil) 59 | } 60 | 61 | required init?(coder aDecoder: NSCoder) { 62 | movieURL = URL(string: "")! 63 | movieView = MoviePlayView(url: movieURL) 64 | super.init(coder: aDecoder) 65 | } 66 | 67 | override init(index: Int, thumbnails: [Thumbnail], isOpenedBy3DTouch: Bool = false) { 68 | let thumbnail = thumbnails[index] 69 | switch thumbnail { 70 | case .Image: 71 | movieURL = URL(string: "")! 72 | case .Movie(let movieURL, _, _): 73 | self.movieURL = movieURL 74 | } 75 | movieView = MoviePlayView(url: movieURL) 76 | super.init(index: index, thumbnails: thumbnails, isOpenedBy3DTouch: isOpenedBy3DTouch) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /application/NewsokurCategoryViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NewsokurCategoryViewController.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/12/27. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | ViewController to browse ニュー速R list json which is downloaded from api.reddift.net. 13 | */ 14 | class NewsokurCategoryViewController: SubredditListCategoryViewController { 15 | 16 | /// Set title for NewsokurCategoryViewController 17 | override init() { 18 | super.init(nibName: nil, bundle: nil) 19 | self.title = NSLocalizedString("ニュー速R", comment: "") 20 | } 21 | 22 | /// Set title for NewsokurCategoryViewController 23 | override init(nibName: String?, bundle: Bundle?) { 24 | super.init(nibName: nibName, bundle: bundle) 25 | self.title = NSLocalizedString("ニュー速R", comment: "") 26 | } 27 | 28 | /// Set title for NewsokurCategoryViewController 29 | required init?(coder: NSCoder) { 30 | super.init(coder: coder) 31 | self.title = NSLocalizedString("ニュー速R", comment: "") 32 | self.tabBarItem = UITabBarItem(title: NSLocalizedString("ニュー速R", comment: ""), image: UIImage(named: "newsokurFolder"), tag: 0) 33 | } 34 | 35 | /// Load json for ニュー速R. 36 | override func loadJSON() { 37 | let session: URLSession = URLSession(configuration: URLSessionConfiguration.default) 38 | guard let url = URL(string: "https://api.reddift.net/newsokur.json") 39 | else { return } 40 | let request = URLRequest(url: url) 41 | let task = session.dataTask(with: request, completionHandler: { (data: Data?, _, _) -> Void in 42 | if let data = data { 43 | (self.categoryLists, self.categoryTitles, self.lastUpdateDate) = SubredditListItem.ReddiftJSON2List(data: data as NSData, showsNSFW: true) 44 | } 45 | DispatchQueue.main.async(execute: { () -> Void in 46 | self.tableView.reloadData() 47 | }) 48 | }) 49 | task.resume() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /application/PostFieldView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PostFieldView.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/12/12. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class PostFieldView: UIView { 12 | let label = UILabel(frame: CGRect.zero) 13 | let field = UITextField(frame: CGRect.zero) 14 | let line = UIView(frame: CGRect.zero) 15 | 16 | override init(frame: CGRect) { 17 | super.init(frame: frame) 18 | setupSubviews() 19 | } 20 | 21 | required init?(coder aDecoder: NSCoder) { 22 | super.init(coder: aDecoder) 23 | setupSubviews() 24 | } 25 | 26 | func setupSubviews() { 27 | let views: [String: Any] = [ 28 | "label": label, 29 | "line": line, 30 | "field": field 31 | ] 32 | label.text = "from" 33 | field.text = "aa" 34 | line.backgroundColor = UIColor.black 35 | 36 | label.translatesAutoresizingMaskIntoConstraints = false 37 | field.translatesAutoresizingMaskIntoConstraints = false 38 | line.translatesAutoresizingMaskIntoConstraints = false 39 | 40 | label.textAlignment = .right 41 | field.textAlignment = .left 42 | 43 | self.addSubview(label) 44 | self.addSubview(field) 45 | self.addSubview(line) 46 | 47 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[label]-10-[field]-10-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)) 48 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[label]-0-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)) 49 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[field]-0-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)) 50 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[line]-0-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)) 51 | self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[line(==0.5)]-0-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)) 52 | self.addConstraint(NSLayoutConstraint(item: label, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 0.1, constant: 0)) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /application/ReddiftAPPError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReddiftAPPError.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/07/28. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum ReddiftAPPError: Int, Error { 12 | case unknown 13 | 14 | /// thumbnail 15 | case cachedImageFileIsNotFound 16 | case canNotCreateURLFromImageURLString 17 | case canNotCreateFilePathFromImageFileURL 18 | case canNotCreateThumbnailImageFromOriginalImage 19 | case canNotCreateImageFromData 20 | case canNotCreatePNGImageDataFromUIImage 21 | case canNotCreateURLStringFromURL 22 | case canNotAcceptDataFromServer 23 | case canNotGetImageViewForSpecifiedImageURL 24 | } 25 | -------------------------------------------------------------------------------- /application/ReddiftTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UZTextView.h 3 | // Text 4 | // 5 | // Created by sonson on 2013/06/13. 6 | // Copyright (c) 2013年 sonson. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class ReddiftTextView; 13 | 14 | @protocol ReddiftTextViewDelegate 15 | @end 16 | 17 | @interface ReddiftTextView : UZTextView { 18 | BOOL _isPushedUIMenuController; 19 | } 20 | @property (nonatomic, assign) id UZDelegate; 21 | @end 22 | -------------------------------------------------------------------------------- /application/ReddiftTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // UZTextView.m 3 | // Text 4 | // 5 | // Created by sonson on 2013/06/13. 6 | // Copyright (c) 2013年 sonson. All rights reserved. 7 | // 8 | 9 | #import "ReddiftTextView.h" 10 | 11 | #import 12 | 13 | #define TAP_MARGIN 15 14 | 15 | @implementation ReddiftTextView 16 | 17 | #pragma mark - dealloc 18 | 19 | - (void)dealloc { 20 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 21 | } 22 | 23 | #pragma mark - for UIMenuController 24 | 25 | /** 26 | * UIMenuControllerのアクションメソッド. 27 | * 選択されているテキストをクリップボードにコピーする. 28 | * @param sender メソッドの呼び出し元.おそらくUIMenuControllerオブジェクト. 29 | **/ 30 | - (void)copy:(id)sender { 31 | [self resignFirstResponder]; 32 | } 33 | 34 | /** 35 | * UIMenuControllerのアクションメソッド. 36 | * 選択されているテキストでfind2chのスレッドタイトル検索を実行する. 37 | * 実行するとブックマークビューが開かれる. 38 | * @param sender メソッドの呼び出し元.おそらくUIMenuControllerオブジェクト. 39 | **/ 40 | - (void)titleSearch:(id)sender { 41 | [self resignFirstResponder]; 42 | } 43 | 44 | /** 45 | * UIMenuControllerのアクションメソッド. 46 | * 選択されているテキストでスレッド内部検索を実行する. 47 | * 実行するとブックマークビューが開かれる. 48 | * @param sender メソッドの呼び出し元.おそらくUIMenuControllerオブジェクト. 49 | **/ 50 | - (void)threadSearch:(id)sender { 51 | [self resignFirstResponder]; 52 | } 53 | 54 | /** 55 | * UIMenuControllerのアクションメソッド. 56 | * 選択されているテキストでGoogle検索を実行する. 57 | * 実行するとWebViewコントローラが開かれる. 58 | * @param sender メソッドの呼び出し元.おそらくUIMenuControllerオブジェクト. 59 | **/ 60 | - (void)google:(id)sender { 61 | [self resignFirstResponder]; 62 | } 63 | 64 | /** 65 | * UIMenuControllerのアクションメソッド. 66 | * 選択されているテキストをNG IDに追加する. 67 | * @param sender メソッドの呼び出し元.おそらくUIMenuControllerオブジェクト. 68 | **/ 69 | - (void)addNGID:(id)sender { 70 | [self resignFirstResponder]; 71 | // NSString *text = [self.attributedString.string substringWithRange:self.selectedRange]; 72 | // NSString *boardTitle = _res.thread.threadInfo.boardInfo.title; 73 | // [[C2CloudDataManager sharedInstance] addNGIDWithIdentifier:text 74 | // board:_res.thread.threadInfo.boardInfo.board 75 | // boardTitle:boardTitle 76 | // threadTitle:_res.thread.title 77 | // number:@(_res.thread.threadInfo.dat) 78 | // applyToAll:[[NSUserDefaults standardUserDefaults] boolForKey:C2UserDefaultsNGApplyAllThreadsKey]]; 79 | } 80 | 81 | /** 82 | * UIMenuControllerのアクションメソッド. 83 | * 選択されているテキストをNGネームに追加する. 84 | * @param sender メソッドの呼び出し元.おそらくUIMenuControllerオブジェクト. 85 | **/ 86 | - (void)addNGName:(id)sender { 87 | [self resignFirstResponder]; 88 | } 89 | 90 | /** 91 | * UIMenuControllerのアクションメソッド. 92 | * 選択されているテキストをNGワードに追加する. 93 | * @param sender メソッドの呼び出し元.おそらくUIMenuControllerオブジェクト. 94 | **/ 95 | - (void)addNGWord:(id)sender { 96 | [self resignFirstResponder]; 97 | } 98 | 99 | /** 100 | * UIMenuControllerのアクションメソッド. 101 | * ビューに含まれるすべてのテキストを選択状態にする. 102 | * @param sender メソッドの呼び出し元.おそらくUIMenuControllerオブジェクト. 103 | **/ 104 | - (void)selectAll:(id)sender { 105 | [self setSelectedRange:NSMakeRange(0, self.attributedString.length)]; 106 | } 107 | 108 | #pragma mark - Override 109 | 110 | - (void)prepareForInitialization { 111 | [super prepareForInitialization]; 112 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didStartSelection:) name:@"didStartSelection" object:nil]; 113 | } 114 | 115 | - (void)didStartSelection:(NSNotification*)notification { 116 | if (notification.object != self) { 117 | [self cancelSelectedText]; 118 | } 119 | } 120 | 121 | - (BOOL)canBecomeFirstResponder { 122 | return YES; 123 | } 124 | 125 | - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { 126 | if (action == @selector(titleSearch:)) 127 | return YES; 128 | if (action == @selector(google:)) 129 | return YES; 130 | if (action == @selector(threadSearch:)) 131 | return YES; 132 | if (action == @selector(copy:)) 133 | return YES; 134 | if (action == @selector(addNGID:)) 135 | return YES; 136 | if (action == @selector(addNGName:)) 137 | return YES; 138 | if (action == @selector(addNGWord:)) 139 | return YES; 140 | if (action == @selector(selectAll:)) 141 | return YES; 142 | return NO; 143 | } 144 | 145 | @end 146 | -------------------------------------------------------------------------------- /application/SearchLinkCellar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchLinkCellar.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/10/07. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import reddift 10 | import Foundation 11 | 12 | class SearchLinkCellar: SubredditCellar { 13 | /// Query for Link search 14 | var query: String 15 | 16 | override func tryLoadingMessage() -> String { 17 | return "Try search with \(query)" 18 | } 19 | 20 | override func loadingMessage() -> String { 21 | return "Searching with \(query)...." 22 | } 23 | 24 | /** 25 | Initialize SearchLinkCellar. 26 | - parameter subredditName: To be written. 27 | - parameter delegate: To be written. 28 | - returns: To be written. 29 | */ 30 | init(query aQuery: String, subreddit name: String?, width: CGFloat, fontSize: CGFloat) { 31 | query = aQuery 32 | super.init() 33 | self.width = width 34 | self.fontSize = fontSize 35 | if let name = name { 36 | subreddit = Subreddit(subreddit: name) 37 | } 38 | } 39 | 40 | /** 41 | Search contents. 42 | - parameter appending: To be written. 43 | - parameter width: To be written. 44 | */ 45 | override func load(atTheBeginning: Bool) { 46 | /// Do nothing in case paginator is vacant and load subreddit to append contents. 47 | if self.paginator.isVacant && !atTheBeginning { return } 48 | /// Do nothing in case this controller is loading. 49 | if loading { return } 50 | do { 51 | loading = true 52 | try UIApplication.appDelegate()?.session?.getSearch(subreddit, query: query, paginator: paginator, sort: .new, completion: { (result) -> Void in 53 | switch result { 54 | case .failure(let error): 55 | /// Callback 56 | self.postNotification(name: LinkContainerCellarDidLoadName, userInfo: [LinkContainerCellar.errorKey: error, LinkContainerCellar.providerKey: self]) 57 | case .success(let listing): 58 | /// Clear all objects before load content from the beginning. 59 | if atTheBeginning { self.removeAllObjects() } 60 | 61 | /// append new contents to self 62 | self.appendContentWithListing(listing: listing, widthConstraint: self.width, atTheBeginning: atTheBeginning) 63 | } 64 | }) 65 | } catch { 66 | let nserror = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "\(error)"]) 67 | postNotification(name: LinkContainerCellarDidLoadName, userInfo: [LinkContainerCellar.errorKey: nserror, LinkContainerCellar.providerKey: self]) 68 | } 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /application/SubredditListCategoryTargetType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubredditListCategoryTargetType.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/08/11. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | "Safe For Work" flag type. 13 | This type is used for creating title for view controller, tab bar title and URL for json. 14 | This type has NSFW and SFW. 15 | */ 16 | enum SubredditListCategoryTargetType { 17 | case NSFW 18 | case SFW 19 | 20 | init(viewController: SubredditListCategoryViewController) { 21 | if viewController.isKind(of: SubredditListNSFWCategoryViewController.self) { 22 | self = .NSFW 23 | } else if viewController.isKind(of: SubredditListSFWCategoryViewController.self) { 24 | self = .SFW 25 | } else { 26 | self = .SFW 27 | } 28 | } 29 | 30 | var tabbarTitle: String { 31 | switch self { 32 | case .NSFW: 33 | return "Category NSFW" 34 | case .SFW: 35 | return "Category SFW" 36 | } 37 | } 38 | 39 | var title: String { 40 | switch self { 41 | case .NSFW: 42 | return "NSFW" 43 | case .SFW: 44 | return "SFW" 45 | } 46 | } 47 | 48 | var url: URL { 49 | switch self { 50 | case .NSFW: 51 | return URL(string: "https://api.reddift.net/nsfw_category_map.json")! 52 | case .SFW: 53 | return URL(string: "https://api.reddift.net/sfw_category_map.json")! 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /application/SubredditListRankingOrderType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubredditListRankingOrderType.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/08/11. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Order type of ranking data at redditlist.com. 13 | There are three order types. 14 | */ 15 | enum SubredditListRankingOrderType { 16 | /// Sort by a number of recent activities of the subreddit. 17 | case RecentActivity 18 | /// Sort by a number of subscribers of the subreddit. 19 | case Subscriber 20 | /// Sort by a rate of growth of subscribers of the subreddit. 21 | case Growth 22 | 23 | /// Title for view controller 24 | var title: String { 25 | switch self { 26 | case .RecentActivity: 27 | return "Recent Activity" 28 | case .Subscriber: 29 | return "SUM" 30 | case .Growth: 31 | return "Growth" 32 | } 33 | } 34 | 35 | /// json key for array value. 36 | var jsonKey: String { 37 | switch self { 38 | case .RecentActivity: 39 | return "Recent Activity" 40 | case .Subscriber: 41 | return "Subscribers" 42 | case .Growth: 43 | return "Growth (24Hrs)" 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /application/SubredditListRankingTargetType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubredditListRankingTargetType.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/08/11. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | "Safe For Work" flag type of ranking data at redditlist.com. 13 | This type is used for creating title for view controller, tab bar title and URL for json. 14 | This type has NSFW, SFW and all. 15 | */ 16 | enum SubredditListRankingTargetType { 17 | case All 18 | case NSFW 19 | case SFW 20 | 21 | init(viewController: SubredditListRankingViewController) { 22 | if viewController.isKind(of: SubredditListAllRankingViewController.self) { 23 | self = .All 24 | } else if viewController.isKind(of: SubredditListNSFWRankingViewController.self) { 25 | self = .NSFW 26 | } else if viewController.isKind(of: SubredditListSFWRankingViewController.self) { 27 | self = .SFW 28 | } else { 29 | self = .All 30 | } 31 | } 32 | 33 | var tabbarTitle: String { 34 | switch self { 35 | case .All: 36 | return "Ranking - All" 37 | case .NSFW: 38 | return "Ranking - NSFW" 39 | case .SFW: 40 | return "Ranking - SFW" 41 | } 42 | } 43 | 44 | var title: String { 45 | switch self { 46 | case .All: 47 | return "Ranking - All subreddits" 48 | case .NSFW: 49 | return "Ranking - NSFW subreddits" 50 | case .SFW: 51 | return "Ranking - SFW subreddits" 52 | } 53 | } 54 | 55 | var url: URL { 56 | switch self { 57 | case .All: 58 | return URL(string: "https://api.reddift.net/all_ranking.json")! 59 | case .NSFW: 60 | return URL(string: "https://api.reddift.net/nsfw_ranking.json")! 61 | case .SFW: 62 | return URL(string: "https://api.reddift.net/sfw_ranking.json")! 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /application/SubredditListViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubredditListViewCell.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/12/29. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | Cell for SubredditListViewController. 13 | It displays a subreddit title. 14 | */ 15 | class SubredditListViewSubtitleCell: UITableViewCell { 16 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 17 | super.init(style: UITableViewCellStyle.subtitle, reuseIdentifier: reuseIdentifier) 18 | } 19 | 20 | required init?(coder: NSCoder) { 21 | super.init(coder: coder) 22 | } 23 | } 24 | 25 | /** 26 | Cell for SubredditListCategoryViewController and SubredditListRankingViewController. 27 | It displays two values. Left title's color is black and right one is light gray. 28 | */ 29 | class SubredditListViewRightValueCell: UITableViewCell { 30 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 31 | super.init(style: UITableViewCellStyle.value1, reuseIdentifier: reuseIdentifier) 32 | } 33 | 34 | required init?(coder: NSCoder) { 35 | super.init(coder: coder) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /application/SubredditListViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubredditListCategoryViewController.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/10/26. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /** 12 | View controller to show subreddits that are obtained from redditlist.com or api.reddift.com. 13 | This controller is used newsokur and hierarchical list of redditlist.com. 14 | */ 15 | class SubredditListViewController: UITableViewController { 16 | var list: [SubredditListItem] = [] 17 | 18 | @IBAction func close(sender: AnyObject) { 19 | dismiss(animated: true, completion: nil) 20 | } 21 | 22 | override func viewDidLoad() { 23 | super.viewDidLoad() 24 | tableView.register(SubredditListViewSubtitleCell.self, forCellReuseIdentifier: "Cell") 25 | let barbutton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(SubredditListViewController.close(sender:))) 26 | self.navigationItem.rightBarButtonItem = barbutton 27 | } 28 | 29 | override func numberOfSections(in tableView: UITableView) -> Int { 30 | return 1 31 | } 32 | 33 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 34 | return list.count 35 | } 36 | 37 | override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { 38 | return 44 39 | } 40 | 41 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 42 | let item = list[indexPath.row] 43 | NotificationCenter.default.post(name: SubredditSelectTabBarControllerDidOpenSubredditName, object: nil, userInfo: ["subreddit": item.subreddit]) 44 | dismiss(animated: true, completion: nil) 45 | } 46 | 47 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 48 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath) 49 | 50 | let item = list[indexPath.row] 51 | if let cell = cell as? SubredditListViewSubtitleCell { 52 | cell.textLabel?.text = item.subreddit 53 | cell.detailTextLabel?.text = item.title 54 | cell.detailTextLabel?.textColor = UIColor.gray 55 | } 56 | 57 | return cell 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /application/SubredditSelectTabBarController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubredditSelectViewController.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/12/14. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | let SubredditSelectTabBarControllerDidOpenSubredditName = Notification.Name(rawValue: "SubredditSelectTabBarControllerDidOpenSubredditName") 12 | 13 | /** 14 | View controller to select a favorite subreddit among list. 15 | The list is generated from reddit 16 | This view controller is shown when right bar bottom item is pushed. 17 | */ 18 | class SubredditSelectTabBarController: UITabBarController { 19 | 20 | /** 21 | Show view controllers acording to the NSFW flag. 22 | */ 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | let showsNSFW = true 26 | var navigationControllers: [UIViewController] = [] 27 | let viewControllers: [(UIViewController, Bool)] = [ 28 | (NewsokurCategoryViewController(), showsNSFW), 29 | (SubredditListNSFWCategoryViewController(), showsNSFW), 30 | (SubredditListSFWCategoryViewController(), true), 31 | (SubredditListAllRankingViewController(), showsNSFW), 32 | (SubredditListNSFWRankingViewController(), true), 33 | (SubredditListSFWRankingViewController(), true) 34 | ] 35 | viewControllers.forEach { (vc, flag) in 36 | if flag { 37 | navigationControllers.append(UINavigationController(rootViewController: vc)) 38 | } 39 | } 40 | self.viewControllers = navigationControllers 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /application/SubredditSelectViewController.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /application/TabViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TabViewCell.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/10/28. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension NSLayoutConstraint { 12 | 13 | func setMultiplier(multiplier: CGFloat) { 14 | 15 | let newConstraint = NSLayoutConstraint( 16 | item: firstItem as Any, 17 | attribute: firstAttribute, 18 | relatedBy: relation, 19 | toItem: secondItem, 20 | attribute: secondAttribute, 21 | multiplier: multiplier, 22 | constant: constant) 23 | 24 | newConstraint.priority = priority 25 | newConstraint.shouldBeArchived = self.shouldBeArchived 26 | newConstraint.identifier = self.identifier 27 | newConstraint.isActive = self.isActive 28 | 29 | NSLayoutConstraint.deactivate([self]) 30 | NSLayoutConstraint.activate([newConstraint]) 31 | } 32 | } 33 | 34 | class TabViewCell: UICollectionViewCell { 35 | @IBOutlet var screenImageView: UIImageView? 36 | @IBOutlet var numberLabel: UILabel? 37 | @IBOutlet var widthRatio: NSLayoutConstraint? 38 | @IBOutlet var aspectRatio: NSLayoutConstraint? 39 | 40 | override func awakeFromNib() { 41 | super.awakeFromNib() 42 | if let size = UIApplication.shared.keyWindow?.rootViewController?.view.frame.size { 43 | let ratio = size.width / (size.height) 44 | widthRatio?.setMultiplier(multiplier: 0.95) 45 | aspectRatio?.setMultiplier(multiplier: ratio) 46 | } 47 | } 48 | 49 | override func prepareForReuse() { 50 | super.prepareForReuse() 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /application/ThingContainable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThingContainable.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/09/29. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import reddift 10 | import Foundation 11 | 12 | let ThingContainableDidUpdate = Notification.Name(rawValue: "ThingContainableDidUpdate") 13 | 14 | class ThingContainable { 15 | internal var intrinsicThing: Thing 16 | var thing: Thing { 17 | get { 18 | return intrinsicThing 19 | } 20 | } 21 | 22 | init(with aThing: Thing) { 23 | intrinsicThing = aThing 24 | } 25 | 26 | var cellIdentifier: String { 27 | return "InvisibleCell" 28 | } 29 | 30 | var height: CGFloat { 31 | return 0 32 | 33 | } 34 | 35 | var isHidden: Bool = false 36 | 37 | // update 38 | func update() { 39 | do { 40 | try UIApplication.appDelegate()?.session?.getInfo([self.thing.name], completion: { (result) in 41 | switch result { 42 | case .failure(let error): 43 | print(error) 44 | case .success(let listing): 45 | if listing.children.count == 1 { 46 | self.intrinsicThing = listing.children[0] 47 | DispatchQueue.main.async(execute: { () -> Void in 48 | NotificationCenter.default.post(name: ThingContainableDidUpdate, object: nil, userInfo: ["contents": self]) 49 | }) 50 | } 51 | } 52 | }) 53 | } catch { print(error) } 54 | } 55 | 56 | // hide 57 | func hide() { 58 | do { 59 | try UIApplication.appDelegate()?.session?.setHide(true, name: self.thing.name, completion: { (result) in 60 | switch result { 61 | case .failure(let error): 62 | print(error) 63 | case .success: 64 | self.update() 65 | } 66 | }) 67 | } catch { print(error) } 68 | } 69 | 70 | // report 71 | func report() { 72 | do { 73 | try UIApplication.appDelegate()?.session?.report(self.thing, reason: "", otherReason: "", completion: { (result) in 74 | switch result { 75 | case .failure(let error): 76 | print(error) 77 | case .success(let obj): 78 | print(obj) 79 | } 80 | }) 81 | } catch { print(error) } 82 | } 83 | 84 | // vote 85 | func vote(voteDirection: VoteDirection) { 86 | do { 87 | try UIApplication.appDelegate()?.session?.setVote(voteDirection, name: self.thing.name, completion: { (result) in 88 | switch result { 89 | case .failure(let error): 90 | print(error) 91 | case .success: 92 | self.update() 93 | } 94 | }) 95 | } catch { print(error) } 96 | } 97 | 98 | // save 99 | func save(saved: Bool) { 100 | do { 101 | try UIApplication.appDelegate()?.session?.setSave(saved, name: self.thing.name, completion: { (result) in 102 | switch result { 103 | case .failure(let error): 104 | print(error) 105 | case .success: 106 | self.update() 107 | } 108 | }) 109 | } catch { print(error) } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /application/Thumbnail.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Thumbnail.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/03/26. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum Thumbnail { 12 | case Image(imageURL: URL, parentID:String) 13 | case Movie(movieURL: URL, thumbnailURL: URL, parentID:String) 14 | 15 | var thumbnailURL: URL { 16 | switch self { 17 | case .Image(let imageURL, _): 18 | return imageURL 19 | case .Movie( _, let thumbnailURL, _): 20 | return thumbnailURL 21 | } 22 | } 23 | 24 | var url: URL { 25 | switch self { 26 | case .Image(let imageURL, _): 27 | return imageURL 28 | case .Movie(let movieURL, _, _): 29 | return movieURL 30 | } 31 | } 32 | 33 | var parentID: String { 34 | switch self { 35 | case .Image(_, let parentID): 36 | return parentID 37 | case .Movie(_, _, let parentID): 38 | return parentID 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /application/ThumbnailLinkContainer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThumbnailLinkContainer.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/10/05. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import reddift 10 | import Foundation 11 | 12 | class ThumbnailLinkContainer: LinkContainer { 13 | let thumbnailURL: URL 14 | 15 | /// Cell identifier for dequeueReusableCellWithIdentifier of FrontViewController class. 16 | override var cellIdentifier: String { 17 | get { 18 | if isHidden { 19 | return "InvisibleCell" 20 | } else { 21 | return "ThumbnailLinkCell" 22 | } 23 | } 24 | } 25 | 26 | override var height: CGFloat { 27 | if isHidden { 28 | return 0 29 | } else { 30 | return ThumbnailLinkCell.estimateHeight(titleHeight: titleSize.height) 31 | } 32 | } 33 | 34 | init(link: Link, width: CGFloat, fontSize: CGFloat = 18, thumbnail: Thumbnail) { 35 | self.thumbnailURL = thumbnail.url 36 | super.init(with: link, width: width, fontSize: fontSize) 37 | self.thumbnails = [thumbnail] 38 | let font = UIFont(name: UIFont.systemFont(ofSize: fontSize).fontName, size: fontSize) ?? UIFont.systemFont(ofSize: fontSize) 39 | attributedTitle = NSAttributedString(string: link.title).reconstruct(with: font, color: UIColor.black, linkColor: UIColor.blue) 40 | titleSize = ThumbnailLinkCell.estimateTitleSize(attributedString: attributedTitle, withBountWidth: width, margin: .zero) 41 | pageLoaded = true 42 | } 43 | 44 | /// download thumbnail 45 | override func downloadImages() { 46 | download(imageURLs: [thumbnailURL], sender: self) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /application/TitleFieldView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TitleFieldView.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/12/12. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class TitleFieldView: PostFieldView { 12 | } 13 | -------------------------------------------------------------------------------- /application/UIViewController+reddift.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+reddift.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/09/11. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension UIViewController { 12 | func createImageViewPageControllerWith(_ thumbnails: [Thumbnail], openThumbnail: Thumbnail, isOpenedBy3DTouch: Bool = false) -> ImageViewPageController { 13 | for i in 0 ..< thumbnails.count { 14 | if thumbnails[i].thumbnailURL == openThumbnail.thumbnailURL && thumbnails[i].parentID == openThumbnail.parentID { 15 | return ImageViewPageController.controller(thumbnails: thumbnails, index: i, isOpenedBy3DTouch: isOpenedBy3DTouch) 16 | } 17 | } 18 | return ImageViewPageController.controller(thumbnails: thumbnails, index: 0, isOpenedBy3DTouch: isOpenedBy3DTouch) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /application/URLFieldView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLFieldView.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/12/12. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class URLFieldView: PostFieldView { 12 | } 13 | -------------------------------------------------------------------------------- /application/UZTextViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UZTextViewCell.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/09/03. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class UZTextViewCell: UITableViewCell { 12 | @IBOutlet var textView: UZTextView? 13 | 14 | override func awakeFromNib() { 15 | super.awakeFromNib() 16 | // Initialization code 17 | } 18 | 19 | override func setSelected(_ selected: Bool, animated: Bool) { 20 | super.setSelected(selected, animated: animated) 21 | 22 | // Configure the view for the selected state 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /application/UserViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserViewController.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/09/13. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class UserViewController: UIViewController { 12 | let name: String 13 | 14 | class func controller(_ name: String) -> UINavigationController { 15 | let con = UserViewController(name) 16 | let nav = UINavigationController(rootViewController: con) 17 | return nav 18 | } 19 | 20 | required init?(coder aDecoder: NSCoder) { 21 | name = "" 22 | super.init(coder: aDecoder) 23 | } 24 | 25 | init(_ aName: String) { 26 | name = aName 27 | super.init(nibName: nil, bundle: nil) 28 | } 29 | 30 | override func viewDidLoad() { 31 | super.viewDidLoad() 32 | let barbutton = UIBarButtonItem(title: "Close", style: .plain, target: self, action: #selector(UserViewController.close(sender:))) 33 | self.navigationItem.rightBarButtonItem = barbutton 34 | view.backgroundColor = UIColor.white 35 | self.navigationItem.title = name 36 | } 37 | 38 | @objc func close(sender: Any) { 39 | dismiss(animated: true, completion: nil) 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /application/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/09/01. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /application/WebViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewController.swift 3 | // Sample3DTouch 4 | // 5 | // Created by sonson on 2016/09/04. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import WebKit 11 | 12 | class WebViewController: UIViewController { 13 | let webView = WKWebView(frame: CGRect.zero) 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | view.addSubview(webView) 18 | webView.translatesAutoresizingMaskIntoConstraints = false 19 | 20 | let views = ["webView": webView] 21 | 22 | view.addConstraints ( 23 | NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[webView]-0-|", options: [], metrics: nil, views: views) 24 | ) 25 | view.addConstraints ( 26 | NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[webView]-0-|", options: [], metrics: nil, views: views) 27 | ) 28 | 29 | let bar = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(WebViewController.close(sender:))) 30 | self.navigationItem.rightBarButtonItem = bar 31 | } 32 | 33 | @objc func close(sender: Any) { 34 | self.dismiss(animated: true, completion: nil) 35 | } 36 | 37 | var url: URL? = nil { 38 | didSet { 39 | if let aUrl = url { 40 | let request = URLRequest(url: aUrl) 41 | webView.load(request) 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /application/application-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #ifndef reddift_objc_header_h 6 | #define reddift_objc_header_h 7 | 8 | #import "ReddiftTextView.h" 9 | #import 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /application/application.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.default-data-protection 6 | NSFileProtectionComplete 7 | keychain-access-groups 8 | 9 | $(AppIdentifierPrefix)com.sonson.reddift 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /application/mona.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/application/mona.ttf -------------------------------------------------------------------------------- /application/reddift-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #ifndef reddift_objc_header_h 6 | #define reddift_objc_header_h 7 | 8 | #import "UZTextView.h" 9 | #import "ReddiftTextView.h" 10 | #import 11 | #import "GTMDefines.h" 12 | #import "GTMNSString+HTML.h" 13 | #import "FLAnimatedImageView.h" 14 | #import "FLAnimatedImage.h" 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /application/reddift.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.default-data-protection 6 | NSFileProtectionComplete 7 | keychain-access-groups 8 | 9 | $(AppIdentifierPrefix)com.sonson.reddift 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /application/reddift_config.json.sample: -------------------------------------------------------------------------------- 1 | { 2 | "DeveloperName": "", 3 | "redirect_uri": "", 4 | "client_id": "" 5 | } -------------------------------------------------------------------------------- /framework/Extension/Dictionary+reddift.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Dictionary+reddift.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/09/17. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | private let allowedCharacterSet = CharacterSet(charactersIn: "!$&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~") 12 | 13 | /** 14 | Protocol to generate URL query string from Dictionary[String:String]. 15 | */ 16 | public protocol QueryEscapableString { 17 | var addPercentEncoding: String { get } 18 | } 19 | 20 | extension String: QueryEscapableString { 21 | /** 22 | Returns string by adding percent encoding in UTF-8 23 | Protocol to generate URL query string from Dictionary[String:String]. 24 | */ 25 | public var addPercentEncoding: String { 26 | get { 27 | return (self as NSString).addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? self 28 | } 29 | } 30 | } 31 | 32 | /** 33 | Protocol to generate URL query string from Dictionary[String:String]. 34 | */ 35 | extension Dictionary where Key: QueryEscapableString, Value: QueryEscapableString { 36 | /** 37 | Gets escped string. 38 | - returns: Returns string by adding percent encoding in UTF-8 39 | */ 40 | var URLQuery: String { 41 | get { 42 | return self.map({"\($0.addPercentEncoding)=\($1.addPercentEncoding)"}).joined(separator: "&") 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /framework/Extension/NSBundle+reddift.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSBundle+reddift.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/04/13. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Bundle { 12 | /** 13 | Returns object from default info.plist. 14 | 15 | - parameter key: key for value 16 | - returns: Value 17 | */ 18 | class func infoValueInMainBundle(for key: String) -> AnyObject? { 19 | if let obj = self.main.localizedInfoDictionary?[key] { 20 | return obj as AnyObject 21 | } 22 | if let obj = self.main.infoDictionary?[key] { 23 | return obj as AnyObject 24 | } 25 | return nil 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /framework/Extension/NSURLComponents+reddift.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSURLComponents+reddift.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/06. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension URLComponents { 12 | var dictionary: [String: String] { 13 | var parameters: [String: String] = [:] 14 | if #available(macOS 10.10, *) { 15 | if let queryItems = self.queryItems { 16 | for queryItem in queryItems { 17 | #if os(iOS) 18 | parameters[queryItem.name] = queryItem.value 19 | #elseif os(macOS) 20 | if let value = queryItem.value { 21 | parameters[queryItem.name] = value 22 | } 23 | #endif 24 | } 25 | } 26 | } else { 27 | // Fallback on earlier versions 28 | } 29 | return parameters 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /framework/Extension/NSURLRequest+reddift.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSURLRequest+reddift.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/06/05. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | -------------------------------------------------------------------------------- /framework/Extension/ReddiftError.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReddiftError.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/07/25. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum ReddiftError: Int, Error { 12 | case unknown 13 | case tokenIsNotAvailable 14 | case canNotCreateURLRequest 15 | 16 | case specifiedNameTokenNotFoundInKeychain 17 | case tokenNameIsInvalid 18 | 19 | case needsCAPTCHAResponseIsInvalid 20 | case imageOfCAPTCHAIsInvalid 21 | case identifierOfCAPTCHAIsMalformed 22 | 23 | case sr_nameOfRecommendedSubredditKeyNotFound 24 | case nameAsResultOfSearchSubredditKeyNotFound 25 | case submit_textxSubredditKeyNotFound 26 | case jsonObjectIsNotListingThing 27 | 28 | case accountJsonObjectIsMalformed 29 | case accountJsonObjectIsNotDictionary 30 | 31 | case tokenJsonObjectIsNotDictionary 32 | case canNotCreateURLRequestForOAuth2Page 33 | case canNotAllocateDataToCreateURLForOAuth2 34 | 35 | case moreCommentJsonObjectIsNotDictionary 36 | case canNotGetMoreCommentForAnyReason 37 | 38 | case multiredditJsonObjectIsNotDictionary 39 | case multiredditJsonObjectIsMalformed 40 | 41 | case canNotCreateDataObjectForClientIDForBasicAuthentication 42 | case canNotCreateDataObjectForUserInfoForBasicAuthentication 43 | 44 | case dataIsNotUTF8String 45 | 46 | case preferenceJsonObjectIsNotDictionary 47 | 48 | case failedToParseThingFromJsonObject 49 | case commentJsonObjectIsMalformed 50 | 51 | case failedToParseThingFromRedditAny 52 | case failedToParseMultiredditArrayFromRedditAny 53 | case failedToParseListingPairFromRedditAny 54 | 55 | case failedToCreateJSONForMultireadditPosting 56 | 57 | public var _code: Int { 58 | return self.rawValue 59 | } 60 | 61 | public var _description: String { 62 | return "not yet" 63 | } 64 | 65 | public var _domain: String { 66 | return "com.reddift" 67 | } 68 | 69 | public var errorDomain: String { 70 | return self._domain 71 | } 72 | 73 | public var errorCode: Int { 74 | return self._code 75 | } 76 | 77 | public var errorUserInfo: [String: AnyObject] { 78 | return [:] 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /framework/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /framework/Model/CAPTCHA.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CAPTCHA.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/29. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | CAPTCHA data class. 13 | */ 14 | public struct CAPTCHA { 15 | public let iden: String 16 | public let image: CAPTCHAImage 17 | 18 | init(iden: String, image: CAPTCHAImage) { 19 | self.iden = iden 20 | self.image = image 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /framework/Model/Config.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Config.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/04/13. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Class to manage parameters of reddift. 13 | This class is used as singleton model 14 | */ 15 | struct Config { 16 | /// Application verison, be updated by Info.plist later. 17 | let version: String 18 | /// Bundle identifier, be updated by Info.plist later. 19 | let bundleIdentifier: String 20 | /// Developer's reddit user name 21 | let developerName: String 22 | /// OAuth redirect URL you register 23 | let redirectURI: String 24 | /// Application ID 25 | let clientID: String 26 | 27 | /** 28 | Singleton model. 29 | */ 30 | static let sharedInstance = Config() 31 | 32 | /** 33 | Returns User-Agent for API 34 | */ 35 | var userAgent: String { 36 | return "ios:" + bundleIdentifier + ":v" + version + "(by /u/" + developerName + ")" 37 | } 38 | 39 | /** 40 | Returns scheme of redirect URI. 41 | */ 42 | var redirectURIScheme: String { 43 | if let scheme = URL(string: redirectURI)?.scheme { 44 | return scheme 45 | } else { 46 | return "" 47 | } 48 | } 49 | 50 | init() { 51 | version = Bundle.infoValueInMainBundle(for: "CFBundleShortVersionString") as? String ?? "1.0" 52 | bundleIdentifier = Bundle.infoValueInMainBundle(for: "CFBundleIdentifier") as? String ?? "" 53 | 54 | var _developerName: String? = nil 55 | var _redirectURI: String? = nil 56 | var _clientID: String? = nil 57 | if let path = Bundle.main.path(forResource: "reddift_config", ofType: "json") { 58 | if let data = try? Data(contentsOf: URL(fileURLWithPath: path)) { 59 | do { 60 | if let json = try JSONSerialization.jsonObject(with: data, options: []) as? JSONDictionary { 61 | _developerName = json["DeveloperName"] as? String 62 | _redirectURI = json["redirect_uri"] as? String 63 | _clientID = json["client_id"] as? String 64 | } 65 | } catch { 66 | 67 | } 68 | } 69 | } 70 | 71 | developerName = _developerName ?? "" 72 | redirectURI = _redirectURI ?? "" 73 | clientID = _clientID ?? "" 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /framework/Model/Created.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Created.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2017/01/09. 6 | // Copyright © 2017年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Created { 12 | var created: Int {get} 13 | var createdUtc: Int {get} 14 | } 15 | -------------------------------------------------------------------------------- /framework/Model/Listing.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Listing.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/04/20. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Listing object. 13 | This class has children, paginator and more. 14 | */ 15 | public struct Listing { 16 | /// elements of the list 17 | public let children: [Thing] 18 | /// paginator of the list 19 | public let paginator: Paginator 20 | 21 | public init() { 22 | self.children = [] 23 | self.paginator = Paginator() 24 | } 25 | 26 | public init(children: [Thing], paginator: Paginator) { 27 | self.children = children 28 | self.paginator = paginator 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /framework/Model/Media.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Media.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/04/20. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Media represents the content which is embeded a link. 13 | */ 14 | public struct Media { 15 | /** 16 | example "i.imgur.com" 17 | */ 18 | public let type: String 19 | /** 20 | oembed object 21 | */ 22 | public let oembed: Oembed 23 | /** 24 | Update each property with JSON object. 25 | 26 | - parameter json: JSON object which is included "t2" JSON. 27 | */ 28 | public init(json: JSONDictionary) { 29 | type = json["type"] as? String ?? "" 30 | oembed = Oembed(json: json["oembed"] as? JSONDictionary ?? [:]) 31 | } 32 | 33 | public var string: String { 34 | get { 35 | return "{type=\(type)}\n" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /framework/Model/MediaEmbed.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MediaEmbed.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/04/21. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import HTMLSpecialCharacters 11 | 12 | /** 13 | Media represents the content which is embeded a link. 14 | */ 15 | public struct MediaEmbed { 16 | /// Height of content. 17 | let height: Int 18 | /// Width of content. 19 | let width: Int 20 | /// Information of content. 21 | let content: String 22 | /// Is content scrolled? 23 | let scrolling: Bool 24 | 25 | /** 26 | Update each property with JSON object. 27 | 28 | - parameter json: JSON object which is included "t2" JSON. 29 | */ 30 | public init (json: JSONDictionary) { 31 | height = json["height"] as? Int ?? 0 32 | width = json["width"] as? Int ?? 0 33 | let tempContent = json["content"] as? String ?? "" 34 | content = tempContent.unescapeHTML 35 | scrolling = json["scrolling"] as? Bool ?? false 36 | } 37 | 38 | var string: String { 39 | get { 40 | return "{content=\(content)\nsize=\(width)x\(height)}\n" 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /framework/Model/More.swift: -------------------------------------------------------------------------------- 1 | // 2 | // More.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/04/21. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | More object. 13 | "more" is included in Listing object(Maybe). 14 | If Listing object has "more" object, it has mure more children to be downloaded. 15 | */ 16 | public struct More: Thing { 17 | /// identifier of Thing like 15bfi0. 18 | public let id: String 19 | /// name of Thing, that is fullname, like t3_15bfi0. 20 | public let name: String 21 | /// type of Thing, like t3. 22 | public static let kind = "more" 23 | 24 | public let parentId: String 25 | public let count: Int 26 | public let children: [String] 27 | 28 | public init(id: String) { 29 | self.id = id 30 | self.name = "\(More.kind)_\(self.id)" 31 | parentId = "" 32 | count = 0 33 | children = [] 34 | } 35 | 36 | /** 37 | Parse more object. 38 | 39 | - parameter data: Dictionary, must be generated parsing "more". 40 | - returns: More object as Thing. 41 | */ 42 | public init(json data: JSONDictionary) { 43 | id = data["id"] as? String ?? "" 44 | name = data["name"] as? String ?? "" 45 | parentId = data["parent_id"] as? String ?? "" 46 | count = data["count"] as? Int ?? 0 47 | children = data["children"] as? [String] ?? [] 48 | } 49 | 50 | public init(id: String, name: String, parentId: String, count: Int = 0, child: String) { 51 | self.id = id 52 | self.name = name 53 | self.parentId = parentId 54 | self.count = count 55 | self.children = [child] 56 | } 57 | 58 | public var isEmpty: Bool { 59 | get { 60 | return id == "_" 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /framework/Model/MultiredditDescription.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MultiredditDescription.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/23. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import HTMLSpecialCharacters 11 | 12 | /** 13 | Multireddit description class. 14 | */ 15 | public struct MultiredditDescription { 16 | public let bodyHtml: String 17 | public let bodyMd: String 18 | 19 | public init(json: JSONDictionary) { 20 | let tempBodyHtml = json["body_html"] as? String ?? "" 21 | bodyHtml = tempBodyHtml.unescapeHTML 22 | bodyMd = json["body_md"] as? String ?? "" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /framework/Model/Oembed.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Oembed.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/04/20. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import HTMLSpecialCharacters 11 | 12 | /** 13 | Media represents the content which is embeded a link. 14 | */ 15 | public struct Oembed { 16 | /** 17 | example, "http://i.imgur.com", 18 | */ 19 | public let providerUrl: String 20 | /** 21 | example, "The Internet's visual storytelling community. Explore, share, and discuss the best visual stories the Internet has to offer.", 22 | */ 23 | public let description: String 24 | /** 25 | example, "Imgur GIF", 26 | */ 27 | public let title: String 28 | /** 29 | example, 245, 30 | */ 31 | public let thumbnailWidth: Int 32 | /** 33 | example, 333, 34 | */ 35 | public let height: Int 36 | /** 37 | example, 245, 38 | */ 39 | public let width: Int 40 | /** 41 | example, "<iframe class=\"embedly-embed\" src=\"//cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fi.imgur.com%2FkhgfcrQ.mp4&src_secure=1&url=http%3A%2F%2Fi.imgur.com%2FkhgfcrQ.gifv&image=http%3A%2F%2Fi.imgur.com%2FkhgfcrQ.gif&key=2aa3c4d5f3de4f5b9120b660ad850dc9&type=video%2Fmp4&schema=imgur\" width=\"245\" height=\"333\" scrolling=\"no\" frameborder=\"0\" allowfullscreen></iframe>", 42 | */ 43 | public let html: String 44 | /** 45 | example, "1.0", 46 | */ 47 | public let version: String 48 | /** 49 | example, "Imgur", 50 | */ 51 | public let providerName: String 52 | /** 53 | example, "http://i.imgur.com/khgfcrQ.gif", 54 | */ 55 | public let thumbnailUrl: String 56 | /** 57 | example, "video", 58 | */ 59 | public let type: String 60 | /** 61 | example, 333 62 | */ 63 | public let thumbnailHeight: Int 64 | /** 65 | Update each property with JSON object. 66 | 67 | - parameter json: JSON object which is included "t2" JSON. 68 | */ 69 | public init (json: JSONDictionary) { 70 | self.providerUrl = json["provider_url"] as? String ?? "" 71 | self.description = json["description"] as? String ?? "" 72 | self.title = json["title"] as? String ?? "" 73 | self.thumbnailWidth = json["thumbnail_width"] as? Int ?? 0 74 | self.height = json["height"] as? Int ?? 0 75 | self.width = json["width"] as? Int ?? 0 76 | let tempHtml = json["html"] as? String ?? "" 77 | self.html = tempHtml.unescapeHTML 78 | self.version = json["version"] as? String ?? "" 79 | self.providerName = json["provider_name"] as? String ?? "" 80 | self.thumbnailUrl = json["thumbnail_url"] as? String ?? "" 81 | self.type = json["type"] as? String ?? "" 82 | self.thumbnailHeight = json["thumbnail_height"] as? Int ?? 0 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /framework/Model/Paginator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Paginator.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/04/14. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Paginator object for paiging listing object. 13 | */ 14 | public struct Paginator { 15 | let after: String 16 | let before: String 17 | let modhash: String 18 | 19 | public init() { 20 | self.after = "" 21 | self.before = "" 22 | self.modhash = "" 23 | } 24 | 25 | public init(after: String, before: String, modhash: String) { 26 | self.after = after 27 | self.before = before 28 | self.modhash = modhash 29 | } 30 | 31 | public var isVacant: Bool { 32 | if (!after.isEmpty) || (!before.isEmpty) { 33 | return false 34 | } 35 | return true 36 | } 37 | 38 | /** 39 | Generate dictionary to add query parameters to URL. 40 | If paginator is vacant, returns vacant dictionary as [String:String]. 41 | 42 | - returns: Dictionary object for paging. 43 | */ 44 | public var parameterDictionary: [String: String] { 45 | get { 46 | var dict: [String: String] = [:] 47 | if !after.isEmpty { 48 | dict["after"] = after 49 | } 50 | if !before.isEmpty { 51 | dict["before"] = before 52 | } 53 | return dict 54 | } 55 | } 56 | 57 | public func dictionaryByAdding(parameters dict: [String: String]) -> [String: String] { 58 | var newDict = dict 59 | if !after.isEmpty { 60 | newDict["after"] = after 61 | } 62 | if !before.isEmpty { 63 | newDict["before"] = before 64 | } 65 | return newDict 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /framework/Model/Response.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Response.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/06/26. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Object to eliminate codes to parse http response object. 13 | */ 14 | struct Response { 15 | let data: Data 16 | let statusCode: Int 17 | 18 | init(data: Data?, urlResponse: URLResponse?) { 19 | if let data = data { 20 | self.data = data 21 | } else { 22 | self.data = Data() 23 | } 24 | if let httpResponse = urlResponse as? HTTPURLResponse { 25 | statusCode = httpResponse.statusCode 26 | } else { 27 | statusCode = 500 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /framework/Model/SubredditKarma.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubredditKarma.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/11/16. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Subreddit karma object 13 | */ 14 | public struct SubredditKarma { 15 | let commentKarma: Int 16 | let linkKarma: Int 17 | let subreddit: String 18 | 19 | init(subreddit: String, commentKarma: Int, linkKarma: Int) { 20 | self.subreddit = subreddit 21 | self.commentKarma = commentKarma 22 | self.linkKarma = linkKarma 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /framework/Model/Thing.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Thing.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/27. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Thing { 12 | var id: String {get} 13 | var name: String {get} 14 | static var kind: String {get} 15 | 16 | init(id: String) 17 | } 18 | -------------------------------------------------------------------------------- /framework/Model/Trophy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Trophy.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/11/13. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Trophy object 13 | */ 14 | public struct Trophy: Thing { 15 | /// identifier of Thing like 15bfi0. 16 | public let id: String 17 | /// name of Thing, that is fullname, like t3_15bfi0. 18 | public let name: String 19 | /// type of Thing, like t3. 20 | static public let kind = "t6" 21 | 22 | /// Trophy data 23 | public let title: String 24 | public let description: String 25 | public let awardID: String 26 | public let icon40: URL? 27 | public let icon70: URL? 28 | public let url: URL? 29 | 30 | public init(id: String) { 31 | self.id = id 32 | self.name = "\(Comment.kind)_\(self.id)" 33 | self.title = "" 34 | self.description = "" 35 | self.awardID = "" 36 | self.icon40 = nil 37 | self.icon70 = nil 38 | self.url = nil 39 | } 40 | 41 | public init(json: JSONDictionary) { 42 | id = json["id"] as? String ?? "" 43 | name = "\(Trophy.kind)_\(id)" 44 | awardID = json["award_id"] as? String ?? "" 45 | description = json["description"] as? String ?? "" 46 | icon40 = URL(string: (json["icon_40"] as? String ?? "")) 47 | icon70 = URL(string: (json["icon_70"] as? String ?? "")) 48 | url = URL(string: (json["url"] as? String ?? "")) 49 | title = json["name"] as? String ?? "" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /framework/Model/User.swift: -------------------------------------------------------------------------------- 1 | // 2 | // User.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/11/12. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | */ 13 | public enum UserModPermission: String { 14 | case all 15 | case wiki 16 | case posts 17 | case mail 18 | case flair 19 | case unknown 20 | 21 | public init(_ value: String) { 22 | switch value { 23 | case "all": 24 | self = .all 25 | case "wiki": 26 | self = .wiki 27 | case "posts": 28 | self = .posts 29 | case "mail": 30 | self = .mail 31 | case "flair": 32 | self = .flair 33 | default: 34 | self = .unknown 35 | } 36 | } 37 | } 38 | 39 | /** 40 | User object 41 | */ 42 | public struct User { 43 | let date: TimeInterval 44 | let modPermissions: [UserModPermission] 45 | let name: String 46 | let id: String 47 | 48 | public init(date: Double, permissions: [String]?, name: String, id: String) { 49 | self.date = date 50 | if let permissions = permissions { 51 | self.modPermissions = permissions.map({UserModPermission($0)}) 52 | } else { 53 | self.modPermissions = [] 54 | } 55 | self.name = name 56 | self.id = id 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /framework/Model/Votable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Votable.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2017/01/09. 6 | // Copyright © 2017年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public protocol Votable { 12 | var ups: Int {get} 13 | var downs: Int {get} 14 | var likes: VoteDirection {get} 15 | } 16 | -------------------------------------------------------------------------------- /framework/Network/Session+Token.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Session+Token.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/09/21. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | func refreshTokenWithJSON(_ result: Result, token: OAuth2Token) -> Result { 12 | switch result { 13 | case .success(let json): 14 | var newJSON = json 15 | newJSON["name"] = token.name as AnyObject 16 | newJSON["refresh_token"] = token.refreshToken as AnyObject 17 | return OAuth2Token.tokenWithJSON(newJSON) 18 | case .failure(let error): 19 | return Result(error: error) 20 | } 21 | } 22 | 23 | extension Session { 24 | /** 25 | Refresh own token. 26 | 27 | - parameter completion: The completion handler to call when the load request is complete. 28 | */ 29 | public func refreshToken(_ completion: @escaping (Result) -> Void) throws { 30 | guard let currentToken = token as? OAuth2Token 31 | else { throw ReddiftError.tokenIsNotAvailable as NSError } 32 | do { 33 | try currentToken.refresh({ (result) -> Void in 34 | switch result { 35 | case .failure(let error): 36 | completion(Result(error: error as NSError)) 37 | case .success(let newToken): 38 | DispatchQueue.main.async(execute: { () -> Void in 39 | self.token = newToken 40 | do { 41 | try OAuth2TokenRepository.save(token: newToken) 42 | completion(Result(value: newToken)) 43 | } catch { completion(Result(error: error as NSError)) } 44 | }) 45 | } 46 | }) 47 | } catch { throw error } 48 | } 49 | 50 | /** 51 | Revoke own token. After calling this function, this object must be released becuase it has lost any conection. 52 | 53 | - parameter completion: The completion handler to call when the load request is complete. 54 | */ 55 | public func revokeToken(_ completion: @escaping (Result) -> Void) throws { 56 | guard let currentToken = token as? OAuth2Token 57 | else { throw ReddiftError.tokenIsNotAvailable as NSError } 58 | do { 59 | try currentToken.revoke({ (result) -> Void in 60 | switch result { 61 | case .failure(let error): 62 | completion(Result(error: error as NSError)) 63 | case .success: 64 | DispatchQueue.main.async(execute: { () -> Void in 65 | do { 66 | try OAuth2TokenRepository.removeToken(of: currentToken.name) 67 | completion(Result(value: currentToken)) 68 | } catch { completion(Result(error: error as NSError)) } 69 | }) 70 | } 71 | }) 72 | } catch { throw error } 73 | } 74 | 75 | /** 76 | Set an expired token to self. 77 | This method is implemented in order to test codes to automatiaclly refresh an expired token. 78 | */ 79 | public func setDummyExpiredToken() { 80 | if let path = Bundle.main.path(forResource: "expired_token.json", ofType: nil), let data = try? Data(contentsOf: URL(fileURLWithPath: path)) { 81 | do { 82 | if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject] { 83 | let token = OAuth2Token(json) 84 | self.token = token 85 | } 86 | } catch { print(error) } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /framework/Network/Session+flair.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Session+flair.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/19. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Session { 12 | } 13 | -------------------------------------------------------------------------------- /framework/Network/Session+gold.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Session+gold.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/19. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Session { 12 | /** 13 | Reddit gold? 14 | Gilds the specified content by fullname? 15 | - parameter fullname: fullname of a thing 16 | - returns: Data task which requests search to reddit.com. 17 | */ 18 | @discardableResult 19 | public func gild(_ fullname: String, completion: @escaping (Result) -> Void) throws -> URLSessionDataTask { 20 | let parameter = ["fullname": fullname] 21 | guard let request = URLRequest.requestForOAuth(with: baseURL, path: "/api/v1/gold/gild/", parameter: parameter, method: "POST", token: token) 22 | else { throw ReddiftError.canNotCreateURLRequest as NSError } 23 | let closure = {(data: Data?, response: URLResponse?, error: NSError?) -> Result in 24 | return Result(from: Response(data: data, urlResponse: response), optional: error) 25 | .flatMap(response2Data) 26 | .flatMap(data2Json) 27 | } 28 | return executeTask(request, handleResponse: closure, completion: completion) 29 | } 30 | 31 | /** 32 | Reddit gold? 33 | Gives gold to the specified user whose name is specified by username? 34 | - parameter username: A valid, existing reddit username 35 | - parameter months: an integer between 1 and 36 36 | - returns: Data task which requests search to reddit.com. 37 | */ 38 | public func giveGold(_ username: String, months: Int, completion: @escaping (Result) -> Void) throws -> URLSessionDataTask { 39 | let parameter = ["fullname": username, "months": String(months)] 40 | guard let request = URLRequest.requestForOAuth(with: baseURL, path: "/api/v1/gold/give/", parameter: parameter, method: "POST", token: token) 41 | else { throw ReddiftError.canNotCreateURLRequest as NSError } 42 | let closure = {(data: Data?, response: URLResponse?, error: NSError?) -> Result in 43 | return Result(from: Response(data: data, urlResponse: response), optional: error) 44 | .flatMap(response2Data) 45 | .flatMap(data2Json) 46 | } 47 | return executeTask(request, handleResponse: closure, completion: completion) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /framework/Network/Session+liveThreads.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Session+liveThreads.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/19. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Session { 12 | } 13 | -------------------------------------------------------------------------------- /framework/Network/Session+misc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Session+misc.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/19. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Session { 12 | } 13 | -------------------------------------------------------------------------------- /framework/Network/Session+moderation.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Session+moderation.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/19. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Session { 12 | } 13 | -------------------------------------------------------------------------------- /framework/Network/Session+search.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Session+search.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/19. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Session { 12 | 13 | /** 14 | Search link with query. If subreddit is nil, this method searched links from all of reddit.com. 15 | 16 | - parameter subreddit: Specified subreddit to which you would like to limit your search. 17 | - parameter query: The search keywords, must be less than 512 characters. 18 | - parameter paginator: Paginator object for paging. 19 | - parameter sort: Sort type, specified by SearchSortBy. 20 | - parameter completion: The completion handler to call when the load request is complete. 21 | - returns: Data task which requests search to reddit.com. 22 | */ 23 | @discardableResult 24 | public func getSearch(_ subreddit: Subreddit?, query: String, paginator: Paginator, sort: SearchSortBy, completion: @escaping (Result) -> Void) throws -> URLSessionDataTask { 25 | let parameter = paginator.dictionaryByAdding(parameters: ["q": query, "sort": sort.path]) 26 | var path = "/search" 27 | if let subreddit = subreddit { path = subreddit.url + "search" } 28 | guard let request = URLRequest.requestForOAuth(with: baseURL, path: path, parameter: parameter, method: "GET", token: token) 29 | else { throw ReddiftError.canNotCreateURLRequest as NSError } 30 | let closure = {(data: Data?, response: URLResponse?, error: NSError?) -> Result in 31 | return Result(from: Response(data: data, urlResponse: response), optional: error) 32 | .flatMap(response2Data) 33 | .flatMap(data2Json) 34 | .flatMap(json2RedditAny) 35 | .flatMap(redditAny2Object) 36 | } 37 | return executeTask(request, handleResponse: closure, completion: completion) 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /framework/Network/Session+wiki.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Session+wiki.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/19. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Session { 12 | } 13 | -------------------------------------------------------------------------------- /framework/OAuth/OAuth2TokenRepository.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OAuth2TokenRepository.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/04/14. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import MiniKeychain 11 | 12 | /** 13 | Repository to contain OAuth2 tokens for reddit.com based on "KeychanAccess". 14 | You can manage mulitple accounts using this class. 15 | OAuth2TokenRepository, is utility class, has only class method. 16 | */ 17 | public class OAuth2TokenRepository { 18 | /** 19 | Restores token for OAuth2 from Keychain. 20 | - parameter name: Specifies user name of token you want to restore from Keychain. 21 | - returns: OAuth2Token object. 22 | */ 23 | public class func token(of name: String) throws -> OAuth2Token { 24 | let keychain = Keychain(service: Config.sharedInstance.bundleIdentifier) 25 | do { 26 | let data = try keychain.data(of: name) 27 | if let json = try JSONSerialization.jsonObject(with: data, options: []) as? JSONDictionary { 28 | return OAuth2Token(json) 29 | } 30 | throw ReddiftError.specifiedNameTokenNotFoundInKeychain as NSError 31 | } catch { 32 | throw error 33 | } 34 | } 35 | 36 | /** 37 | Restores user name list from Keychain. 38 | 39 | - returns: List contains user names that was used to save tokens. 40 | */ 41 | public class var savedNames: [String] { 42 | let keychain = Keychain(service: Config.sharedInstance.bundleIdentifier) 43 | do { 44 | return try keychain.keys() 45 | } catch { 46 | print(error) 47 | return [] 48 | } 49 | } 50 | 51 | /** 52 | Saves OAuth2 token object into Keychain. 53 | 54 | - parameter token: OAuth2Token object, that must have valid user name which is used to save it into Keychain. 55 | */ 56 | public class func save(token: OAuth2Token) throws { 57 | if token.name.isEmpty { 58 | throw ReddiftError.tokenNameIsInvalid as NSError 59 | } 60 | do { 61 | let data = try JSONSerialization.data(withJSONObject: token.JSONObject, options: []) 62 | let keychain = Keychain(service: Config.sharedInstance.bundleIdentifier) 63 | try keychain.save(key: token.name, data: data) 64 | } catch { 65 | throw error 66 | } 67 | } 68 | 69 | /** 70 | Saves OAuth2 token object into Keychain. 71 | 72 | - parameter token: OAuth2Token object. 73 | - parameter name: Valid user name which is used to save it into Keychain. 74 | */ 75 | public class func save(token: OAuth2Token, of name: String) throws { 76 | if name.isEmpty { 77 | throw ReddiftError.tokenNameIsInvalid as NSError 78 | } 79 | do { 80 | let data = try JSONSerialization.data(withJSONObject: token.JSONObject, options: []) 81 | let keychain = Keychain(service: Config.sharedInstance.bundleIdentifier) 82 | try keychain.save(key: name, data: data) 83 | } catch { 84 | throw error 85 | } 86 | } 87 | 88 | /** 89 | Removes OAuth2 token whose user name is specified by the name parmeter from Keychain. 90 | 91 | - parameter name: Valid user name which is used to save it into Keychain. 92 | */ 93 | public class func removeToken(of name: String) throws { 94 | if name.isEmpty { 95 | throw ReddiftError.tokenNameIsInvalid as NSError 96 | } 97 | let keychain = Keychain(service: Config.sharedInstance.bundleIdentifier) 98 | keychain.delete(key: name) 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /framework/OAuth/Token.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Token.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/28. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /** 12 | Protocol for OAuthToken. 13 | */ 14 | public protocol Token { 15 | /// token 16 | var accessToken: String {get} 17 | /// the type of token 18 | var tokenType: String {get} 19 | var expiresIn: Int {get} 20 | var expiresDate: TimeInterval {get} 21 | var scope: String {get} 22 | var refreshToken: String {get} 23 | 24 | /// user name to identifiy token. 25 | var name: String {get} 26 | 27 | /// base URL of API 28 | static var baseURL: String {get} 29 | 30 | /// vacant token 31 | init() 32 | 33 | /// deserials Token from JSON data 34 | init(_ json: JSONDictionary) 35 | } 36 | 37 | extension Token { 38 | /** 39 | Returns json object 40 | 41 | - returns: Dictinary object containing JSON data. 42 | */ 43 | var JSONObject: JSONDictionary { 44 | let dict: JSONDictionary = [ 45 | "name": self.name as AnyObject, 46 | "access_token": self.accessToken as AnyObject, 47 | "token_type": self.tokenType as AnyObject, 48 | "expires_in": self.expiresIn as AnyObject, 49 | "expires_date": self.expiresDate as AnyObject, 50 | "scope": self.scope as AnyObject, 51 | "refresh_token": self.refreshToken as AnyObject 52 | ] 53 | return dict 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /framework/Utility/Result.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Result.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/06. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public enum Result { 12 | case success(A) 13 | case failure(NSError) 14 | 15 | public init(value: A) { 16 | self = .success(value) 17 | } 18 | 19 | public init(fromOptional: A?, error: NSError) { 20 | if let value = fromOptional { 21 | self = .success(value) 22 | } else { 23 | self = .failure(error) 24 | } 25 | } 26 | 27 | public init(from: A, optional error: NSError?) { 28 | if let error = error { 29 | self = .failure(error) 30 | } else { 31 | self = .success(from ) 32 | } 33 | } 34 | 35 | public init(error: NSError?) { 36 | if let error = error { 37 | self = .failure(error) 38 | } else { 39 | self = .failure(ReddiftError.unknown as NSError) 40 | } 41 | } 42 | 43 | func package(ifSuccess: (A) -> B, ifFailure: (NSError) -> B) -> B { 44 | switch self { 45 | case .success(let value): 46 | return ifSuccess(value) 47 | case .failure(let value): 48 | return ifFailure(value) 49 | } 50 | } 51 | 52 | func map(_ transform: (A) -> B) -> Result { 53 | return flatMap { .success(transform($0)) } 54 | } 55 | 56 | public func flatMap(_ transform: (A) -> Result) -> Result { 57 | return package( 58 | ifSuccess: transform, 59 | ifFailure: Result.failure) 60 | } 61 | 62 | public var error: NSError? { 63 | switch self { 64 | case .failure(let error): 65 | return error 66 | default: 67 | return nil 68 | } 69 | } 70 | 71 | public var value: A? { 72 | switch self { 73 | case .success(let success): 74 | return success 75 | default: 76 | return nil 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /framework/Utility/helper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // helper.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/04/27. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | #if os(iOS) || os(tvOS) 12 | import UIKit 13 | #elseif os(macOS) 14 | import Cocoa 15 | #endif 16 | 17 | /// Shared color class 18 | #if os(iOS) || os(tvOS) 19 | public typealias ReddiftColor = UIColor 20 | #elseif os(macOS) 21 | public typealias ReddiftColor = NSColor 22 | #endif 23 | -------------------------------------------------------------------------------- /framework/reddift.h: -------------------------------------------------------------------------------- 1 | // 2 | // reddift.h 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/01. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #if TARGET_OS_IPHONE 12 | #import 13 | #endif 14 | 15 | //! Project version number for reddift. 16 | FOUNDATION_EXPORT double reddiftVersionNumber; 17 | 18 | //! Project version string for reddift. 19 | FOUNDATION_EXPORT const unsigned char reddiftVersionString[]; 20 | 21 | // In this header, you should import all the public headers of your framework using statements like #import 2 | 3 | 4 | -------------------------------------------------------------------------------- /playground/reddift.playground/Resources/test_config.json.sample: -------------------------------------------------------------------------------- 1 | { 2 | "username": "test user account", 3 | "password": "test user password", 4 | "client_id": "test app client ID(must be script type app)", 5 | "secret": "test app secret" 6 | } -------------------------------------------------------------------------------- /playground/reddift.playground/Sources/SupportCode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // This file (and all other Swift source files in the Sources directory of this playground) will be precompiled into a framework which is automatically made available to reddift.playground. 3 | // 4 | -------------------------------------------------------------------------------- /playground/reddift.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /reddift.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "reddift" 3 | s.version = "2.0.3" 4 | s.summary = "Swift Reddit API Wrapper." 5 | s.description = <<-DESC 6 | reddift is Swift Reddit API Wrapper. 7 | - Supports OAuth2(and DOES NOT support Cookie-authentication). 8 | - Supports multi-accounts using KeyChain. 9 | DESC 10 | s.homepage = "https://github.com/sonsongithub/reddift" 11 | s.license = 'MIT' 12 | s.author = { "sonson" => "yoshida.yuichi@gmail.com" } 13 | s.source = { 14 | :git => "https://github.com/sonsongithub/reddift.git", 15 | :tag => "#{s.version}", 16 | :submodules => true 17 | } 18 | 19 | s.social_media_url = 'https://twitter.com/sonson_twit' 20 | 21 | s.ios.deployment_target = "8.4" 22 | s.osx.deployment_target = "10.9" 23 | s.tvos.deployment_target = "9.2" 24 | s.requires_arc = true 25 | 26 | s.source_files = [ 27 | 'framework/*/*.swift' 28 | ] 29 | s.dependency 'HTMLSpecialCharacters' 30 | s.dependency 'MiniKeychain' 31 | end 32 | -------------------------------------------------------------------------------- /reddift.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /reddift.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /reddift.xcodeproj/xcshareddata/xcschemes/application.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /reddift.xcodeproj/xcshareddata/xcschemes/reddift-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /test/CAPTCHATest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CAPTCHATest.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/05/07. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | 12 | #if os(iOS) 13 | import UIKit 14 | #endif 15 | 16 | class CAPTCHATest: SessionTestSpec { 17 | 18 | // now, CAPTCHA API does not work.....? 19 | // func testCheckWhetherCAPTCHAIsNeededOrNot() { 20 | // let msg = "is true or false as Bool" 21 | // print(msg) 22 | // var check_result: Bool? = nil 23 | // let documentOpenExpectation = self.expectation(description: msg) 24 | // do { 25 | // try self.session?.checkNeedsCAPTCHA({(result) -> Void in 26 | // switch result { 27 | // case .failure(let error): 28 | // print(error) 29 | // case .success(let check): 30 | // check_result = check 31 | // } 32 | // XCTAssert(check_result != nil, msg) 33 | // documentOpenExpectation.fulfill() 34 | // }) 35 | // } catch { XCTFail((error as NSError).description) } 36 | // self.waitForExpectations(timeout: self.timeoutDuration, handler: nil) 37 | // } 38 | 39 | // now, CAPTCHA API does not work.....? 40 | // func testGetIdenForNewCAPTCHA() { 41 | // let msg = "is String" 42 | // print(msg) 43 | // var iden: String? = nil 44 | // let documentOpenExpectation = self.expectation(description: msg) 45 | // do { 46 | // try self.session?.getIdenForNewCAPTCHA({ (result) -> Void in 47 | // switch result { 48 | // case .failure(let error): 49 | // print(error.description) 50 | // case .success(let identifier): 51 | // iden = identifier 52 | // } 53 | // XCTAssert(iden != nil, msg) 54 | // documentOpenExpectation.fulfill() 55 | // }) 56 | // } catch { XCTFail((error as NSError).description) } 57 | // self.waitForExpectations(timeout: self.timeoutDuration, handler: nil) 58 | // } 59 | 60 | // now, CAPTCHA API does not work.....? 61 | // func testSizeOfNewImageGeneratedUsingIden() { 62 | // let msg = "is 120x50" 63 | // print(msg) 64 | //#if os(iOS) || os(tvOS) 65 | // var size: CGSize? = nil 66 | //#elseif os(macOS) 67 | // var size: NSSize? = nil 68 | //#endif 69 | // let documentOpenExpectation = self.expectation(description: msg) 70 | // do { 71 | // try self.session?.getIdenForNewCAPTCHA({ (result) -> Void in 72 | // switch result { 73 | // case .failure(let error): 74 | // print(error.description) 75 | // case .success(let string): 76 | // try! self.session?.getCAPTCHA(string, completion: { (result) -> Void in 77 | // switch result { 78 | // case .failure(let error): 79 | // print(error.description) 80 | // case .success(let image): 81 | // size = image.size 82 | // } 83 | // documentOpenExpectation.fulfill() 84 | // }) 85 | // } 86 | // }) 87 | // } catch { XCTFail((error as NSError).description) } 88 | // self.waitForExpectations(timeout: self.timeoutDuration, handler: nil) 89 | // 90 | // if let size = size { 91 | //#if os(iOS) 92 | // XCTAssert(size == CGSize(width: 120, height: 50), msg) 93 | //#elseif os(macOS) 94 | // XCTAssert(size == NSSize(width: 120, height: 50), msg) 95 | //#endif 96 | // } else { 97 | // XCTFail(msg) 98 | // } 99 | // } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /test/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 | -------------------------------------------------------------------------------- /test/MoreChildrenTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoreChildrenTest.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2016/02/26. 6 | // Copyright © 2016年 sonson. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class MoreChildrenTest: SessionTestSpec { 12 | 13 | /** 14 | Test procedure 15 | 1. Get Link list from speficified Subreddit. 16 | 2. Get the Link which has the most comments in the list. 17 | 3. Get Comments and More from Link. 18 | 4. Expand More objects. 19 | */ 20 | func testGetMoreChildren() { 21 | 22 | var moreList: [More] = [] 23 | 24 | // https://www.reddit.com/r/redditdev/comments/2ujhkr/important_api_licensing_terms_clarified/ 25 | let link = Link(id: "2ujhkr") 26 | 27 | do { 28 | let documentOpenExpectation = self.expectation(description: "") 29 | try session?.getArticles(link, sort: .new, comments: nil, depth: 1, limit: 10, completion: { (result) -> Void in 30 | switch result { 31 | case .failure(let error): 32 | print(error) 33 | case .success(_, let listing): 34 | let incomming = listing.children.compactMap({ $0 as? More}) 35 | moreList.append(contentsOf: incomming) 36 | } 37 | documentOpenExpectation.fulfill() 38 | }) 39 | self.waitForExpectations(timeout: self.timeoutDuration, handler: nil) 40 | } catch { XCTFail((error as NSError).description) } 41 | 42 | XCTAssert(moreList.count > 0, "Cannot get More objects.") 43 | 44 | var check = true 45 | 46 | moreList.forEach({ 47 | do { 48 | let documentOpenExpectation = self.expectation(description: "") 49 | try session?.getMoreChildren($0.children, link: link, sort: .new, completion: { (result) -> Void in 50 | switch result { 51 | case .failure(let error): 52 | print(error) 53 | check = false 54 | case .success(let list): 55 | // print(list) 56 | if list.count == 0 { 57 | check = false 58 | } 59 | } 60 | documentOpenExpectation.fulfill() 61 | }) 62 | self.waitForExpectations(timeout: self.timeoutDuration, handler: nil) 63 | } catch { XCTFail((error as NSError).description) } 64 | }) 65 | XCTAssert(check, "Cannot expand More objects.") 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /test/ParseCommentMarkdownTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParseCommentMarkdownTest.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/09/24. 6 | // Copyright © 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class ParseCommentMarkdownTest: XCTestCase { 12 | var json: Any? 13 | 14 | override func setUp() { 15 | super.setUp() 16 | json = self.jsonFromFileName("comment_parse_data.json") 17 | } 18 | 19 | override func tearDown() { 20 | super.tearDown() 21 | } 22 | 23 | /// Perfomance test for markdown parsing. 24 | func testPerformanceOfParserCommentMarkdown() { 25 | print("Check performance of Simple Markdown Parser to parse reddit's makrdown format.") 26 | print("test data : comment_parse_data.json") 27 | 28 | /// Start to test 29 | self.measure { 30 | } 31 | } 32 | 33 | /// Unit test for markdown parsing 34 | func testParserCommentMarkdown() { 35 | print("Test whether Simple Markdown Parser can parse reddit's makrdown format.") 36 | print("test data : comment_parse_data.json") 37 | 38 | /// Start to test 39 | if let _ = self.json as? [AnyObject] { 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /test/ReddiftColorTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReddiftColorTest.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2017/01/05. 6 | // Copyright © 2017年 sonson. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class ReddiftColorTest: XCTestCase { 12 | 13 | func testReddiftColor() { 14 | let hexString = "#FFFF00" 15 | let color = ReddiftColor.color(with: hexString) 16 | XCTAssert(color.hexString() == hexString) 17 | } 18 | 19 | func testReddiftClassMethodColor() { 20 | XCTAssert(ReddiftColor.red.hexString() == "#FF0000") 21 | XCTAssert(ReddiftColor.green.hexString() == "#00FF00") 22 | XCTAssert(ReddiftColor.blue.hexString() == "#0000FF") 23 | XCTAssert(ReddiftColor.yellow.hexString() == "#FFFF00") 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/SearchTest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchTest.swift 3 | // reddift 4 | // 5 | // Created by sonson on 2015/06/01. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class SearchTest: SessionTestSpec { 12 | 13 | /** 14 | Test procedure 15 | */ 16 | func testSearch() { 17 | var links: [Link] = [] 18 | let query = "apple" 19 | let msg = "Search subreddit name used of \(query)" 20 | let documentOpenExpectation = self.expectation(description: msg) 21 | let subreddit = Subreddit(subreddit: "apple") 22 | 23 | do { 24 | try self.session?.getSearch(subreddit, query: query, paginator: Paginator(), sort: .new, completion: { (result) -> Void in 25 | switch result { 26 | case .failure(let error): 27 | print(error) 28 | case .success(let listing): 29 | links.append(contentsOf: listing.children.compactMap { $0 as? Link }) 30 | } 31 | documentOpenExpectation.fulfill() 32 | }) 33 | self.waitForExpectations(timeout: self.timeoutDuration, handler: nil) 34 | } catch { XCTFail((error as NSError).description) } 35 | XCTAssert(links.count > 0, msg) 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /test/data/other/create_token.json: -------------------------------------------------------------------------------- 1 | {"access_token": "37688300-b1c3Fm8YEl5YFqQi0YUESyBxTVA", "token_type": "bearer", "expires_in": 3600, "refresh_token": "37688300-flMxq9iR9sjnPCvepg64V_98Bng", "scope": "edit flair history identity modconfig modflair modlog modposts modwiki mysubreddits privatemessages read report save submit subscribe vote wikiedit wikiread"} -------------------------------------------------------------------------------- /test/data/other/refresh_token.json: -------------------------------------------------------------------------------- 1 | {"access_token": "37688300-PbETNGjqI-NnVXgJQdUVPV8X1Ng", "token_type": "bearer", "expires_in": 3600, "scope": "edit flair history identity modconfig modflair modlog modposts modwiki mysubreddits privatemessages read report save submit subscribe vote wikiedit wikiread"} -------------------------------------------------------------------------------- /test/data/response/TrophyList.json: -------------------------------------------------------------------------------- 1 | {"kind": "TrophyList", "data": {"trophies": [{"kind": "t6", "data": {"icon_70": "https://s3.amazonaws.com/redditstatic/award/n00b-70.png", "description": null, "url": null, "icon_40": "https://s3.amazonaws.com/redditstatic/award/n00b-40.png", "award_id": "j", "id": "10wnxy", "name": "New User"}}]}} 2 | -------------------------------------------------------------------------------- /test/data/response/api_comment_response.json: -------------------------------------------------------------------------------- 1 | {"json": {"errors": [], "data": {"things": [{"kind": "t1", "data": {"subreddit_id": "t5_31t2q", "banned_by": null, "link_id": "t3_35dpes", "likes": true, "replies": "", "user_reports": [], "saved": false, "id": "cr3g41y", "gilded": 0, "archived": false, "report_reasons": null, "author": "sonson_twit", "parent_id": "t3_35dpes", "score": 1, "approved_by": null, "controversiality": 0, "body": "test comment2", "edited": false, "author_flair_css_class": null, "downs": 0, "body_html": "<div class=\"md\"><p>test comment2</p>\n</div>", "subreddit": "sandboxtest", "score_hidden": false, "name": "t1_cr3g41y", "created": 1431192188.0, "author_flair_text": null, "created_utc": 1431163388.0, "ups": 1, "mod_reports": [], "num_reports": null, "distinguished": null}}]}}} -------------------------------------------------------------------------------- /test/data/response/api_needs_captcha.json: -------------------------------------------------------------------------------- 1 | true -------------------------------------------------------------------------------- /test/data/response/api_new_captcha.json: -------------------------------------------------------------------------------- 1 | {"json": {"errors": [], "data": {"iden": "3DKrBtTv6nGrB9Pua2HOK7iM0uW7XnV9"}}} -------------------------------------------------------------------------------- /test/data/response/error.json: -------------------------------------------------------------------------------- 1 | {"error": 401} -------------------------------------------------------------------------------- /test/data/response/message.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "Listing", 3 | "data": { 4 | "modhash": null, 5 | "children": [ 6 | { 7 | "kind": "t1", 8 | "data": { 9 | "body": "Checking it out now. I'l.....", 10 | "link_title": "Reddit Redirecting back to iOS app after login", 11 | "was_comment": true, 12 | "first_message": null, 13 | "name": "t1_cqdtl5p", 14 | "first_message_name": null, 15 | "created": 1429150024, 16 | "dest": "sonson_twit", 17 | "author": "supburger", 18 | "created_utc": 1429146424, 19 | "body_html": "<!-- SC_OFF --><div class=\"md\"><p>Check.....", 20 | "subreddit": "redditdev", 21 | "parent_id": "t1_cqdth7o", 22 | "likes": null, 23 | "context": "/r/redditdev/comments/32ik4r/reddit_redirecting_back_to_ios_app_after_login/cqdtl5p?context=3", 24 | "replies": null, 25 | "id": "cqdtl5p", 26 | "new": false, 27 | "distinguished": null, 28 | "subject": "コメントの返信" 29 | } 30 | }, 31 | { 32 | "kind": "t1", 33 | "data": { 34 | "body": "Correct. Everything is match.....", 35 | "link_title": "Reddit Redirecting back to iOS app after login", 36 | "was_comment": true, 37 | "first_message": null, 38 | "name": "t1_cqdclak", 39 | "first_message_name": null, 40 | "created": 1429123203, 41 | "dest": "sonson_twit", 42 | "author": "supburger", 43 | "created_utc": 1429119603, 44 | "body_html": "<!-- SC_OFF --><div class=\"md.....", 45 | "subreddit": "redditdev", 46 | "parent_id": "t1_cqdba2b", 47 | "likes": null, 48 | "context": "/r/redditdev/comments/32ik4r/reddit_redirecting_back_to_ios_app_after_login/cqdclak?context=3", 49 | "replies": null, 50 | "id": "cqdclak", 51 | "new": false, 52 | "distinguished": null, 53 | "subject": "コメントの返信" 54 | } 55 | }, 56 | { 57 | "kind": "t1", 58 | "data": { 59 | "body": "I did add URL Types to my Xc.....", 60 | "was_comment": true, 61 | "first_message": null, 62 | "name": "t1_cqd7lk1", 63 | "first_message_name": null, 64 | "created": 1429115592, 65 | "dest": "sonson_twit", 66 | "author": "supburger", 67 | "created_utc": 1429111992, 68 | "body_html": "<!-- .....", 69 | "subreddit": "redditdev", 70 | "parent_id": "t1_cqczrs3", 71 | "likes": null, 72 | "context": "/r/redditdev/comments/32ik4r/reddit_redirecting_back_to_ios_app_after_login/cqd7lk1?context=3", 73 | "replies": null, 74 | "id": "cqd7lk1", 75 | "new": false, 76 | "distinguished": null, 77 | "subject": "コメントの返信" 78 | } 79 | }, 80 | { 81 | "kind": "t4", 82 | "data": { 83 | "body": "Hello! [Hola!](https://www.reddit.com/r/reddit.com/wiki/templat.....", 84 | "was_comment": false, 85 | "first_message": null, 86 | "name": "t4_36sfhx", 87 | "first_message_name": null, 88 | "created": 1427126074, 89 | "dest": "sonson_twit", 90 | "author": "reddit", 91 | "created_utc": 1427122474, 92 | "body_html": "<!-- SC_.....", 93 | "subreddit": null, 94 | "parent_id": null, 95 | "context": "", 96 | "replies": "", 97 | "id": "36sfhx", 98 | "new": false, 99 | "distinguished": "admin", 100 | "subject": "Hello, /u/sonson_twit! Welcome to reddit!" 101 | } 102 | } 103 | ], 104 | "after": null, 105 | "before": null 106 | } 107 | } -------------------------------------------------------------------------------- /test/data/response/multi.json: -------------------------------------------------------------------------------- 1 | [{"kind": "LabeledMulti", "data": {"can_edit": true, "display_name": "english", "name": "english", "description_html": "", "created": 1432028681.0, "copied_from": null, "icon_url": null, "subreddits": [{"name": "redditdev"}, {"name": "swift"}], "created_utc": 1431999881.0, "key_color": "#cee3f8", "visibility": "private", "icon_name": "", "weighting_scheme": "classic", "path": "/user/sonson_twit/m/english", "description_md": ""}}, {"kind": "LabeledMulti", "data": {"can_edit": true, "display_name": "mine", "name": "mine", "description_html": "", "created": 1432027779.0, "copied_from": null, "icon_url": null, "subreddits": [{"name": "newsokur"}, {"name": "newsokuvip"}], "created_utc": 1431998979.0, "key_color": "#cee3f8", "visibility": "private", "icon_name": "", "weighting_scheme": "classic", "path": "/user/sonson_twit/m/mine", "description_md": ""}}] -------------------------------------------------------------------------------- /test/data/response/multidesc.json: -------------------------------------------------------------------------------- 1 | {"kind": "LabeledMultiDescription", "data": {"body_html": "<!-- SC_OFF --><div class=\"md\"><p>updated description</p>\n</div><!-- SC_ON -->", "body_md": "updated description"}} -------------------------------------------------------------------------------- /test/data/thing/LabeledMulti.json: -------------------------------------------------------------------------------- 1 | { 2 | "can_edit": true, 3 | "display_name": "english", 4 | "name": "english", 5 | "description_html": "", 6 | "created": 1432028681, 7 | "copied_from": null, 8 | "icon_url": null, 9 | "subreddits": [ 10 | { 11 | "name": "redditdev" 12 | }, 13 | { 14 | "name": "swift" 15 | } 16 | ], 17 | "created_utc": 1431999881, 18 | "key_color": "#cee3f8", 19 | "visibility": "private", 20 | "icon_name": "", 21 | "weighting_scheme": "classic", 22 | "path": "/user/sonson_twit/m/english", 23 | "description_md": "" 24 | } -------------------------------------------------------------------------------- /test/data/thing/LabeledMultiDescription.json: -------------------------------------------------------------------------------- 1 | { 2 | "body_html": "<!-- SC_OFF --><div class=\"md\"><p>updated</p>\n</div><!-- SC_ON -->", 3 | "body_md": "updated" 4 | } -------------------------------------------------------------------------------- /test/data/thing/UserList.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "UserList", 3 | "data": { 4 | "children": [ 5 | { 6 | "date": 1382991535, 7 | "mod_permissions": [], 8 | "name": "PicsMod", 9 | "id": "t2_5onsi" 10 | }, 11 | { 12 | "date": 1415392097, 13 | "mod_permissions": [ 14 | "all" 15 | ], 16 | "name": "cwenham", 17 | "id": "t2_2fpn" 18 | }, 19 | { 20 | "date": 1445810001, 21 | "mod_permissions": [ 22 | "wiki", 23 | "posts", 24 | "mail", 25 | "flair" 26 | ], 27 | "name": "adeadhead", 28 | "id": "t2_5tt1l" 29 | } 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test/data/thing/more.json: -------------------------------------------------------------------------------- 1 | { 2 | "count": 0, 3 | "parent_id": "t1_cp88kh5", 4 | "children": [ 5 | "cpddp7v", 6 | "cp8jvj8", 7 | "cp8cv4b" 8 | ], 9 | "name": "t1_cpddp7v", 10 | "id": "cpddp7v" 11 | } -------------------------------------------------------------------------------- /test/data/thing/t1.json: -------------------------------------------------------------------------------- 1 | { 2 | "subreddit_id": "t5_2qizd", 3 | "banned_by": null, 4 | "link_id": "t3_32wnhw", 5 | "likes": true, 6 | "replies": { 7 | "kind": "Listing", 8 | "data": { 9 | "modhash": null, 10 | "children": [ 11 | { 12 | "kind": "more", 13 | "data": { 14 | "count": 0, 15 | "parent_id": "t1_cqfhkcb", 16 | "children": [ 17 | "cqfmmpp" 18 | ], 19 | "name": "t1_cqfmmpp", 20 | "id": "cqfmmpp" 21 | } 22 | } 23 | ], 24 | "after": null, 25 | "before": null 26 | } 27 | }, 28 | "user_reports": [], 29 | "saved": false, 30 | "id": "cqfhkcb", 31 | "gilded": 0, 32 | "archived": false, 33 | "report_reasons": null, 34 | "author": "Icnoyotl", 35 | "parent_id": "t1_cqfh5kz", 36 | "score": 1, 37 | "approved_by": null, 38 | "controversiality": 0, 39 | "body": "The bot has been having this problem for awhile, there have been thousands of new comments since it last worked properly, so it seems like this must be something recurring? Could it have something to do with our AutoModerator?", 40 | "edited": false, 41 | "author_flair_css_class": null, 42 | "downs": 0, 43 | "body_html": "<div class=\"md\"><p>The bot has been having this problem for awhile, there have been thousands of new comments since it last worked properly, so it seems like this must be something recurring? Could it have something to do with our AutoModerator?</p>\n</div>", 44 | "subreddit": "redditdev", 45 | "score_hidden": false, 46 | "name": "t1_cqfhkcb", 47 | "created": 1429284845, 48 | "author_flair_text": null, 49 | "created_utc": 1429281245, 50 | "distinguished": null, 51 | "mod_reports": [], 52 | "num_reports": null, 53 | "ups": 1 54 | } -------------------------------------------------------------------------------- /test/data/thing/t2.json: -------------------------------------------------------------------------------- 1 | { 2 | "has_mail": false, 3 | "name": "sonson_twit", 4 | "created": 1427126074, 5 | "hide_from_robots": false, 6 | "gold_creddits": 0, 7 | "created_utc": 1427122474, 8 | "has_mod_mail": false, 9 | "link_karma": 1, 10 | "comment_karma": 1, 11 | "over_18": true, 12 | "is_gold": false, 13 | "is_mod": false, 14 | "gold_expiration": null, 15 | "has_verified_email": false, 16 | "id": "mfsh8", 17 | "inbox_count": 0 18 | } -------------------------------------------------------------------------------- /test/data/thing/t4.json: -------------------------------------------------------------------------------- 1 | { 2 | "body": "Hello! [Hola!](https://www.reddit.com/r/reddit.com/wiki/templat.....", 3 | "was_comment": false, 4 | "first_message": null, 5 | "name": "t4_36sfhx", 6 | "first_message_name": null, 7 | "created": 1427126074, 8 | "dest": "sonson_twit", 9 | "author": "reddit", 10 | "created_utc": 1427122474, 11 | "body_html": "<!-- SC_.....", 12 | "subreddit": null, 13 | "parent_id": null, 14 | "context": "", 15 | "replies": "", 16 | "id": "36sfhx", 17 | "new": false, 18 | "distinguished": "admin", 19 | "subject": "Hello, /u/sonson_twit! Welcome to reddit!" 20 | } -------------------------------------------------------------------------------- /test/objc-header.h: -------------------------------------------------------------------------------- 1 | // 2 | // objc-header.h 3 | // redditch 4 | // 5 | // Created by sonson on 2015/04/05. 6 | // Copyright (c) 2015年 sonson. All rights reserved. 7 | // 8 | 9 | #ifndef reddift_test_objc_header_h 10 | #define reddift_test_objc_header_h 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /test/test_config.json.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonsongithub/reddift/d93320dc35ad81e7bce9e5b76a87654a5bc84d7b/test/test_config.json.enc -------------------------------------------------------------------------------- /test/test_config.json.sample: -------------------------------------------------------------------------------- 1 | { 2 | "username": "test user account", 3 | "password": "test user password", 4 | "client_id": "test app client ID(must be script type app)", 5 | "secret": "test app secret" 6 | } --------------------------------------------------------------------------------