├── .gitignore ├── .swiftlint.yml ├── CONTRIBUTING.md ├── Constants └── L10nEnum.swift ├── Fabric.framework ├── Fabric ├── Headers │ ├── FABAttributes.h │ └── Fabric.h ├── Info.plist ├── Modules │ └── module.modulemap ├── run └── uploadDSYM ├── LICENSE ├── Podfile ├── Podfile.lock ├── Preview.html ├── README.md ├── SEDaily-IOS.xcodeproj ├── project.pbxproj ├── project.pbxproj.mergesave ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── SEDaily-IOS.xcscheme ├── SEDaily-IOS.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── SEDaily-IOS ├── API.swift ├── APIStripeExtension.swift ├── ActionView.swift ├── AnalyticsHelper.swift ├── AnswersTracker.swift ├── AppDelegate.swift ├── AskForReview.swift ├── Asset.swift ├── AssetPlayer.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-57x57@1x.png │ │ ├── Icon-App-57x57@2x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-72x72@1x.png │ │ ├── Icon-App-72x72@2x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ ├── Icon-App-83.5x83.5@2x.png │ │ ├── Icon-Small-50x50@1x.png │ │ ├── Icon-Small-50x50@2x.png │ │ └── SEDaily_Logo_Marketing_Icon.png │ ├── Arrow-Down.imageset │ │ ├── Arrow-Down.png │ │ ├── Arrow-Down@2x.png │ │ ├── Arrow-Down@3x.png │ │ └── Contents.json │ ├── Arrow-Up.imageset │ │ ├── Arrow-Up.png │ │ ├── Arrow-Up@2x.png │ │ ├── Arrow-Up@3x.png │ │ └── Contents.json │ ├── BigCircle.imageset │ │ ├── BigCircle.png │ │ ├── BigCircle@2x.png │ │ ├── BigCircle@3x.png │ │ └── Contents.json │ ├── Contents.json │ ├── Logo_BarButton.imageset │ │ ├── Contents.json │ │ ├── Logo_BarButton.png │ │ ├── Logo_BarButton@2x.png │ │ └── Logo_BarButton@3x.png │ ├── SEDaily_Logo.imageset │ │ ├── Contents.json │ │ ├── SEDaily_Logo.png │ │ ├── SEDaily_Logo@2x.png │ │ └── SEDaily_Logo@3x.png │ ├── SmallCircle.imageset │ │ ├── Contents.json │ │ ├── SmallCircle.png │ │ ├── SmallCircle@2x.png │ │ └── SmallCircle@3x.png │ ├── Square.imageset │ │ ├── Contents.json │ │ ├── Square.png │ │ ├── Square@2x.png │ │ └── Square@3x.png │ ├── Triangle.imageset │ │ ├── Contents.json │ │ ├── Triangle.png │ │ ├── Triangle@2x.png │ │ └── Triangle@3x.png │ ├── activity_feed_selected.imageset │ │ ├── Contents.json │ │ ├── activity_feed_selected.png │ │ ├── activity_feed_selected@2x.png │ │ └── activity_feed_selected@3x.png │ ├── bookmark.imageset │ │ ├── Contents.json │ │ ├── bookmark@1x.png │ │ ├── bookmark@2x.png │ │ └── bookmark@3x.png │ ├── bookmark_outline.imageset │ │ ├── Contents.json │ │ ├── bookmark_outline@1x.png │ │ ├── bookmark_outline@2x.png │ │ └── bookmark_outline@3x.png │ ├── comment.imageset │ │ ├── Contents.json │ │ ├── comment@1x.png │ │ ├── comment@2x.png │ │ └── comment@3x.png │ ├── download.imageset │ │ ├── Contents.json │ │ ├── download@1x.png │ │ ├── download@2x.png │ │ └── download@3x.png │ ├── download_outline.imageset │ │ ├── Contents.json │ │ ├── download_outline@1x.png │ │ ├── download_outline@2x.png │ │ └── download_outline@3x.png │ ├── download_panel.imageset │ │ ├── Contents.json │ │ ├── download_panel@1x.png │ │ ├── download_panel@2x.png │ │ └── download_panel@3x.png │ ├── download_panel_outline.imageset │ │ ├── Contents.json │ │ ├── download_panel_outline@1x.png │ │ ├── download_panel_outline@2x.png │ │ └── download_panel_outline@3x.png │ ├── forward_audio.imageset │ │ ├── Contents.json │ │ ├── forward_audio.png │ │ ├── forward_audio@2x.png │ │ └── forward_audio@3x.png │ ├── info.imageset │ │ ├── Contents.json │ │ ├── info.png │ │ ├── info@2x.png │ │ └── info@3x.png │ ├── latest.imageset │ │ ├── Contents.json │ │ ├── latest@1x.png │ │ ├── latest@2x.png │ │ └── latest@3x.png │ ├── latest_outline.imageset │ │ ├── Contents.json │ │ ├── latest_outline@1x.png │ │ ├── latest_outline@2x.png │ │ └── latest_outline@3x.png │ ├── like.imageset │ │ ├── Contents.json │ │ ├── Contents.json~4878a9558ba262a552fdc061e5bc104e8c791a06 │ │ ├── Contents.json~HEAD │ │ ├── like@1x.png │ │ ├── like@2x.png │ │ └── like@3x.png │ ├── like_outline.imageset │ │ ├── Contents.json │ │ ├── like_outline@1x.png │ │ ├── like_outline@2x.png │ │ └── like_outline@3x.png │ ├── link.imageset │ │ ├── Contents.json │ │ ├── link@1x.png │ │ ├── link@2x.png │ │ └── link@3x.png │ ├── logo_subtitle.imageset │ │ ├── Contents.json │ │ ├── logo_subtitle.png │ │ ├── logo_subtitle@2x.png │ │ └── logo_subtitle@3x.png │ ├── menu_hamburger.imageset │ │ ├── Contents.json │ │ ├── menu_hamburger.png │ │ ├── menu_hamburger@2x.png │ │ └── menu_hamburger@3x.png │ ├── mic_stand.imageset │ │ ├── Contents.json │ │ ├── mic_stand.png │ │ ├── mic_stand@2x.png │ │ └── mic_stand@3x.png │ ├── mic_stand_selected.imageset │ │ ├── Contents.json │ │ ├── mic_stand_selected.png │ │ ├── mic_stand_selected@2x.png │ │ └── mic_stand_selected@3x.png │ ├── pause-big.imageset │ │ ├── Contents.json │ │ ├── pause-big.png │ │ ├── pause-big@2x.png │ │ └── pause-big@3x.png │ ├── pause.imageset │ │ ├── Contents.json │ │ ├── pause.png │ │ ├── pause@2x.png │ │ └── pause@3x.png │ ├── pause_audio.imageset │ │ ├── Contents.json │ │ ├── pause_audio.png │ │ ├── pause_audio@2x.png │ │ └── pause_audio@3x.png │ ├── pause_white.imageset │ │ ├── Contents.json │ │ ├── pause_white.png │ │ ├── pause_white@2x.png │ │ └── pause_white@3x.png │ ├── person.imageset │ │ ├── Contents.json │ │ ├── person@1x.png │ │ ├── person@2x.png │ │ └── person@3x.png │ ├── person_outline.imageset │ │ ├── Contents.json │ │ ├── person_outline@1x.png │ │ ├── person_outline@2x.png │ │ └── person_outline@3x.png │ ├── play-big.imageset │ │ ├── Contents.json │ │ ├── play-big.png │ │ ├── play-big@2x.png │ │ └── play-big@3x.png │ ├── play.imageset │ │ ├── Contents.json │ │ ├── play.png │ │ ├── play@2x.png │ │ └── play@3x.png │ ├── play_audio.imageset │ │ ├── Contents.json │ │ ├── play_audio.png │ │ ├── play_audio@2x.png │ │ └── play_audio@3x.png │ ├── play_white.imageset │ │ ├── Contents.json │ │ ├── play_white.png │ │ ├── play_white@2x.png │ │ └── play_white@3x.png │ ├── profile-icon-9.imageset │ │ ├── Contents.json │ │ └── profile-icon-9.png │ ├── rewind_audio.imageset │ │ ├── Contents.json │ │ ├── rewind_audio@1x.png │ │ ├── rewind_audio@2x.png │ │ └── rewind_audio@3x.png │ ├── sedaily-logo.imageset │ │ ├── Contents.json │ │ ├── sedaily-logo.png │ │ ├── sedaily-logo@2x.png │ │ └── sedaily-logo@3x.png │ └── share.imageset │ │ ├── Contents.json │ │ ├── share@1x.png │ │ ├── share@2x.png │ │ └── share@3x.png ├── AudioOverlayViewController.swift ├── AudioPlayerView.swift ├── AudioView.swift ├── Author.swift ├── AvatarCell.swift ├── Base.lproj │ ├── LaunchScreen.storyboard │ ├── Localizable.strings │ └── Main.storyboard ├── BaseFeedItem.swift ├── Bookmark │ ├── BookmarkCollectionViewController.swift │ ├── BookmarkViewModelController.swift │ └── StateBookmarkView.swift ├── BookmarkService.swift ├── Comment.swift ├── CommentCell.swift ├── CommentReplyTableViewCell.swift ├── CommentTableViewCell.swift ├── CommentsResponse.swift ├── CommentsViewController.swift ├── ContainerViewController.swift ├── CurrentlyPlaying.swift ├── CustomTabViewController.swift ├── Debouncer.swift ├── Debug │ ├── Debug.storyboard │ ├── DebugTabViewController.swift │ ├── TestHook.swift │ ├── TestHookBool.swift │ ├── TestHookBoolTableViewCell.swift │ ├── TestHookEvent.swift │ ├── TestHookEventTableViewCell.swift │ └── TestHookManager.swift ├── DescriptionCell.swift ├── DiskKeys.swift ├── DownloadService.swift ├── DownloadsCollectionViewController.swift ├── DownloadsViewModelController.swift ├── EpisodeHeaderCell.swift ├── EpisodeViewController.swift ├── FeedItem.swift ├── FeedItemCell.swift ├── FeedList.storyboard ├── FeedListViewController.swift ├── FilterObject.swift ├── ForumHeaderViewController.swift ├── ForumList.storyboard ├── ForumListViewController.swift ├── ForumThread.swift ├── ForumThreadCell.swift ├── ForumThreadLite.swift ├── GeneralCollectionViewController.swift ├── GoogleService-Info.plist ├── Haptics.swift ├── HeaderView.swift ├── Helpers.swift ├── HtmlHelper.swift ├── Info.plist ├── ItemCollectionViewCell.swift ├── KoalaTeaFlowLayout.swift ├── LabelCell.swift ├── LoginViewController.swift ├── MainFlowCoordinator.swift ├── MainTabBarController.swift ├── NavigationControllerExtension.swift ├── NetworkService.swift ├── NotificationTableViewCell.swift ├── Notifications.swift ├── NotificationsController.swift ├── NotificationsTableViewController.swift ├── OfflineDownloadsManager.swift ├── OpenSans-Light.ttf ├── OpenSans-Regular.ttf ├── OpenSans-Semibold.ttf ├── OverlayViewController.swift ├── PlayProgress.swift ├── PlayProgressModelController.swift ├── PlaybackSpeed.swift ├── PlayerView.swift ├── Podcast.swift ├── PodcastCollectionViewCell.swift ├── PodcastCollectionViewController.swift ├── PodcastDataSource.swift ├── PodcastDescriptionView.swift ├── PodcastDetailViewController.swift ├── PodcastLite.swift ├── PodcastPageViewController.swift ├── PodcastRepository.swift ├── PodcastTableViewCell.swift ├── PodcastViewModel.swift ├── PodcastViewModelController.swift ├── PostsForTopicCollectionViewController.swift ├── ProfileCell.swift ├── ProfileTableViewDataSource.swift ├── ProfileViewController.swift ├── ProgressIndicator.swift ├── PurchaseSubscriptionViewController.swift ├── RelatedLink.swift ├── RelatedLinkWebVC.swift ├── RelatedLinkWebVC.xib ├── RelatedLinks.storyboard ├── RelatedLinksViewController.swift ├── RemoteCommandDataSource.swift ├── RemoteCommandManager.swift ├── Roboto-Bold.ttf ├── Roboto-Light.ttf ├── Roboto-Regular.ttf ├── RootViewController.swift ├── SearchCollectionViewController.swift ├── SeparatorCell.swift ├── SettingsCell.swift ├── SkeletonCollectionView.swift ├── StateController.swift ├── Stylesheet.swift ├── SubscriptionModel.swift ├── SubscriptionStatusViewController.swift ├── SummaryCell.swift ├── SwitchCell.swift ├── TagsCell.swift ├── ThreadHeaderView.swift ├── Topic.swift ├── TopicTableViewController.swift ├── UIButtonExtension.swift ├── UIColor+Extensions.swift ├── URLSchemaHelper.swift ├── UpvoteService.swift ├── User+ProfileViewController.Section.swift ├── UserModel.swift ├── ViewPlayground.playground │ ├── Contents.swift │ ├── Sources │ │ └── KTResponsiveUI │ │ │ ├── KTResponsiveUI │ │ │ └── Classes │ │ │ │ ├── Extensions.swift │ │ │ │ └── UIViewExtensions.swift │ │ │ ├── LICENSE │ │ │ └── README.md │ └── contents.xcplayground ├── WebViewCell.swift ├── en.lproj │ └── Localizable.strings └── fr.lproj │ ├── LaunchScreen.strings │ ├── Localizable.strings │ └── Main.strings ├── SEDaily-IOSTests ├── APITests │ ├── LoginTests.swift │ ├── PostsTests.swift │ ├── RegisterTests.swift │ └── VotingTests.swift ├── HelpersTests.swift ├── Info.plist ├── Mocks │ ├── Responses │ │ ├── login │ │ │ ├── login_nonexistinguser.json │ │ │ ├── login_success.json │ │ │ └── login_wrongpass.json │ │ ├── posts │ │ │ ├── getPostsWith_success.json │ │ │ ├── getPosts_topPosts.json │ │ │ ├── upvote_failure.json │ │ │ └── upvote_success.json │ │ └── register │ │ │ ├── register_emptyusernamepass.json │ │ │ ├── register_success.json │ │ │ └── register_userexists.json │ └── UserDefaultsMock.swift ├── SEDailyIOSTests.swift └── UserModelTests.swift ├── fastlane ├── Appfile ├── Deliverfile ├── Fastfile ├── README.md └── metadata │ ├── copyright.txt │ ├── en-US │ ├── description.txt │ ├── keywords.txt │ ├── marketing_url.txt │ ├── name.txt │ ├── privacy_url.txt │ ├── promotional_text.txt │ ├── release_notes.txt │ ├── subtitle.txt │ └── support_url.txt │ ├── primary_category.txt │ ├── primary_first_sub_category.txt │ ├── primary_second_sub_category.txt │ ├── review_information │ ├── demo_password.txt │ ├── demo_user.txt │ ├── email_address.txt │ ├── first_name.txt │ ├── last_name.txt │ ├── notes.txt │ └── phone_number.txt │ ├── secondary_category.txt │ ├── secondary_first_sub_category.txt │ ├── secondary_second_sub_category.txt │ └── trade_representative_contact_information │ ├── address_line1.txt │ ├── city_name.txt │ ├── country.txt │ ├── is_displayed_on_app_store.txt │ ├── postal_code.txt │ ├── state.txt │ └── trade_name.txt └── screenshots └── app_screenshots.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | <<<<<<< HEAD 23 | *.xccheckout 24 | *.xcscmblueprint 25 | 26 | /Pods 27 | .DS_Store 28 | ReadyRosie.xcworkspace/xcuserdata/CraigHolliday.xcuserdatad/UserInterfaceState.xcuserstate 29 | *.xcuserstate 30 | 31 | ## Obj-C/Swift specific 32 | *.hmap 33 | *.ipa 34 | *.dSYM.zip 35 | *.dSYM 36 | 37 | ## Playgrounds 38 | timeline.xctimeline 39 | playground.xcworkspace 40 | 41 | # Swift Package Manager 42 | # 43 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 44 | # Packages/ 45 | .build/ 46 | 47 | # CocoaPods 48 | # 49 | # We recommend against adding the Pods directory to your .gitignore. However 50 | # you should judge for yourself, the pros and cons are mentioned at: 51 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 52 | # 53 | Pods/ 54 | 55 | # Carthage 56 | # 57 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 58 | # Carthage/Checkouts 59 | 60 | Carthage/Build 61 | 62 | # fastlane 63 | # 64 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 65 | # screenshots whenever they are needed. 66 | # For more information about the recommended setup visit: 67 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 68 | 69 | fastlane/report.xml 70 | fastlane/Preview.html 71 | fastlane/screenshots 72 | fastlane/test_output 73 | 74 | .DS_Store 75 | GoogleService-Info.plist 76 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | excluded: # paths to ignore during linting. Takes precedence over `included`. 2 | - Pods 3 | 4 | disabled_rules: 5 | - line_length 6 | - identifier_name 7 | - superfluous_disable_command 8 | - todo 9 | - cyclomatic_complexity 10 | - function_body_length 11 | - nesting 12 | - file_length 13 | - type_body_length 14 | - trailing_whitespace 15 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | How to Contribute 2 | ----------------- 3 | We'd love to accept your patches and contributions to this project. There are just a few small guidelines you need to follow. 4 | 5 | Getting Started 6 | --------------- 7 | We use [gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) so instead of a single `master` branch, we use two branches to record the history of the project. The `master` branch stores the official release history, and the `develop` branch serves as an integration branch for features. It's also convenient to tag all commits in the master branch with a version number. 8 | 9 | Workflow 10 | -------- 11 | If you would like to contribute to this project, please: 12 | - Pick an [issue](https://github.com/SoftwareEngineeringDaily/se-daily-iOS/issues) to work on or create a [proposal](https://github.com/SoftwareEngineeringDaily/se-daily-iOS//blob/master/CONTRIBUTING.md#feature-proposals) for a new feature. 13 | - Fork this project. 14 | - Create your feature branch based off the `develop` branch. 15 | - Create a pull request to get your worked reviewed and merged back into the upstream `develop` branch. 16 | 17 | Please include screenshots of your app changes and write down the test scenarios you followed to verify that your code works. 18 | 19 | Feature proposals 20 | ----------------- 21 | Please create an issue, label it as a `feature proposal` and follow the following template: 22 | ```markdown 23 | # Proposal: [your title here] 24 | 25 | ## Summary 26 | {Also include any designs or wireframes here} 27 | 28 | ## Rationale 29 | {First reason for why we should consider this proposal} 30 | {Second reason for why we should consider this proposal} 31 | {etc} 32 | 33 | ## Scope 34 | 35 | ## Important Notes 36 | 37 | ## Open Questions 38 | ``` 39 | 40 | How to get unstuck 41 | ------------------ 42 | We have an active Slack community that you can reach out to for more information or just to chat with anyone. Check out the [Slack Channel SED iOS app development](https://softwaredaily.slack.com/app_redirect?channel=sed_app_ios) slack channel. 43 | 44 | Also checkout the [Open Source Guide](https://softwareengineeringdaily.github.io/). 45 | 46 | Code reviews 47 | ------------ 48 | All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests. 49 | 50 | Community Guidelines 51 | -------------------- 52 | - Be considerate, kind, constructive, and helpful. 53 | - Do not engage in demeaning, discriminatory, harassing, or hateful speech, and imagery. 54 | -------------------------------------------------------------------------------- /Fabric.framework/Fabric: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/Fabric.framework/Fabric -------------------------------------------------------------------------------- /Fabric.framework/Headers/FABAttributes.h: -------------------------------------------------------------------------------- 1 | // 2 | // FABAttributes.h 3 | // Fabric 4 | // 5 | // Copyright (C) 2015 Twitter, Inc. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #pragma once 21 | 22 | #define FAB_UNAVAILABLE(x) __attribute__((unavailable(x))) 23 | 24 | #if !__has_feature(nullability) 25 | #define nonnull 26 | #define nullable 27 | #define _Nullable 28 | #define _Nonnull 29 | #endif 30 | 31 | #ifndef NS_ASSUME_NONNULL_BEGIN 32 | #define NS_ASSUME_NONNULL_BEGIN 33 | #endif 34 | 35 | #ifndef NS_ASSUME_NONNULL_END 36 | #define NS_ASSUME_NONNULL_END 37 | #endif 38 | 39 | 40 | /** 41 | * The following macros are defined here to provide 42 | * backwards compatability. If you are still using 43 | * them you should migrate to the native nullability 44 | * macros. 45 | */ 46 | #define fab_nullable nullable 47 | #define fab_nonnull nonnull 48 | #define FAB_NONNULL __fab_nonnull 49 | #define FAB_NULLABLE __fab_nullable 50 | #define FAB_START_NONNULL NS_ASSUME_NONNULL_BEGIN 51 | #define FAB_END_NONNULL NS_ASSUME_NONNULL_END 52 | -------------------------------------------------------------------------------- /Fabric.framework/Headers/Fabric.h: -------------------------------------------------------------------------------- 1 | // 2 | // Fabric.h 3 | // Fabric 4 | // 5 | // Copyright (C) 2015 Twitter, Inc. 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #import 21 | #import "FABAttributes.h" 22 | 23 | NS_ASSUME_NONNULL_BEGIN 24 | 25 | #if TARGET_OS_IPHONE 26 | #if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000 27 | #error "Fabric's minimum iOS version is 6.0" 28 | #endif 29 | #else 30 | #if __MAC_OS_X_VERSION_MIN_REQUIRED < 1070 31 | #error "Fabric's minimum OS X version is 10.7" 32 | #endif 33 | #endif 34 | 35 | /** 36 | * Fabric Base. Coordinates configuration and starts all provided kits. 37 | */ 38 | @interface Fabric : NSObject 39 | 40 | /** 41 | * Initialize Fabric and all provided kits. Call this method within your App Delegate's `application:didFinishLaunchingWithOptions:` and provide the kits you wish to use. 42 | * 43 | * For example, in Objective-C: 44 | * 45 | * `[Fabric with:@[[Crashlytics class], [Twitter class], [Digits class], [MoPub class]]];` 46 | * 47 | * Swift: 48 | * 49 | * `Fabric.with([Crashlytics.self(), Twitter.self(), Digits.self(), MoPub.self()])` 50 | * 51 | * Only the first call to this method is honored. Subsequent calls are no-ops. 52 | * 53 | * @param kitClasses An array of kit Class objects 54 | * 55 | * @return Returns the shared Fabric instance. In most cases this can be ignored. 56 | */ 57 | + (instancetype)with:(NSArray *)kitClasses; 58 | 59 | /** 60 | * Returns the Fabric singleton object. 61 | */ 62 | + (instancetype)sharedSDK; 63 | 64 | /** 65 | * This BOOL enables or disables debug logging, such as kit version information. The default value is NO. 66 | */ 67 | @property (nonatomic, assign) BOOL debug; 68 | 69 | /** 70 | * Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance. 71 | */ 72 | - (id)init FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance."); 73 | 74 | /** 75 | * Unavailable. Use `+sharedSDK` to retrieve the shared Fabric instance. 76 | */ 77 | + (instancetype)new FAB_UNAVAILABLE("Use +sharedSDK to retrieve the shared Fabric instance."); 78 | 79 | @end 80 | 81 | NS_ASSUME_NONNULL_END 82 | 83 | -------------------------------------------------------------------------------- /Fabric.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/Fabric.framework/Info.plist -------------------------------------------------------------------------------- /Fabric.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module Fabric { 2 | umbrella header "Fabric.h" 3 | 4 | export * 5 | module * { export * } 6 | } -------------------------------------------------------------------------------- /Fabric.framework/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # run 4 | # 5 | # Copyright (c) 2015 Crashlytics. All rights reserved. 6 | 7 | # Figure out where we're being called from 8 | DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 9 | 10 | # Quote path in case of spaces or special chars 11 | DIR="\"${DIR}" 12 | 13 | PATH_SEP="/" 14 | VALIDATE_COMMAND="uploadDSYM\" $@ validate run-script" 15 | UPLOAD_COMMAND="uploadDSYM\" $@ run-script" 16 | 17 | # Ensure params are as expected, run in sync mode to validate 18 | eval $DIR$PATH_SEP$VALIDATE_COMMAND 19 | return_code=$? 20 | 21 | if [[ $return_code != 0 ]]; then 22 | exit $return_code 23 | fi 24 | 25 | # Verification passed, upload dSYM in background to prevent Xcode from waiting 26 | # Note: Validation is performed again before upload. 27 | # Output can still be found in Console.app 28 | eval $DIR$PATH_SEP$UPLOAD_COMMAND > /dev/null 2>&1 & 29 | -------------------------------------------------------------------------------- /Fabric.framework/uploadDSYM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/Fabric.framework/uploadDSYM -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2017 Kunal Kapadia 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 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | platform :ios, '10.3' 3 | 4 | target 'SEDaily-IOS' do 5 | # Comment the next line if you're not using Swift and don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | # Pods for SEDaily-IOS 9 | pod 'ActiveLabel', :git => 'https://github.com/optonaut/ActiveLabel.swift.git' 10 | p 11 | pod 'Alamofire', '~> 4.5.1' 12 | pod 'Down' 13 | pod 'Disk', '~> 0.3.1' 14 | pod 'Eureka', '~> 4.1.1' 15 | pod 'Firebase/Core' 16 | pod 'Firebase/Analytics' 17 | pod 'Fabric', '~> 1.10.2' 18 | pod 'Crashlytics', '~> 3.13.4' 19 | pod 'IQKeyboardManagerSwift', '~> 5.0.8' 20 | pod 'Kingfisher', '~> 4.2.0' 21 | pod 'KTResponsiveUI', '~> 0.2.4' 22 | pod 'MBProgressHUD', '~> 1.1.0' 23 | pod 'Pageboy', '~> 2.0.2' 24 | pod 'PopupDialog', '~> 0.6.0' 25 | pod 'Reusable', '~> 4.0.0' 26 | pod 'Skeleton', '~> 0.1.0' 27 | pod 'SnapKit', '~> 4.0.0' 28 | pod 'StatefulViewController', '~> 3.0' 29 | pod 'SwiftGen', '~> 5.2.1' 30 | pod 'SwiftMoment' 31 | pod 'SwiftLint', '~> 0.25.1' 32 | pod 'SwiftSoup', '~> 1.5.8' 33 | pod 'SwifterSwift', '~> 4.0.1' 34 | pod 'SwiftyBeaver', '~> 1.4.2' 35 | pod 'SwiftyJSON' 36 | pod 'Tabman', '~> 1.0.5' 37 | pod 'WaitForIt', '~> 2.0.0' 38 | pod 'Tags' 39 | 40 | target 'SEDaily-IOSTests' do 41 | inherit! :search_paths 42 | pod 'Quick' 43 | pod 'Nimble' 44 | pod 'Mockingjay' 45 | end 46 | 47 | end 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Software Engineering Daily iOS App 2 | 3 | [![logo](https://i.imgur.com/3OtP3p8.png)](https://softwareengineeringdaily.com/) 4 | 5 | Native iOS app for [Software Engineering Daily](https://softwareengineeringdaily.com/). 6 | 7 | ## Screenshots 8 | 9 | ![App screenshots](screenshots/app_screenshots.png) 10 | 11 | ## Getting Started 12 | 13 | The app is 100% Swift. User interface is built mostly in code using [SnapKit](https://github.com/SnapKit/SnapKit) DSL. The current architecture is MVVM-C, but moving forward we are open to consider some Redux-like state management implementation. 14 | 15 | ## Setup 16 | 17 | We are using [CocoaPods](http://cocoapods.org) to manage dependencies. 18 | Clone the repo and then run: 19 | 20 | ``` 21 | $ sudo gem install cocoapods 22 | $ pod install 23 | ``` 24 | 25 | CocoaPods requires that you open the *SEDaily-IOS.xcworkspace*. 26 | 27 | ``` 28 | $ open SEDaily-IOS.xcworkspace 29 | ``` 30 | 31 | ## Dependencies 32 | 33 | There are +25 various dependencies used in the project. Moving forward some of them may be subject to change/removal. 34 | The most important ones are: 35 | 36 | * [SnapKit](https://github.com/SnapKit/SnapKit) - Build layouts in code. 37 | * [Alamofire](https://github.com/Alamofire/Alamofire) - Industry standard for networking. 38 | * [Kingfisher](https://github.com/onevcat/Kingfisher) - Caching images. 39 | * [SwiftLint](https://github.com/realm/SwiftLint) - Swift language linter. 40 | 41 | 42 | 43 | ## Upcoming features 44 | 45 | Interested in seeing a particular feature implemented in this app? Please open a new [issue](https://github.com/SoftwareEngineeringDaily/se-daily-iOS/issues) with a [feature proposal](https://github.com/SoftwareEngineeringDaily/se-daily-iOS/blob/master/CONTRIBUTING.md#feature-proposals). 46 | 47 | Contributing 48 | ------------ 49 | Checkout [CONTRIBUTING.md](https://github.com/SoftwareEngineeringDaily/se-daily-iOS/blob/master/CONTRIBUTING.md) for details. 50 | 51 | -------------------------------------------------------------------------------- /SEDaily-IOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SEDaily-IOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SEDaily-IOS.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SEDaily-IOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SEDaily-IOS/ActionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionView.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 5/1/19. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class ActionView { 13 | let actionStackView: UIStackView = UIStackView() 14 | let upvoteButton: UIButton = UIButton() 15 | let commentButton: UIButton = UIButton() 16 | let bookmarkButton: UIButton = UIButton() 17 | 18 | var commentShowCallback: ( ()-> Void) = {} 19 | 20 | let upvoteCountLabel: UILabel = UILabel() 21 | 22 | let upvoteStackView: UIStackView = UIStackView() 23 | 24 | func setupComponents(superview: UIView) { 25 | func setupButtons() { 26 | upvoteButton.setImage(UIImage(named: "like_outline"), for: .normal) 27 | upvoteButton.setImage(UIImage(named: "like"), for: .selected) 28 | 29 | bookmarkButton.setImage(UIImage(named: "bookmark_outline"), for: .normal) 30 | bookmarkButton.setImage(UIImage(named: "bookmark"), for: .selected) 31 | 32 | commentButton.setImage(UIImage(named: "comment"), for: .normal) 33 | commentButton.setImage(UIImage(named: "comment"), for: .normal) 34 | } 35 | func setupUpvoteStackView() { 36 | upvoteStackView.alignment = .center 37 | upvoteStackView.axis = .horizontal 38 | upvoteStackView.distribution = .fillEqually 39 | 40 | upvoteStackView.addArrangedSubview(upvoteButton) 41 | upvoteStackView.addArrangedSubview(upvoteCountLabel) 42 | } 43 | 44 | func setupActionStackView() { 45 | actionStackView.alignment = .center 46 | actionStackView.axis = .horizontal 47 | actionStackView.distribution = .fillEqually 48 | 49 | actionStackView.addArrangedSubview(upvoteStackView) 50 | actionStackView.addArrangedSubview(commentButton) 51 | actionStackView.addArrangedSubview(bookmarkButton) 52 | superview.addSubview(actionStackView) 53 | } 54 | setupButtons() 55 | setupUpvoteStackView() 56 | setupActionStackView() 57 | 58 | } 59 | 60 | 61 | func setupContraints() { 62 | upvoteButton.snp.makeConstraints { (make) -> Void in 63 | make.right.equalTo(upvoteCountLabel.snp.left) 64 | make.height.width.equalTo(UIView.getValueScaledByScreenWidthFor(baseValue: 50.0)).priority(999) 65 | } 66 | bookmarkButton.snp.makeConstraints { (make) -> Void in 67 | 68 | make.height.width.equalTo(UIView.getValueScaledByScreenWidthFor(baseValue: 50.0)).priority(999) 69 | } 70 | commentButton.snp.makeConstraints { (make) -> Void in 71 | 72 | make.height.width.equalTo(UIView.getValueScaledByScreenWidthFor(baseValue: 50.0)).priority(999) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /SEDaily-IOS/AskForReview.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AskForReview.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Eduardo Saenz on 11/9/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import WaitForIt 11 | 12 | struct AskForReview: ScenarioProtocol { 13 | static let completedReviewKey = "completedReview" 14 | 15 | static func config() { 16 | /* 17 | Trigger an event three times minimum before executing 18 | Wait at least one day after the first event to execute 19 | Execute at most three times with a check if the review has been completed 20 | */ 21 | minEventsRequired = 3 22 | minSecondsSinceFirstEvent = 86_400 // seconds in one day 23 | minSecondsSinceLastEvent = 86_400 // seconds in one day 24 | maxExecutionsPermitted = 3 25 | customConditions = { 26 | let defaults = UserDefaults.standard 27 | return !(defaults.object(forKey: completedReviewKey) != nil && 28 | defaults.bool(forKey: completedReviewKey)) 29 | } 30 | } 31 | 32 | static func setReviewed() { 33 | let defaults = UserDefaults.standard 34 | defaults.set(true, forKey: AskForReview.completedReviewKey) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SEDaily-IOS/Asset.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016 Apple Inc. All Rights Reserved. 3 | See LICENSE.txt for this sample’s licensing information 4 | 5 | Abstract: 6 | `Asset` is a wrapper struct around an `AVURLAsset` and its asset name. 7 | */ 8 | 9 | import Foundation 10 | import AVFoundation 11 | 12 | public class Asset { 13 | // MARK: Types 14 | static let nameKey = "AssetName" 15 | 16 | // MARK: Properties 17 | 18 | /// The name of the asset to present in the application. 19 | public var assetName: String = "" 20 | 21 | // Custom artwork 22 | public var artworkURL: URL? = nil 23 | 24 | /// The `AVURLAsset` corresponding to an asset in either the application bundle or on the Internet. 25 | public var urlAsset: AVURLAsset 26 | 27 | public var savedTime: Float = 0 // This is in seconds 28 | 29 | // @TODO: Idk if CMTime is the right thing to use 30 | public var savedCMTime: CMTime { 31 | get { 32 | return CMTimeMake(Int64(savedTime), 1) 33 | } 34 | } 35 | 36 | public init(assetName: String, url: URL, artworkURL: URL? = nil, savedTime: Float = 0) { 37 | self.assetName = assetName 38 | let avURLAsset = AVURLAsset(url: url) 39 | self.urlAsset = avURLAsset 40 | self.artworkURL = artworkURL 41 | self.savedTime = savedTime 42 | } 43 | } 44 | 45 | extension Asset: Equatable { 46 | public static func == (lhs: Asset, rhs: Asset) -> Bool { 47 | return lhs.assetName == rhs.assetName && lhs.urlAsset == lhs.urlAsset 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/SEDaily_Logo_Marketing_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/AppIcon.appiconset/SEDaily_Logo_Marketing_Icon.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Arrow-Down.imageset/Arrow-Down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Arrow-Down.imageset/Arrow-Down.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Arrow-Down.imageset/Arrow-Down@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Arrow-Down.imageset/Arrow-Down@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Arrow-Down.imageset/Arrow-Down@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Arrow-Down.imageset/Arrow-Down@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Arrow-Down.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Arrow-Down.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Arrow-Down@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Arrow-Down@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Arrow-Up.imageset/Arrow-Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Arrow-Up.imageset/Arrow-Up.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Arrow-Up.imageset/Arrow-Up@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Arrow-Up.imageset/Arrow-Up@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Arrow-Up.imageset/Arrow-Up@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Arrow-Up.imageset/Arrow-Up@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Arrow-Up.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Arrow-Up.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Arrow-Up@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Arrow-Up@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/BigCircle.imageset/BigCircle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/BigCircle.imageset/BigCircle.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/BigCircle.imageset/BigCircle@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/BigCircle.imageset/BigCircle@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/BigCircle.imageset/BigCircle@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/BigCircle.imageset/BigCircle@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/BigCircle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "BigCircle.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "BigCircle@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "BigCircle@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Logo_BarButton.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Logo_BarButton.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Logo_BarButton@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Logo_BarButton@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Logo_BarButton.imageset/Logo_BarButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Logo_BarButton.imageset/Logo_BarButton.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Logo_BarButton.imageset/Logo_BarButton@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Logo_BarButton.imageset/Logo_BarButton@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Logo_BarButton.imageset/Logo_BarButton@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Logo_BarButton.imageset/Logo_BarButton@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/SEDaily_Logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "SEDaily_Logo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "SEDaily_Logo@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "SEDaily_Logo@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/SEDaily_Logo.imageset/SEDaily_Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/SEDaily_Logo.imageset/SEDaily_Logo.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/SEDaily_Logo.imageset/SEDaily_Logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/SEDaily_Logo.imageset/SEDaily_Logo@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/SEDaily_Logo.imageset/SEDaily_Logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/SEDaily_Logo.imageset/SEDaily_Logo@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/SmallCircle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "SmallCircle.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "SmallCircle@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "SmallCircle@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/SmallCircle.imageset/SmallCircle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/SmallCircle.imageset/SmallCircle.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/SmallCircle.imageset/SmallCircle@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/SmallCircle.imageset/SmallCircle@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/SmallCircle.imageset/SmallCircle@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/SmallCircle.imageset/SmallCircle@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Square.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Square.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Square@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Square@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Square.imageset/Square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Square.imageset/Square.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Square.imageset/Square@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Square.imageset/Square@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Square.imageset/Square@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Square.imageset/Square@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Triangle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Triangle.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Triangle@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Triangle@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Triangle.imageset/Triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Triangle.imageset/Triangle.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Triangle.imageset/Triangle@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Triangle.imageset/Triangle@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/Triangle.imageset/Triangle@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/Triangle.imageset/Triangle@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/activity_feed_selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "activity_feed_selected.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "activity_feed_selected@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "activity_feed_selected@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/activity_feed_selected.imageset/activity_feed_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/activity_feed_selected.imageset/activity_feed_selected.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/activity_feed_selected.imageset/activity_feed_selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/activity_feed_selected.imageset/activity_feed_selected@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/activity_feed_selected.imageset/activity_feed_selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/activity_feed_selected.imageset/activity_feed_selected@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/bookmark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bookmark@1x.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 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/bookmark.imageset/bookmark@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/bookmark.imageset/bookmark@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/bookmark.imageset/bookmark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/bookmark.imageset/bookmark@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/bookmark.imageset/bookmark@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/bookmark.imageset/bookmark@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/bookmark_outline.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bookmark_outline@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "bookmark_outline@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "bookmark_outline@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/bookmark_outline.imageset/bookmark_outline@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/bookmark_outline.imageset/bookmark_outline@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/bookmark_outline.imageset/bookmark_outline@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/bookmark_outline.imageset/bookmark_outline@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/bookmark_outline.imageset/bookmark_outline@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/bookmark_outline.imageset/bookmark_outline@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/comment.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "comment@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "comment@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "comment@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/comment.imageset/comment@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/comment.imageset/comment@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/comment.imageset/comment@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/comment.imageset/comment@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/comment.imageset/comment@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/comment.imageset/comment@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "download@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "download@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "download@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download.imageset/download@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download.imageset/download@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download.imageset/download@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download.imageset/download@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download.imageset/download@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download.imageset/download@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_outline.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "download_outline@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "download_outline@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "download_outline@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_outline.imageset/download_outline@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download_outline.imageset/download_outline@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_outline.imageset/download_outline@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download_outline.imageset/download_outline@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_outline.imageset/download_outline@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download_outline.imageset/download_outline@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_panel.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "download_panel@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "download_panel@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "download_panel@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_panel.imageset/download_panel@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download_panel.imageset/download_panel@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_panel.imageset/download_panel@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download_panel.imageset/download_panel@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_panel.imageset/download_panel@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download_panel.imageset/download_panel@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_panel_outline.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "download_panel_outline@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "download_panel_outline@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "download_panel_outline@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_panel_outline.imageset/download_panel_outline@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download_panel_outline.imageset/download_panel_outline@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_panel_outline.imageset/download_panel_outline@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download_panel_outline.imageset/download_panel_outline@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/download_panel_outline.imageset/download_panel_outline@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/download_panel_outline.imageset/download_panel_outline@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/forward_audio.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "forward_audio.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "forward_audio@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "forward_audio@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/forward_audio.imageset/forward_audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/forward_audio.imageset/forward_audio.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/forward_audio.imageset/forward_audio@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/forward_audio.imageset/forward_audio@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/forward_audio.imageset/forward_audio@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/forward_audio.imageset/forward_audio@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/info.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "info.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "info@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "info@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/info.imageset/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/info.imageset/info.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/info.imageset/info@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/info.imageset/info@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/info.imageset/info@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/info.imageset/info@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/latest.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "latest@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "latest@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "latest@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/latest.imageset/latest@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/latest.imageset/latest@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/latest.imageset/latest@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/latest.imageset/latest@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/latest.imageset/latest@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/latest.imageset/latest@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/latest_outline.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "latest_outline@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "latest_outline@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "latest_outline@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/latest_outline.imageset/latest_outline@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/latest_outline.imageset/latest_outline@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/latest_outline.imageset/latest_outline@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/latest_outline.imageset/latest_outline@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/latest_outline.imageset/latest_outline@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/latest_outline.imageset/latest_outline@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/like.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "like@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "like@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "like@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/like.imageset/Contents.json~4878a9558ba262a552fdc061e5bc104e8c791a06: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "like@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "like@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "like@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/like.imageset/Contents.json~HEAD: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "like@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "like@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "like@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/like.imageset/like@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/like.imageset/like@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/like.imageset/like@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/like.imageset/like@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/like.imageset/like@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/like.imageset/like@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/like_outline.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "like_outline@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "like_outline@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "like_outline@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/like_outline.imageset/like_outline@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/like_outline.imageset/like_outline@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/like_outline.imageset/like_outline@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/like_outline.imageset/like_outline@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/like_outline.imageset/like_outline@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/like_outline.imageset/like_outline@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/link.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "link@1x.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 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/link.imageset/link@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/link.imageset/link@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/link.imageset/link@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/link.imageset/link@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/link.imageset/link@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/link.imageset/link@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/logo_subtitle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "logo_subtitle.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "logo_subtitle@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "logo_subtitle@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/logo_subtitle.imageset/logo_subtitle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/logo_subtitle.imageset/logo_subtitle.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/logo_subtitle.imageset/logo_subtitle@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/logo_subtitle.imageset/logo_subtitle@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/logo_subtitle.imageset/logo_subtitle@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/logo_subtitle.imageset/logo_subtitle@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/menu_hamburger.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "menu_hamburger.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "menu_hamburger@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "menu_hamburger@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/menu_hamburger.imageset/menu_hamburger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/menu_hamburger.imageset/menu_hamburger.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/menu_hamburger.imageset/menu_hamburger@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/menu_hamburger.imageset/menu_hamburger@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/menu_hamburger.imageset/menu_hamburger@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/menu_hamburger.imageset/menu_hamburger@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/mic_stand.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "mic_stand.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "mic_stand@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "mic_stand@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/mic_stand.imageset/mic_stand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/mic_stand.imageset/mic_stand.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/mic_stand.imageset/mic_stand@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/mic_stand.imageset/mic_stand@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/mic_stand.imageset/mic_stand@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/mic_stand.imageset/mic_stand@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/mic_stand_selected.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "mic_stand_selected.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "mic_stand_selected@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "mic_stand_selected@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/mic_stand_selected.imageset/mic_stand_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/mic_stand_selected.imageset/mic_stand_selected.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/mic_stand_selected.imageset/mic_stand_selected@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/mic_stand_selected.imageset/mic_stand_selected@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/mic_stand_selected.imageset/mic_stand_selected@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/mic_stand_selected.imageset/mic_stand_selected@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause-big.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "pause-big.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "pause-big@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "pause-big@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause-big.imageset/pause-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause-big.imageset/pause-big.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause-big.imageset/pause-big@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause-big.imageset/pause-big@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause-big.imageset/pause-big@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause-big.imageset/pause-big@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "pause.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "pause@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "pause@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause.imageset/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause.imageset/pause.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause.imageset/pause@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause.imageset/pause@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause.imageset/pause@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause.imageset/pause@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause_audio.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "pause_audio.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "pause_audio@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "pause_audio@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause_audio.imageset/pause_audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause_audio.imageset/pause_audio.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause_audio.imageset/pause_audio@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause_audio.imageset/pause_audio@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause_audio.imageset/pause_audio@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause_audio.imageset/pause_audio@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause_white.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "pause_white.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "pause_white@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "pause_white@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause_white.imageset/pause_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause_white.imageset/pause_white.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause_white.imageset/pause_white@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause_white.imageset/pause_white@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/pause_white.imageset/pause_white@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/pause_white.imageset/pause_white@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/person.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "person@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "person@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "person@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/person.imageset/person@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/person.imageset/person@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/person.imageset/person@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/person.imageset/person@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/person.imageset/person@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/person.imageset/person@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/person_outline.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "person_outline@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "person_outline@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "person_outline@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/person_outline.imageset/person_outline@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/person_outline.imageset/person_outline@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/person_outline.imageset/person_outline@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/person_outline.imageset/person_outline@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/person_outline.imageset/person_outline@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/person_outline.imageset/person_outline@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play-big.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "play-big.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "play-big@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "play-big@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play-big.imageset/play-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play-big.imageset/play-big.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play-big.imageset/play-big@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play-big.imageset/play-big@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play-big.imageset/play-big@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play-big.imageset/play-big@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "play.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "play@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "play@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play.imageset/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play.imageset/play.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play.imageset/play@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play.imageset/play@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play.imageset/play@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play.imageset/play@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play_audio.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "play_audio.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "play_audio@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "play_audio@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play_audio.imageset/play_audio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play_audio.imageset/play_audio.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play_audio.imageset/play_audio@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play_audio.imageset/play_audio@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play_audio.imageset/play_audio@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play_audio.imageset/play_audio@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play_white.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "play_white.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "play_white@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "play_white@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play_white.imageset/play_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play_white.imageset/play_white.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play_white.imageset/play_white@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play_white.imageset/play_white@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/play_white.imageset/play_white@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/play_white.imageset/play_white@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/profile-icon-9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "profile-icon-9.png", 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 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/profile-icon-9.imageset/profile-icon-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/profile-icon-9.imageset/profile-icon-9.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/rewind_audio.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "rewind_audio@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "rewind_audio@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "rewind_audio@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/rewind_audio.imageset/rewind_audio@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/rewind_audio.imageset/rewind_audio@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/rewind_audio.imageset/rewind_audio@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/rewind_audio.imageset/rewind_audio@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/rewind_audio.imageset/rewind_audio@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/rewind_audio.imageset/rewind_audio@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/sedaily-logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "sedaily-logo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "sedaily-logo@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "sedaily-logo@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/sedaily-logo.imageset/sedaily-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/sedaily-logo.imageset/sedaily-logo.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/sedaily-logo.imageset/sedaily-logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/sedaily-logo.imageset/sedaily-logo@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/sedaily-logo.imageset/sedaily-logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/sedaily-logo.imageset/sedaily-logo@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/share.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "share@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "share@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "share@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/share.imageset/share@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/share.imageset/share@1x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/share.imageset/share@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/share.imageset/share@2x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Assets.xcassets/share.imageset/share@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Assets.xcassets/share.imageset/share@3x.png -------------------------------------------------------------------------------- /SEDaily-IOS/Author.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Author.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 2/5/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | // TODO: should merge this with User constuct? 11 | 12 | public struct Author: Codable { 13 | let email: String? 14 | let username: String? 15 | let name: String? 16 | let avatarUrl: String? 17 | let _id: String? 18 | } 19 | 20 | 21 | extension Author { 22 | func displayName() -> String { 23 | 24 | if let name = self.name { 25 | return name 26 | } 27 | if let username = self.username { 28 | return username 29 | } 30 | 31 | return L10n.anonymous 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SEDaily-IOS/AvatarCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AvatarCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 6/5/19. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | 10 | import UIKit 11 | import Reusable 12 | 13 | class AvatarCell: UITableViewCell, Reusable { 14 | private var avatarImageView: UIImageView! 15 | 16 | var avatarURL: URL? = nil { 17 | didSet { 18 | setupLayout() 19 | setupAvatar(imageURL: avatarURL) 20 | } 21 | } 22 | } 23 | 24 | extension AvatarCell { 25 | private func setupLayout() { 26 | self.selectionStyle = .none 27 | 28 | avatarImageView = UIImageView() 29 | contentView.addSubview(avatarImageView) 30 | avatarImageView.contentMode = .scaleAspectFill 31 | avatarImageView.clipsToBounds = true 32 | avatarImageView.cornerRadius = UIView.getValueScaledByScreenWidthFor(baseValue: 50) 33 | avatarImageView.kf.indicatorType = .activity 34 | 35 | avatarImageView.snp.makeConstraints { (make) -> Void in 36 | make.top.equalToSuperview().offset(UIView.getValueScaledByScreenWidthFor(baseValue: 15.0)) 37 | make.bottom.equalToSuperview().inset(UIView.getValueScaledByScreenWidthFor(baseValue: 15.0)) 38 | make.width.equalTo(UIView.getValueScaledByScreenWidthFor(baseValue: 100.0)) 39 | make.height.equalTo(UIView.getValueScaledByScreenWidthFor(baseValue: 100.0)) 40 | make.centerX.equalToSuperview() 41 | } 42 | } 43 | private func setupAvatar(imageURL: URL?) { 44 | avatarImageView.kf.cancelDownloadTask() 45 | avatarImageView.image = nil 46 | guard let imageURL = imageURL else { 47 | avatarImageView.image = #imageLiteral(resourceName: "SEDaily_Logo") 48 | return 49 | } 50 | avatarImageView.kf.setImage(with: imageURL, options: [.transition(.fade(0.2))]) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SEDaily-IOS/BaseFeedItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseFeedItem.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 5/18/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | protocol BaseFeedItem: Codable { 12 | var _id: String {get set} 13 | var score: Int {get set} 14 | var downvoted: Bool? {get set} 15 | var upvoted: Bool? {get set} 16 | } 17 | -------------------------------------------------------------------------------- /SEDaily-IOS/Bookmark/BookmarkViewModelController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BookmarkViewModelController.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Justin Lam on 12/4/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class BookmarkViewModelController { 12 | typealias Model = Podcast 13 | typealias ViewModel = PodcastViewModel 14 | typealias SuccessCallback = () -> Void 15 | typealias ErrorCallback = (RepositoryError?) -> Void 16 | 17 | private let repository = PodcastRepository() 18 | private var viewModels: [ViewModel?] = [] 19 | 20 | var viewModelsCount: Int { 21 | return viewModels.count 22 | } 23 | 24 | func viewModel(at index: Int) -> ViewModel? { 25 | guard index >= 0 && index < viewModelsCount else { return nil } 26 | return viewModels[index] 27 | } 28 | 29 | func update(with podcast: PodcastViewModel) { 30 | let index = self.viewModels.index { (item) -> Bool in 31 | return item?._id == podcast._id 32 | } 33 | guard let modelsIndex = index else { return } 34 | self.viewModels.remove(at: modelsIndex) 35 | if podcast.isBookmarked { 36 | self.viewModels.insert(podcast, at: modelsIndex) 37 | } 38 | 39 | self.repository.updateDataSource(diskKey: .PodcastFolder, item: podcast.baseModelRepresentation) 40 | } 41 | 42 | func retrieveCachedBookmarkData(onSuccess: @escaping SuccessCallback) { 43 | self.repository.retrieveCachedBookmarkData( 44 | onSuccess: { (podcasts) in 45 | self.viewModels.removeAll() 46 | podcasts.forEach({ podcast in 47 | self.viewModels.push(ViewModel(podcast: podcast)) 48 | }) 49 | onSuccess() }, 50 | onFailure: { _ in }) 51 | } 52 | 53 | func retrieveNetworkBookmarkData(onSuccess: @escaping SuccessCallback) { 54 | self.repository.retrieveNetworkBookmarkData( 55 | onSuccess: { (podcasts) in 56 | self.viewModels.removeAll() 57 | podcasts.forEach({ podcast in 58 | self.viewModels.push(ViewModel(podcast: podcast)) 59 | }) 60 | onSuccess() }, 61 | onFailure: { _ in }) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /SEDaily-IOS/Bookmark/StateBookmarkView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StateBookmarkView.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Justin Lam on 12/16/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | protocol StateViewDelegate: class { 13 | func refreshPressed() 14 | } 15 | 16 | /// Generic view for states used in view controllers 17 | class StateView: UIView { 18 | private var stackView: UIStackView! 19 | private var refreshButton: UIButton! 20 | weak var delegate: StateViewDelegate? 21 | 22 | init( 23 | frame: CGRect, 24 | text: String, 25 | showLoadingIndicator: Bool, 26 | showRefreshButton: Bool, 27 | delegate: StateViewDelegate?) { 28 | super.init(frame: frame) 29 | 30 | self.delegate = delegate 31 | 32 | self.stackView = UIStackView() 33 | self.stackView.axis = .vertical 34 | self.addSubview(self.stackView) 35 | 36 | let label = UILabel(text: text) 37 | 38 | let horizontalStackView = UIStackView() 39 | horizontalStackView.spacing = 10 40 | if showLoadingIndicator { 41 | let activityIndicator = UIActivityIndicatorView() 42 | activityIndicator.startAnimating() 43 | activityIndicator.color = UIColor.gray 44 | horizontalStackView.addArrangedSubview(activityIndicator) 45 | } 46 | horizontalStackView.addArrangedSubview(label) 47 | 48 | self.stackView.addArrangedSubview(horizontalStackView) 49 | 50 | if showRefreshButton { 51 | self.refreshButton = UIButton() 52 | self.refreshButton.setTitle(L10n.tapToRefresh, for: .normal) 53 | self.refreshButton.setTitleColor(UIColor.init(hex: 0x007AFF), for: .normal) 54 | self.refreshButton.addTarget(self, action: #selector(self.refreshPressed), for: .touchUpInside) 55 | self.stackView.addArrangedSubview(self.refreshButton) 56 | } 57 | 58 | self.stackView.snp.makeConstraints { (make) in 59 | make.centerX.centerY.equalToSuperview() 60 | } 61 | } 62 | 63 | @objc func refreshPressed() { 64 | self.delegate?.refreshPressed() 65 | } 66 | 67 | required init?(coder aDecoder: NSCoder) { 68 | fatalError("init(coder:) has not been implemented") 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /SEDaily-IOS/BookmarkService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BookmarkService.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 4/24/19. 6 | // Copyright © 2019 Altalogy All rights reserved. 7 | // 8 | 9 | protocol BookmarkServiceUIDelegate: class { 10 | func bookmarkUIDidChange(isBookmarked: Bool) 11 | func bookmarkUIImmediateUpdate() 12 | } 13 | 14 | import Foundation 15 | 16 | class BookmarkService { 17 | 18 | let networkService: API = API() 19 | 20 | var podcastViewModel: PodcastViewModel 21 | 22 | 23 | weak var UIDelegate: BookmarkServiceUIDelegate? 24 | 25 | init(podcastViewModel: PodcastViewModel) { 26 | self.podcastViewModel = podcastViewModel 27 | } 28 | 29 | func setBookmark() { 30 | guard UserManager.sharedInstance.isCurrentUserLoggedIn() == true else { 31 | Helpers.alertWithMessage(title: Helpers.Alerts.error, message: Helpers.Messages.youMustLogin, completionHandler: nil) 32 | return 33 | } 34 | UIDelegate?.bookmarkUIImmediateUpdate() 35 | self.setBookmark(value: true) 36 | } 37 | 38 | private func setBookmark(value: Bool) { 39 | let podcastId = podcastViewModel._id 40 | networkService.setBookmarkPodcast( 41 | value: value, 42 | podcastId: podcastId, 43 | completion: { [weak self] (success, active) in 44 | guard success != nil else { 45 | self?.UIDelegate?.bookmarkUIImmediateUpdate() 46 | return } 47 | if success == true { 48 | guard let active = active else { return } 49 | self?.updateBookmarked(active: active) 50 | } else { self?.UIDelegate?.bookmarkUIImmediateUpdate() } 51 | }) 52 | Analytics2.bookmarkButtonPressed(podcastId: podcastViewModel._id) 53 | } 54 | 55 | private func updateBookmarked(active: Bool) { 56 | self.podcastViewModel.isBookmarked = active 57 | let userInfo = ["viewModel": podcastViewModel] 58 | NotificationCenter.default.post(name: .viewModelUpdated, object: nil, userInfo: userInfo) 59 | self.UIDelegate?.bookmarkUIDidChange(isBookmarked: active) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SEDaily-IOS/Comment.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Comment.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 2/1/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Down 11 | import SwiftMoment 12 | 13 | public struct Comment: Codable { 14 | let author: Author 15 | let _id: String 16 | let content: String 17 | let dateCreated: String 18 | let deleted: Bool 19 | let rootEntity: String 20 | let replies: [Comment]? 21 | let score: Int 22 | let upvoted: Bool? 23 | let downvoted: Bool? 24 | let parentComment: String? 25 | } 26 | 27 | extension Comment { 28 | 29 | func getDatedCreatedPretty() -> String { 30 | return moment(self.dateCreated)?.fromNow() ?? "" 31 | } 32 | 33 | func commentBody() -> NSAttributedString { 34 | // This should be done on the server 35 | let down = Down(markdownString: self.content) 36 | if let content = try? down.toAttributedString() { 37 | return content 38 | } else { 39 | return NSAttributedString(string: self.content) 40 | } 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /SEDaily-IOS/CommentReplyTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CommentReplyTableViewCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 2/2/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CommentReplyTableViewCell: UITableViewCell { 12 | 13 | @IBOutlet weak var avatarImage: UIImageView! 14 | @IBOutlet weak var contentLabel: UILabel! 15 | @IBOutlet weak var usernameLabel: UILabel! 16 | @IBOutlet weak var dateLabel: UILabel! 17 | var comment: Comment? { 18 | didSet { 19 | contentLabel.attributedText = comment?.commentBody() 20 | let prettyDate = comment?.getDatedCreatedPretty() 21 | dateLabel.text = prettyDate 22 | usernameLabel.text = comment?.author.displayName() 23 | 24 | if let imageString = comment?.author.avatarUrl { 25 | let url = URL(string: imageString) 26 | avatarImage.kf.setImage(with: url) 27 | } else { 28 | avatarImage.image = UIImage(named: "profile-icon-9") 29 | } 30 | 31 | if comment?.deleted == true { 32 | contentLabel.textColor = UIColor.lightGray 33 | } else { 34 | contentLabel.textColor = UIColor.black 35 | } 36 | } 37 | } 38 | 39 | override func awakeFromNib() { 40 | super.awakeFromNib() 41 | setupLayout() 42 | 43 | // Initialization code 44 | } 45 | 46 | override func setSelected(_ selected: Bool, animated: Bool) { 47 | super.setSelected(selected, animated: animated) 48 | 49 | // Configure the view for the selected state 50 | } 51 | 52 | } 53 | 54 | extension CommentReplyTableViewCell { 55 | private func setupLayout() { 56 | func setupAvatarImage() { 57 | avatarImage.contentMode = .scaleAspectFill 58 | avatarImage.cornerRadius = avatarImage.frame.height / 2.0 59 | avatarImage.clipsToBounds = true 60 | } 61 | setupAvatarImage() 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /SEDaily-IOS/CommentTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CommentTableViewCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 2/2/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | class CommentTableViewCell: UITableViewCell { 13 | @IBOutlet weak var avatarImage: UIImageView! 14 | @IBOutlet weak var usernameLabel: UILabel! 15 | @IBOutlet weak var contentLabel: UILabel! 16 | @IBOutlet weak var replyButton: UIButton! 17 | @IBOutlet weak var dateLabel: UILabel! 18 | weak var delegate: CommentReplyTableViewCellDelegate? 19 | var hideReplyCell = false { 20 | didSet { 21 | replyButton.isHidden = hideReplyCell 22 | } 23 | } 24 | 25 | var comment: Comment? { 26 | didSet { 27 | let prettyDate = comment?.getDatedCreatedPretty() 28 | dateLabel.text = prettyDate 29 | contentLabel.attributedText = comment?.commentBody() 30 | usernameLabel.text = comment?.author.displayName() 31 | 32 | if let imageString = comment?.author.avatarUrl { 33 | let url = URL(string: imageString) 34 | avatarImage.kf.setImage(with: url) 35 | } else { 36 | avatarImage.image = UIImage(named: "profile-icon-9") 37 | } 38 | if comment?.deleted == true { 39 | contentLabel.textColor = UIColor.lightGray 40 | } else { 41 | contentLabel.textColor = UIColor.black 42 | } 43 | } 44 | } 45 | 46 | override func awakeFromNib() { 47 | super.awakeFromNib() 48 | // Initialization code 49 | } 50 | 51 | @IBAction func replyButtonPressed(_ sender: UIButton) { 52 | if let comment = comment { 53 | delegate?.replyToCommentPressed(comment: comment) 54 | } 55 | } 56 | 57 | override func setSelected(_ selected: Bool, animated: Bool) { 58 | super.setSelected(selected, animated: animated) 59 | 60 | // Configure the view for the selected state 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /SEDaily-IOS/CommentsResponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CommentsResponse.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 2/1/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct CommentsResponse: Codable { 12 | let result: [Comment] 13 | } 14 | -------------------------------------------------------------------------------- /SEDaily-IOS/CurrentlyPlaying.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CurrentlyPlaying.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 5/6/19. 6 | // Copyright © 2019 Altalogy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | // This is a workaround to keep global playing state 11 | class CurrentlyPlaying { 12 | // static let shared = CurrentlyPlaying() 13 | // private var currentlyPlayingId: String = "" 14 | // func setCurrentlyPlaying(id: String) { 15 | // currentlyPlayingId = id 16 | // } 17 | // func getCurrentlyPlayingId()-> String { 18 | // return currentlyPlayingId 19 | // } 20 | } 21 | -------------------------------------------------------------------------------- /SEDaily-IOS/Debouncer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Debouncer.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 4/24/19. 6 | // Copyright © 2019 Altalogy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class Debouncer: NSObject { 12 | var callback: (() -> ()) 13 | var delay: Double 14 | weak var timer: Timer? 15 | 16 | init(delay: Double, callback: @escaping (() -> ())) { 17 | self.delay = delay 18 | self.callback = callback 19 | } 20 | 21 | func call() { 22 | timer?.invalidate() 23 | let nextTimer = Timer.scheduledTimer(timeInterval: delay, target: self, selector: #selector(Debouncer.fireNow), userInfo: nil, repeats: false) 24 | timer = nextTimer 25 | } 26 | 27 | @objc func fireNow() { 28 | self.callback() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SEDaily-IOS/Debug/TestHook.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestHook.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Justin Lam on 10/7/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class TestHook { 12 | let name: String 13 | let id: TestHookId 14 | 15 | var reuseId: String { 16 | return "" 17 | } 18 | var order = 0 19 | 20 | init(id: TestHookId, name: String) { 21 | self.id = id 22 | self.name = name 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SEDaily-IOS/Debug/TestHookBool.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestHookBool.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Justin Lam on 12/15/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class TestHookBool: TestHook { 12 | override var reuseId: String { 13 | return "TestHookBoolCellId" 14 | } 15 | 16 | private var _defaultValue = false 17 | 18 | var value: Bool { 19 | get { 20 | return UserDefaults.standard.bool(forKey: self.id.rawValue) 21 | } 22 | 23 | set(newValue) { 24 | UserDefaults.standard.set(newValue, forKey: self.id.rawValue) 25 | } 26 | } 27 | 28 | var defaultValue: Bool { 29 | get { 30 | return self._defaultValue 31 | } 32 | set(newDefaultValue) { 33 | self._defaultValue = newDefaultValue 34 | if UserDefaults.standard.object(forKey: self.id.rawValue) == nil { 35 | UserDefaults.standard.set(newDefaultValue, forKey: self.id.rawValue) 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SEDaily-IOS/Debug/TestHookBoolTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestHookBoolTableViewCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Justin Lam on 12/15/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class TestHookBoolTableViewCell: UITableViewCell, TestHookTableViewCell { 13 | @IBOutlet private weak var title: UILabel! 14 | @IBOutlet private weak var boolSwitch: UISwitch! 15 | 16 | private weak var testHookBool: TestHookBool? 17 | 18 | @IBAction func valueChanged(_ sender: Any) { 19 | self.testHookBool?.value = self.boolSwitch.isOn 20 | } 21 | 22 | func configure(testHook: TestHook) { 23 | self.title.text = testHook.name 24 | 25 | if let testHookBool = testHook as? TestHookBool { 26 | self.testHookBool = testHookBool 27 | self.boolSwitch.isOn = testHookBool.value 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SEDaily-IOS/Debug/TestHookEvent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestHookEvent.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Justin Lam on 12/15/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class TestHookEvent: TestHook { 12 | override var reuseId: String { 13 | return "TestHookEventCellId" 14 | } 15 | var execute: (() -> Void)? 16 | } 17 | -------------------------------------------------------------------------------- /SEDaily-IOS/Debug/TestHookEventTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestHookEventTableViewCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Justin Lam on 12/15/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class TestHookEventTableViewCell: UITableViewCell, TestHookTableViewCell { 13 | @IBOutlet private weak var title: UILabel! 14 | private var testHookEvent: TestHookEvent? 15 | 16 | func configure(testHook: TestHook) { 17 | self.title.text = testHook.name 18 | 19 | if let testHookEvent = testHook as? TestHookEvent { 20 | self.testHookEvent = testHookEvent 21 | } 22 | } 23 | 24 | @IBAction func buttonTapped(_ sender: Any) { 25 | self.testHookEvent?.execute?() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SEDaily-IOS/Debug/TestHookManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TestHookManager.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Justin Lam on 12/15/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum TestHookId: String { 12 | case useStagingEndpoint 13 | case viewDisk 14 | case getPodcastBookmarks 15 | case clearAlreadyLoadedToday 16 | } 17 | 18 | class TestHookManager { 19 | private(set) static var testHooksMap = [TestHookId: TestHook]() 20 | private(set) static var testHooksArray = [TestHook]() 21 | private static var order = 0 22 | 23 | private init() { 24 | } 25 | 26 | static func add(testHook: TestHook) { 27 | testHook.order = order 28 | order += 1 29 | TestHookManager.testHooksMap[testHook.id] = testHook 30 | 31 | TestHookManager.testHooksArray = Array(TestHookManager.testHooksMap.values) 32 | TestHookManager.testHooksArray.sort { $0.order < $1.order } 33 | } 34 | 35 | static func testHookBool(id: TestHookId) -> TestHookBool? { 36 | return TestHookManager.testHooksMap[id] as? TestHookBool 37 | } 38 | 39 | static func testHookEvent(id: TestHookId) -> TestHookEvent? { 40 | return TestHookManager.testHooksMap[id] as? TestHookEvent 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SEDaily-IOS/DescriptionCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 5/2/19. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Reusable 11 | import WebKit 12 | 13 | class DescriptionCell: UITableViewCell, Reusable { 14 | 15 | var descriptionLabel: UILabel! 16 | //webView.navigationDelegate = self 17 | 18 | var viewModel: PodcastViewModel = PodcastViewModel() { 19 | willSet { 20 | guard newValue != self.viewModel else { return } 21 | } 22 | didSet { 23 | //updateUI() 24 | var str: String! 25 | // Due to asynchronuous nature of decoding html content, this is a better way to do it 26 | DispatchQueue.global(qos: .background).async { [weak self] in 27 | str = self?.viewModel.podcastDescription 28 | DispatchQueue.main.async { 29 | print(str) 30 | self?.descriptionLabel.text = str 31 | self?.layoutIfNeeded() 32 | } 33 | } 34 | } 35 | } 36 | 37 | 38 | override func awakeFromNib() { 39 | super.awakeFromNib() 40 | // Initialization code 41 | } 42 | 43 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 44 | super.init(style: style, reuseIdentifier: reuseIdentifier) 45 | setupLayout() 46 | 47 | } 48 | required init 49 | (coder aDecoder: NSCoder) { 50 | fatalError("init(coder:)") 51 | } 52 | 53 | override func setSelected(_ selected: Bool, animated: Bool) { 54 | super.setSelected(selected, animated: animated) 55 | 56 | // Configure the view for the selected state 57 | } 58 | 59 | } 60 | 61 | extension DescriptionCell { 62 | private func setupLayout() { 63 | descriptionLabel = UILabel() 64 | descriptionLabel.numberOfLines = 0 65 | descriptionLabel.font = UIFont(name: "OpenSans", size: UIView.getValueScaledByScreenWidthFor(baseValue: 13)) 66 | descriptionLabel.textColor = Stylesheet.Colors.dark 67 | self.contentView.addSubview(descriptionLabel) 68 | descriptionLabel.snp.makeConstraints { (make) in 69 | make.left.right.top.equalToSuperview().offset(UIView.getValueScaledByScreenWidthFor(baseValue: 10)) 70 | make.bottom.equalToSuperview().inset(UIView.getValueScaledByScreenWidthFor(baseValue: 10)) 71 | } 72 | } 73 | } 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /SEDaily-IOS/DiskKeys.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DiskKeys.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Craig Holliday on 11/16/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum DiskKeys: String { 12 | case PodcastFolder = "Podcasts" 13 | case OfflineDownloads = "Offline-Downloads" 14 | 15 | var folderPath: String { 16 | return self.rawValue + "/" + self.rawValue + ".json" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SEDaily-IOS/DownloadService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownloadService.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 4/24/19. 6 | // Copyright © 2019 Altalogy All rights reserved. 7 | // 8 | 9 | protocol DownloadServiceUIDelegate: class { 10 | func downloadUIDidChange(progress: Int?, success: Bool?) 11 | } 12 | import Foundation 13 | import UIKit 14 | 15 | class DownloadService { 16 | 17 | weak var UIDelegate: DownloadServiceUIDelegate? 18 | 19 | var podcastViewModel: PodcastViewModel 20 | 21 | private let downloadManager = OfflineDownloadsManager.sharedInstance 22 | 23 | init(podcastViewModel: PodcastViewModel) { 24 | self.podcastViewModel = podcastViewModel 25 | } 26 | 27 | func savePodcast() { 28 | 29 | let podcastId = self.podcastViewModel._id 30 | 31 | self.downloadManager.save( 32 | podcast: self.podcastViewModel, 33 | onProgress: { progress in 34 | // Show progress 35 | let progressAsInt = Int((progress * 100).rounded()) 36 | self.UIDelegate?.downloadUIDidChange(progress: progressAsInt, success: nil) 37 | self.podcastViewModel.downloadingProgress = progressAsInt 38 | }, 39 | onSuccess: { [weak self] in 40 | // for search bug fix 41 | guard let strongSelf = self else { return } 42 | let userInfo = ["viewModel": strongSelf.podcastViewModel] 43 | NotificationCenter.default.post(name: .viewModelUpdated, object: nil, userInfo: userInfo) 44 | // 45 | strongSelf.UIDelegate?.downloadUIDidChange(progress: nil, success: true) 46 | }, 47 | onFailure: { error in 48 | self.UIDelegate?.downloadUIDidChange(progress: nil, success: false) 49 | guard let error = error else { return } 50 | // Alert Error 51 | Helpers.alertWithMessage(title: error.localizedDescription.capitalized, message: "") 52 | 53 | }) 54 | } 55 | 56 | func deletePodcast() { 57 | 58 | Helpers.alertWithMessageCustomAction(title: L10n.deletePodcast, message: nil, actionTitle: L10n.deletePodcastButtonTitle) { [weak self] in 59 | guard let strongSelf = self else { return } 60 | strongSelf.downloadManager.deletePodcast(podcast: strongSelf.podcastViewModel) { 61 | strongSelf.UIDelegate?.downloadUIDidChange(progress: nil, success: false) 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /SEDaily-IOS/DownloadsViewModelController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DownloadsViewModelController.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 5/21/19. 6 | // Copyright © 2019 Altalogy. All rights reserved. 7 | // 8 | 9 | 10 | import Foundation 11 | 12 | public class DownloadsViewModelController { 13 | typealias Model = Podcast 14 | typealias ViewModel = PodcastViewModel 15 | typealias SuccessCallback = () -> Void 16 | typealias ErrorCallback = (RepositoryError?) -> Void 17 | 18 | private let repository = PodcastRepository() 19 | private var viewModels: [ViewModel?] = [] 20 | 21 | var viewModelsCount: Int { 22 | return viewModels.count 23 | } 24 | 25 | func viewModel(at index: Int) -> ViewModel? { 26 | guard index >= 0 && index < viewModelsCount else { return nil } 27 | return viewModels[index] 28 | } 29 | 30 | func update(with podcast: PodcastViewModel) { 31 | let index = self.viewModels.index { (item) -> Bool in 32 | return item?._id == podcast._id 33 | } 34 | guard let modelsIndex = index else { return } 35 | self.viewModels.remove(at: modelsIndex) 36 | self.viewModels.insert(podcast, at: modelsIndex) 37 | 38 | // Tell repository to update Datasource 39 | self.repository.updateDataSource(diskKey: .PodcastFolder, item: podcast.baseModelRepresentation) 40 | } 41 | 42 | func retrieveCachedDownloadsData(onSuccess: @escaping SuccessCallback) { 43 | self.repository.retrieveDownloadsData( 44 | onSuccess: { (podcasts) in 45 | self.viewModels.removeAll() 46 | podcasts.forEach({ podcast in 47 | self.viewModels.push(ViewModel(podcast: podcast)) 48 | }) 49 | onSuccess() }, 50 | onFailure: { _ in }) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SEDaily-IOS/FeedItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FeedItem.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 5/15/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | 13 | import Foundation 14 | 15 | public struct FeedItem: Codable { 16 | let _id: String 17 | let randomOrder: Double 18 | var relatedLink: RelatedLink 19 | // let author: Author // Is a string at times.. 20 | } 21 | -------------------------------------------------------------------------------- /SEDaily-IOS/FilterObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FilterObject.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Craig Holliday on 10/21/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct FilterObject: Codable { 12 | let type: String 13 | let tags: [Int] 14 | var tagsAsString: String { 15 | let stringArray = tags.map { String($0) } 16 | return stringArray.joined(separator: " ") 17 | } 18 | let lastDate: String 19 | let categories: [Int] 20 | var categoriesAsString: String { 21 | let stringArray = categories.map { String($0) } 22 | return stringArray.joined(separator: " ") 23 | } 24 | 25 | init(type: String = "", 26 | tags: [Int] = [], 27 | lastDate: String = "", 28 | categories: [Int] = []) { 29 | self.type = type 30 | self.tags = tags 31 | self.lastDate = lastDate 32 | self.categories = categories 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SEDaily-IOS/ForumHeaderViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ForumHeaderViewController.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 4/26/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ForumHeaderViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | // Do any additional setup after loading the view. 17 | } 18 | 19 | override func didReceiveMemoryWarning() { 20 | super.didReceiveMemoryWarning() 21 | // Dispose of any resources that can be recreated. 22 | } 23 | 24 | 25 | /* 26 | // MARK: - Navigation 27 | 28 | // In a storyboard-based application, you will often want to do a little preparation before navigation 29 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 30 | // Get the new view controller using segue.destinationViewController. 31 | // Pass the selected object to the new view controller. 32 | } 33 | */ 34 | 35 | } 36 | -------------------------------------------------------------------------------- /SEDaily-IOS/ForumThread.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ForumThread.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 4/24/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftMoment 11 | 12 | public struct ForumThread: BaseFeedItem { 13 | var _id: String 14 | let title: String 15 | let content: String 16 | let author: Author 17 | let commentsCount: Int 18 | let dateCreated: String 19 | let dateLastAcitiy: String // An annoying bug that will require database migrations + miner update 20 | var score: Int = 0 21 | let deleted: Bool 22 | var downvoted: Bool? 23 | var upvoted: Bool? 24 | let podcastEpisode: PodcastLite? 25 | } 26 | 27 | extension ForumThread { 28 | func getPrettyTitle() -> String { 29 | if podcastEpisode == nil { 30 | return self.title 31 | } 32 | // Remove "Discuss: " from threads with posts defined: 33 | return self.title.substring(from: self.title.index(self.title.startIndex, offsetBy: 9)) 34 | } 35 | func getCommentsSummary() -> String { 36 | if commentsCount != 1 { 37 | return "\(commentsCount) comments" 38 | } else { 39 | return "\(commentsCount) comment" 40 | } 41 | } 42 | 43 | func getDateLastActivityPretty() -> String { 44 | return moment(self.dateLastAcitiy)?.fromNow() ?? "" 45 | } 46 | 47 | func getDatedCreatedPretty() -> String { 48 | return moment(self.dateCreated)?.fromNow() ?? "" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /SEDaily-IOS/ForumThreadLite.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Thread.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 4/24/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct ForumThreadLite: Codable { 12 | let _id: String 13 | // let author: Author // Is a string at times.. 14 | } 15 | -------------------------------------------------------------------------------- /SEDaily-IOS/GoogleService-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CLIENT_ID 6 | 139717358510-83krai1okqvenaus4onn4qlndvs1vk64.apps.googleusercontent.com 7 | REVERSED_CLIENT_ID 8 | com.googleusercontent.apps.139717358510-83krai1okqvenaus4onn4qlndvs1vk64 9 | API_KEY 10 | AIzaSyAdaeUl4tnLv2jfV-3z9h2IwDfvz3qzP3A 11 | GCM_SENDER_ID 12 | 139717358510 13 | PLIST_VERSION 14 | 1 15 | BUNDLE_ID 16 | koala-tea.SEDaily 17 | PROJECT_ID 18 | sedaily-ebb27 19 | STORAGE_BUCKET 20 | sedaily-ebb27.appspot.com 21 | IS_ADS_ENABLED 22 | 23 | IS_ANALYTICS_ENABLED 24 | 25 | IS_APPINVITE_ENABLED 26 | 27 | IS_GCM_ENABLED 28 | 29 | IS_SIGNIN_ENABLED 30 | 31 | GOOGLE_APP_ID 32 | 1:139717358510:ios:a92590b1eee7f0b7 33 | DATABASE_URL 34 | https://sedaily-ebb27.firebaseio.com 35 | 36 | -------------------------------------------------------------------------------- /SEDaily-IOS/Haptics.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Haptics.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 5/21/19. 6 | // Copyright © 2019 Altalogy All rights reserved. 7 | // 8 | import UIKit 9 | 10 | enum FeedbackType { 11 | case impact 12 | case notification 13 | case selection 14 | } 15 | 16 | import Foundation 17 | 18 | class Haptics { 19 | static func feedback(_ feedback: FeedbackType) { 20 | switch feedback { 21 | case .impact: 22 | let impact = UIImpactFeedbackGenerator() 23 | impact.impactOccurred() 24 | case .notification: 25 | let notification = UINotificationFeedbackGenerator() 26 | notification.notificationOccurred(.success) 27 | case .selection: 28 | let selection = UISelectionFeedbackGenerator() 29 | selection.selectionChanged() 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /SEDaily-IOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | SEDaily 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 | 2.0.1 21 | CFBundleVersion 22 | 5 23 | ITSAppUsesNonExemptEncryption 24 | 25 | LSApplicationCategoryType 26 | 27 | LSRequiresIPhoneOS 28 | 29 | NSAppTransportSecurity 30 | 31 | NSAllowsArbitraryLoads 32 | 33 | 34 | UIAppFonts 35 | 36 | Roboto-Bold.ttf 37 | OpenSans-Semibold.ttf 38 | OpenSans-Regular.ttf 39 | Roboto-Light.ttf 40 | Roboto-Regular.ttf 41 | OpenSans-Light.ttf 42 | 43 | UIBackgroundModes 44 | 45 | audio 46 | fetch 47 | 48 | UILaunchStoryboardName 49 | LaunchScreen 50 | UIRequiredDeviceCapabilities 51 | 52 | armv7 53 | 54 | UIStatusBarHidden 55 | 56 | UIStatusBarStyle 57 | UIStatusBarStyleDefault 58 | UISupportedInterfaceOrientations 59 | 60 | UIInterfaceOrientationPortrait 61 | 62 | UISupportedInterfaceOrientations~ipad 63 | 64 | UIInterfaceOrientationPortrait 65 | UIInterfaceOrientationPortraitUpsideDown 66 | UIInterfaceOrientationLandscapeLeft 67 | UIInterfaceOrientationLandscapeRight 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /SEDaily-IOS/LabelCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LabelCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 6/10/19. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import Foundation 12 | import Reusable 13 | import UIKit 14 | 15 | class LabelCell: UITableViewCell, Reusable { 16 | 17 | private var label: UILabel = UILabel() 18 | 19 | var viewModel: ViewModel = ViewModel() { 20 | didSet { 21 | label.text = viewModel.text 22 | setupLayout(style: viewModel.style) 23 | 24 | } 25 | } 26 | 27 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 28 | super.init(style: style, reuseIdentifier: reuseIdentifier) 29 | contentView.addSubview(label) 30 | self.selectionStyle = .none 31 | self.isUserInteractionEnabled = true 32 | } 33 | 34 | required init 35 | (coder aDecoder: NSCoder) { 36 | fatalError("init(coder:)") 37 | } 38 | } 39 | 40 | 41 | extension LabelCell { 42 | private func setupLayout(style: ViewModel.Style) { 43 | 44 | label.snp.makeConstraints { (make) in 45 | make.left.right.equalToSuperview().offset(style.marginX) 46 | make.right.equalToSuperview().inset(style.marginX) 47 | make.top.equalToSuperview().offset(style.marginY) 48 | make.bottom.equalToSuperview().inset(style.marginY) 49 | } 50 | label.textAlignment = style.alignment 51 | label.font = style.font 52 | label.textColor = style.color 53 | 54 | self.accessoryType = style.accessory 55 | } 56 | } 57 | 58 | // MARK: - ViewModel 59 | extension LabelCell { 60 | struct ViewModel { 61 | struct Style { 62 | var marginX: CGFloat = 0 63 | var marginY: CGFloat = 0 64 | var font: UIFont = UIFont(name: "Roboto", size: 10.0)! //arbitrary 65 | var color = UIColor.clear 66 | var alignment = NSTextAlignment.left 67 | var accessory: UITableViewCell.AccessoryType = .disclosureIndicator 68 | } 69 | var text = "" 70 | var style = Style() 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SEDaily-IOS/MainFlowCoordinator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainFlowCoordinator.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 6/26/19. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import Foundation 12 | import UIKit 13 | 14 | protocol Coordinator: AnyObject { 15 | func configure(viewController: UIViewController) 16 | } 17 | 18 | protocol MainCoordinated: AnyObject { 19 | var mainCoordinator: MainFlowCoordinator? { get set } 20 | } 21 | 22 | protocol AudioControllable: AnyObject { 23 | var audioControlDelegate: EpisodeViewDelegate? { get set } 24 | } 25 | 26 | protocol Stateful: AnyObject { 27 | var stateController: StateController? { get set } 28 | } 29 | 30 | 31 | class MainFlowCoordinator: NSObject { 32 | let stateController = StateController() 33 | let rootViewController: RootViewController 34 | 35 | 36 | init(mainViewController: RootViewController) { 37 | self.rootViewController = mainViewController 38 | super.init() 39 | configure(viewController: mainViewController) 40 | } 41 | 42 | //Here you will pass viewModel as parameter, "info" String now for the exemplary purpose 43 | func viewController(_ viewController: UINavigationController, with viewModel: PodcastViewModel) { 44 | if let vc = viewController.visibleViewController as? EpisodeViewController { // a mechanism to prevent pushing the same view controllers 45 | if vc.viewModel == viewModel { 46 | return 47 | } 48 | } 49 | let vc = EpisodeViewController() 50 | vc.viewModel = viewModel 51 | configure(viewController: vc) 52 | viewController.pushViewController(vc, animated: true) 53 | } 54 | 55 | func viewController(_ navigationController: UINavigationController, push viewController: UIViewController) { 56 | configure(viewController: viewController) 57 | navigationController.pushViewController(viewController, animated: true) 58 | } 59 | 60 | 61 | 62 | } 63 | 64 | extension MainFlowCoordinator: Coordinator { 65 | func configure(viewController: UIViewController) { 66 | (viewController as? MainCoordinated)?.mainCoordinator = self 67 | (viewController as? Stateful)?.stateController = stateController 68 | (viewController as? AudioControllable)?.audioControlDelegate = rootViewController.overlayController 69 | if let rootController = viewController as? RootViewController { 70 | rootController.childViewControllers.forEach(configure(viewController:)) 71 | } 72 | if let tabBarController = viewController as? UITabBarController { 73 | tabBarController.viewControllers?.forEach(configure(viewController:)) 74 | } 75 | if let navigationController = viewController as? UINavigationController, 76 | let rootViewController = navigationController.viewControllers.first { 77 | configure(viewController: rootViewController) 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /SEDaily-IOS/NavigationControllerExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationControllerExtension.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Craig Holliday on 6/27/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UINavigationController { 12 | override open func viewDidLoad() { 13 | super.viewDidLoad() 14 | 15 | // Do any additional setup after loading the view. 16 | Stylesheet.applyOn(self) 17 | } 18 | 19 | override open func didReceiveMemoryWarning() { 20 | super.didReceiveMemoryWarning() 21 | // Dispose of any resources that can be recreated. 22 | } 23 | 24 | override open var preferredStatusBarStyle: UIStatusBarStyle { 25 | return Stylesheet.Contexts.Global.StatusBarStyle 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SEDaily-IOS/NetworkService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkRequest.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Berk Mollamustafaoglu on 13/01/2018. 6 | // Copyright © 2018. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Alamofire 11 | 12 | protocol NetworkService { 13 | func networkRequest(_ urlString: URLConvertible, method: HTTPMethod, parameters: Parameters?, encoding: ParameterEncoding, headers: HTTPHeaders?) -> DataRequest 14 | } 15 | 16 | extension NetworkService { 17 | func networkRequest(_ urlString: URLConvertible, method: HTTPMethod, parameters: Parameters?, encoding: ParameterEncoding = URLEncoding.default, headers: HTTPHeaders?) { 18 | return networkRequest(urlString, method: method, parameters: parameters, encoding: encoding, headers: headers) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SEDaily-IOS/NotificationTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationTableViewCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Keith Holliday on 4/2/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Reusable 11 | import SnapKit 12 | import SwifterSwift 13 | import KTResponsiveUI 14 | import Kingfisher 15 | 16 | class NotificationTableViewCell: UITableViewCell, Reusable { 17 | public var cellLabel: UILabel! 18 | public var cellToggle: UISwitch! 19 | var separator: UIView! 20 | 21 | 22 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 23 | super.init(style: style, reuseIdentifier: reuseIdentifier) 24 | 25 | cellLabel = UILabel() 26 | cellLabel.textColor = .black 27 | cellLabel.baselineAdjustment = .alignCenters 28 | cellLabel.numberOfLines = 0 29 | cellLabel.font = UIFont(name: "OpenSans", size: UIView.getValueScaledByScreenWidthFor(baseValue: 15)) 30 | cellLabel.textColor = Stylesheet.Colors.dark 31 | cellToggle = UISwitch() 32 | cellToggle.tintColor = Stylesheet.Colors.light 33 | cellToggle.onTintColor = Stylesheet.Colors.base 34 | 35 | 36 | self.contentView.addSubview(cellLabel) 37 | self.contentView.addSubview(cellToggle) 38 | setupSeparator() 39 | 40 | cellLabel.snp.makeConstraints { (make) in 41 | make.left.equalToSuperview().offset(UIView.getValueScaledByScreenWidthFor(baseValue: 15.0)) 42 | make.centerY.equalToSuperview() 43 | make.top.equalToSuperview().offset(UIView.getValueScaledByScreenWidthFor(baseValue: 15.0)) 44 | make.bottom.equalToSuperview().inset(UIView.getValueScaledByScreenWidthFor(baseValue: 15.0)) 45 | } 46 | 47 | cellToggle.snp.makeConstraints { (make) in 48 | make.right.equalToSuperview().inset(UIView.getValueScaledByScreenWidthFor(baseValue: 15.0)) 49 | make.centerY.equalToSuperview() 50 | } 51 | separator.snp.makeConstraints { (make) -> Void in 52 | make.left.right.bottom.equalToSuperview() 53 | make.height.equalTo(2.0) 54 | } 55 | } 56 | 57 | required init(coder aDecoder: NSCoder) { 58 | fatalError("init(coder:)") 59 | } 60 | 61 | func setupSeparator() { 62 | separator = UIView() 63 | contentView.addSubview(separator) 64 | separator.backgroundColor = Stylesheet.Colors.light 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /SEDaily-IOS/Notifications.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Notifications.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Craig Holliday on 7/24/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension Notification.Name { 12 | static let loginChanged = Notification.Name("loginChanged") 13 | static let viewModelUpdated = Notification.Name("viewModelUpdated") 14 | static let episodeViewWillExpand = Notification.Name("episodeViewWillExpand") 15 | static let reloadEpisodeView = Notification.Name("reloadEpisodeView") 16 | } 17 | -------------------------------------------------------------------------------- /SEDaily-IOS/OpenSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/OpenSans-Light.ttf -------------------------------------------------------------------------------- /SEDaily-IOS/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /SEDaily-IOS/OpenSans-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/OpenSans-Semibold.ttf -------------------------------------------------------------------------------- /SEDaily-IOS/PlayProgress.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PlayProgress.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 4/11/19. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct PlayProgress: Codable { 12 | let id: String 13 | var currentTime: Float 14 | var totalLength: Float 15 | var progressFraction: Float { 16 | get { 17 | return currentTime / totalLength 18 | } 19 | } 20 | var timeLeft: Float { 21 | get { 22 | return totalLength - currentTime 23 | } 24 | } 25 | 26 | init(id: String, currentTime: Float, totalLength: Float) { 27 | self.id = id 28 | self.currentTime = currentTime 29 | self.totalLength = totalLength 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SEDaily-IOS/PlayProgressModelController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PlayProgressModelController.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 4/12/19. 6 | // Copyright © 2019 Altalogy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | typealias PlayProgressDict = [String: PlayProgress] 12 | 13 | class PlayProgressModelController { 14 | 15 | var episodesPlayProgress: PlayProgressDict = PlayProgressDict() 16 | 17 | static func saveRecentlyListenedEpisodeId(id: String) { 18 | let defaults = UserDefaults.standard 19 | defaults.set(id, forKey: "sedaily-recentlyListened") 20 | } 21 | 22 | static func cleanRecentlyListenedEpisodeId() { 23 | let defaults = UserDefaults.standard 24 | defaults.set("", forKey: "sedaily-recentlyListened") 25 | } 26 | 27 | static func getRecentlyListenedEpisodeId() -> String? { 28 | let defaults = UserDefaults.standard 29 | guard let id = defaults.object(forKey: "sedaily-recentlyListened") as? String else { return nil} 30 | return id 31 | } 32 | 33 | func save() { 34 | var progressToSave: [String: Data] = [String: Data]() 35 | for (key, playProgress) in self.episodesPlayProgress { 36 | guard let playProgressData = encodePlayProgress(from: playProgress) else { return } 37 | progressToSave[key] = playProgressData 38 | } 39 | saveToDefaults(progressToSave: progressToSave) 40 | } 41 | 42 | func retrieve() { 43 | guard let fetched = fetchFromDefaults() else { return } 44 | var result: PlayProgressDict = PlayProgressDict() 45 | for (key, playProgressData) in fetched { 46 | guard let playProgress = decodePlayProgress(from: playProgressData) else { return } 47 | result[key] = playProgress 48 | } 49 | episodesPlayProgress = result 50 | } 51 | 52 | } 53 | 54 | private extension PlayProgressModelController { 55 | 56 | private func saveToDefaults(progressToSave: [String: Data]) { 57 | let defaults = UserDefaults.standard 58 | defaults.set(progressToSave, forKey: "sedaily-playProgress") 59 | } 60 | 61 | private func fetchFromDefaults()-> [String: Data]? { 62 | let defaults = UserDefaults.standard 63 | guard let fetchedData = defaults.object(forKey: "sedaily-playProgress") as? [String: Data] else { return nil} 64 | return fetchedData 65 | } 66 | 67 | private func decodePlayProgress(from data: Data)-> PlayProgress? { 68 | guard let fetchedPlayProgress = try? PropertyListDecoder().decode(PlayProgress.self, from: data) 69 | else { return nil } 70 | return fetchedPlayProgress 71 | } 72 | 73 | private func encodePlayProgress(from playProgress: PlayProgress)-> Data? { 74 | guard let progressData = try? PropertyListEncoder().encode(playProgress) else { return nil } 75 | return progressData 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /SEDaily-IOS/PlaybackSpeed.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PlaybackSpeed.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 16/07/2019. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum PlaybackSpeed: Float { 12 | case _1x = 1.0 13 | case _1_2x = 1.2 14 | case _1_4x = 1.4 15 | case _1_6x = 1.6 16 | case _1_8x = 1.8 17 | case _2x = 2.0 18 | case _2_5x = 2.5 19 | case _3x = 3.0 20 | 21 | var title: String { 22 | switch self { 23 | case ._1x: 24 | return "1x (Normal Speed)" 25 | case ._1_2x: 26 | return "1.2x" 27 | case ._1_4x: 28 | return "1.4x" 29 | case ._1_6x: 30 | return "1.6x" 31 | case ._1_8x: 32 | return "1.8x" 33 | case ._2x: 34 | return "⏩ 2x ⏩" 35 | case ._2_5x: 36 | return "2.5x" 37 | case ._3x: 38 | return "🔥 3x 🔥" 39 | } 40 | } 41 | 42 | var shortTitle: String { 43 | switch self { 44 | case ._1x: 45 | return "1x" 46 | case ._1_2x: 47 | return "1.2x" 48 | case ._1_4x: 49 | return "1.4x" 50 | case ._1_6x: 51 | return "1.6x" 52 | case ._1_8x: 53 | return "1.8x" 54 | case ._2x: 55 | return "2x" 56 | case ._2_5x: 57 | return "2.5x" 58 | case ._3x: 59 | return "3x" 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /SEDaily-IOS/PlayerView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PlayerView.swift 3 | // KoalaTeaPlayer 4 | // 5 | // Created by Craig Holliday on 8/4/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | import UIKit 9 | import AVFoundation 10 | 11 | import UIKit 12 | import AVFoundation 13 | 14 | /// A simple `UIView` subclass that is backed by an `AVPlayerLayer` layer. 15 | public class PlayerView: UIView { 16 | public var player: AVPlayer? { 17 | get { 18 | return playerLayer.player 19 | } 20 | 21 | set { 22 | playerLayer.player = newValue 23 | } 24 | } 25 | 26 | var playerLayer: AVPlayerLayer { 27 | // swiftlint:disable force_cast 28 | return layer as! AVPlayerLayer 29 | // swiftlint:enable force_cast 30 | } 31 | 32 | override public class var layerClass: AnyClass { 33 | return AVPlayerLayer.self 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /SEDaily-IOS/PodcastDescriptionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PodcastDescriptionView.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Craig Holliday on 10/18/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ActiveLabel 11 | import KTResponsiveUI 12 | 13 | class PodcastDescriptionView: UIView { 14 | 15 | private lazy var label: ActiveLabel = { 16 | return ActiveLabel(leftInset: 15, topInset: 15, width: 375 - 30, height: 600) 17 | }() 18 | 19 | private let bottomMarginForLabel = UIView.getValueScaledByScreenHeightFor(baseValue: 30) 20 | 21 | override func performLayout() { 22 | self.backgroundColor = Stylesheet.Colors.offWhite 23 | 24 | self.addSubview(label) 25 | self.height = label.height 26 | 27 | label.numberOfLines = 0 28 | label.enabledTypes = [.url] 29 | label.textColor = Stylesheet.Colors.offBlack 30 | label.handleURLTap { url in 31 | if #available(iOS 10.0, *) { 32 | UIApplication.shared.open(url, options: [:], completionHandler: nil) 33 | Tracker.logMovedToWebView(url: url.absoluteString) 34 | } else { 35 | UIApplication.shared.openURL(url) 36 | Tracker.logMovedToWebView(url: url.absoluteString) 37 | } 38 | } 39 | } 40 | 41 | func setupView(podcastModel: PodcastViewModel) { 42 | podcastModel.getHTMLDecodedDescription { (returnedString) in 43 | let paragraphStyle = NSMutableParagraphStyle() 44 | paragraphStyle.paragraphSpacing = 10 45 | 46 | self.label.attributedText = NSAttributedString(string: returnedString, attributes: [NSAttributedStringKey.paragraphStyle: paragraphStyle]) 47 | self.label.sizeToFit() 48 | self.height = self.label.height + self.bottomMarginForLabel 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /SEDaily-IOS/PodcastLite.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PodcastLite.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 4/27/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct PodcastLite: Codable { 12 | let _id: String 13 | let thread: String? 14 | let title: String 15 | let rendered:String 16 | let featuredImage: String? 17 | 18 | public init(from decoder: Decoder) throws { 19 | let container = try decoder.container(keyedBy: CodingKeys.self) 20 | 21 | let titleHolder = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .title) 22 | rendered = try titleHolder.decode(String.self, forKey: .rendered) 23 | 24 | featuredImage = try container.decode(String.self, forKey: .featuredImage) 25 | _id = try container.decode(String.self, forKey: ._id) 26 | thread = try container.decode(String.self, forKey: .thread) 27 | title = "" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /SEDaily-IOS/ProgressIndicator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProgressIndicator.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Justin Lam on 11/23/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import MBProgressHUD 11 | 12 | class ProgressIndicator { 13 | static func showBlockingProgress() { 14 | if let app = UIApplication.shared.delegate as? AppDelegate, let window = app.window { 15 | MBProgressHUD.showAdded(to: window, animated: true) 16 | } 17 | } 18 | 19 | static func hideBlockingProgress() { 20 | if let app = UIApplication.shared.delegate as? AppDelegate, let window = app.window { 21 | MBProgressHUD.hide(for: window, animated: true) 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SEDaily-IOS/RelatedLink.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RelatedLink.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 1/26/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct RelatedLink: BaseFeedItem { 12 | var score: Int = 0 13 | 14 | var _id: String 15 | var downvoted: Bool? 16 | 17 | var upvoted: Bool? 18 | 19 | let title: String 20 | let url: String 21 | 22 | let postId: String? 23 | let post: PodcastLite? 24 | let image: String? 25 | public init(from decoder: Decoder) throws { 26 | let container = try decoder.container(keyedBy: CodingKeys.self) 27 | 28 | _id = try container.decode(String.self, forKey: ._id) 29 | 30 | if let upvotedResult = try? container.decode(Bool.self, forKey: .upvoted) { 31 | upvoted = upvotedResult 32 | } else { 33 | downvoted = false 34 | } 35 | if let downvotedResult = try? container.decode(Bool.self, forKey: .downvoted) { 36 | downvoted = downvotedResult 37 | } else { 38 | downvoted = false 39 | } 40 | 41 | score = try container.decode(Int.self, forKey: .score) 42 | title = try container.decode(String.self, forKey: .title) 43 | url = try container.decode(String.self, forKey: .url) 44 | 45 | if let value = try? container.decode(PodcastLite.self, forKey: .post) { 46 | post = value 47 | postId = post?._id 48 | } else { 49 | postId = try container.decode(String.self, forKey: .post) 50 | post = nil 51 | } 52 | if let _image = try? container.decode(String.self, forKey: .image) { 53 | image = _image 54 | } else { 55 | image = nil 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /SEDaily-IOS/RelatedLinkWebVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RelatedLinkWebVC.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 5/20/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | 13 | 14 | // 15 | // RelatedLInkWebVC.swift 16 | // SEDaily-IOS 17 | // 18 | // Created by jason on 5/18/18. 19 | // Copyright © 2018 Koala Tea. All rights reserved. 20 | // 21 | 22 | import UIKit 23 | import WebKit 24 | 25 | class RelatedLinkWebVC: UIViewController, WKUIDelegate, WKNavigationDelegate { 26 | var webView: WKWebView! 27 | var url:URL? 28 | @IBOutlet weak var simpleSpinner: UIActivityIndicatorView! 29 | 30 | func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { 31 | simpleSpinner.stopAnimating() 32 | webView.isHidden = false 33 | self.view = webView 34 | } 35 | 36 | @IBAction func openInSafariTapped(_ sender: UIButton) { 37 | if let linkUrl = url { 38 | UIApplication.shared.open(linkUrl, options: [:], completionHandler: nil) 39 | Analytics2.relatedLinkSafariOpen(url: linkUrl) 40 | } else { 41 | print("link null") 42 | } 43 | } 44 | 45 | override func viewWillAppear(_ animated: Bool) { 46 | super.viewDidLoad() 47 | simpleSpinner.startAnimating() 48 | if let url = url { 49 | let webConfiguration = WKWebViewConfiguration() 50 | webView = WKWebView(frame: .zero, configuration: webConfiguration) 51 | webView.uiDelegate = self 52 | 53 | webView.navigationDelegate = self 54 | webView.isHidden = true 55 | 56 | let myRequest = URLRequest(url: url) 57 | webView.load(myRequest) 58 | Analytics2.relatedLinkViewed(url: url) 59 | Tracker.logRelatedLinkViewedFromFeed(url: url) 60 | } 61 | // Do any additional setup after loading the view. 62 | } 63 | 64 | override func didReceiveMemoryWarning() { 65 | super.didReceiveMemoryWarning() 66 | // Dispose of any resources that can be recreated. 67 | } 68 | 69 | /* 70 | // MARK: - Navigation 71 | 72 | // In a storyboard-based application, you will often want to do a little preparation before navigation 73 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 74 | // Get the new view controller using segue.destinationViewController. 75 | // Pass the selected object to the new view controller. 76 | } 77 | */ 78 | 79 | } 80 | -------------------------------------------------------------------------------- /SEDaily-IOS/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Roboto-Bold.ttf -------------------------------------------------------------------------------- /SEDaily-IOS/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Roboto-Light.ttf -------------------------------------------------------------------------------- /SEDaily-IOS/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/SEDaily-IOS/Roboto-Regular.ttf -------------------------------------------------------------------------------- /SEDaily-IOS/SeparatorCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SeparatorCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 6/7/19. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | 10 | import UIKit 11 | import Reusable 12 | 13 | class SeparatorCell: UITableViewCell, Reusable { 14 | private var separator: UIView = UIView() 15 | 16 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 17 | super.init(style: style, reuseIdentifier: reuseIdentifier) 18 | contentView.addSubview(separator) 19 | setupLayout() 20 | } 21 | 22 | required init(coder aDecoder: NSCoder) { 23 | fatalError("init(coder:)") 24 | } 25 | } 26 | 27 | extension SeparatorCell { 28 | private func setupLayout() { 29 | 30 | separator.backgroundColor = Stylesheet.Colors.light 31 | 32 | separator.snp.makeConstraints { (make) -> Void in 33 | make.left.right.bottom.top.equalToSuperview() 34 | make.height.equalTo(5.0) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /SEDaily-IOS/SettingsCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NotificationTableViewCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Keith Holliday on 4/2/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Reusable 11 | 12 | class SettingsCell: UITableViewCell, Reusable { 13 | public var cellLabel: UILabel! 14 | var separator: UIView! 15 | 16 | 17 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 18 | super.init(style: style, reuseIdentifier: reuseIdentifier) 19 | 20 | cellLabel = UILabel() 21 | cellLabel.baselineAdjustment = .alignCenters 22 | cellLabel.numberOfLines = 0 23 | cellLabel.font = UIFont(name: "OpenSans", size: UIView.getValueScaledByScreenWidthFor(baseValue: 15)) 24 | cellLabel.textColor = Stylesheet.Colors.dark 25 | 26 | 27 | self.contentView.addSubview(cellLabel) 28 | setupSeparator() 29 | 30 | cellLabel.snp.makeConstraints { (make) in 31 | make.left.equalToSuperview().offset(UIView.getValueScaledByScreenWidthFor(baseValue: 15.0)) 32 | make.centerY.equalToSuperview() 33 | make.top.equalToSuperview().offset(UIView.getValueScaledByScreenWidthFor(baseValue: 15.0)) 34 | make.bottom.equalToSuperview().inset(UIView.getValueScaledByScreenWidthFor(baseValue: 15.0)) 35 | } 36 | 37 | separator.snp.makeConstraints { (make) -> Void in 38 | make.left.right.bottom.equalToSuperview() 39 | make.height.equalTo(2.0) 40 | } 41 | } 42 | 43 | required init(coder aDecoder: NSCoder) { 44 | fatalError("init(coder:)") 45 | } 46 | 47 | func setupSeparator() { 48 | separator = UIView() 49 | contentView.addSubview(separator) 50 | separator.backgroundColor = Stylesheet.Colors.light 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SEDaily-IOS/SkeletonCollectionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SkeletonCollectionView.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Craig Holliday on 10/10/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private let reuseIdentifier = "Cell" 12 | 13 | class SkeletonCollectionView: UIView, UICollectionViewDataSource { 14 | var collectionView: UICollectionView! 15 | 16 | override init(frame: CGRect) { 17 | super.init(frame: frame) 18 | self.collectionView = UICollectionView(frame: frame, collectionViewLayout: UICollectionViewLayout()) 19 | self.addSubview(self.collectionView) 20 | self.collectionView.dataSource = self 21 | 22 | self.collectionView!.register(ItemCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier) 23 | 24 | let layout = KoalaTeaFlowLayout(cellWidth: Helpers.getScreenWidth(), 25 | cellHeight: UIView.getValueScaledByScreenWidthFor(baseValue: 185.0), 26 | topBottomMargin: UIView.getValueScaledByScreenHeightFor(baseValue: 10), 27 | leftRightMargin: UIView.getValueScaledByScreenWidthFor(baseValue: 0), 28 | cellSpacing: UIView.getValueScaledByScreenWidthFor(baseValue: 10)) 29 | self.collectionView?.collectionViewLayout = layout 30 | self.collectionView?.backgroundColor = Stylesheet.Colors.light 31 | } 32 | 33 | required init?(coder aDecoder: NSCoder) { 34 | fatalError("init(coder:) has not been implemented") 35 | } 36 | 37 | // MARK: UICollectionViewDataSource 38 | 39 | func numberOfSections(in collectionView: UICollectionView) -> Int { 40 | // #warning Incomplete implementation, return the number of sections 41 | return 1 42 | } 43 | 44 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 45 | // #warning Incomplete implementation, return the number of items 46 | return 6 47 | } 48 | 49 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 50 | guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as? ItemCollectionViewCell else { 51 | return UICollectionViewCell() 52 | } 53 | 54 | // Configure the cell 55 | cell.setupSkeletonCell() 56 | 57 | return cell 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /SEDaily-IOS/StateController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StateController.swift 3 | // ExpandableOverlay 4 | // 5 | // Created by Dawid Cedrych on 6/18/19. 6 | // Copyright © 2019 Altalogy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class StateController { 12 | 13 | var isFirstLoad = true 14 | 15 | var isOverlayShowing = false 16 | 17 | private var currentlyPlayingId: String = "" 18 | 19 | func setCurrentlyPlaying(id: String) { 20 | currentlyPlayingId = id 21 | } 22 | 23 | func getCurrentlyPlayingId()-> String { 24 | return currentlyPlayingId 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SEDaily-IOS/SubscriptionModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SubscriptionModel.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Craig Holliday on 1/15/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct StripeModel: Codable { 12 | let _id: String 13 | let planFrequency: String 14 | let dateCreated: String 15 | } 16 | 17 | public struct SubscriptionModel: Codable { 18 | let _id: String 19 | let createdAt: String 20 | let username: String 21 | let subscription: StripeModel 22 | } 23 | 24 | extension SubscriptionModel { 25 | func getCreatedAtDate() -> Date? { 26 | let date = Date(iso8601String: self.subscription.dateCreated) 27 | return date 28 | } 29 | 30 | func getPlanFrequency() -> String { 31 | return self.subscription.planFrequency.capitalized 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SEDaily-IOS/SummaryCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SummaryCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 6/5/19. 6 | // Copyright © 2019 Altalogy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Reusable 11 | import UIKit 12 | 13 | class SummaryCell: UITableViewCell, Reusable { 14 | 15 | private var label: UILabel = UILabel() 16 | 17 | var viewModel: ViewModel = ViewModel() { 18 | didSet { 19 | label.text = viewModel.text 20 | setupLayout(style: viewModel.style) 21 | 22 | } 23 | } 24 | 25 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 26 | super.init(style: style, reuseIdentifier: reuseIdentifier) 27 | contentView.addSubview(label) 28 | self.isUserInteractionEnabled = true 29 | self.selectionStyle = .none 30 | } 31 | 32 | required init 33 | (coder aDecoder: NSCoder) { 34 | fatalError("init(coder:)") 35 | } 36 | } 37 | 38 | 39 | extension SummaryCell { 40 | private func setupLayout(style: ViewModel.Style) { 41 | 42 | label.snp.updateConstraints { (make) in 43 | make.left.right.equalToSuperview().offset(style.marginX) 44 | make.right.equalToSuperview().inset(style.marginX) 45 | make.top.equalToSuperview().offset(style.marginY) 46 | make.bottom.equalToSuperview().inset(style.marginY) 47 | } 48 | label.textAlignment = style.alignment 49 | label.font = style.font 50 | label.textColor = style.color 51 | label.numberOfLines = 0 52 | } 53 | } 54 | 55 | // MARK: - ViewModel 56 | extension SummaryCell { 57 | struct ViewModel { 58 | struct Style { 59 | var marginX: CGFloat = 0 60 | var marginY: CGFloat = 0 61 | var font: UIFont = UIFont(name: "Roboto", size: 10.0)! //arbitrary 62 | var color = UIColor.clear 63 | var alignment = NSTextAlignment.left 64 | } 65 | var text = "" 66 | var style = Style() 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /SEDaily-IOS/TagsCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TagsCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 5/14/19. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Reusable 11 | import Tags 12 | 13 | class TagsCell: UITableViewCell, Reusable, UIScrollViewDelegate { 14 | 15 | let tagsView = TagsView() 16 | let scrollView = UIScrollView() 17 | 18 | var topics:[String] = [] { willSet { 19 | guard newValue != self.topics else { return } 20 | } 21 | didSet { 22 | tagsView.set(contentsOf: topics) 23 | tagsView.lastTag = "+" 24 | print(tagsView.frame.width) 25 | } 26 | } 27 | 28 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 29 | super.init(style: style, reuseIdentifier: reuseIdentifier) 30 | setupLayout() 31 | scrollView.delegate = self 32 | 33 | } 34 | required init 35 | (coder aDecoder: NSCoder) { 36 | fatalError("init(coder:)") 37 | } 38 | 39 | override func layoutSubviews() { 40 | print(self.contentView.height) 41 | } 42 | 43 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 44 | if scrollView.contentOffset.y > 0 || scrollView.contentOffset.y < 0 { 45 | scrollView.contentOffset.y = 0 46 | } 47 | } 48 | 49 | } 50 | 51 | extension TagsCell { 52 | private func setupLayout() { 53 | scrollView.translatesAutoresizingMaskIntoConstraints = false 54 | tagsView.translatesAutoresizingMaskIntoConstraints = false 55 | scrollView.showsHorizontalScrollIndicator = true 56 | scrollView.backgroundColor = .white 57 | scrollView.contentSize = tagsView.frame.size 58 | let label: UILabel = UILabel() 59 | label.text = "" 60 | contentView.addSubview(scrollView) 61 | scrollView.addSubview(tagsView) 62 | scrollView.addSubview(label) 63 | // layer radius 64 | tagsView.tagLayerRadius = 6 65 | // layer width 66 | tagsView.tagLayerWidth = 1 67 | // layer color 68 | tagsView.tagLayerColor = Stylesheet.Colors.base 69 | // text color 70 | tagsView.tagTitleColor = Stylesheet.Colors.base 71 | // background color 72 | tagsView.tagBackgroundColor = .white 73 | // font 74 | tagsView.tagFont = .systemFont(ofSize: 15) 75 | // text longer ... 76 | tagsView.lineBreakMode = .byTruncatingMiddle 77 | 78 | scrollView.snp.makeConstraints { (make) in 79 | make.top.left.right.bottom.equalToSuperview() 80 | } 81 | 82 | tagsView.snp.makeConstraints { (make) in 83 | make.top.left.right.bottom.equalToSuperview() 84 | //make.height.equalTo(30.0) 85 | make.width.equalTo(5000.0) // this is a workaround for scrollView 86 | } 87 | 88 | if #available(iOS 11, *) { 89 | scrollView.contentInsetAdjustmentBehavior = .never 90 | } 91 | scrollView.contentSize.height = 1.0 92 | //scrollView.contentSize = tagsView.frame.size 93 | 94 | 95 | } 96 | } 97 | 98 | 99 | -------------------------------------------------------------------------------- /SEDaily-IOS/ThreadHeaderView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThreadHeaderView.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by jason on 4/28/18. 6 | // Copyright © 2018 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Down 11 | 12 | class ThreadHeaderView: UIView { 13 | 14 | @IBOutlet weak var titleLabel: UILabel! 15 | @IBOutlet weak var contentLabel: UILabel! 16 | @IBOutlet weak var authorLabel: UILabel! 17 | @IBOutlet weak var dateLabel: UILabel! 18 | @IBOutlet weak var commentCountLabel: UILabel! 19 | 20 | var thread: ForumThread? { 21 | didSet { 22 | titleLabel.text = thread?.title 23 | if let threadContent = thread?.content { 24 | let content = Down(markdownString: threadContent) 25 | contentLabel.attributedText = try? content.toAttributedString() 26 | } 27 | commentCountLabel.text = thread?.getCommentsSummary() 28 | if let author = thread?.author { 29 | authorLabel.text = (author.name != nil) ? author.name : author.username 30 | } 31 | dateLabel.text = thread?.getDatedCreatedPretty() 32 | if let thread = thread { 33 | Analytics2.forumThreadViewed(forumThread: thread) 34 | Tracker.logForumThreadViewed(forumThread: thread) 35 | } 36 | } 37 | } 38 | 39 | /* 40 | // Only override draw() if you perform custom drawing. 41 | // An empty implementation adversely affects performance during animation. 42 | override func draw(_ rect: CGRect) { 43 | // Drawing code 44 | } 45 | */ 46 | 47 | override func layoutSubviews() { 48 | super.layoutSubviews() 49 | titleLabel.preferredMaxLayoutWidth = titleLabel.bounds.width 50 | 51 | contentLabel.preferredMaxLayoutWidth = titleLabel.bounds.width 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /SEDaily-IOS/Topic.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Topic.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 5/14/19. 6 | // Copyright © 2019 Altalogy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct Topic: Codable { 12 | let _id: String 13 | let name: String 14 | let slug: String 15 | let status: String 16 | let postCount: Int 17 | } 18 | 19 | extension Topic: Equatable { 20 | public static func == (lhs: Topic, rhs: Topic) -> Bool { 21 | return lhs._id == rhs._id && 22 | lhs.name == rhs.name && 23 | lhs.slug == rhs.slug && 24 | lhs.status == rhs.status && 25 | lhs.postCount == rhs.postCount 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SEDaily-IOS/UIButtonExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIButtonExtension.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Craig Holliday on 6/27/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIButton { 12 | func setBackgroundColor(color: UIColor, forState: UIControlState) { 13 | UIGraphicsBeginImageContext(CGSize(width: 1, height: 1)) 14 | UIGraphicsGetCurrentContext()!.setFillColor(color.cgColor) 15 | UIGraphicsGetCurrentContext()!.fill(CGRect(x: 0, y: 0, width: 1, height: 1)) 16 | let colorImage = UIGraphicsGetImageFromCurrentImageContext() 17 | UIGraphicsEndImageContext() 18 | self.setBackgroundImage(colorImage, for: forState) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SEDaily-IOS/UIColor+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+Extensions.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 5/30/19. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension UIColor { 13 | func brightened(by factor: CGFloat) -> UIColor { 14 | var h: CGFloat = 0, s: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0 15 | getHue(&h, saturation: &s, brightness: &b, alpha: &a) 16 | return UIColor(hue: h, saturation: s, brightness: b * factor, alpha: a) 17 | } 18 | 19 | func getGradientColors(brightenedBy: CGFloat) -> [Any] { 20 | return [self.cgColor, 21 | self.brightened(by: brightenedBy).cgColor, 22 | self.cgColor] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SEDaily-IOS/URLSchemaHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // URLSchemaHelper.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 6/14/19. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class URLSchemaHelper { 12 | class func addSchema(url: String)->String { 13 | var urlString: String = url 14 | let urlPrefix = urlString.prefix(4) 15 | if urlPrefix != "http" { 16 | // Defaulting to http: 17 | if urlPrefix.prefix(3) == "://" { 18 | urlString = "http\(url)" 19 | } else { 20 | urlString = "http://\(url)" 21 | } 22 | } 23 | return urlString 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SEDaily-IOS/UpvoteService.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UpvoteService.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 4/23/19. 6 | // Copyright © 2019 Altalogy. All rights reserved. 7 | // 8 | 9 | protocol UpvoteServiceUIDelegate: class { 10 | func upvoteUIDidChange(isUpvoted: Bool, score: Int) 11 | func upvoteUIImmediateUpdate() 12 | } 13 | 14 | 15 | import Foundation 16 | 17 | class UpvoteService { 18 | 19 | private let networkService = API() 20 | 21 | var podcastViewModel: PodcastViewModel { 22 | didSet { 23 | updateViewModel() 24 | updateUI(isUpvoted: self.podcastViewModel.isUpvoted, score: self.podcastViewModel.score) 25 | } 26 | } 27 | 28 | weak var UIDelegate: UpvoteServiceUIDelegate? 29 | 30 | init(podcastViewModel: PodcastViewModel) { 31 | self.podcastViewModel = podcastViewModel 32 | } 33 | 34 | func upvote() { 35 | guard UserManager.sharedInstance.isCurrentUserLoggedIn() == true else { 36 | Helpers.alertWithMessage(title: Helpers.Alerts.error, message: Helpers.Messages.youMustLogin, completionHandler: nil) 37 | return 38 | } 39 | self.UIDelegate?.upvoteUIImmediateUpdate() 40 | 41 | let podcastId = self.podcastViewModel._id 42 | networkService.upvotePodcast(podcastId: podcastId, completion: { [weak self] (success, active) in 43 | guard success != nil else { 44 | self?.UIDelegate?.upvoteUIImmediateUpdate() 45 | return 46 | } 47 | if success == true { 48 | guard let active = active else { return } 49 | self?.addScore(active: active) 50 | self?.setStatus(active: active) 51 | } else { self?.UIDelegate?.upvoteUIImmediateUpdate() } 52 | }) 53 | } 54 | 55 | func addScore(active: Bool) { 56 | guard active != false else { 57 | self.setScoreTo(self.podcastViewModel.score - 1) 58 | return 59 | } 60 | self.setScoreTo(self.podcastViewModel.score + 1) 61 | } 62 | 63 | private func updateViewModel() { 64 | let userInfo = ["viewModel": podcastViewModel] 65 | NotificationCenter.default.post(name: .viewModelUpdated, object: nil, userInfo: userInfo) 66 | } 67 | private func updateUI(isUpvoted: Bool, score: Int) { 68 | self.UIDelegate?.upvoteUIDidChange(isUpvoted: isUpvoted, score: self.podcastViewModel.score) 69 | } 70 | 71 | func setScoreTo(_ score: Int) { 72 | guard self.podcastViewModel.score != score else { return } 73 | self.podcastViewModel.score = score 74 | } 75 | private func setStatus(active: Bool) { 76 | self.podcastViewModel.isUpvoted = active 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /SEDaily-IOS/User+ProfileViewController.Section.swift: -------------------------------------------------------------------------------- 1 | // 2 | // User+ProfileViewController.Section.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 6/5/19. 6 | // Copyright © 2019 Altalogy. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension User { 13 | subscript(row: ProfileViewController.Section.SummaryRow) -> Any? { 14 | switch row { 15 | case .bio: return bio 16 | case .name: return name ?? username 17 | case .username: return username 18 | case .avatar: return URL(string: avatarUrl ?? "https://sd-profile-pictures.s3.amazonaws.com/5d03934823a39c002ae7dd70") 19 | case .link: return website 20 | case .signInPlaceholder: return nil 21 | } 22 | } 23 | } 24 | 25 | extension UITableView { 26 | func dequeueReusableCell(for indexPath: IndexPath) -> Cell? { 27 | return dequeueReusableCell(withIdentifier: String(describing: Cell.self), for: indexPath) as? Cell 28 | } 29 | 30 | func dequeueReusableCell(with type: Cell.Type, for indexPath: IndexPath) -> Cell? { 31 | return dequeueReusableCell(withIdentifier: String(describing: type), for: indexPath) as? Cell 32 | } 33 | } 34 | 35 | 36 | -------------------------------------------------------------------------------- /SEDaily-IOS/ViewPlayground.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | //: A UIKit based Playground for presenting user interface 2 | 3 | import UIKit 4 | import PlaygroundSupport 5 | import ViewPlayground_Sources 6 | 7 | class PodcastCell: UICollectionViewCell { 8 | var imageView: UIImageView! 9 | var titleLabel: UILabel! 10 | var timeDayLabel: UILabel! 11 | 12 | override init(frame: CGRect) { 13 | super.init(frame: frame) 14 | self.backgroundColor = .white 15 | let newContentView = UIView(width: 158, height: 250) 16 | self.contentView.frame = newContentView.frame 17 | 18 | imageView = UIImageView(leftInset: 0, topInset: 4, width: 158) 19 | self.contentView.addSubview(imageView) 20 | self.addSubview(imageView) 21 | 22 | titleLabel = UILabel(origin: imageView.bottomLeftPoint(), topInset: 15, width: 158, height: 50) 23 | self.addSubview(titleLabel) 24 | 25 | timeDayLabel = UILabel(origin: titleLabel.bottomLeftPoint(), topInset: 8, width: 158, height: 10) 26 | self.addSubview(timeDayLabel) 27 | } 28 | 29 | required init(coder aDecoder: NSCoder) { 30 | fatalError("init(coder:)") 31 | } 32 | 33 | func setupCell(image: UIImage, title: String, timeLength: Int, date: Date) { 34 | imageView.image = image 35 | titleLabel.text = title 36 | timeDayLabel.text 37 | } 38 | } 39 | 40 | extension PodcastCell { 41 | func setupSkeletonCell() { 42 | 43 | } 44 | } 45 | 46 | // Present the view controller in the Live View window 47 | let frame = CGRect(x: 0, y: 0, width: UIView.getValueScaledByScreenWidthFor(baseValue: 158), height: UIView.getValueScaledByScreenHeightFor(baseValue: 400)) 48 | let cell = PodcastCell(frame: frame) 49 | cell.titleLabel.text = "An American Success Story" 50 | PlaygroundPage.current.liveView = cell 51 | -------------------------------------------------------------------------------- /SEDaily-IOS/ViewPlayground.playground/Sources/KTResponsiveUI/KTResponsiveUI/Classes/Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions.swift 3 | // KTResponsiveUI_Example 4 | // 5 | // Created by Craig Holliday on 8/28/17. 6 | // Copyright © 2017 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | let iphone7Height: CGFloat = 667.0 12 | let iphone7Width: CGFloat = 375.0 13 | 14 | public extension UIView { 15 | public func topRightPoint() -> CGPoint { 16 | return CGPoint(x: self.frame.maxX, y: self.frame.minY) 17 | } 18 | 19 | public func topMidPoint() -> CGPoint { 20 | return CGPoint(x: self.frame.midX, y: self.frame.minY) 21 | } 22 | 23 | public func topLeftPoint() -> CGPoint { 24 | return CGPoint(x: self.frame.minX, y: self.frame.minY) 25 | } 26 | 27 | public func bottomRightPoint() -> CGPoint { 28 | return CGPoint(x: self.frame.maxX, y: self.frame.maxY) 29 | } 30 | 31 | public func bottomMidPoint() -> CGPoint { 32 | return CGPoint(x: self.frame.midX, y: self.frame.maxY) 33 | } 34 | 35 | public func bottomLeftPoint() -> CGPoint { 36 | return CGPoint(x: self.frame.minX, y: self.frame.maxY) 37 | } 38 | 39 | public func leftMidPoint() -> CGPoint { 40 | return CGPoint(x: self.frame.minX, y: self.frame.midY) 41 | } 42 | 43 | public func rightMidPoint() -> CGPoint { 44 | return CGPoint(x: self.frame.maxX, y: self.frame.midY) 45 | } 46 | 47 | public class func getValueScaledByScreenHeightFor(baseValue: CGFloat) -> CGFloat { 48 | let screenHeight = UIScreen.main.bounds.height 49 | let divisor: CGFloat = iphone7Height / baseValue 50 | let calculatedHeight = screenHeight / divisor 51 | return calculatedHeight 52 | } 53 | 54 | public class func getValueScaledByScreenWidthFor(baseValue: CGFloat) -> CGFloat { 55 | let screenWidth = UIScreen.main.bounds.width 56 | let divisor: CGFloat = iphone7Width / baseValue 57 | let calculatedWidth = screenWidth / divisor 58 | return calculatedWidth 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /SEDaily-IOS/ViewPlayground.playground/Sources/KTResponsiveUI/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 themisterholliday 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /SEDaily-IOS/ViewPlayground.playground/Sources/KTResponsiveUI/README.md: -------------------------------------------------------------------------------- 1 | # KTResponsiveUI (WIP) 2 | 3 | [![CI Status](http://img.shields.io/travis/themisterholliday/KTResponsiveUI.svg?style=flat)](https://travis-ci.org/themisterholliday/KTResponsiveUI) 4 | [![Version](https://img.shields.io/cocoapods/v/KTResponsiveUI.svg?style=flat)](http://cocoapods.org/pods/KTResponsiveUI) 5 | [![License](https://img.shields.io/cocoapods/l/KTResponsiveUI.svg?style=flat)](http://cocoapods.org/pods/KTResponsiveUI) 6 | [![Platform](https://img.shields.io/cocoapods/p/KTResponsiveUI.svg?style=flat)](http://cocoapods.org/pods/KTResponsiveUI) 7 | 8 | ## Example 9 | 10 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 11 | 12 | ## Requirements 13 | 14 | ## Installation 15 | 16 | KTResponsiveUI is available through [CocoaPods](http://cocoapods.org). To install 17 | it, simply add the following line to your Podfile: 18 | 19 | ```ruby 20 | pod 'KTResponsiveUI' 21 | ``` 22 | 23 | ## Author 24 | 25 | themisterholliday, themisterholliday@gmail.com 26 | 27 | ## License 28 | 29 | KTResponsiveUI is available under the MIT license. See the LICENSE file for more info. 30 | -------------------------------------------------------------------------------- /SEDaily-IOS/ViewPlayground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /SEDaily-IOS/WebViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebViewCell.swift 3 | // SEDaily-IOS 4 | // 5 | // Created by Dawid Cedrych on 5/2/19. 6 | // Copyright © 2019 Koala Tea. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Reusable 11 | import WebKit 12 | import SnapKit 13 | 14 | 15 | class WebViewCell: UITableViewCell, Reusable { 16 | 17 | var webView: WKWebView! 18 | 19 | var webViewHeight: CGFloat = 0.0 { 20 | didSet { 21 | snp.removeConstraints() 22 | webView.snp.remakeConstraints { (make) in 23 | make.left.top.right.bottom.equalToSuperview() 24 | make.height.equalTo(webViewHeight).priority(999) 25 | make.width.equalToSuperview() 26 | } 27 | } 28 | } 29 | 30 | var delegate: WebViewCellDelegate? 31 | 32 | 33 | override func awakeFromNib() { 34 | super.awakeFromNib() 35 | // Initialization code 36 | } 37 | 38 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 39 | super.init(style: style, reuseIdentifier: reuseIdentifier) 40 | webView = WKWebView() 41 | self.contentView.addSubview(webView) 42 | webView.scrollView.snp.makeConstraints { make in 43 | make.left.equalToSuperview().offset(15.0) 44 | make.right.equalToSuperview().offset(-15.0) 45 | } 46 | } 47 | 48 | required init 49 | (coder aDecoder: NSCoder) { 50 | fatalError("init(coder:)") 51 | } 52 | 53 | override func setSelected(_ selected: Bool, animated: Bool) { 54 | super.setSelected(selected, animated: animated) 55 | } 56 | } 57 | 58 | 59 | 60 | extension WebViewCell: WKNavigationDelegate { 61 | func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { 62 | webView.evaluateJavaScript("document.readyState", completionHandler: { (complete, error) in 63 | if complete != nil { 64 | webView.evaluateJavaScript("document.body.scrollHeight", completionHandler: { (height, error) in 65 | guard let h:CGFloat = height as? CGFloat else { return } 66 | self.delegate?.updateWebViewHeight(didCalculateHeight: h) 67 | }) 68 | } 69 | }) 70 | } 71 | func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { 72 | if navigationAction.navigationType == .linkActivated { 73 | if let url = navigationAction.request.url, 74 | UIApplication.shared.canOpenURL(url) { 75 | UIApplication.shared.open(url) 76 | decisionHandler(.cancel) 77 | } else { 78 | decisionHandler(.allow) 79 | } 80 | } else { 81 | decisionHandler(.allow) 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /SEDaily-IOS/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | SEDaily-IOS 4 | 5 | Created by Justin Lam on 10/6/17. 6 | Copyright © 2017 Koala Tea. All rights reserved. 7 | */ 8 | -------------------------------------------------------------------------------- /SEDaily-IOS/fr.lproj/LaunchScreen.strings: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /SEDaily-IOS/fr.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | SEDaily-IOS 4 | 5 | Created by Justin Lam on 10/6/17. 6 | Copyright © 2017 Koala Tea. All rights reserved. 7 | */ 8 | 9 | /* */ 10 | "TabBarTitleLatest" = "Latest*"; 11 | "TabBarJustForYou" = "Just For You*"; 12 | "TabTitleAll" = "All*"; 13 | "TabTitleBusinessAndPhilosophy" = "Business and Philosophy*"; 14 | "TabTitleBlockchain" = "Blockchain*"; 15 | "TabTitleCloudEngineering" = "Cloud Engineering*"; 16 | "TabTitleData" = "Data*"; 17 | "TabTitleJavaScript" = "JavaScript*"; 18 | "TabTitleMachineLearning" = "Machine Learning*"; 19 | "TabTitleOpenSource" = "Open Source*"; 20 | "TabTitleSecurity" = "Security*"; 21 | "TabTitleHackers" = "Hackers*"; 22 | "TabTitleGreatestHits" = "Greatest Hits*"; 23 | "LoginTitle" = "Login*"; 24 | "LogoutTitle" = "Logout*"; 25 | "EmailAddressPlaceholder" = "Email*"; 26 | "PasswordPlaceholder" = "Password*"; 27 | "ConfirmPasswordPlaceholder" = "Confirm Password*"; 28 | "FirstNamePlaceholder" = "First Name*"; 29 | "LastNamePlaceholder" = "Last Name*"; 30 | "LoginButtonTitle" = "Login*"; 31 | "CancelButtonTitle" = "Cancel*"; 32 | "SignUpButtonTitle" = "Sign Up*"; 33 | "AlertMessageEmailEmpty" = "Email Field Empty*"; 34 | "AlertMessagePasswordEmpty" = "Password Field Empty*"; 35 | "AlertMessagePasswordConfirmEmpty" = "Confirm Password Field Empty*"; 36 | "AlertMessageEmailWrongFormat" = "Invalid Email Format*"; 37 | "AlertMessagePasswordNotLongEnough" = "Password must be longer than 6 characters*"; 38 | "AlertMessagePasswordsDonotMatch" = "Password do not match*"; 39 | "AlertMessageFirstNameEmpty" = "First Name Field Empty*"; 40 | "AlertMessageFirstNameNotLongEnough" = "First Name must be longer than 1 characters*"; 41 | "AlertMessageLastNameEmpty" = "Last Name Field Empty*"; 42 | "AlertMessageLastNameNotLongEnough" = "Last Name must be longer than 1 characters*"; 43 | "AlertMessagePleaseLogin" = "Please Login*"; 44 | "AlertMessageIssueWithUserToken" = "Issue with User Token*"; 45 | "AlertMessageYouMustLogin" = "You must login to use this feature.*"; 46 | "AlertMessageLogoutSuccess" = "Successfully Logged Out*"; 47 | "GenericSuccess" = "Success*"; 48 | "GenericError" = "Error*"; 49 | "GenericOkay" = "Okay*"; 50 | "GenericOK" = "OK*"; 51 | "Play" = "Play*"; 52 | "NoBookmarks" = "No Bookmarks*"; 53 | "LoginSeeBookmarks" = "Login to see your bookmarks*"; 54 | "TapToRefresh" = "Tap to refresh*"; 55 | -------------------------------------------------------------------------------- /SEDaily-IOS/fr.lproj/Main.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "UITabBarItem"; title = "Item 1"; ObjectID = "1oc-bk-EZe"; */ 3 | "1oc-bk-EZe.title" = "Item 1"; 4 | 5 | /* Class = "UITabBarItem"; title = "Item 2"; ObjectID = "teR-pK-dgQ"; */ 6 | "teR-pK-dgQ.title" = "Item 2"; 7 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/HelpersTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HelpersTests.swift 3 | // SEDaily-IOSTests 4 | // 5 | // Created by Berk Mollamustafaoglu on 25/11/2017. 6 | // 7 | // 8 | 9 | import XCTest 10 | import Quick 11 | import Nimble 12 | @testable import SEDaily_IOS 13 | 14 | class HelpersTests: QuickSpec { 15 | 16 | override func spec() { 17 | describe("isValidEmailAddress") { 18 | it("accepts regular email address format") { 19 | expect(Helpers.isValidEmailAddress(emailAddressString: "test@example.com")).to(beTrue()) 20 | } 21 | 22 | it("accepts dots and underscores") { 23 | expect(Helpers.isValidEmailAddress(emailAddressString: "test.exampl_e@example.com")).to(beTrue()) 24 | } 25 | 26 | it("accepts letters and numbers") { 27 | expect(Helpers.isValidEmailAddress(emailAddressString: "test.exampl_e981@example.com")).to(beTrue()) 28 | } 29 | 30 | it("accepts emails with multiple dots") { 31 | expect(Helpers.isValidEmailAddress(emailAddressString: "bla@university.ac.uk")).to(beTrue()) 32 | } 33 | 34 | it("doesn't accept empty string before the @ sign") { 35 | expect(Helpers.isValidEmailAddress(emailAddressString: "@example.com")).to(beFalse()) 36 | } 37 | 38 | it("doesn't accept characters other than dots and underscores in the main part of the address") { 39 | expect(Helpers.isValidEmailAddress(emailAddressString: "test.exam&pl_e981@example.com")).to(beFalse()) 40 | } 41 | 42 | it("doesn't accept single characters after the final dot") { 43 | expect(Helpers.isValidEmailAddress(emailAddressString: "test@example.c")).to(beFalse()) 44 | } 45 | 46 | it("doesn't accept numbers after the final dot") { 47 | expect(Helpers.isValidEmailAddress(emailAddressString: "test@example.coa3f")).to(beFalse()) 48 | } 49 | 50 | it("doesn't accept symbols after the final dot") { 51 | expect(Helpers.isValidEmailAddress(emailAddressString: "test@example.co/f")).to(beFalse()) 52 | } 53 | 54 | } 55 | 56 | describe("getStringFrom tests") { 57 | it("displays the value if the value is above 10") { 58 | expect(Helpers.getStringFrom(seconds: 15)).to(equal("15")) 59 | } 60 | 61 | it("displays the value with a leading zero if it's below 10") { 62 | expect(Helpers.getStringFrom(seconds: 9)).to(equal("09")) 63 | } 64 | } 65 | 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/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 | CFBundleVersion 20 | 10 21 | 22 | 23 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/Mocks/Responses/login/login_nonexistinguser.json: -------------------------------------------------------------------------------- 1 | {"message":"User not found."} 2 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/Mocks/Responses/login/login_success.json: -------------------------------------------------------------------------------- 1 | {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1YTVhOTgyZjdlNGY0MDAwMmEzMDEyZGEiLCJlbWFpbCI6ImJlcmt0ZXN0MTFAdGVzdC5jb20iLCJ1c2VybmFtZSI6ImJtIiwicGFzc3dvcmQiOiIkMmEkMDgkMUpRbnY5OGx2S2k4L0tiT29GVmk5dXM3YU5NME9WWTBHcHYwOFplM2E4YS4yWDlHd2pJdUsiLCJfX3YiOjAsImNyZWF0ZWRBdCI6IjIwMTgtMDEtMTNUMjM6Mzc6MTkuNTc2WiIsInZlcmlmaWVkIjpmYWxzZSwiaWF0IjoxNTE2MTMzNjEzLCJleHAiOjE2NjAxMzM2MTN9.5omwn1EzDPqyzfyMLcVbGdpaSlNAKvzwfQ_4HeEBdws"} 2 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/Mocks/Responses/login/login_wrongpass.json: -------------------------------------------------------------------------------- 1 | {"message":"Password is incorrect."} 2 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/Mocks/Responses/posts/upvote_failure.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Not Found", 3 | "stack": {} 4 | } 5 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/Mocks/Responses/posts/upvote_success.json: -------------------------------------------------------------------------------- 1 | { 2 | "_id": "5a63b51866503d002a70f809", 3 | "direction": "upvote", 4 | "userId": "5a5a982f7e4f40002a3012da", 5 | "postId": "59df362f4a8a50462d2b475e", 6 | "entityId": "59df362f4a8a50462d2b475e", 7 | "__v": 0, 8 | "active": true 9 | } 10 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/Mocks/Responses/register/register_emptyusernamepass.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "\"username\" is not allowed to be empty and \"password\" is not allowed to be empty", 3 | "stack": {} 4 | } 5 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/Mocks/Responses/register/register_success.json: -------------------------------------------------------------------------------- 1 | { 2 | "user": { 3 | "__v": 0, 4 | "username": "testuser@test.com", 5 | "password": "$2a$08$PmyX0n5VMY8zVte7.dDGMOdSIP1oU7FfBWN9uCukjp1.V4ryFqtmW", 6 | "_id": "5a60ff9de29fa3002a639e5a", 7 | "createdAt": "2018-01-18T20:12:13.358Z", 8 | "verified": false 9 | }, 10 | "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfX3YiOjAsInVzZXJuYW1lIjoiYmVya3Rlc3QxMTExMUB0ZXN0LmNvbSIsInBhc3N3b3JkIjoiJDJhJDA4JFBteVgwbjVWTVk4elZ0ZTcuZERHTU9kU0lQMW9VN0ZmQldOOXVDdWtqcDEuVjRyeUZxdG1XIiwiX2lkIjoiNWE2MGZmOWRlMjlmYTMwMDJhNjM5ZTVhIiwiY3JlYXRlZEF0IjoiMjAxOC0wMS0xOFQyMDoxMjoxMy4zNThaIiwidmVyaWZpZWQiOmZhbHNlLCJpYXQiOjE1MTYzMDYzMzMsImV4cCI6MTY2MDMwNjMzM30.uk4ixawSQ11vcS2Cvw3MoxlTvwNlCBnu8MUzE9QgqQM" 11 | } 12 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/Mocks/Responses/register/register_userexists.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "User already exists.", 3 | "stack": {} 4 | } 5 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/Mocks/UserDefaultsMock.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserDefaultsMock.swift 3 | // SEDaily-IOSTests 4 | // 5 | // Created by Berk Mollamustafaoglu on 26/11/2017. 6 | // 7 | // 8 | 9 | import Foundation 10 | @testable import SEDaily_IOS 11 | 12 | class UserDefaultsMock: UserDefaultsProtocol { 13 | 14 | var dict: [String: Any] 15 | 16 | init(dict: [String: Any]) { 17 | self.dict = dict 18 | } 19 | 20 | func set(_ value: Any?, forKey defaultName: String) { 21 | if let validValue = value { 22 | dict[defaultName] = validValue 23 | } 24 | } 25 | 26 | func data(forKey defaultName: String) -> Data? { 27 | let dataObj = dict[defaultName] as? Data 28 | return dataObj 29 | } 30 | 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /SEDaily-IOSTests/SEDailyIOSTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SEDaily_IOSTests.swift 3 | // SEDaily-IOSTests 4 | // 5 | // Created by Craig Holliday on 6/25/17. 6 | // Copyright © 2017 Koala Tea. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SEDaily_IOS 11 | 12 | class SEDailyIOSTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /fastlane/Appfile: -------------------------------------------------------------------------------- 1 | app_identifier "koala-tea.SEDaily" # The bundle identifier of your app 2 | apple_id "hollidaycraig@yahoo.com" # Your Apple email address 3 | 4 | team_id "54L2FT34WS" # Developer Portal Team ID 5 | 6 | itc_team_id "117695750" 7 | # you can even provide different app identifiers, Apple IDs and team names per lane: 8 | # More information: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Appfile.md 9 | -------------------------------------------------------------------------------- /fastlane/Deliverfile: -------------------------------------------------------------------------------- 1 | ###################### More Options ###################### 2 | # If you want to have even more control, check out the documentation 3 | # https://github.com/fastlane/fastlane/blob/master/deliver/Deliverfile.md 4 | 5 | 6 | ###################### Automatically generated ###################### 7 | # Feel free to remove the following line if you use fastlane (which you should) 8 | 9 | app_identifier "koala-tea.SEDaily" # The bundle identifier of your app 10 | username "hollidaycraig@yahoo.com" # your Apple ID user 11 | -------------------------------------------------------------------------------- /fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | # Customise this file, documentation can be found here: 2 | # https://github.com/fastlane/fastlane/tree/master/fastlane/docs 3 | # All available actions: https://docs.fastlane.tools/actions 4 | # can also be listed using the `fastlane actions` command 5 | 6 | # Change the syntax highlighting to Ruby 7 | # All lines starting with a # are ignored when running `fastlane` 8 | 9 | # If you want to automatically update fastlane if a new version is available: 10 | # update_fastlane 11 | 12 | # This is the minimum version number required. 13 | # Update this, if you use features of a newer version 14 | fastlane_version "2.42.0" 15 | 16 | default_platform :ios 17 | 18 | platform :ios do 19 | before_all do 20 | # ENV["SLACK_URL"] = "https://hooks.slack.com/services/..." 21 | cocoapods 22 | 23 | end 24 | 25 | desc "Runs all the tests" 26 | lane :test do 27 | scan 28 | end 29 | 30 | desc "Submit a new Beta Build to Apple TestFlight" 31 | desc "This will also make sure the profile is up to date" 32 | lane :beta do 33 | # match(type: "appstore") # more information: https://codesigning.guide 34 | increment_build_number 35 | gym(scheme: "SEDaily-IOS") # Build your app - more options available 36 | pilot 37 | 38 | # sh "your_script.sh" 39 | # You can also use other beta testing services here (run `fastlane actions`) 40 | end 41 | 42 | desc "Deploy a new version to the App Store" 43 | lane :release do 44 | # match(type: "appstore") 45 | # snapshot 46 | gym(scheme: "SEDaily-IOS") # Build your app - more options available 47 | deliver(force: true) 48 | # frameit 49 | end 50 | 51 | # You can define as many lanes as you want 52 | 53 | after_all do |lane| 54 | # This block is called, only if the executed lane was successful 55 | 56 | # slack( 57 | # message: "Successfully deployed new App Update." 58 | # ) 59 | end 60 | 61 | error do |lane, exception| 62 | # slack( 63 | # message: exception.message, 64 | # success: false 65 | # ) 66 | end 67 | 68 | desc "Create ipa" 69 | lane :build do 70 | increment_build_number 71 | gym(scheme: "SEDaily-IOS") 72 | end 73 | 74 | desc "Upload to App Store" 75 | lane :upload do 76 | deliver(force: true) 77 | end 78 | end 79 | 80 | 81 | # More information about multiple platforms in fastlane: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Platforms.md 82 | # All available actions: https://docs.fastlane.tools/actions 83 | 84 | # fastlane reports which actions are used. No personal data is recorded. 85 | # Learn more at https://github.com/fastlane/fastlane#metrics 86 | -------------------------------------------------------------------------------- /fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ================ 3 | # Installation 4 | 5 | Make sure you have the latest version of the Xcode command line tools installed: 6 | 7 | ``` 8 | xcode-select --install 9 | ``` 10 | 11 | Install _fastlane_ using 12 | ``` 13 | [sudo] gem install fastlane -NV 14 | ``` 15 | or alternatively using `brew cask install fastlane` 16 | 17 | # Available Actions 18 | ## iOS 19 | ### ios test 20 | ``` 21 | fastlane ios test 22 | ``` 23 | Runs all the tests 24 | ### ios beta 25 | ``` 26 | fastlane ios beta 27 | ``` 28 | Submit a new Beta Build to Apple TestFlight 29 | 30 | This will also make sure the profile is up to date 31 | ### ios release 32 | ``` 33 | fastlane ios release 34 | ``` 35 | Deploy a new version to the App Store 36 | ### ios build 37 | ``` 38 | fastlane ios build 39 | ``` 40 | Create ipa 41 | ### ios upload 42 | ``` 43 | fastlane ios upload 44 | ``` 45 | Upload to App Store 46 | 47 | ---- 48 | 49 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. 50 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). 51 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 52 | -------------------------------------------------------------------------------- /fastlane/metadata/copyright.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/en-US/description.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/en-US/keywords.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/en-US/marketing_url.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/en-US/name.txt: -------------------------------------------------------------------------------- 1 | SEDaily 2 | -------------------------------------------------------------------------------- /fastlane/metadata/en-US/privacy_url.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/en-US/promotional_text.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/en-US/release_notes.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/en-US/subtitle.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/en-US/support_url.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/primary_category.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/primary_first_sub_category.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/primary_second_sub_category.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/review_information/demo_password.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/review_information/demo_user.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/review_information/email_address.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/review_information/first_name.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/review_information/last_name.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/review_information/notes.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/review_information/phone_number.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/secondary_category.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/secondary_first_sub_category.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/secondary_second_sub_category.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /fastlane/metadata/trade_representative_contact_information/address_line1.txt: -------------------------------------------------------------------------------- 1 | 2711 Parkview Dr 2 | -------------------------------------------------------------------------------- /fastlane/metadata/trade_representative_contact_information/city_name.txt: -------------------------------------------------------------------------------- 1 | Corinth 2 | -------------------------------------------------------------------------------- /fastlane/metadata/trade_representative_contact_information/country.txt: -------------------------------------------------------------------------------- 1 | United States 2 | -------------------------------------------------------------------------------- /fastlane/metadata/trade_representative_contact_information/is_displayed_on_app_store.txt: -------------------------------------------------------------------------------- 1 | false 2 | -------------------------------------------------------------------------------- /fastlane/metadata/trade_representative_contact_information/postal_code.txt: -------------------------------------------------------------------------------- 1 | 76210 2 | -------------------------------------------------------------------------------- /fastlane/metadata/trade_representative_contact_information/state.txt: -------------------------------------------------------------------------------- 1 | Texas 2 | -------------------------------------------------------------------------------- /fastlane/metadata/trade_representative_contact_information/trade_name.txt: -------------------------------------------------------------------------------- 1 | Keith Holliday 2 | -------------------------------------------------------------------------------- /screenshots/app_screenshots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SoftwareEngineeringDaily/se-daily-iOS/a29d0f99d5eb34b683806e6d5292c4fe4addf3af/screenshots/app_screenshots.png --------------------------------------------------------------------------------