├── .circleci └── config.yml ├── .github └── workflows │ ├── copy-branch.yml │ └── gradle-wrapper-validation.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── NOTICE ├── PRIVACY.md ├── README.md ├── about ├── build.gradle └── src │ ├── androidTest │ ├── java │ │ └── io │ │ │ └── plaidapp │ │ │ └── about │ │ │ └── ui │ │ │ └── model │ │ │ └── AboutViewModelIntegrationTest.kt │ └── resources │ │ └── mockito-extensions │ │ └── org.mockito.plugins.MockMaker │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── io │ │ │ └── plaidapp │ │ │ └── about │ │ │ ├── dagger │ │ │ ├── AboutActivityModule.kt │ │ │ ├── AboutComponent.kt │ │ │ └── Injector.kt │ │ │ ├── domain │ │ │ └── model │ │ │ │ └── Library.kt │ │ │ └── ui │ │ │ ├── AboutActivity.kt │ │ │ ├── AboutStyler.kt │ │ │ ├── adapter │ │ │ ├── AboutPagerAdapter.kt │ │ │ ├── LibraryAdapter.kt │ │ │ ├── LibraryHolder.kt │ │ │ └── LibraryIntroHolder.kt │ │ │ ├── model │ │ │ ├── AboutUiModel.kt │ │ │ ├── AboutViewModel.kt │ │ │ ├── AboutViewModelFactory.kt │ │ │ └── LibrariesUiModel.kt │ │ │ └── widget │ │ │ ├── CutoutTextView.kt │ │ │ └── InkPageIndicator.java │ └── res │ │ ├── layout │ │ ├── about_icon.xml │ │ ├── about_lib_intro.xml │ │ ├── about_libs.xml │ │ ├── about_plaid.xml │ │ ├── activity_about.xml │ │ └── library.xml │ │ ├── transition │ │ ├── about_enter.xml │ │ ├── about_return.xml │ │ └── about_return_downward.xml │ │ └── values │ │ ├── attrs_cutout_text_view.xml │ │ ├── attrs_paging_indicator.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ ├── java │ └── io │ │ └── plaidapp │ │ └── about │ │ └── ui │ │ └── model │ │ └── AboutViewModelTest.kt │ └── resources │ └── mockito-extensions │ └── org.mockito.plugins.MockMaker ├── app ├── build.gradle ├── google-services.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── io │ │ └── plaidapp │ │ └── ui │ │ └── HomeActivityTest.kt │ ├── debug │ └── res │ │ └── mipmap-xxxhdpi-v26 │ │ └── ic_launcher_foreground.png │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── io │ │ │ └── plaidapp │ │ │ ├── dagger │ │ │ ├── HomeComponent.kt │ │ │ ├── HomeModule.kt │ │ │ └── Injector.kt │ │ │ ├── ui │ │ │ ├── HomeActivity.kt │ │ │ ├── HomeViewModel.kt │ │ │ ├── HomeViewModelFactory.kt │ │ │ ├── PlaidApplication.kt │ │ │ ├── recyclerview │ │ │ │ ├── FilterTouchHelperCallback.kt │ │ │ │ └── GridItemDividerDecoration.kt │ │ │ └── transitions │ │ │ │ └── StaggeredDistanceSlide.kt │ │ │ └── util │ │ │ └── DrawingExtensions.kt │ └── res │ │ ├── anim │ │ ├── chrome_custom_tab_enter.xml │ │ ├── grid_enter.xml │ │ └── layout_grid_enter.xml │ │ ├── animator │ │ ├── active_raise.xml │ │ ├── app_bar_pin.xml │ │ ├── button_frown.xml │ │ ├── comment_add_to_lines.xml │ │ ├── comment_lines_add_rotate.xml │ │ ├── comment_lines_to_add.xml │ │ ├── disable_text_entry.xml │ │ ├── selected_comment.xml │ │ ├── show_connection_cross.xml │ │ ├── show_connection_line.xml │ │ └── upvote.xml │ │ ├── color │ │ └── layered_icon_base.xml │ │ ├── drawable-nodpi │ │ └── ic_launcher_512px.png │ │ ├── drawable-v26 │ │ ├── ic_launcher_background.xml │ │ └── ic_shortcut_search.xml │ │ ├── drawable │ │ ├── asl_add_comment.xml │ │ ├── asl_password_visibility.xml │ │ ├── asl_theme.xml │ │ ├── asl_upvote.xml │ │ ├── avatar_placeholder.xml │ │ ├── avatar_ripple.xml │ │ ├── avd_add_to_comment.xml │ │ ├── avd_comment_to_add.xml │ │ ├── avd_day_to_night.xml │ │ ├── avd_hide_password.xml │ │ ├── avd_likes.xml │ │ ├── avd_night_to_day.xml │ │ ├── avd_no_connection.xml │ │ ├── avd_share.xml │ │ ├── avd_show_password.xml │ │ ├── avd_views.xml │ │ ├── comment_background.xml │ │ ├── designer_news_custom_tab_placeholder.xml │ │ ├── dialog_background.xml │ │ ├── ic_action_share_24dp.xml │ │ ├── ic_add_light.xml │ │ ├── ic_arrow_back.xml │ │ ├── ic_comment_add.xml │ │ ├── ic_comment_lines.xml │ │ ├── ic_delete.xml │ │ ├── ic_edit.xml │ │ ├── ic_filter.xml │ │ ├── ic_filter_small.xml │ │ ├── ic_hacker_news.xml │ │ ├── ic_news.xml │ │ ├── ic_no_comments.xml │ │ ├── ic_password_masked.xml │ │ ├── ic_password_visible.xml │ │ ├── ic_player.xml │ │ ├── ic_reply.xml │ │ ├── ic_shortcut_search.xml │ │ ├── ic_shortcut_search_foreground.xml │ │ ├── ic_theme_day.xml │ │ ├── ic_theme_night.xml │ │ ├── ic_upvote_anim.xml │ │ ├── ic_upvote_empty_24dp_grey.xml │ │ ├── ic_upvote_filled_24dp_blue.xml │ │ ├── mid_grey_bounded_ripple.xml │ │ ├── no_connection.xml │ │ └── post_story.xml │ │ ├── interpolator │ │ ├── slow_out_fast_in.xml │ │ ├── trim_end_interpolator.xml │ │ └── trim_start_interpolator.xml │ │ ├── layout │ │ ├── activity_home.xml │ │ ├── list_loading.xml │ │ ├── no_connection.xml │ │ └── no_filters.xml │ │ ├── menu │ │ └── main.xml │ │ ├── mipmap-anydpi-v26 │ │ └── ic_launcher.xml │ │ ├── mipmap-hdpi-v26 │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi-v26 │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi-v26 │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi-v26 │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi-v26 │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v23 │ │ └── colors.xml │ │ ├── values-v26 │ │ └── colors.xml │ │ ├── values │ │ ├── attrs_self_timing_transition.xml │ │ ├── attrs_staggered_distance_slide.xml │ │ ├── colors.xml │ │ ├── comment_lines_add.xml │ │ ├── feature_names.xml │ │ ├── follow.xml │ │ ├── images_below_anim.xml │ │ ├── integers.xml │ │ ├── no_connection.xml │ │ ├── password_visibility.xml │ │ ├── paths.xml │ │ ├── share_anim.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ ├── glide_disk_cache_path.xml │ │ ├── searchable.xml │ │ └── shortcuts.xml │ └── test │ ├── java │ └── io │ │ └── plaidapp │ │ ├── MockitoKotlinHelpers.kt │ │ ├── TestData.kt │ │ └── ui │ │ └── HomeViewModelTest.kt │ └── resources │ └── mockito-extensions │ └── org.mockito.plugins.MockMaker ├── art ├── dribbble_logo.svg ├── ic_add_comment.svg ├── ic_comment.svg ├── ic_designer_news.sketch ├── ic_designer_news.svg ├── ic_dribbble.sketch ├── ic_dribbble.svg ├── ic_launcher_layered.sketch ├── ic_no_comments.sketch ├── ic_no_comments.svg ├── ic_player.sketch ├── ic_player.svg ├── ic_pocket.sketch │ ├── Data │ ├── metadata │ └── version ├── ic_pocket.svg ├── ic_product_hunt.svg ├── ic_search.svg ├── launcher_shortcuts.sketch ├── no_connection.sketch ├── no_connection.svg ├── plaid_product_icon.psd └── plaid_product_icon_noshadow.ai ├── build.gradle ├── core ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── io │ │ └── plaidapp │ │ └── core │ │ ├── data │ │ └── prefs │ │ │ └── SourcesLocalDataSourceTest.kt │ │ ├── designernews │ │ └── data │ │ │ └── login │ │ │ ├── AuthTokenLocalDataSourceTest.kt │ │ │ └── LoginLocalDataSourceTest.kt │ │ └── util │ │ ├── SpannableExtensionsTest.kt │ │ └── TextViewExtensionTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── io │ │ │ └── plaidapp │ │ │ └── core │ │ │ ├── dagger │ │ │ ├── BaseComponent.kt │ │ │ ├── CoreComponent.kt │ │ │ ├── CoreDataModule.kt │ │ │ ├── DataManagerModule.kt │ │ │ ├── LocalApis.kt │ │ │ ├── MarkdownModule.kt │ │ │ ├── ProductHuntModule.kt │ │ │ ├── SharedPreferencesModule.kt │ │ │ ├── SourcesRepositoryModule.kt │ │ │ ├── designernews │ │ │ │ ├── DesignerNewsDataModule.kt │ │ │ │ ├── Injector.kt │ │ │ │ ├── UpvoteStoryServiceComponent.kt │ │ │ │ └── UpvoteStoryServiceModule.kt │ │ │ ├── dribbble │ │ │ │ └── DribbbleDataModule.kt │ │ │ ├── qualifier │ │ │ │ └── IsPocketInstalled.kt │ │ │ └── scope │ │ │ │ ├── AppScope.kt │ │ │ │ └── FeatureScope.kt │ │ │ ├── data │ │ │ ├── CoroutinesDispatcherProvider.kt │ │ │ ├── DataLoadingSubject.kt │ │ │ ├── DataManager.kt │ │ │ ├── OnDataLoadedCallback.kt │ │ │ ├── PlaidItem.kt │ │ │ ├── PlaidItemSorting.java │ │ │ ├── Result.kt │ │ │ ├── SourceItem.kt │ │ │ ├── api │ │ │ │ ├── DeEnvelopingConverter.kt │ │ │ │ └── EnvelopePayload.kt │ │ │ ├── pocket │ │ │ │ └── PocketUtils.kt │ │ │ └── prefs │ │ │ │ ├── DeprecatedSources.kt │ │ │ │ ├── SourcesLocalDataSource.kt │ │ │ │ └── SourcesRepository.kt │ │ │ ├── designernews │ │ │ ├── data │ │ │ │ ├── DesignerNewsSourceItem.kt │ │ │ │ ├── api │ │ │ │ │ ├── ClientAuthInterceptor.kt │ │ │ │ │ ├── DesignerNewsSearch.kt │ │ │ │ │ ├── DesignerNewsSearchConverter.kt │ │ │ │ │ └── DesignerNewsService.kt │ │ │ │ ├── login │ │ │ │ │ ├── AuthTokenLocalDataSource.kt │ │ │ │ │ ├── LoginLocalDataSource.kt │ │ │ │ │ ├── LoginRemoteDataSource.kt │ │ │ │ │ ├── LoginRepository.kt │ │ │ │ │ └── model │ │ │ │ │ │ ├── AccessToken.kt │ │ │ │ │ │ ├── LoggedInUser.kt │ │ │ │ │ │ └── LoggedInUserResponse.kt │ │ │ │ ├── stories │ │ │ │ │ ├── StoriesRemoteDataSource.kt │ │ │ │ │ ├── StoriesRepository.kt │ │ │ │ │ └── model │ │ │ │ │ │ ├── Story.kt │ │ │ │ │ │ ├── StoryLinks.kt │ │ │ │ │ │ └── StoryResponse.kt │ │ │ │ ├── users │ │ │ │ │ └── model │ │ │ │ │ │ └── User.kt │ │ │ │ └── votes │ │ │ │ │ └── UpvoteStoryService.java │ │ │ ├── domain │ │ │ │ ├── LoadStoriesUseCase.kt │ │ │ │ ├── SearchStoriesUseCase.kt │ │ │ │ ├── StoryWeigher.java │ │ │ │ └── model │ │ │ │ │ ├── Comment.kt │ │ │ │ │ └── CommentWithReplies.kt │ │ │ └── ui │ │ │ │ └── stories │ │ │ │ └── StoryViewHolder.kt │ │ │ ├── dribbble │ │ │ └── data │ │ │ │ ├── DribbbleSourceItem.kt │ │ │ │ ├── ShotsRepository.kt │ │ │ │ ├── api │ │ │ │ ├── ShotWeigher.kt │ │ │ │ └── model │ │ │ │ │ ├── Images.kt │ │ │ │ │ ├── Shot.kt │ │ │ │ │ └── User.kt │ │ │ │ └── search │ │ │ │ ├── DribbbleSearchConverter.kt │ │ │ │ ├── DribbbleSearchService.kt │ │ │ │ └── SearchRemoteDataSource.kt │ │ │ ├── feed │ │ │ ├── FeedAdapter.kt │ │ │ └── FeedUiModel.kt │ │ │ ├── interfaces │ │ │ ├── PlaidDataSource.kt │ │ │ ├── SearchDataSourceFactory.kt │ │ │ └── SearchDataSourceFactoryProvider.kt │ │ │ ├── producthunt │ │ │ ├── data │ │ │ │ ├── ProductHuntRemoteDataSource.kt │ │ │ │ ├── ProductHuntSourceItem.kt │ │ │ │ └── api │ │ │ │ │ ├── AuthInterceptor.kt │ │ │ │ │ ├── PostWeigher.java │ │ │ │ │ ├── ProductHuntRepository.kt │ │ │ │ │ ├── ProductHuntService.kt │ │ │ │ │ └── model │ │ │ │ │ ├── GetPostItemResponse.kt │ │ │ │ │ └── Post.kt │ │ │ ├── domain │ │ │ │ └── LoadPostsUseCase.kt │ │ │ └── ui │ │ │ │ └── ProductHuntPostHolder.kt │ │ │ ├── ui │ │ │ ├── ConnectivityChecker.kt │ │ │ ├── DribbbleShotHolder.kt │ │ │ ├── HomeGridItemAnimator.java │ │ │ ├── PlaidItemsListExtension.kt │ │ │ ├── drawable │ │ │ │ └── MorphDrawable.java │ │ │ ├── filter │ │ │ │ ├── FilterAdapter.kt │ │ │ │ ├── FilterAnimator.kt │ │ │ │ ├── FilterHolderInfo.kt │ │ │ │ ├── FilterViewHolder.kt │ │ │ │ ├── FiltersChangedCallback.kt │ │ │ │ └── SourceUiModel.kt │ │ │ ├── recyclerview │ │ │ │ ├── Divided.java │ │ │ │ ├── FilterSwipeDismissListener.kt │ │ │ │ ├── InfiniteScrollListener.kt │ │ │ │ └── SlideInItemAnimator.kt │ │ │ ├── span │ │ │ │ └── TextColorSpan.java │ │ │ ├── transitions │ │ │ │ ├── BackgroundFade.java │ │ │ │ ├── DarkenImage.kt │ │ │ │ ├── DeparallaxingChangeBounds.java │ │ │ │ ├── FabTransform.java │ │ │ │ ├── GravityArcMotion.java │ │ │ │ ├── LiftOff.java │ │ │ │ ├── MorphTransform.java │ │ │ │ ├── Pop.java │ │ │ │ ├── ReflowText.java │ │ │ │ ├── ShotSharedEnter.java │ │ │ │ └── StartAnimatable.java │ │ │ └── widget │ │ │ │ ├── AuthorTextView.java │ │ │ │ ├── BadgedFourThreeImageView.kt │ │ │ │ ├── BaselineGridTextView.java │ │ │ │ ├── BottomSheet.java │ │ │ │ ├── CircularImageView.kt │ │ │ │ ├── CollapsingTitleLayout.java │ │ │ │ ├── ElasticDragDismissFrameLayout.java │ │ │ │ ├── ForegroundImageView.java │ │ │ │ ├── ForegroundLinearLayout.java │ │ │ │ ├── ForegroundRelativeLayout.java │ │ │ │ ├── FourThreeImageView.java │ │ │ │ ├── FourThreeLinearLayout.java │ │ │ │ ├── FourThreeView.java │ │ │ │ ├── ObservableScrollView.java │ │ │ │ └── ParallaxScrimageView.java │ │ │ └── util │ │ │ ├── ActivityHelper.kt │ │ │ ├── AnimUtils.java │ │ │ ├── BindingAdapters.kt │ │ │ ├── CollapsingTextHelper.java │ │ │ ├── ColorUtils.java │ │ │ ├── DrawableExtensions.kt │ │ │ ├── Extensions.kt │ │ │ ├── FileAuthority.kt │ │ │ ├── HtmlParser.kt │ │ │ ├── HtmlUtils.java │ │ │ ├── ImageUriProvider.kt │ │ │ ├── ImeUtils.java │ │ │ ├── LinkTouchMovementMethod.java │ │ │ ├── NetworkUtils.kt │ │ │ ├── ObservableColorMatrix.java │ │ │ ├── ScrimUtil.java │ │ │ ├── ShortcutHelper.java │ │ │ ├── SpannableExtensions.kt │ │ │ ├── SpringUtils.kt │ │ │ ├── TextViewExtension.kt │ │ │ ├── TransitionUtils.java │ │ │ ├── ViewExtensions.kt │ │ │ ├── ViewOffsetHelper.java │ │ │ ├── ViewUtils.java │ │ │ ├── customtabs │ │ │ ├── CustomTabActivityHelper.java │ │ │ ├── CustomTabsHelper.java │ │ │ └── KeepAliveService.java │ │ │ ├── delegates │ │ │ └── ContentViewBindingDelegate.kt │ │ │ ├── event │ │ │ ├── Event.kt │ │ │ └── EventObserver.kt │ │ │ └── glide │ │ │ ├── DribbbleTarget.kt │ │ │ ├── GlideExtensions.kt │ │ │ ├── ImageSpanTarget.kt │ │ │ └── PlaidGlideModule.java │ └── res │ │ ├── anim │ │ └── fade_out_rapidly.xml │ │ ├── animator │ │ ├── filter_active.xml │ │ ├── raise.xml │ │ ├── searchback_hide_arrow_head.xml │ │ ├── searchback_hide_arrow_head_move.xml │ │ ├── searchback_hide_circle.xml │ │ ├── searchback_show_arrow_head.xml │ │ ├── searchback_show_arrow_head_move.xml │ │ ├── searchback_show_circle.xml │ │ ├── searchback_stem_back_to_search.xml │ │ └── searchback_stem_search_to_back.xml │ │ ├── color │ │ ├── divider.xml │ │ ├── filter_text.xml │ │ ├── original_poster_text_color.xml │ │ ├── plaid_links.xml │ │ ├── ripple_on_primary.xml │ │ ├── surface_contrast.xml │ │ └── text_color_tertiary.xml │ │ ├── drawable-v26 │ │ └── ic_shortcut_post.xml │ │ ├── drawable │ │ ├── avd_back_to_search.xml │ │ ├── avd_search_to_back.xml │ │ ├── dark_ripple.xml │ │ ├── fab.xml │ │ ├── filter_placeholder.xml │ │ ├── ic_add_dark.xml │ │ ├── ic_app_shortcut_background.xml │ │ ├── ic_comment_light.xml │ │ ├── ic_designer_news.xml │ │ ├── ic_dribbble.xml │ │ ├── ic_pocket.xml │ │ ├── ic_product_hunt.xml │ │ ├── ic_search_24dp.xml │ │ ├── ic_shortcut_post.xml │ │ ├── ic_shortcut_post_foreground.xml │ │ ├── ic_upvote_filled_24dp_white.xml │ │ ├── mid_grey_ripple.xml │ │ ├── ripple_on_primary.xml │ │ ├── searchback_back.xml │ │ ├── searchback_search.xml │ │ └── surface_contrast.xml │ │ ├── font │ │ └── roboto_mono.xml │ │ ├── layout │ │ ├── designer_news_story_item.xml │ │ ├── dribbble_shot_item.xml │ │ ├── filter_item.xml │ │ ├── infinite_loading.xml │ │ └── product_hunt_item.xml │ │ ├── transition │ │ ├── auto.xml │ │ └── home_enter.xml │ │ ├── values-h500dp │ │ └── dimens.xml │ │ ├── values-night │ │ └── colors.xml │ │ ├── values-sw600dp │ │ └── dimens.xml │ │ ├── values-v29 │ │ └── colors.xml │ │ ├── values-w360dp │ │ └── dimens.xml │ │ ├── values-w480dp │ │ └── dimens.xml │ │ ├── values-w540dp │ │ └── dimens.xml │ │ ├── values-w600dp │ │ ├── colors.xml │ │ └── dimens.xml │ │ ├── values-w800dp │ │ └── dimens.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── attrs_author_text_view.xml │ │ ├── attrs_badged_image_view.xml │ │ ├── attrs_baseline_grid_text_view.xml │ │ ├── attrs_collapsing_title_layout.xml │ │ ├── attrs_darken_image.xml │ │ ├── attrs_dribbble_feed.xml │ │ ├── attrs_elastic_drag_dismiss_frame_layout.xml │ │ ├── attrs_fab_transform.xml │ │ ├── attrs_foreground_view.xml │ │ ├── attrs_lift_off.xml │ │ ├── attrs_parallax_scrimage_view.xml │ │ ├── attrs_pinnable.xml │ │ ├── attrs_plaid.xml │ │ ├── attrs_reflow_text.xml │ │ ├── attrs_start_animatable.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── font_certs.xml │ │ ├── ids.xml │ │ ├── integers.xml │ │ ├── paths.xml │ │ ├── preloaded_fonts.xml │ │ ├── searchback.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ └── transition_names.xml │ └── test │ ├── java │ └── io │ │ └── plaidapp │ │ └── core │ │ ├── data │ │ └── prefs │ │ │ └── SourcesRepositoryTest.kt │ │ ├── designernews │ │ ├── TestData.kt │ │ ├── data │ │ │ ├── api │ │ │ │ └── DesignerNewsSearchConverterTest.kt │ │ │ ├── login │ │ │ │ ├── LoginRemoteDataSourceTest.kt │ │ │ │ └── LoginRepositoryTest.kt │ │ │ └── stories │ │ │ │ ├── StoriesRemoteDataSourceTest.kt │ │ │ │ ├── StoriesRepositoryTest.kt │ │ │ │ └── model │ │ │ │ └── StoryResponseTest.kt │ │ └── domain │ │ │ ├── LoadStoriesUseCaseTest.kt │ │ │ └── SearchStoriesUseCaseTest.kt │ │ ├── dribbble │ │ └── data │ │ │ ├── ShotsRepositoryTest.kt │ │ │ ├── TestData.kt │ │ │ ├── api │ │ │ └── ShotWeigherTest.kt │ │ │ └── search │ │ │ ├── DribbbleSearchConverterTest.kt │ │ │ └── SearchRemoteDataSourceTest.kt │ │ └── producthunt │ │ └── data │ │ ├── ProductHuntRemoteDataSourceTest.kt │ │ ├── TestData.kt │ │ └── api │ │ ├── FakeProductHuntService.kt │ │ └── ProductHuntRepositoryTest.kt │ └── resources │ ├── designernews_search.html │ ├── dribbble_search.html │ └── mockito-extensions │ └── org.mockito.plugins.MockMaker ├── designernews ├── build.gradle └── src │ ├── androidTest │ └── java │ │ └── io │ │ └── plaidapp │ │ └── designernews │ │ └── data │ │ └── database │ │ └── LoggedInUserDaoTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── io │ │ │ └── plaidapp │ │ │ ├── designernews │ │ │ ├── dagger │ │ │ │ ├── DataModule.kt │ │ │ │ ├── DesignerNewsPreferencesModule.kt │ │ │ │ ├── DesignerNewsSearchComponent.kt │ │ │ │ ├── Injector.kt │ │ │ │ ├── LoginComponent.kt │ │ │ │ ├── SearchDataModule.kt │ │ │ │ ├── StoryComponent.kt │ │ │ │ └── StoryModule.kt │ │ │ ├── data │ │ │ │ ├── api │ │ │ │ │ ├── ClientAuthInterceptor.kt │ │ │ │ │ └── DesignerNewsService.kt │ │ │ │ ├── comments │ │ │ │ │ ├── CommentsRemoteDataSource.kt │ │ │ │ │ ├── CommentsRepository.kt │ │ │ │ │ └── model │ │ │ │ │ │ ├── CommentLinksResponse.kt │ │ │ │ │ │ ├── CommentResponse.kt │ │ │ │ │ │ ├── NewCommentRequest.kt │ │ │ │ │ │ └── PostCommentResponse.kt │ │ │ │ ├── database │ │ │ │ │ ├── Converters.kt │ │ │ │ │ ├── DesignerNewsDatabase.kt │ │ │ │ │ └── LoggedInUserDao.kt │ │ │ │ └── users │ │ │ │ │ ├── UserRemoteDataSource.kt │ │ │ │ │ └── UserRepository.kt │ │ │ ├── domain │ │ │ │ ├── GetCommentsWithRepliesAndUsersUseCase.kt │ │ │ │ ├── GetCommentsWithRepliesUseCase.kt │ │ │ │ ├── GetStoryUseCase.kt │ │ │ │ ├── PostReplyUseCase.kt │ │ │ │ ├── PostStoryCommentUseCase.kt │ │ │ │ └── search │ │ │ │ │ ├── DesignerNewsDataSource.kt │ │ │ │ │ ├── DesignerNewsSearchDataSourceFactory.kt │ │ │ │ │ └── DesignerNewsSearchDataSourceFactoryProvider.kt │ │ │ └── ui │ │ │ │ ├── DesignerNewsViewModelFactory.kt │ │ │ │ ├── login │ │ │ │ ├── LoginActivity.kt │ │ │ │ ├── LoginBindingAdapters.kt │ │ │ │ └── LoginViewModel.kt │ │ │ │ └── story │ │ │ │ ├── CommentAnimator.kt │ │ │ │ ├── CommentReplyViewHolder.kt │ │ │ │ ├── CommentUiModel.kt │ │ │ │ ├── CommentViewHolder.kt │ │ │ │ ├── StoryActivity.java │ │ │ │ ├── StoryViewModel.kt │ │ │ │ └── StoryViewModelFactory.kt │ │ │ └── ui │ │ │ ├── drawable │ │ │ └── ThreadedCommentDrawable.kt │ │ │ ├── transitions │ │ │ ├── MorphDialogToFab.java │ │ │ └── StretchyChangeBounds.java │ │ │ └── widget │ │ │ ├── DynamicTypeTextView.java │ │ │ ├── PasswordEntry.java │ │ │ ├── PinnedOffsetView.java │ │ │ └── SquareLinearLayout.java │ └── res │ │ ├── anim │ │ ├── post_story_enter.xml │ │ └── post_story_exit.xml │ │ ├── color │ │ ├── designer_news_button.xml │ │ ├── designer_news_links.xml │ │ └── thread_depth.xml │ │ ├── layout-w600dp │ │ └── activity_designer_news_story.xml │ │ ├── layout │ │ ├── account_dropdown_item.xml │ │ ├── activity_designer_news_login.xml │ │ ├── activity_designer_news_story.xml │ │ ├── designer_news_comment.xml │ │ ├── designer_news_comment_actions.xml │ │ ├── designer_news_enter_comment.xml │ │ ├── designer_news_no_comments.xml │ │ ├── designer_news_story_description.xml │ │ ├── designer_news_story_fab.xml │ │ └── toast_logged_in_confirmation.xml │ │ ├── transition │ │ ├── designer_news_story_enter.xml │ │ ├── designer_news_story_return.xml │ │ ├── designer_news_story_shared_enter.xml │ │ └── designer_news_story_shared_return.xml │ │ └── values │ │ ├── attrs_stretchy_change_bounds.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ ├── java │ └── io │ │ └── plaidapp │ │ └── designernews │ │ ├── TestData.kt │ │ ├── data │ │ ├── comments │ │ │ ├── CommentsRemoteDataSourceTest.kt │ │ │ └── CommentsRepositoryTest.kt │ │ ├── database │ │ │ └── ConvertersTest.kt │ │ └── users │ │ │ ├── UserRemoteDataSourceTest.kt │ │ │ └── UserRepositoryTest.kt │ │ ├── domain │ │ ├── GetCommentsWithRepliesAndUsersUseCaseIntegrationTest.kt │ │ ├── GetCommentsWithRepliesAndUsersUseCaseTest.kt │ │ ├── GetCommentsWithRepliesUseCaseTest.kt │ │ ├── GetStoryUseCaseTest.kt │ │ ├── PostReplyUseCaseTest.kt │ │ ├── PostStoryCommentUseCaseTest.kt │ │ └── search │ │ │ └── DesignerNewsSearchDataSourceFactoryTest.kt │ │ └── ui │ │ ├── login │ │ └── LoginViewModelTest.kt │ │ └── story │ │ └── StoryViewModelTest.kt │ └── resources │ └── mockito-extensions │ └── org.mockito.plugins.MockMaker ├── dribbble ├── build.gradle └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── io │ │ │ └── plaidapp │ │ │ └── dribbble │ │ │ ├── dagger │ │ │ ├── DribbbleComponent.kt │ │ │ ├── DribbbleModule.kt │ │ │ ├── DribbbleSearchComponent.kt │ │ │ ├── Injector.kt │ │ │ └── SearchDataModule.kt │ │ │ ├── domain │ │ │ ├── CreateShotUiModelUseCase.kt │ │ │ ├── GetShareShotInfoUseCase.kt │ │ │ └── search │ │ │ │ ├── DribbbleDataSource.kt │ │ │ │ ├── DribbbleSearchDataSourceFactory.kt │ │ │ │ └── DribbbleSearchDataSourceFactoryProvider.kt │ │ │ └── ui │ │ │ └── shot │ │ │ ├── ShotActivity.kt │ │ │ ├── ShotBindingAdapters.kt │ │ │ ├── ShotStyler.kt │ │ │ ├── ShotUiModel.kt │ │ │ ├── ShotViewModel.kt │ │ │ └── ShotViewModelFactory.kt │ └── res │ │ ├── color │ │ ├── dribbble_button.xml │ │ ├── dribbble_links.xml │ │ └── dribble_comment_author.xml │ │ ├── layout │ │ └── activity_dribbble_shot.xml │ │ ├── transition │ │ ├── dribbble_shot_enter.xml │ │ ├── dribbble_shot_return.xml │ │ ├── dribbble_shot_shared_enter.xml │ │ └── dribbble_shot_shared_return.xml │ │ └── values │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ ├── java │ └── io │ │ └── plaidapp │ │ └── dribbble │ │ ├── TestData.kt │ │ ├── domain │ │ ├── CreateShotUiModelUseCaseTest.kt │ │ ├── GetShareShotInfoUseCaseTest.kt │ │ └── search │ │ │ └── DribbbleSearchDataSourceFactoryTest.kt │ │ └── ui │ │ └── shot │ │ └── ShotViewModelTest.kt │ └── resources │ └── mockito-extensions │ └── org.mockito.plugins.MockMaker ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── pull_request_template.md ├── repositories.gradle ├── screenshots ├── dn_story_framed.png ├── dribbble_shot_framed.png ├── home_grid_framed.png ├── plaid_demo.gif └── post_story_framed.png ├── scripts ├── README.md ├── copy_lint_results.sh ├── copyright.kt ├── ftl_run_tests.sh ├── ftl_setup.sh ├── greclipse.properties └── installFromBundle.sh ├── search ├── build.gradle └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── io │ │ │ └── plaidapp │ │ │ └── search │ │ │ ├── dagger │ │ │ ├── Injector.kt │ │ │ ├── SearchComponent.kt │ │ │ └── SearchModule.kt │ │ │ ├── domain │ │ │ ├── LoadSearchDataUseCase.kt │ │ │ └── SearchDataSourceFactoriesRegistry.kt │ │ │ └── ui │ │ │ ├── SearchActivity.kt │ │ │ ├── SearchViewModel.kt │ │ │ ├── SearchViewModelFactory.kt │ │ │ └── transitions │ │ │ └── CircularReveal.java │ └── res │ │ ├── drawable │ │ ├── ic_arrow_back_padded.xml │ │ └── ic_save_24dp.xml │ │ ├── layout │ │ ├── activity_search.xml │ │ └── no_search_results.xml │ │ ├── transition │ │ ├── search_enter.xml │ │ ├── search_hide_confirm.xml │ │ ├── search_return.xml │ │ ├── search_shared_enter.xml │ │ ├── search_shared_return.xml │ │ ├── search_show_confirm.xml │ │ └── search_show_results.xml │ │ └── values │ │ ├── attrs_circular_reveal.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ ├── java │ └── io │ │ └── plaidapp │ │ └── search │ │ ├── TestData.kt │ │ └── ui │ │ └── SearchViewModelTest.kt │ └── resources │ └── mockito-extensions │ └── org.mockito.plugins.MockMaker ├── settings.gradle ├── shared_dependencies.gradle ├── test_dependencies.gradle ├── test_shared ├── .gitignore ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── io │ └── plaidapp │ └── test │ └── shared │ ├── FakeAppInjection.kt │ ├── LiveDataTestUtil.kt │ └── MainCoroutineRule.kt └── third_party └── bypass ├── LICENSE.txt ├── README.google ├── README.md ├── build.gradle └── src └── main ├── AndroidManifest.xml ├── java └── in │ └── uncod │ └── android │ └── bypass │ ├── Bypass.java │ ├── Document.java │ ├── Element.java │ ├── LoadImageCallback.kt │ ├── Markdown.kt │ ├── ReverseSpannableStringBuilder.java │ └── style │ ├── FancyQuoteSpan.java │ ├── HorizontalLineSpan.java │ ├── ImageLoadingSpan.java │ └── TouchableUrlSpan.java ├── jniLibs ├── arm64-v8a │ └── libbypass.so ├── armeabi-v7a │ └── libbypass.so ├── armeabi │ └── libbypass.so ├── mips │ └── libbypass.so ├── mips64 │ └── libbypass.so ├── x86 │ └── libbypass.so └── x86_64 │ └── libbypass.so └── res └── values └── strings.xml /.github/workflows/copy-branch.yml: -------------------------------------------------------------------------------- 1 | # Duplicates default main branch to the old master branch 2 | 3 | name: Duplicates main to old master branch 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the main branch 7 | on: 8 | push: 9 | branches: [ main ] 10 | 11 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 12 | jobs: 13 | # This workflow contains a single job called "copy-branch" 14 | copy-branch: 15 | # The type of runner that the job will run on 16 | runs-on: ubuntu-latest 17 | 18 | # Steps represent a sequence of tasks that will be executed as part of the job 19 | steps: 20 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it, 21 | # but specifies master branch (old default). 22 | - uses: actions/checkout@v2 23 | with: 24 | fetch-depth: 0 25 | ref: master 26 | 27 | - run: | 28 | git config user.name github-actions 29 | git config user.email github-actions@github.com 30 | git merge origin/main 31 | git push 32 | -------------------------------------------------------------------------------- /.github/workflows/gradle-wrapper-validation.yml: -------------------------------------------------------------------------------- 1 | name: "Validate Gradle Wrapper" 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | validation: 6 | name: "Validation" 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: gradle/wrapper-validation-action@v1 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.iml 3 | *.project 4 | *.buildship.core.prefs 5 | out 6 | .idea 7 | prebuilts 8 | .DS_Store 9 | local.properties 10 | .gradle 11 | ktlint 12 | google-services.json 13 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This sample uses the following software: 2 | 3 | Copyright 2015 Google LLC. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | -------------------------------------------------------------------------------- /PRIVACY.md: -------------------------------------------------------------------------------- 1 | # Privacy Policy 2 | 3 | If you do not log in to any third party services that Plaid accesses, then it will not store any information about you. 4 | 5 | If you do choose to log in to [Designer News](https://www.designernews.co/) or [Dribbble](https://dribbble.com/) then Plaid stores the following information **locally** on your device: 6 | 7 | ### Dribbble 8 | - **Access Token** identifying your Dribbble account. You can revoke this [here](https://dribbble.com/account/applications) or by logging out. 9 | - Your **name**, **username**, **user id**, **avatar url** & **account type** are stored to be presented in the UI later. 10 | 11 | This behavior is implemented [here](https://github.com/nickbutcher/plaid/blob/master/app/src/main/java/io/plaidapp/data/prefs/DribbblePrefs.java) if you'd like to verify it. 12 | 13 | ### Designer News 14 | - **Access Token** identifying your Designer News account. You can revoke this by logging out. 15 | - Your **username**, **user id** & **avatar url** are stored to be presented in the UI later. 16 | 17 | This behavior is implemented [here](https://github.com/nickbutcher/plaid/blob/master/app/src/main/java/io/plaidapp/data/prefs/DesignerNewsPrefs.java). -------------------------------------------------------------------------------- /about/src/androidTest/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /about/src/main/java/io/plaidapp/about/dagger/Injector.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.about.dagger 18 | 19 | import io.plaidapp.about.ui.AboutActivity 20 | import io.plaidapp.core.dagger.MarkdownModule 21 | 22 | /** 23 | * Inject all required modules into [AboutActivity]. 24 | */ 25 | fun AboutActivity.inject() { 26 | DaggerAboutComponent.builder() 27 | .activity(this) 28 | .aboutActivityModule(AboutActivityModule(this)) 29 | .markdownModule(MarkdownModule(resources.displayMetrics)) 30 | .build() 31 | .inject(this) 32 | } 33 | -------------------------------------------------------------------------------- /about/src/main/java/io/plaidapp/about/domain/model/Library.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.about.domain.model 18 | 19 | /** 20 | * Models an open source library we want to credit 21 | */ 22 | internal data class Library( 23 | val name: String, 24 | val description: String, 25 | val link: String, 26 | val imageUrl: String, 27 | val circleCrop: Boolean 28 | ) 29 | -------------------------------------------------------------------------------- /about/src/main/java/io/plaidapp/about/ui/adapter/LibraryIntroHolder.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.about.ui.adapter 18 | 19 | import android.view.View 20 | import androidx.recyclerview.widget.RecyclerView 21 | 22 | internal class LibraryIntroHolder(itemView: View) : RecyclerView.ViewHolder(itemView) 23 | -------------------------------------------------------------------------------- /about/src/main/java/io/plaidapp/about/ui/model/AboutUiModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.about.ui.model 18 | 19 | /** 20 | * Hold values displayed in the about Ui. 21 | */ 22 | internal data class AboutUiModel( 23 | val appAboutText: CharSequence, 24 | val iconAboutText: CharSequence, 25 | val librariesUiModel: LibrariesUiModel 26 | ) 27 | -------------------------------------------------------------------------------- /about/src/main/java/io/plaidapp/about/ui/model/LibrariesUiModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.about.ui.model 18 | 19 | import io.plaidapp.about.domain.model.Library 20 | import io.plaidapp.about.ui.adapter.OnClick 21 | 22 | /** 23 | * * Hold values displayed in the libraries Ui. 24 | */ 25 | internal data class LibrariesUiModel(val libraries: List, val onClick: OnClick) 26 | -------------------------------------------------------------------------------- /about/src/main/res/values/attrs_cutout_text_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /about/src/main/res/values/attrs_paging_indicator.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /about/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /app/src/debug/res/mipmap-xxxhdpi-v26/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/debug/res/mipmap-xxxhdpi-v26/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/java/io/plaidapp/util/DrawingExtensions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.util 18 | 19 | import android.graphics.Matrix 20 | import android.graphics.Shader 21 | 22 | fun Shader.setTranslation(x: Float = 0f, y: Float = 0f) { 23 | getLocalMatrix(matrix) 24 | matrix.setTranslate(x, y) 25 | setLocalMatrix(matrix) 26 | } 27 | 28 | private val matrix: Matrix by lazy(LazyThreadSafetyMode.NONE) { 29 | Matrix() 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/res/anim/chrome_custom_tab_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/anim/layout_grid_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/animator/button_frown.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/animator/comment_add_to_lines.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/animator/comment_lines_add_rotate.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/animator/comment_lines_to_add.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/animator/show_connection_line.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/animator/upvote.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/color/layered_icon_base.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/ic_launcher_512px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/main/res/drawable-nodpi/ic_launcher_512px.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v26/ic_shortcut_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/avatar_placeholder.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/avatar_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/avd_add_to_comment.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 25 | 26 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/avd_comment_to_add.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 25 | 26 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/avd_no_connection.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 25 | 26 | 29 | 30 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/comment_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/dialog_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_light.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 26 | 27 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_back.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 24 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_edit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 26 | 27 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_filter_small.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 24 | 25 | 27 | 28 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_news.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_password_visible.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_reply.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 25 | 26 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_shortcut_search.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_upvote_empty_24dp_grey.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_upvote_filled_24dp_blue.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/mid_grey_bounded_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/post_story.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/interpolator/slow_out_fast_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/interpolator/trim_end_interpolator.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/interpolator/trim_start_interpolator.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/list_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/no_connection.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/no_filters.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi-v26/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/main/res/mipmap-hdpi-v26/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi-v26/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/main/res/mipmap-mdpi-v26/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi-v26/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/main/res/mipmap-xhdpi-v26/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/main/res/mipmap-xxhdpi-v26/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/main/res/mipmap-xxxhdpi-v26/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-v23/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | @color/light_immersive_bars 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/values-v26/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | @color/light_immersive_bars 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs_self_timing_transition.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs_staggered_distance_slide.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/values/feature_names.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/values/follow.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | M15,12C17.21,12 19,10.21 19,8C19,5.79 17.21,4 15,4C12.79,4 11,5.79 11,8C11,10.21 12.79,12 15,12L15,12ZM15,14C12.33,14 7,15.34 7,18L7,20L23,20L23,18C23,15.34 17.67,14 15,14L15,14Z 22 | M6,7 L4,7 L4,10 L1,10 L1,12 L4,12 L4,15 L6,15 L6,12 L9,12 L9,10 L6,10 L6,7 Z 23 | M6,10 L4,10 L4,10 L1,10 L1,12 L4,12 L4,12 L6,12 L6,12 L9,12 L9,10 L6,10 L6,10 Z 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/values/integers.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 360 20 | 120 21 | -------------------------------------------------------------------------------- /app/src/main/res/values/no_connection.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | M26,159 L26,159 L32,159 L32,159 Z 20 | M26,67 L26,159 L32,159 L32,67 Z 21 | M24,206.5 C24,206.5 27.6392462,206.449997 28,206.449997 C28.3607538,206.449997 32,206.5 32,206.5 22 | M23.6061137,207.020699 C23.6061137,207.020699 26.2397148,206 28.494994,206 C30.7502732,206 32.753258,207.020699 32.753258,207.020699 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/values/paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | M20,36h8v-4h-8V36z M6,12v4h36v-4H6z M12,26h24v-4H12V26z 20 | -------------------------------------------------------------------------------- /app/src/main/res/xml/glide_disk_cache_path.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 23 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/xml/searchable.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 23 | -------------------------------------------------------------------------------- /app/src/test/java/io/plaidapp/MockitoKotlinHelpers.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp 18 | 19 | import org.mockito.ArgumentCaptor 20 | 21 | /** 22 | * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException 23 | * when null is returned. 24 | */ 25 | fun capture(argumentCaptor: ArgumentCaptor): T = argumentCaptor.capture() 26 | 27 | /** 28 | * Helper function for creating an argumentCaptor in kotlin. 29 | */ 30 | inline fun argumentCaptor(): ArgumentCaptor = 31 | ArgumentCaptor.forClass(T::class.java) 32 | -------------------------------------------------------------------------------- /app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /art/ic_designer_news.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/art/ic_designer_news.sketch -------------------------------------------------------------------------------- /art/ic_dribbble.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/art/ic_dribbble.sketch -------------------------------------------------------------------------------- /art/ic_launcher_layered.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/art/ic_launcher_layered.sketch -------------------------------------------------------------------------------- /art/ic_no_comments.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/art/ic_no_comments.sketch -------------------------------------------------------------------------------- /art/ic_player.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/art/ic_player.sketch -------------------------------------------------------------------------------- /art/ic_pocket.sketch/Data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/art/ic_pocket.sketch/Data -------------------------------------------------------------------------------- /art/ic_pocket.sketch/metadata: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | app 6 | com.bohemiancoding.sketch3 7 | build 8 | 7891 9 | commit 10 | debc570766a4cc5a2e31258967910f7e5776f485 11 | fonts 12 | 13 | length 14 | 14930 15 | version 16 | 37 17 | 18 | 19 | -------------------------------------------------------------------------------- /art/ic_pocket.sketch/version: -------------------------------------------------------------------------------- 1 | 37 -------------------------------------------------------------------------------- /art/ic_search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ic_search 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /art/launcher_shortcuts.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/art/launcher_shortcuts.sketch -------------------------------------------------------------------------------- /art/no_connection.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/art/no_connection.sketch -------------------------------------------------------------------------------- /art/plaid_product_icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/art/plaid_product_icon.psd -------------------------------------------------------------------------------- /art/plaid_product_icon_noshadow.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/art/plaid_product_icon_noshadow.ai -------------------------------------------------------------------------------- /core/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/dagger/BaseComponent.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.dagger 18 | 19 | import android.app.Activity 20 | import android.app.Service 21 | 22 | interface BaseComponent { 23 | 24 | fun inject(target: T) 25 | } 26 | 27 | /** 28 | * Base dagger component for use in activities. 29 | */ 30 | interface BaseActivityComponent : BaseComponent 31 | 32 | /** 33 | * Base dagger components for use in services. 34 | */ 35 | interface BaseServiceComponent : BaseComponent 36 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/dagger/LocalApis.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.dagger 18 | 19 | import javax.inject.Qualifier 20 | 21 | @Retention(AnnotationRetention.BINARY) 22 | @Qualifier 23 | annotation class DesignerNewsApi 24 | 25 | @Retention(AnnotationRetention.BINARY) 26 | @Qualifier 27 | annotation class ProductHuntApi 28 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/dagger/qualifier/IsPocketInstalled.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.dagger.qualifier 18 | 19 | import javax.inject.Qualifier 20 | import kotlin.annotation.AnnotationRetention.BINARY 21 | 22 | @Retention(BINARY) 23 | @Qualifier 24 | annotation class IsPocketInstalled 25 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/dagger/scope/AppScope.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.dagger.scope 18 | 19 | import javax.inject.Scope 20 | import kotlin.annotation.AnnotationRetention.RUNTIME 21 | 22 | /** 23 | * Scope for the entire app runtime. 24 | */ 25 | @Scope 26 | @Retention(RUNTIME) 27 | annotation class AppScope 28 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/dagger/scope/FeatureScope.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.dagger.scope 18 | 19 | import javax.inject.Scope 20 | import kotlin.annotation.AnnotationRetention.RUNTIME 21 | 22 | /** 23 | * Scope for a feature module. 24 | */ 25 | @Scope 26 | @Retention(RUNTIME) 27 | annotation class FeatureScope 28 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/data/CoroutinesDispatcherProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.data 18 | 19 | import javax.inject.Inject 20 | import kotlinx.coroutines.CoroutineDispatcher 21 | import kotlinx.coroutines.Dispatchers.Default 22 | import kotlinx.coroutines.Dispatchers.IO 23 | import kotlinx.coroutines.Dispatchers.Main 24 | 25 | /** 26 | * Provide coroutines context. 27 | */ 28 | data class CoroutinesDispatcherProvider( 29 | val main: CoroutineDispatcher, 30 | val computation: CoroutineDispatcher, 31 | val io: CoroutineDispatcher 32 | ) { 33 | 34 | @Inject constructor() : this(Main, Default, IO) 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/data/DataLoadingSubject.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.data 18 | 19 | /** 20 | * An interface for classes offering data loading state to be observed. 21 | */ 22 | interface DataLoadingSubject { 23 | fun registerCallback(callbacks: DataLoadingCallbacks) 24 | 25 | interface DataLoadingCallbacks { 26 | fun dataStartedLoading() 27 | fun dataFinishedLoading() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/data/OnDataLoadedCallback.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.data 18 | 19 | /** 20 | * Callback to be triggered when data was loaded. 21 | */ 22 | interface OnDataLoadedCallback { 23 | fun onDataLoaded(data: T) 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/data/PlaidItem.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.data 18 | 19 | /** 20 | * Base class for all model types. 21 | * // TODO - make the item immutable (https://github.com/android/plaid/issues/795) 22 | */ 23 | abstract class PlaidItem( 24 | @Transient open val id: Long, 25 | @Transient open val title: String, 26 | @Transient open var url: String? = null, 27 | @Transient open val page: Int 28 | ) { 29 | var dataSource: String? = null 30 | var weight: Float = 0F // used for sorting 31 | var colspan: Int = 0 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/data/Result.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.data 18 | 19 | /** 20 | * A generic class that holds a value with its loading status. 21 | * @param 22 | */ 23 | sealed class Result { 24 | 25 | data class Success(val data: T) : Result() 26 | data class Error(val exception: Exception) : Result() 27 | 28 | override fun toString(): String { 29 | return when (this) { 30 | is Success<*> -> "Success[data=$data]" 31 | is Error -> "Error[exception=$exception]" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/data/api/EnvelopePayload.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.data.api 18 | 19 | import kotlin.annotation.AnnotationRetention.RUNTIME 20 | 21 | /** 22 | * An annotation for identifying the payload that we want to extract from an API response wrapped in 23 | * an envelope object. 24 | */ 25 | @Target( 26 | AnnotationTarget.FUNCTION, 27 | AnnotationTarget.PROPERTY_GETTER, 28 | AnnotationTarget.PROPERTY_SETTER 29 | ) 30 | @Retention(RUNTIME) 31 | annotation class EnvelopePayload(val value: String = "") 32 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/designernews/data/api/DesignerNewsSearch.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.designernews.data.api 18 | 19 | /** 20 | * Used to differentiate Designer News search response (HTML) from the JSON API responses. 21 | */ 22 | @Target(AnnotationTarget.FUNCTION) 23 | @Retention(AnnotationRetention.RUNTIME) 24 | internal annotation class DesignerNewsSearch 25 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/designernews/data/login/model/AccessToken.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.designernews.data.login.model 18 | 19 | import com.google.gson.annotations.SerializedName 20 | 21 | /** 22 | * Models a Designer News API access token 23 | */ 24 | data class AccessToken(@SerializedName("access_token") val accessToken: String) 25 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/designernews/data/stories/model/StoryLinks.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.designernews.data.stories.model 18 | 19 | import android.os.Parcelable 20 | import com.google.gson.annotations.SerializedName 21 | import kotlinx.android.parcel.Parcelize 22 | 23 | /** 24 | * Models story links received from DesignerNews v2 API 25 | */ 26 | @Parcelize 27 | data class StoryLinks( 28 | @SerializedName("user") val user: Long, 29 | @SerializedName("comments") val comments: List, 30 | @SerializedName("upvotes") val upvotes: List, 31 | @SerializedName("downvotes") val downvotes: List 32 | ) : Parcelable 33 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/designernews/data/users/model/User.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.designernews.data.users.model 18 | 19 | import com.google.gson.annotations.SerializedName 20 | 21 | /** 22 | * Models a Designer News User 23 | */ 24 | data class User( 25 | @SerializedName("id") val id: Long, 26 | @SerializedName("first_name") val firstName: String, 27 | @SerializedName("last_name") val lastName: String, 28 | @SerializedName("display_name") val displayName: String, 29 | @SerializedName("portrait_url") val portraitUrl: String? = null 30 | ) 31 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/designernews/domain/model/Comment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.designernews.domain.model 18 | 19 | import java.util.Date 20 | 21 | /** 22 | * Models a comment on a designer news story. 23 | */ 24 | data class Comment( 25 | val id: Long, 26 | val parentCommentId: Long?, 27 | val body: String, 28 | val createdAt: Date, 29 | val depth: Int, 30 | val upvotesCount: Int, 31 | val userId: Long, 32 | val userDisplayName: String?, 33 | val userPortraitUrl: String?, 34 | var upvoted: Boolean // TODO change this to val when getting to the upvoting 35 | ) 36 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/dribbble/data/DribbbleSourceItem.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.dribbble.data 18 | 19 | import io.plaidapp.core.R 20 | import io.plaidapp.core.data.SourceItem 21 | 22 | data class DribbbleSourceItem( 23 | val query: String, 24 | override var active: Boolean = true 25 | ) : SourceItem( 26 | DRIBBBLE_QUERY_PREFIX + query, 27 | query, 28 | SEARCH_SORT_ORDER, 29 | "“$query”", 30 | R.drawable.ic_dribbble, 31 | active, 32 | true 33 | ) { 34 | 35 | companion object { 36 | const val DRIBBBLE_QUERY_PREFIX = "DRIBBBLE_QUERY_" 37 | private const val SEARCH_SORT_ORDER = 400 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/dribbble/data/api/model/User.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.dribbble.data.api.model 18 | 19 | import com.google.gson.annotations.SerializedName 20 | 21 | /** 22 | * Models a dribbble user 23 | */ 24 | data class User( 25 | @SerializedName("id") val id: Long, 26 | @SerializedName("name") val name: String, 27 | @SerializedName("username") val username: String, 28 | @SerializedName("avatar_url") val avatarUrl: String 29 | ) { 30 | 31 | val highQualityAvatarUrl: String by lazy { 32 | avatarUrl.replace("/normal/", "/original/") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/feed/FeedUiModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.feed 18 | 19 | import io.plaidapp.core.data.PlaidItem 20 | 21 | /** 22 | * UI model for feed data 23 | */ 24 | data class FeedUiModel( 25 | val items: List 26 | ) 27 | 28 | data class FeedProgressUiModel( 29 | val isLoading: Boolean 30 | ) 31 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourceFactory.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.interfaces 18 | 19 | /** 20 | * Factory for data sources that can be searched, based on a query. 21 | */ 22 | interface SearchDataSourceFactory { 23 | 24 | fun create(query: String): PlaidDataSource 25 | } 26 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourceFactoryProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.interfaces 18 | 19 | import android.content.Context 20 | 21 | /** 22 | * Provider for [SearchDataSourceFactory], that based on the context, is able to construct the 23 | * factory 24 | */ 25 | interface SearchDataSourceFactoryProvider { 26 | 27 | fun getFactory(context: Context): SearchDataSourceFactory 28 | } 29 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/producthunt/data/ProductHuntSourceItem.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.producthunt.data 18 | 19 | import io.plaidapp.core.R 20 | import io.plaidapp.core.data.SourceItem 21 | 22 | data class ProductHuntSourceItem(override val name: String) : SourceItem( 23 | SOURCE_PRODUCT_HUNT, 24 | SOURCE_PRODUCT_HUNT, 25 | 500, 26 | name, 27 | R.drawable.ic_product_hunt, 28 | false 29 | ) { 30 | companion object { 31 | const val SOURCE_PRODUCT_HUNT = "SOURCE_PRODUCT_HUNT" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/producthunt/data/api/AuthInterceptor.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.producthunt.data.api 18 | 19 | import java.io.IOException 20 | import okhttp3.Interceptor 21 | import okhttp3.Response 22 | 23 | /** 24 | * A {@see RequestInterceptor} that adds an auth token to requests 25 | */ 26 | class AuthInterceptor(private val accessToken: String) : Interceptor { 27 | 28 | @Throws(IOException::class) 29 | override fun intercept(chain: Interceptor.Chain): Response { 30 | val request = chain.request().newBuilder().addHeader("Authorization", "Bearer $accessToken").build() 31 | return chain.proceed(request) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/producthunt/data/api/ProductHuntService.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.producthunt.data.api 18 | 19 | import io.plaidapp.core.producthunt.data.api.model.GetPostsResponse 20 | import retrofit2.Response 21 | import retrofit2.http.GET 22 | import retrofit2.http.Query 23 | 24 | /** 25 | * Models the Product Hunt API. See https://api.producthunt.com/v1/docs 26 | */ 27 | interface ProductHuntService { 28 | 29 | @GET("v1/posts") 30 | suspend fun getPostsAsync(@Query("days_ago") page: Int): Response 31 | 32 | companion object { 33 | 34 | const val ENDPOINT = "https://api.producthunt.com/" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/producthunt/data/api/model/Post.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.producthunt.data.api.model 18 | 19 | import io.plaidapp.core.data.PlaidItem 20 | 21 | /** 22 | * Models a post on Product Hunt. 23 | */ 24 | class Post( 25 | override val id: Long, 26 | override val title: String, 27 | override var url: String? = null, 28 | val tagline: String, 29 | val discussionUrl: String, 30 | val redirectUrl: String, 31 | val commentsCount: Int, 32 | val votesCount: Int 33 | ) : PlaidItem(id, title, url, 0) 34 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/ui/filter/FilterHolderInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.ui.filter 18 | 19 | import androidx.recyclerview.widget.RecyclerView 20 | 21 | class FilterHolderInfo : RecyclerView.ItemAnimator.ItemHolderInfo() { 22 | 23 | var doEnable: Boolean = false 24 | var doDisable: Boolean = false 25 | var doHighlight: Boolean = false 26 | 27 | companion object { 28 | 29 | const val FILTER_ENABLED = 1 30 | const val FILTER_DISABLED = 2 31 | const val HIGHLIGHT = 3 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/ui/filter/FiltersChangedCallback.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.ui.filter 18 | 19 | import io.plaidapp.core.data.SourceItem 20 | 21 | /** 22 | * Callbacks called when a filter was changed or when a filter was removed 23 | */ 24 | abstract class FiltersChangedCallback { 25 | 26 | open fun onFiltersChanged(changedFilter: SourceItem) {} 27 | 28 | open fun onFilterRemoved(sourceKey: String) {} 29 | 30 | open fun onFiltersUpdated(sources: List) {} 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/ui/recyclerview/Divided.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package io.plaidapp.core.ui.recyclerview; 19 | 20 | /** 21 | * A marker interface used by {RecyclerView.ItemDecoration}s to 22 | * denote {RecyclerView.ViewHolder}s that should have dividers. 23 | */ 24 | public interface Divided { } 25 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/ui/recyclerview/FilterSwipeDismissListener.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.ui.recyclerview 18 | 19 | /** 20 | * Interface for events related to swipe dismissing filters 21 | */ 22 | interface FilterSwipeDismissListener { 23 | fun onItemDismiss(position: Int) 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/ui/span/TextColorSpan.java: -------------------------------------------------------------------------------- 1 | package io.plaidapp.core.ui.span; 2 | 3 | import androidx.annotation.ColorInt; 4 | import androidx.annotation.FloatRange; 5 | import android.text.TextPaint; 6 | import android.text.style.ForegroundColorSpan; 7 | 8 | import io.plaidapp.core.util.ColorUtils; 9 | 10 | /** 11 | * An extension to {@link ForegroundColorSpan} which allows updating the color or alpha component. 12 | * Note that Spans cannot invalidate themselves so consumers must ensure that the Spannable is 13 | * refreshed themselves. 14 | */ 15 | public class TextColorSpan extends ForegroundColorSpan { 16 | 17 | private @ColorInt int color; 18 | 19 | public TextColorSpan(@ColorInt int color) { 20 | super(color); 21 | this.color = color; 22 | } 23 | 24 | public @ColorInt int getColor() { 25 | return color; 26 | } 27 | 28 | public void setColor(@ColorInt int color) { 29 | this.color = color; 30 | } 31 | 32 | public void setAlpha(@FloatRange(from = 0f, to = 1f) float alpha) { 33 | color = ColorUtils.modifyAlpha(color, alpha); 34 | } 35 | 36 | @Override 37 | public void updateDrawState(TextPaint ds) { 38 | ds.setColor(color); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/ui/widget/CircularImageView.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.ui.widget 18 | 19 | import android.content.Context 20 | import android.util.AttributeSet 21 | import io.plaidapp.core.util.ViewUtils 22 | 23 | /** 24 | * An extension to image view that has a circular outline. 25 | */ 26 | class CircularImageView( 27 | context: Context, 28 | attrs: AttributeSet 29 | ) : ForegroundImageView(context, attrs) { 30 | 31 | init { 32 | outlineProvider = ViewUtils.CIRCULAR_OUTLINE 33 | clipToOutline = true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/util/FileAuthority.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.util 18 | 19 | /** 20 | * Wrapping the file authority value in a data class, to make it more type safe. 21 | */ 22 | data class FileAuthority(val authority: String) 23 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/util/SpannableExtensions.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @file:Suppress("NOTHING_TO_INLINE") 18 | 19 | package io.plaidapp.core.util 20 | 21 | import android.text.Spannable 22 | import android.text.Spanned.SPAN_INCLUSIVE_EXCLUSIVE 23 | 24 | /** 25 | * Adds [span] to the entire text. 26 | * 27 | * Ported from 28 | * https://github.com/android/android-ktx/blob/89ee2e1cde1e1b0226ed944b9abd55cee0f9b9d4/src/main/java/androidx/core/text/SpannableString.kt#L32 29 | */ 30 | inline operator fun Spannable.plusAssign(span: Any) = setSpan(span, 0, length, SPAN_INCLUSIVE_EXCLUSIVE) 31 | -------------------------------------------------------------------------------- /core/src/main/java/io/plaidapp/core/util/event/EventObserver.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.util.event 18 | 19 | import androidx.lifecycle.Observer 20 | 21 | /** 22 | * An [Observer] for [Event]s, simplifying the pattern of checking if the [Event]'s content has 23 | * already been consumed. 24 | * 25 | * [onEventUnconsumedContent] is *only* called if the [Event]'s contents has not been consumed. 26 | */ 27 | class EventObserver(private val onEventUnconsumedContent: (T) -> Unit) : Observer> { 28 | override fun onChanged(event: Event?) { 29 | event?.consume()?.run(onEventUnconsumedContent) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/res/anim/fade_out_rapidly.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 27 | -------------------------------------------------------------------------------- /core/src/main/res/animator/searchback_hide_arrow_head.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /core/src/main/res/animator/searchback_hide_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 25 | -------------------------------------------------------------------------------- /core/src/main/res/color/divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /core/src/main/res/color/filter_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/color/original_poster_text_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/color/plaid_links.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/color/ripple_on_primary.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /core/src/main/res/color/surface_contrast.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /core/src/main/res/color/text_color_tertiary.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /core/src/main/res/drawable-v26/ic_shortcut_post.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/dark_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/fab.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/filter_placeholder.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/ic_add_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/ic_app_shortcut_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/ic_comment_light.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/ic_search_24dp.xml: -------------------------------------------------------------------------------- 1 | 16 | 21 | 25 | 26 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/ic_shortcut_post.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/ic_upvote_filled_24dp_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/mid_grey_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/ripple_on_primary.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 18 | -------------------------------------------------------------------------------- /core/src/main/res/drawable/surface_contrast.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /core/src/main/res/layout/dribbble_shot_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 29 | -------------------------------------------------------------------------------- /core/src/main/res/layout/infinite_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 29 | -------------------------------------------------------------------------------- /core/src/main/res/transition/auto.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 22 | -------------------------------------------------------------------------------- /core/src/main/res/transition/home_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /core/src/main/res/values-h500dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 168dp 22 | 23 | 24 | 400dp 25 | @dimen/spacing_large 26 | 27 | 28 | -------------------------------------------------------------------------------- /core/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 19 | @color/background_dark 20 | #ff404040 21 | #ff292929 22 | #80cccccc 23 | #ffcccccc 24 | 25 | 26 | #003c8f 27 | #0b3c87 28 | 29 | 30 | #7f311a 31 | 32 | 33 | -------------------------------------------------------------------------------- /core/src/main/res/values-sw600dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 16dp 22 | 8dp 23 | 24dp 24 | 80dp 25 | 9dp 26 | 27 | 28 | 56dp 29 | 30 | 31 | -------------------------------------------------------------------------------- /core/src/main/res/values-v29/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 19 | @android:color/transparent 20 | 21 | 22 | -------------------------------------------------------------------------------- /core/src/main/res/values-w360dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 304dp 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/values-w480dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 480dp 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/values-w540dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 3 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/values-w600dp/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | @color/color_surface 18 | 19 | 20 | -------------------------------------------------------------------------------- /core/src/main/res/values-w800dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 672dp 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 4 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_author_text_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_baseline_grid_text_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_darken_image.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_dribbble_feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_elastic_drag_dismiss_frame_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_fab_transform.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_foreground_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_lift_off.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_parallax_scrimage_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_pinnable.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_plaid.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_reflow_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /core/src/main/res/values/attrs_start_animatable.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /core/src/main/res/values/integers.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 22 | 120 23 | 24 | -------------------------------------------------------------------------------- /core/src/main/res/values/preloaded_fonts.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | @font/roboto_mono 18 | 19 | 20 | -------------------------------------------------------------------------------- /core/src/test/java/io/plaidapp/core/producthunt/data/api/FakeProductHuntService.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.core.producthunt.data.api 18 | 19 | import io.plaidapp.core.producthunt.data.api.model.GetPostsResponse 20 | import retrofit2.Response 21 | 22 | /** 23 | * Fake implementation of [ProductHuntService] 24 | */ 25 | abstract class FakeProductHuntService : ProductHuntService { 26 | 27 | override suspend fun getPostsAsync(page: Int): Response { 28 | return getPostsResponse() 29 | } 30 | 31 | abstract fun getPostsResponse(): Response 32 | } 33 | -------------------------------------------------------------------------------- /core/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /designernews/src/main/java/io/plaidapp/designernews/dagger/DesignerNewsPreferencesModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.designernews.dagger 18 | 19 | import android.content.Context 20 | import dagger.Module 21 | import io.plaidapp.core.dagger.SharedPreferencesModule 22 | import io.plaidapp.core.designernews.data.login.LoginLocalDataSource 23 | 24 | @Module 25 | class DesignerNewsPreferencesModule( 26 | context: Context 27 | ) : SharedPreferencesModule(context, LoginLocalDataSource.DESIGNER_NEWS_PREF) 28 | -------------------------------------------------------------------------------- /designernews/src/main/java/io/plaidapp/designernews/data/comments/model/PostCommentResponse.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.designernews.data.comments.model 18 | 19 | import com.google.gson.annotations.SerializedName 20 | 21 | data class PostCommentResponse(@SerializedName("comments") val comments: List) 22 | -------------------------------------------------------------------------------- /designernews/src/main/java/io/plaidapp/designernews/ui/story/CommentUiModel.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.designernews.ui.story 18 | 19 | /** 20 | * Comment model for the UI 21 | */ 22 | data class CommentUiModel( 23 | val body: CharSequence, 24 | val timeSinceCommentCreation: String, 25 | val depth: Int, 26 | val author: String?, 27 | val isOriginalPoster: Boolean 28 | ) 29 | -------------------------------------------------------------------------------- /designernews/src/main/res/anim/post_story_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | -------------------------------------------------------------------------------- /designernews/src/main/res/anim/post_story_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | -------------------------------------------------------------------------------- /designernews/src/main/res/color/designer_news_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /designernews/src/main/res/color/designer_news_links.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /designernews/src/main/res/color/thread_depth.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /designernews/src/main/res/values/attrs_stretchy_change_bounds.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /designernews/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /dribbble/src/main/java/io/plaidapp/dribbble/dagger/Injector.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.dribbble.dagger 18 | 19 | import io.plaidapp.dribbble.ui.shot.ShotActivity 20 | import io.plaidapp.ui.coreComponent 21 | 22 | /** 23 | * Inject dependencies into [ShotActivity] 24 | */ 25 | fun ShotActivity.inject(shotId: Long) { 26 | DaggerDribbbleComponent.builder() 27 | .coreComponent(coreComponent()) 28 | .dribbbleModule(DribbbleModule(this, shotId)) 29 | .build() 30 | .inject(this) 31 | } 32 | -------------------------------------------------------------------------------- /dribbble/src/main/res/color/dribbble_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /dribbble/src/main/res/color/dribbble_links.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /dribbble/src/main/res/color/dribble_comment_author.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /dribbble/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | no likes 24 | %s like 25 | %s likes 26 | 27 | 28 | no views 29 | %s view 30 | %s views 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /dribbble/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## :loudspeaker: Type of change 2 | 3 | - [ ] Bugfix 4 | - [ ] New feature 5 | - [ ] Enhancement 6 | - [ ] Refactoring 7 | 8 | 9 | ## :scroll: Description 10 | 11 | 12 | 13 | ## :bulb: Motivation and Context 14 | 15 | 16 | 17 | 18 | ## :green_heart: How did you test it? 19 | 20 | 21 | ## :pencil: Checklist 22 | 23 | - [ ] I ran `./gradlew spotlessApply` before submitting the PR 24 | - [ ] I reviewed submitted code 25 | - [ ] I added tests to verify changes 26 | - [ ] All tests passing 27 | 28 | 29 | ## :crystal_ball: Next steps 30 | 31 | 32 | ## :camera_flash: Screenshots / GIFs 33 | 34 | 35 | 38 | -------------------------------------------------------------------------------- /screenshots/dn_story_framed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/screenshots/dn_story_framed.png -------------------------------------------------------------------------------- /screenshots/dribbble_shot_framed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/screenshots/dribbble_shot_framed.png -------------------------------------------------------------------------------- /screenshots/home_grid_framed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/screenshots/home_grid_framed.png -------------------------------------------------------------------------------- /screenshots/plaid_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/screenshots/plaid_demo.gif -------------------------------------------------------------------------------- /screenshots/post_story_framed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/screenshots/post_story_framed.png -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | The files in this directory are only used for continuous integration and lint 2 | purposes. They are not part of the Android app. 3 | -------------------------------------------------------------------------------- /scripts/copy_lint_results.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | RESULTS_DIR="ci_results/lint/" 4 | mkdir -p $RESULTS_DIR 5 | 6 | # Find all lint result files, except ones for third party libraries 7 | LINT_FILES=`find . -type f -regex ".*/build/reports/lint-results\..*" | grep -v third_party` 8 | 9 | # Rename each file and append the module name. Examples: 10 | # app/build/reports/lint-results.html -> app/build/reports/lint-results-app.html 11 | # base/build/reports/lint-results.html -> base/build/reports/lint-results-base.html 12 | for file in $LINT_FILES 13 | do 14 | rename 's/\/(.*)\/build\/reports\/lint-results/\/$1\/build\/reports\/lint-results-$1/' $file 15 | done 16 | 17 | # Move all of the renamed files to the $RESULTS_DIR 18 | find . -type f -regex ".*/build/reports/lint-results-.*\..*" -exec cp {} $RESULTS_DIR \; 19 | -------------------------------------------------------------------------------- /scripts/copyright.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright $YEAR Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /scripts/ftl_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Check if this script is running on the main, non-forked repository. 4 | # Environment variables are not set in forked repository builds; 5 | # in this case, skip Firebase Test Lab steps and finish the build. 6 | if [ -z "$IS_MAIN_PLAID_REPO" ]; then 7 | echo "Running build on a forked repository - skipping FTL tests." 8 | circleci step halt 9 | exit 0 10 | fi 11 | 12 | # Check if service key environment variable is set; exit if not 13 | if [ -z "$GCLOUD_SERVICE_KEY" ]; then 14 | echo "GCLOUD_SERVICE_KEY env variable is empty. Exiting." 15 | exit 1 16 | fi 17 | 18 | # Export to secrets file 19 | echo $GCLOUD_SERVICE_KEY | base64 -di > client_secret.json 20 | 21 | # Set project ID 22 | gcloud config set project android-devrel-ci 23 | 24 | # Auth account 25 | gcloud auth activate-service-account plaid-ftl@android-devrel-ci.iam.gserviceaccount.com --key-file client_secret.json 26 | 27 | # Delete secret 28 | rm client_secret.json 29 | -------------------------------------------------------------------------------- /scripts/installFromBundle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Build & extract a set of apk from an aab for a specific device and install the results on it. 3 | # 4 | # This needs https://github.com/google/bundletool to be available as `bundletool`. 5 | # Also **exactly** one device needs to be connected to adb. 6 | # Usage: installFromBundle bundle.aab 7 | # optional `--extract-apks` to keep the set on your workstation as well. 8 | 9 | basename=${1%%.*} 10 | keystore="~/.android/debug.keystore" 11 | ks_alias="androiddebugkey" 12 | pass="pass:android" 13 | 14 | bundletool build-apks --bundle=$1 --ks=$keystore --ks-key-alias=$ks_alias --ks-pass=$pass --output=$basename.apks 15 | bundletool install-apks --apks=$basename.apks 16 | 17 | if [ "$2" = "--extract-apks" ] 18 | then 19 | bundletool get-device-spec --output=spec.json 20 | bundletool extract-apks --apks=$basename.apks --device-spec=spec.json --output-dir=. 21 | fi 22 | -------------------------------------------------------------------------------- /search/src/main/java/io/plaidapp/search/dagger/Injector.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.plaidapp.search.dagger 18 | 19 | import io.plaidapp.search.ui.SearchActivity 20 | import io.plaidapp.ui.coreComponent 21 | 22 | /** 23 | * Injector for SearchActivity. 24 | * 25 | * TODO: Convert to extension function once [SearchActivity] is converted to Kotlin. 26 | */ 27 | object Injector { 28 | 29 | @JvmStatic 30 | fun inject(activity: SearchActivity) { 31 | DaggerSearchComponent.builder() 32 | .coreComponent(activity.coreComponent()) 33 | .searchActivity(activity) 34 | .build() 35 | .inject(activity) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /search/src/main/res/drawable/ic_arrow_back_padded.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /search/src/main/res/drawable/ic_save_24dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 25 | 26 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /search/src/main/res/layout/no_search_results.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 29 | -------------------------------------------------------------------------------- /search/src/main/res/transition/search_shared_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /search/src/main/res/transition/search_shared_return.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /search/src/main/res/values/attrs_circular_reveal.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /search/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | Search Dribbble & Designer News 22 | No results for\n“%1$s” 23 | Save Dribbble 24 | Save Designer News 25 | Save 26 | -------------------------------------------------------------------------------- /search/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker: -------------------------------------------------------------------------------- 1 | mock-maker-inline -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':bypass' 2 | include ':about', ':core', ':dribbble', ':designernews', ':search' 3 | include ':test_shared' 4 | project(':bypass').projectDir = new File(rootDir, 'third_party/bypass') 5 | -------------------------------------------------------------------------------- /test_shared/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /test_shared/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 19 | -------------------------------------------------------------------------------- /third_party/bypass/README.google: -------------------------------------------------------------------------------- 1 | URL: https://github.com/Uncodin/bypass/tree/b0e33f9b9dce33a128ab6e9ab895ffbea518c878 2 | Version: 1.1 3 | License: Apache License v2.0 4 | License File: LICENSE.txt 5 | 6 | Description: 7 | Fork of https://github.com/Uncodin/bypass 8 | 9 | Local Modifications: 10 | Added TouchableUrlSpan, FancyQuoteSpan & ImageLoadingSpan + LoadImageCallback 11 | mechanism. 12 | -------------------------------------------------------------------------------- /third_party/bypass/README.md: -------------------------------------------------------------------------------- 1 | # Bypass 2 | 3 | Fork of the awesome markdown processor [Bypass](https://github.com/Uncodin/bypass). 4 | 5 | ## Modifications 6 | 7 | Augmented to add: 8 | 9 | - `TouchableUrlSpan` An extension to URLSpan which changes it's background & foreground color when 10 | pressed. 11 | - `FancyQuoteSpan` A quote span with a nicer presentation 12 | - `ImageLoadingSpan` A simple text span used to mark text that will be replaced by an image once it 13 | has been downloaded 14 | - `LoadImageCallback` a callback mechanism for loading images 15 | -------------------------------------------------------------------------------- /third_party/bypass/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /third_party/bypass/src/main/java/in/uncod/android/bypass/Document.java: -------------------------------------------------------------------------------- 1 | package in.uncod.android.bypass; 2 | 3 | public class Document { 4 | 5 | Element[] elements; 6 | 7 | public Document(Element[] elements) { 8 | this.elements = elements; 9 | } 10 | 11 | public int getElementCount() { 12 | return elements.length; 13 | } 14 | 15 | public Element getElement(int pos) { 16 | return elements[pos]; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /third_party/bypass/src/main/java/in/uncod/android/bypass/Markdown.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package `in`.uncod.android.bypass 18 | 19 | import android.content.res.ColorStateList 20 | import androidx.annotation.ColorInt 21 | 22 | /** 23 | * Interface for Markdown capabilities. 24 | */ 25 | interface Markdown { 26 | /** 27 | * Create a spannable [CharSequence] from a text containing markdown data. 28 | */ 29 | fun markdownToSpannable( 30 | content: String, 31 | linksColor: ColorStateList, 32 | @ColorInt highlightColor: Int, 33 | callback: LoadImageCallback? 34 | ): CharSequence 35 | } 36 | -------------------------------------------------------------------------------- /third_party/bypass/src/main/java/in/uncod/android/bypass/style/ImageLoadingSpan.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Google LLC. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package in.uncod.android.bypass.style; 18 | 19 | import android.text.TextPaint; 20 | import android.text.style.CharacterStyle; 21 | 22 | /** 23 | * A simple text span used to mark text that will be replaced by an image once it has been 24 | * downloaded. See {@link in.uncod.android.bypass.Bypass.LoadImageCallback} 25 | */ 26 | public class ImageLoadingSpan extends CharacterStyle { 27 | @Override 28 | public void updateDrawState(TextPaint textPaint) { 29 | // no-op 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /third_party/bypass/src/main/jniLibs/arm64-v8a/libbypass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/third_party/bypass/src/main/jniLibs/arm64-v8a/libbypass.so -------------------------------------------------------------------------------- /third_party/bypass/src/main/jniLibs/armeabi-v7a/libbypass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/third_party/bypass/src/main/jniLibs/armeabi-v7a/libbypass.so -------------------------------------------------------------------------------- /third_party/bypass/src/main/jniLibs/armeabi/libbypass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/third_party/bypass/src/main/jniLibs/armeabi/libbypass.so -------------------------------------------------------------------------------- /third_party/bypass/src/main/jniLibs/mips/libbypass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/third_party/bypass/src/main/jniLibs/mips/libbypass.so -------------------------------------------------------------------------------- /third_party/bypass/src/main/jniLibs/mips64/libbypass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/third_party/bypass/src/main/jniLibs/mips64/libbypass.so -------------------------------------------------------------------------------- /third_party/bypass/src/main/jniLibs/x86/libbypass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/third_party/bypass/src/main/jniLibs/x86/libbypass.so -------------------------------------------------------------------------------- /third_party/bypass/src/main/jniLibs/x86_64/libbypass.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickbutcher/plaid/15958cc287f4a8efb2c39b65ca57cd41c7aad518/third_party/bypass/src/main/jniLibs/x86_64/libbypass.so -------------------------------------------------------------------------------- /third_party/bypass/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Bypass 4 | 5 | --------------------------------------------------------------------------------