From b95c00c1f7e4dd62c3606cd8e23c1c7f6481a2dd Mon Sep 17 00:00:00 2001 From: k0shk0sh Date: Sat, 13 Jul 2019 22:28:08 +0200 Subject: [PATCH 001/124] merge v5 --- .codecov.yml | 2 - .editorconfig | 5 + .github/CONTRIBUTING.md | 89 - .github/ISSUE_TEMPLATE.md | 22 - .github/assets/direct-apk-download.png | Bin 14310 -> 0 bytes .github/assets/feature_graphic.png | Bin 165948 -> 0 bytes .github/assets/first.png | Bin 540030 -> 0 bytes .github/assets/fourth.png | Bin 307540 -> 0 bytes .github/assets/sec.png | Bin 188798 -> 0 bytes .github/assets/third.png | Bin 802310 -> 0 bytes .github_changelog_generator | 7 - .gitignore | 4 +- .travis.yml | 46 - CODE_OF_CONDUCT.md | 46 - LICENSE | 674 - README.md | 199 - _config.yml | 1 - app/build.gradle | 180 +- app/proguard-rules.pro | 157 +- .../com/fastaccess/helper/TestHelper.java | 77 - .../ui/modules/login/LoginActivityTest.java | 54 - .../login/LoginChooserActivityTest.java | 39 - .../ui/modules/main/MainActivityTest.java | 69 - app/src/main/AndroidManifest.xml | 332 +- app/src/main/assets/colors.json | 1394 - app/src/main/assets/fonts/app_font.ttf | Bin 162876 -> 0 bytes app/src/main/assets/highlight/js/prettify.js | 3 - .../highlight/js/prettify_line_number.js | 88 - app/src/main/assets/highlight/js/scrollto.js | 65 - .../main/assets/highlight/styles/prettify.css | 98 - .../assets/highlight/styles/prettify_dark.css | 74 - .../assets/highlight/styles/themes/agate.css | 107 - .../highlight/styles/themes/androidstudio.css | 65 - .../highlight/styles/themes/arduino-light.css | 87 - .../assets/highlight/styles/themes/arta.css | 73 - .../highlight/styles/themes/ascetic.css | 44 - .../styles/themes/atelier-cave-dark.css | 83 - .../styles/themes/atelier-cave-light.css | 85 - .../styles/themes/atelier-dune-dark.css | 69 - .../styles/themes/atelier-dune-light.css | 69 - .../styles/themes/atelier-estuary-dark.css | 84 - .../styles/themes/atelier-estuary-light.css | 84 - .../styles/themes/atelier-forest-dark.css | 69 - .../styles/themes/atelier-forest-light.css | 69 - .../styles/themes/atelier-heath-dark.css | 69 - .../styles/themes/atelier-heath-light.css | 69 - .../styles/themes/atelier-lakeside-dark.css | 69 - .../styles/themes/atelier-lakeside-light.css | 69 - .../styles/themes/atelier-plateau-dark.css | 84 - .../styles/themes/atelier-plateau-light.css | 84 - .../styles/themes/atelier-savanna-dark.css | 84 - .../styles/themes/atelier-savanna-light.css | 84 - .../styles/themes/atelier-seaside-dark.css | 69 - .../styles/themes/atelier-seaside-light.css | 69 - .../themes/atelier-sulphurpool-dark.css | 69 - .../themes/atelier-sulphurpool-light.css | 69 - .../highlight/styles/themes/atom-one-dark.css | 96 - .../styles/themes/atom-one-light.css | 96 - .../highlight/styles/themes/brown-paper.css | 63 - .../highlight/styles/themes/codepen-embed.css | 60 - .../highlight/styles/themes/color-brewer.css | 71 - .../highlight/styles/themes/darcula.css | 77 - .../assets/highlight/styles/themes/dark.css | 63 - .../highlight/styles/themes/darkula.css | 6 - .../highlight/styles/themes/default.css | 99 - .../assets/highlight/styles/themes/docco.css | 97 - .../highlight/styles/themes/dracula.css | 76 - .../assets/highlight/styles/themes/far.css | 71 - .../highlight/styles/themes/foundation.css | 88 - .../highlight/styles/themes/github-gist.css | 70 - .../assets/highlight/styles/themes/github.css | 99 - .../highlight/styles/themes/googlecode.css | 88 - .../highlight/styles/themes/grayscale.css | 100 - .../highlight/styles/themes/gruvbox-dark.css | 108 - .../highlight/styles/themes/gruvbox-light.css | 108 - .../highlight/styles/themes/hopscotch.css | 83 - .../assets/highlight/styles/themes/hybrid.css | 102 - .../assets/highlight/styles/themes/idea.css | 97 - .../highlight/styles/themes/ir-black.css | 73 - .../highlight/styles/themes/kimbie.dark.css | 74 - .../highlight/styles/themes/kimbie.light.css | 74 - .../assets/highlight/styles/themes/magula.css | 69 - .../highlight/styles/themes/mono-blue.css | 59 - .../styles/themes/monokai-sublime.css | 83 - .../highlight/styles/themes/monokai.css | 70 - .../highlight/styles/themes/obsidian.css | 88 - .../assets/highlight/styles/themes/ocean.css | 74 - .../highlight/styles/themes/paraiso-dark.css | 72 - .../highlight/styles/themes/paraiso-light.css | 72 - .../highlight/styles/themes/pojoaque.css | 82 - .../highlight/styles/themes/purebasic.css | 96 - .../styles/themes/qtcreator_dark.css | 83 - .../styles/themes/qtcreator_light.css | 83 - .../highlight/styles/themes/railscasts.css | 106 - .../highlight/styles/themes/rainbow.css | 85 - .../highlight/styles/themes/routeros.css | 108 - .../highlight/styles/themes/school-book.css | 66 - .../styles/themes/solarized-dark.css | 84 - .../styles/themes/solarized-light.css | 84 - .../highlight/styles/themes/sunburst.css | 101 - .../styles/themes/tomorrow-night-blue.css | 75 - .../styles/themes/tomorrow-night-bright.css | 73 - .../styles/themes/tomorrow-night-eighties.css | 74 - .../styles/themes/tomorrow-night.css | 75 - .../highlight/styles/themes/tomorrow.css | 71 - .../assets/highlight/styles/themes/vs.css | 67 - .../assets/highlight/styles/themes/vs2015.css | 115 - .../assets/highlight/styles/themes/xcode.css | 92 - .../assets/highlight/styles/themes/xt256.css | 92 - .../highlight/styles/themes/zenburn.css | 80 - .../main/assets/lottie/bounching_ball.json | 1 - .../assets/lottie/code_invite_success.json | 1 - app/src/main/assets/md/github.css | 637 - app/src/main/assets/md/github_dark.css | 642 - app/src/main/assets/md/intercept-hash.js | 43 - app/src/main/assets/md/intercept-touch.js | 29 - .../main/graphql/github/PinnedRepos.graphql | 28 - .../github/PullRequestTimeline.graphql | 521 - .../main/graphql/github/RepoProject.graphql | 157 - app/src/main/java/com/fastaccess/App.java | 84 - .../fastaccess/data/dao/AccessTokenModel.java | 46 - .../fastaccess/data/dao/AppLanguageModel.java | 48 - .../data/dao/AssigneesRequestModel.java | 17 - .../com/fastaccess/data/dao/AuthModel.java | 59 - .../fastaccess/data/dao/BranchesModel.java | 53 - .../data/dao/CommentRequestModel.java | 72 - .../fastaccess/data/dao/CommitCountModel.java | 41 - .../data/dao/CommitFileChanges.java | 83 - .../data/dao/CommitFileListModel.java | 9 - .../fastaccess/data/dao/CommitFileModel.java | 150 - .../fastaccess/data/dao/CommitLinesModel.java | 172 - .../fastaccess/data/dao/CommitListModel.java | 11 - .../data/dao/CommitRequestModel.java | 52 - .../fastaccess/data/dao/CreateGistModel.java | 43 - .../fastaccess/data/dao/CreateIssueModel.java | 47 - .../data/dao/CreateMilestoneModel.java | 18 - .../fastaccess/data/dao/EditRepoFileModel.kt | 44 - .../data/dao/EditReviewCommentModel.java | 49 - .../fastaccess/data/dao/FilesListModel.java | 55 - .../data/dao/FilterOptionsModel.java | 174 - .../data/dao/FragmentPagerAdapterModel.java | 294 - .../data/dao/GistHubErrorsModel.java | 15 - .../data/dao/GitCommitListModel.java | 9 - .../fastaccess/data/dao/GitCommitModel.java | 71 - .../data/dao/GitHubErrorResponse.java | 26 - .../data/dao/GitHubStatusModel.java | 52 - .../fastaccess/data/dao/GithubFileModel.java | 11 - .../com/fastaccess/data/dao/GithubState.java | 39 - .../data/dao/GroupedNotificationModel.java | 84 - .../data/dao/GroupedReviewModel.java | 98 - .../data/dao/ImgurReponseModel.java | 67 - .../data/dao/IssueEventAdapterModel.java | 69 - .../data/dao/IssueRequestModel.java | 89 - .../fastaccess/data/dao/IssuesPageable.java | 53 - .../fastaccess/data/dao/LabelListModel.java | 9 - .../com/fastaccess/data/dao/LabelModel.java | 60 - .../data/dao/LanguageColorModel.java | 38 - .../com/fastaccess/data/dao/LicenseModel.java | 45 - .../fastaccess/data/dao/LockIssuePrModel.java | 14 - .../fastaccess/data/dao/MarkdownModel.java | 39 - .../data/dao/MergeRequestModel.java | 44 - .../data/dao/MergeResponseModel.java | 43 - .../fastaccess/data/dao/MilestoneModel.java | 81 - .../com/fastaccess/data/dao/NameParser.java | 49 - .../data/dao/NotificationSoundModel.kt | 8 - .../data/dao/NotificationSubjectModel.java | 54 - .../NotificationSubscriptionBodyModel.java | 14 - .../com/fastaccess/data/dao/Pageable.java | 55 - .../com/fastaccess/data/dao/PayloadModel.java | 116 - .../data/dao/PostReactionModel.java | 30 - .../fastaccess/data/dao/ProUsersModel.java | 67 - .../fastaccess/data/dao/ProjectCardModel.java | 121 - .../data/dao/ProjectColumnModel.java | 122 - .../fastaccess/data/dao/ProjectsModel.java | 165 - .../data/dao/PullRequestAdapterModel.java | 69 - .../data/dao/PullRequestStatusModel.java | 65 - .../data/dao/PullsIssuesParser.java | 146 - .../fastaccess/data/dao/ReactionsModel.java | 133 - .../data/dao/ReleasesAssetsListModel.java | 9 - .../data/dao/ReleasesAssetsModel.java | 72 - .../com/fastaccess/data/dao/RenameModel.java | 38 - .../fastaccess/data/dao/RepoPathsManager.java | 32 - .../data/dao/RepoPermissionsModel.java | 40 - .../data/dao/RepoSubscriptionModel.java | 20 - .../data/dao/ReviewCommentModel.java | 245 - .../com/fastaccess/data/dao/ReviewModel.java | 155 - .../data/dao/ReviewRequestModel.java | 45 - .../fastaccess/data/dao/SearchCodeModel.java | 56 - .../fastaccess/data/dao/SettingsModel.java | 41 - .../fastaccess/data/dao/SimpleUrlsModel.java | 46 - .../data/dao/SlackInvitePostModel.java | 39 - .../data/dao/SlackResponseModel.java | 36 - .../dao/SparseBooleanArrayParcelable.java | 64 - .../fastaccess/data/dao/StatusesModel.java | 58 - .../data/dao/TabsCountStateModel.java | 76 - .../com/fastaccess/data/dao/TeamsModel.java | 56 - .../fastaccess/data/dao/TimelineModel.java | 223 - .../com/fastaccess/data/dao/TopicsModel.java | 9 - .../data/dao/TreeResponseModel.java | 20 - .../com/fastaccess/data/dao/TrendingModel.kt | 35 - .../fastaccess/data/dao/UsersListModel.java | 11 - .../com/fastaccess/data/dao/WikiModel.java | 49 - .../data/dao/converters/BaseConverter.java | 34 - .../data/dao/converters/CommitConverter.java | 14 - .../dao/converters/CommitFilesConverter.java | 13 - .../data/dao/converters/CommitsConverter.java | 13 - .../data/dao/converters/GistConverter.java | 13 - .../dao/converters/GitCommitConverter.java | 13 - .../dao/converters/GitHubFilesConverter.java | 13 - .../dao/converters/GitHubStateConverter.java | 13 - .../data/dao/converters/IssueConverter.java | 13 - .../data/dao/converters/LabelConverter.java | 13 - .../dao/converters/LabelsListConverter.java | 14 - .../data/dao/converters/LicenseConverter.java | 13 - .../dao/converters/MilestoneConverter.java | 14 - .../NotificationSubjectConverter.java | 14 - .../data/dao/converters/PayloadConverter.java | 13 - .../dao/converters/PullRequestConverter.java | 14 - .../dao/converters/ReactionsConverter.java | 13 - .../converters/ReleasesAssetsConverter.java | 14 - .../data/dao/converters/RenameConverter.java | 13 - .../data/dao/converters/RepoConverter.java | 14 - .../converters/RepoPermissionConverter.java | 13 - .../data/dao/converters/TeamConverter.java | 15 - .../data/dao/converters/TopicsConverter.java | 13 - .../data/dao/converters/UserConverter.java | 14 - .../data/dao/converters/UsersConverter.java | 13 - .../data/dao/model/AbstractComment.java | 224 - .../data/dao/model/AbstractCommit.java | 203 - .../data/dao/model/AbstractEvent.java | 115 - .../model/AbstractFastHubNotification.java | 106 - .../data/dao/model/AbstractGist.java | 257 - .../data/dao/model/AbstractIssue.java | 205 - .../data/dao/model/AbstractIssueEvent.java | 162 - .../data/dao/model/AbstractLogin.java | 263 - .../data/dao/model/AbstractNotification.java | 195 - .../dao/model/AbstractNotificationQueue.java | 77 - .../data/dao/model/AbstractPinnedGists.java | 76 - .../data/dao/model/AbstractPinnedIssues.java | 92 - .../dao/model/AbstractPinnedPullRequests.java | 92 - .../data/dao/model/AbstractPinnedRepos.java | 150 - .../data/dao/model/AbstractPullRequest.java | 335 - .../data/dao/model/AbstractRelease.java | 168 - .../data/dao/model/AbstractRepo.java | 419 - .../data/dao/model/AbstractRepoFile.java | 126 - .../data/dao/model/AbstractSearchHistory.java | 85 - .../data/dao/model/AbstractUser.java | 274 - .../data/dao/model/AbstractViewerFile.java | 69 - .../data/dao/timeline/AuthorModel.java | 38 - .../data/dao/timeline/CommentEvent.java | 126 - .../data/dao/timeline/GenericEvent.java | 119 - .../data/dao/timeline/ParentsModel.java | 35 - .../dao/timeline/PullRequestCommitModel.java | 98 - .../dao/timeline/PullRequestReviewModel.java | 169 - .../timeline/PullRequestTimelineModel.java | 85 - .../data/dao/timeline/SourceModel.java | 51 - .../fastaccess/data/dao/types/EventsType.java | 52 - .../fastaccess/data/dao/types/FilesType.java | 27 - .../data/dao/types/GitEntryType.java | 7 - .../data/dao/types/IssueEventType.java | 58 - .../fastaccess/data/dao/types/IssueState.java | 21 - .../data/dao/types/MyIssuesType.java | 13 - .../data/dao/types/NotificationReason.java | 12 - .../data/dao/types/NotificationType.java | 23 - .../data/dao/types/ReactionTypes.java | 46 - .../data/dao/types/ReviewStateType.java | 45 - .../data/dao/types/StatusStateType.java | 36 - .../data/dao/wiki/WikiContentModel.kt | 27 - .../data/dao/wiki/WikiSideBarModel.kt | 24 - .../fastaccess/data/service/ContentService.kt | 30 - .../fastaccess/data/service/GistService.java | 78 - .../fastaccess/data/service/ImgurService.java | 20 - .../fastaccess/data/service/IssueService.java | 127 - .../data/service/LoginRestService.java | 30 - .../data/service/NotificationService.java | 66 - .../data/service/OrganizationService.java | 51 - .../data/service/ProjectsService.kt | 58 - .../data/service/PullRequestService.java | 87 - .../data/service/ReactionsService.java | 88 - .../fastaccess/data/service/RepoService.java | 193 - .../data/service/ReviewService.java | 72 - .../data/service/SearchService.java | 30 - .../fastaccess/data/service/SlackService.java | 20 - .../data/service/UserRestService.java | 82 - .../main/java/com/fastaccess/github/App.kt | 42 + .../fastaccess/github/base/BaseActivity.kt | 72 + .../base/BaseBottomSheetDialogFragment.kt | 164 + .../github/base/BaseDialogFragment.kt | 72 + .../fastaccess/github/base/BaseFragment.kt | 172 + .../github/base/BasePagerFragment.kt | 24 + .../fastaccess/github/base/BaseViewModel.kt | 95 + .../github/base/callback/UpdateTabCount.kt | 10 + .../github/base/engine/ThemeEngine.kt | 39 + .../github/di/annotations/ForActivity.kt | 11 + .../github/di/annotations/ForApplication.kt | 10 + .../github/di/annotations/ForAuth.kt | 11 + .../fastaccess/github/di/annotations/ForDB.kt | 11 + .../github/di/annotations/ViewModelKey.kt | 15 + .../github/di/annotations/WorkerKey.kt | 10 + .../github/di/components/AppComponent.kt | 71 + .../di/components/WorkerSubComponent.kt | 22 + .../di/modules/ActivityBindingModule.kt | 27 + .../github/di/modules/ActivityModule.kt | 9 + .../github/di/modules/ApplicationModule.kt | 23 + .../di/modules/DialogFragmentBindingModule.kt | 19 + .../di/modules/FastHubDatabaseModule.kt | 52 + .../di/modules/FragmentBindingModule.kt | 65 + .../github/di/modules/FragmentModule.kt | 51 + .../github/di/modules/NetworkModule.kt | 233 + .../github/di/modules/RepositoryModule.kt | 94 + .../github/di/modules/UseCaseModule.kt | 187 + .../github/di/modules/ViewModelModule.kt | 99 + .../github/di/modules/WorkersModule.kt | 24 + .../github/di/scopes/PerActivity.kt | 10 + .../github/di/scopes/PerFragment.kt | 10 + .../github/platform/deeplink/AppDeepLink.kt | 6 + .../platform/deeplink/RawWebDeepLink.kt | 6 + .../github/platform/deeplink/WebDeepLink.kt | 8 + .../platform/extension/ClickExtenion.kt | 41 + .../platform}/fabric/FabricProvider.kt | 17 +- .../github/platform/glide/GlideModule.kt | 8 + .../github/platform/timber/LogTree.kt | 36 + .../viewmodel/FastHubViewModelFactory.kt | 26 + .../workmanager/DaggerWorkerFactory.kt | 51 + .../works/MarkAsReadNotificationWorker.kt | 72 + .../github/platform/works/ReactionWorker.kt | 55 + .../ui/adapter/AllNotificationsAdapter.kt | 52 + .../github/ui/adapter/AssigneesAdapter.kt | 45 + .../github/ui/adapter/IssueTimelineAdapter.kt | 75 + .../github/ui/adapter/LabelColorAdapter.kt | 23 + .../github/ui/adapter/LabelsAdapter.kt | 45 + .../github/ui/adapter/LanguagesAdapter.kt | 39 + .../github/ui/adapter/LoggedInUsersAdapter.kt | 30 + .../github/ui/adapter/MainScreenAdapter.kt | 96 + .../github/ui/adapter/MilestonesAdapter.kt | 35 + .../github/ui/adapter/MyIssuesPrsAdapter.kt | 34 + .../github/ui/adapter/OrganizationsAdapter.kt | 30 + .../github/ui/adapter/PagerAdapter.kt | 20 + .../github/ui/adapter/ProfileFeedsAdapter.kt | 30 + .../ProfileFollowingFollowersAdapter.kt | 30 + .../github/ui/adapter/ProfileGistsAdapter.kt | 23 + .../github/ui/adapter/ProfileOrgsAdapter.kt | 24 + .../ui/adapter/ProfilePinnedReposAdapter.kt | 24 + .../github/ui/adapter/ProfileReposAdapter.kt | 23 + .../ui/adapter/ProfileStarredReposAdapter.kt | 23 + .../github/ui/adapter/SearchReposAdapter.kt | 22 + .../github/ui/adapter/ShortUsersAdapter.kt | 30 + .../github/ui/adapter/TrendingsAdapter.kt | 22 + .../ui/adapter/UnreadNotificationsAdapter.kt | 23 + .../ui/adapter/base/BasePagedAdapter.kt | 56 + .../github/ui/adapter/base/BaseViewHolder.kt | 14 + .../adapter/viewholder/AssigneeViewHolder.kt | 25 + .../adapter/viewholder/CommentViewHolder.kt | 83 + .../ui/adapter/viewholder/FeedsViewHolder.kt | 378 + .../viewholder/IssueContentViewHolder.kt | 219 + .../viewholder/LabelColorViewHolder.kt | 23 + .../ui/adapter/viewholder/LabelViewHolder.kt | 24 + .../adapter/viewholder/LanguagesViewHolder.kt | 33 + .../adapter/viewholder/LoadingViewHolder.kt | 14 + .../viewholder/LoggedInUserViewHolder.kt | 26 + .../adapter/viewholder/MilestoneViewHolder.kt | 25 + .../viewholder/MyIssuesPrsViewHolder.kt | 47 + .../viewholder/NotificationsViewHolder.kt | 58 + .../viewholder/OrganizationViewHolder.kt | 28 + .../ProfileFollowerFollowingViewHolder.kt | 26 + .../viewholder/ProfileGistsViewHolder.kt | 32 + .../viewholder/ProfileOrgsViewHolder.kt | 20 + .../ProfilePinnedReposViewHolder.kt | 35 + .../viewholder/ReposProfileViewHolder.kt | 48 + .../ReposStarredProfileViewHolder.kt | 48 + .../adapter/viewholder/ShortRepoViewHolder.kt | 43 + .../adapter/viewholder/ShortUserViewHolder.kt | 26 + .../viewholder/TitleSectionViewHolder.kt | 18 + .../adapter/viewholder/TrendingViewHolder.kt | 31 + .../ui/modules/auth/LoginChooserActivity.kt | 137 + .../ui/modules/auth/LoginChooserViewModel.kt | 70 + .../auth/callback/LoginChooserCallback.kt | 17 + .../auth/chooser/LoginChooserFragment.kt | 82 + .../modules/auth/login/AuthLoginFragment.kt | 149 + .../ui/modules/auth/login/LoginViewModel.kt | 108 + .../modules/editor/EditorWebViewActivity.kt | 24 + .../ui/modules/feed/fragment/FeedsFragment.kt | 76 + .../feed/fragment/viewmodel/FeedsViewModel.kt | 48 + .../github/ui/modules/issue/IssueActivity.kt | 33 + .../modules/issue/fragment/IssueFragment.kt | 292 + .../viewmodel/IssueTimelineViewModel.kt | 108 + .../issuesprs/edit/LockUnlockFragment.kt | 59 + .../edit/assignees/AssigneesFragment.kt | 121 + .../assignees/viewmodel/AssigneesViewModel.kt | 60 + .../issuesprs/edit/labels/LabelsFragment.kt | 133 + .../edit/labels/create/CreateLabelFragment.kt | 62 + .../edit/labels/viewmodel/LabelsViewModel.kt | 75 + .../CreateMilestoneDialogFragment.kt | 71 + .../edit/milestone/MilestoneFragment.kt | 130 + .../milestone/viewmodel/MilestoneViewModel.kt | 77 + .../filter/FilterIssuesPrsBottomSheet.kt | 126 + .../FilterIssuePullRequestsFragment.kt | 95 + .../FilterIssuePullRequestsViewModel.kt | 75 + .../github/ui/modules/main/MainActivity.kt | 25 + .../ui/modules/main/fragment/MainFragment.kt | 176 + .../viewmodel/MainFragmentViewModel.kt | 137 + .../multipurpose/MultiPurposeActivity.kt | 52 + .../MultiPurposeBottomSheetDialog.kt | 80 + .../NotificationPagerFragment.kt | 61 + .../fragment/read/AllNotificationsFragment.kt | 55 + .../read/AllNotificationsViewModel.kt | 25 + .../unread/UnreadNotificationsFragment.kt | 94 + .../viewmodel/UnreadNotificationsViewModel.kt | 52 + .../ui/modules/profile/ProfileActivity.kt | 35 + .../profile/feeds/ProfileFeedFragment.kt | 82 + .../feeds/viewmodel/ProfileFeedsViewModel.kt | 49 + .../ProfileFollowersFragment.kt | 81 + .../viewmodel/FollowersFollowingViewModel.kt | 51 + .../profile/fragment/ProfileFragment.kt | 229 + .../fragment/viewmodel/ProfileViewModel.kt | 64 + .../profile/gists/ProfileGistsFragment.kt | 77 + .../gists/viewmodel/ProfileGistsViewModel.kt | 45 + .../profile/orgs/userorgs/UserOrgsFragment.kt | 71 + .../userorgs/viewmodel/UserOrgsViewModel.kt | 43 + .../profile/repos/ProfileReposFragment.kt | 76 + .../repos/viewmodel/ProfileReposViewModel.kt | 45 + .../starred/ProfileStarredReposFragment.kt | 76 + .../viewmodel/ProfileStarredReposViewModel.kt | 45 + .../ui/modules/routing/RoutingActivity.kt | 24 + .../ui/modules/routing/RoutingModule.kt | 9 + .../search/filter/FilterSearchBottomSheet.kt | 250 + .../modules/search/fragment/SearchFragment.kt | 149 + .../viewmodel/FilterSearchViewModel.kt | 133 + .../ui/modules/trending/TrendingActivity.kt | 25 + .../filter/FilterTrendingBottomSheet.kt | 89 + .../trending/fragment/TrendingFragment.kt | 84 + .../fragment/viewmodel/TrendingViewModel.kt | 78 + .../github/ui/widget/AnchorSheetBehavior.java | 950 + .../ui/widget/AppBarBottomSheetBehaviour.kt | 39 + .../github/ui/widget/AvatarImageView.kt | 38 + .../ui/widget/ParentSwipeRefreshLayout.kt | 35 + .../github/ui/widget/ReactionsChipGroup.kt | 91 + .../github/ui/widget/ViewPagerView.kt | 67 + .../ui/widget/dialog/IconDialogFragment.kt | 82 + .../widget/recyclerview/BaseRecyclerView.kt | 104 + .../EndlessRecyclerViewScrollListener.kt | 90 + .../recyclerview/RecyclerViewFastScroller.kt | 206 + .../recyclerview/SwipeToDeleteCallback.kt | 107 + .../decoration/InsetDividerDecoration.kt | 59 + .../recyclerview/lm/SafeGridLayoutManager.kt | 52 + .../lm/SafeLinearLayoutManager.kt | 31 + .../lm/SafeStaggeredLayoutManager.kt | 28 + .../usecase/auth/GetAccessTokenUseCase.kt | 24 + .../github/usecase/auth/LoginUseCase.kt | 33 + .../auth/LoginWithAccessTokenUseCase.kt | 28 + .../github/usecase/feed/FeedsUseCase.kt | 16 + .../usecase/issuesprs/AddAssigneesUseCase.kt | 28 + .../issuesprs/CloseOpenIssuePrUseCase.kt | 40 + .../usecase/issuesprs/CreateLabelUseCase.kt | 26 + .../issuesprs/CreateMilestoneUseCase.kt | 24 + .../usecase/issuesprs/FilterIssuesUseCase.kt | 119 + .../issuesprs/FilterPullRequestsUseCase.kt | 100 + .../usecase/issuesprs/GetAssigneesUseCase.kt | 40 + .../issuesprs/GetIssueTimelineUseCase.kt | 234 + .../usecase/issuesprs/GetIssueUseCase.kt | 55 + .../usecase/issuesprs/GetLabelsUseCase.kt | 40 + .../usecase/issuesprs/GetMilestonesUseCase.kt | 43 + .../issuesprs/LockUnlockIssuePrUseCase.kt | 53 + .../issuesprs/MilestoneIssuePrUseCase.kt | 45 + .../usecase/issuesprs/PutLabelsUseCase.kt | 30 + .../usecase/main/FeedsMainScreenUseCase.kt | 13 + .../usecase/main/IssuesMainScreenUseCase.kt | 48 + .../main/PullRequestsMainScreenUseCase.kt | 47 + .../notification/NotificationUseCase.kt | 53 + .../search/FilterSearchReposUseCase.kt | 68 + .../search/FilterSearchUsersUseCase.kt | 38 + .../usecase/user/BlockUnblockUserUseCase.kt | 25 + .../usecase/user/FollowUnfollowUserUseCase.kt | 29 + .../usecase/user/IsUserBlockedUseCase.kt | 18 + .../github/usecase/user/UserFeedsUseCase.kt | 21 + .../github/usecase/user/UserUseCase.kt | 18 + .../com/fastaccess/github/utils/Constants.kt | 51 + .../extensions/ActivityFragmentExtension.kt | 41 + .../github/utils/extensions/PrefExtension.kt | 96 + .../github/utils/extensions/ViewExtension.kt | 174 + .../com/fastaccess/helper/ActivityHelper.java | 266 - .../com/fastaccess/helper/AnimHelper.java | 208 - .../java/com/fastaccess/helper/AppHelper.java | 200 - .../com/fastaccess/helper/BundleConstant.java | 67 - .../java/com/fastaccess/helper/Bundler.java | 239 - .../fastaccess/helper/CustomTabsHelper.java | 113 - .../fastaccess/helper/DeviceNameGetter.java | 50 - .../com/fastaccess/helper/FileHelper.java | 90 - .../fastaccess/helper/GithubConfigHelper.java | 23 - .../com/fastaccess/helper/InputHelper.java | 91 - .../java/com/fastaccess/helper/Logger.java | 76 - .../com/fastaccess/helper/ObjectsCompat.java | 14 - .../com/fastaccess/helper/ParcelableHelper.kt | 18 - .../fastaccess/helper/ParseDateFormat.java | 86 - .../com/fastaccess/helper/PrefGetter.java | 519 - .../com/fastaccess/helper/PrefHelper.java | 88 - .../java/com/fastaccess/helper/RxHelper.java | 32 - .../com/fastaccess/helper/TypeFaceHelper.java | 25 - .../com/fastaccess/helper/ViewHelper.java | 212 - .../provider/colors/ColorsProvider.java | 88 - .../com/fastaccess/provider/emoji/Emoji.java | 217 - .../provider/emoji/EmojiLoader.java | 80 - .../provider/emoji/EmojiManager.java | 110 - .../provider/emoji/EmojiParser.java | 515 - .../fastaccess/provider/emoji/EmojiTrie.java | 111 - .../provider/emoji/Fitzpatrick.java | 58 - .../provider/fcm/PushNotificationService.java | 58 - .../provider/gson/ToGsonProvider.java | 35 - .../provider/markdown/CachedComments.kt | 29 - .../provider/markdown/MarkDownProvider.java | 339 - .../markdown/extension/emoji/Emoji.java | 21 - .../extension/emoji/EmojiExtension.java | 28 - .../internal/EmojiDelimiterProcessor.java | 42 - .../emoji/internal/EmojiNodeRenderer.java | 41 - .../markdown/extension/mention/Mention.java | 21 - .../extension/mention/MentionExtension.java | 28 - .../internal/MentionDelimiterProcessor.java | 42 - .../mention/internal/MentionNodeRenderer.java | 43 - .../provider/rest/ApolloProdivder.kt | 23 - .../provider/rest/ImgurProvider.java | 62 - .../provider/rest/LoginProvider.java | 69 - .../provider/rest/RepoQueryProvider.java | 48 - .../provider/rest/RestProvider.java | 224 - .../converters/GithubResponseConverter.java | 47 - .../interceptors/AuthenticationInterceptor.kt | 40 - .../interceptors/ContentTypeInterceptor.kt | 19 - .../interceptors/PaginationInterceptor.java | 63 - .../provider/rest/jsoup/JsoupProvider.java | 54 - .../provider/rest/loadmore/OnLoadMore.java | 39 - .../provider/scheme/LinkParserHelper.java | 141 - .../provider/scheme/SchemeParser.java | 578 - .../tasks/git/GithubActionService.java | 235 - .../provider/tasks/git/ReactionService.java | 109 - .../NotificationSchedulerJobTask.java | 305 - .../notification/ReadNotificationService.java | 163 - .../tasks/slack/SlackInvitationService.java | 46 - .../tasks/version/CheckVersionService.kt | 28 - .../fastaccess/provider/theme/ThemeEngine.kt | 270 - .../provider/timeline/CommentsHelper.java | 191 - .../provider/timeline/HtmlHelper.java | 207 - .../provider/timeline/ReactionsProvider.java | 109 - .../provider/timeline/TimelineConverter.kt | 133 - .../provider/timeline/TimelineProvider.java | 208 - .../handler/BetterLinkMovementExtended.java | 267 - .../handler/CodeBackgroundRoundedSpan.java | 52 - .../timeline/handler/DrawableHandler.java | 52 - .../timeline/handler/EmojiHandler.java | 38 - .../timeline/handler/HeaderHandler.kt | 33 - .../provider/timeline/handler/HrHandler.java | 33 - .../provider/timeline/handler/HrSpan.java | 43 - .../timeline/handler/ItalicHandler.java | 21 - .../timeline/handler/LinkHandler.java | 27 - .../timeline/handler/ListsHandler.java | 82 - .../timeline/handler/MarginHandler.java | 27 - .../timeline/handler/PreTagHandler.java | 87 - .../timeline/handler/QuoteHandler.java | 26 - .../handler/StrikethroughHandler.java | 16 - .../timeline/handler/SubScriptHandler.java | 17 - .../timeline/handler/SuperScriptHandler.java | 18 - .../timeline/handler/TableHandler.java | 252 - .../timeline/handler/UnderlineHandler.java | 15 - .../handler/drawable/DrawableGetter.java | 67 - .../handler/drawable/GlideDrawableTarget.java | 54 - .../handler/drawable/UrlDrawable.java | 55 - .../ui/adapter/AssigneesAdapter.java | 40 - .../ui/adapter/BranchesAdapter.java | 55 - .../ui/adapter/ColumnCardAdapter.kt | 21 - .../ui/adapter/CommentsAdapter.java | 30 - .../ui/adapter/CommitCommentsAdapter.kt | 26 - .../ui/adapter/CommitFilesAdapter.java | 42 - .../ui/adapter/CommitLinesAdapter.java | 28 - .../fastaccess/ui/adapter/CommitsAdapter.java | 30 - .../com/fastaccess/ui/adapter/EmojiAdapter.kt | 58 - .../ui/adapter/FastHubNotificationsAdapter.kt | 25 - .../fastaccess/ui/adapter/FeedsAdapter.java | 37 - .../ui/adapter/FragmentsPagerAdapter.java | 53 - .../ui/adapter/GistFilesAdapter.java | 39 - .../fastaccess/ui/adapter/GistsAdapter.java | 37 - .../fastaccess/ui/adapter/IssuesAdapter.java | 52 - .../ui/adapter/IssuesTimelineAdapter.java | 109 - .../ui/adapter/LabelColorsAdapter.java | 30 - .../fastaccess/ui/adapter/LabelsAdapter.java | 41 - .../com/fastaccess/ui/adapter/LoginAdapter.kt | 22 - .../ui/adapter/MilestonesAdapter.java | 31 - .../ui/adapter/NotificationsAdapter.java | 64 - .../ui/adapter/PinnedReposAdapter.java | 37 - .../ui/adapter/ProfileOrgsAdapter.java | 23 - .../ui/adapter/ProfilePinnedReposAdapter.kt | 27 - .../fastaccess/ui/adapter/ProjectsAdapter.kt | 20 - .../ui/adapter/PullRequestAdapter.java | 47 - .../ui/adapter/ReleasesAdapter.java | 30 - .../ui/adapter/RepoFilePathsAdapter.java | 32 - .../ui/adapter/RepoFilesAdapter.java | 32 - .../fastaccess/ui/adapter/ReposAdapter.java | 38 - .../ui/adapter/ReviewCommentsAdapter.java | 47 - .../ui/adapter/SearchCodeAdapter.java | 39 - .../ui/adapter/SettingsAdapter.java | 70 - .../ui/adapter/SimpleListAdapter.java | 27 - .../fastaccess/ui/adapter/SpinnerAdapter.java | 74 - .../fastaccess/ui/adapter/TeamsAdapter.java | 29 - .../fastaccess/ui/adapter/TopicsAdapter.java | 49 - .../fastaccess/ui/adapter/TrendingAdapter.kt | 25 - .../fastaccess/ui/adapter/UsersAdapter.java | 43 - .../ui/adapter/callback/OnToggleView.java | 7 - .../adapter/callback/ReactionsCallback.java | 11 - .../viewholder/AssigneesViewHolder.java | 62 - .../viewholder/ColumnCardViewHolder.kt | 52 - .../viewholder/CommentsViewHolder.java | 91 - .../viewholder/CommitCommentsViewHolder.kt | 121 - .../viewholder/CommitLinesViewHolder.java | 72 - .../viewholder/CommitThreadViewHolder.kt | 83 - .../adapter/viewholder/CommitsViewHolder.java | 61 - .../ui/adapter/viewholder/EmojiViewHolder.kt | 29 - .../FastHubNotificationViewHolder.kt | 32 - .../adapter/viewholder/FeedsViewHolder.java | 469 - .../viewholder/GistFilesViewHolder.java | 52 - .../adapter/viewholder/GistsViewHolder.java | 57 - .../viewholder/GroupedReviewsViewHolder.java | 149 - .../viewholder/IssueDetailsViewHolder.java | 276 - .../viewholder/IssueTimelineViewHolder.java | 82 - .../adapter/viewholder/IssuesViewHolder.java | 125 - .../viewholder/LabelColorsViewHolder.java | 40 - .../adapter/viewholder/LabelsViewHolder.java | 70 - .../ui/adapter/viewholder/LoginViewHolder.kt | 41 - .../viewholder/MilestonesViewHolder.java | 44 - .../NotificationsHeaderViewHolder.java | 42 - .../viewholder/NotificationsViewHolder.java | 77 - .../viewholder/PinnedReposViewHolder.java | 90 - .../viewholder/ProfileOrgsViewHolder.java | 41 - .../ProfilePinnedReposViewHolder.kt | 53 - .../adapter/viewholder/ProjectViewHolder.kt | 38 - .../viewholder/PullRequestEventViewHolder.kt | 414 - .../PullRequestFilesViewHolder.java | 148 - .../viewholder/PullRequestViewHolder.java | 64 - .../viewholder/PullStatusViewHolder.java | 105 - .../viewholder/ReleasesViewHolder.java | 56 - .../viewholder/RepoFilePathsViewHolder.java | 34 - .../viewholder/RepoFilesViewHolder.java | 62 - .../adapter/viewholder/ReposViewHolder.java | 103 - .../viewholder/ReviewCommentsViewHolder.java | 241 - .../adapter/viewholder/ReviewsViewHolder.kt | 62 - .../viewholder/SearchCodeViewHolder.java | 47 - .../adapter/viewholder/SimpleViewHolder.java | 29 - .../adapter/viewholder/TeamsViewHolder.java | 42 - .../TimelineCommentsViewHolder.java | 270 - .../adapter/viewholder/TrendingViewHolder.kt | 54 - .../viewholder/UnknownTypeViewHolder.kt | 11 - .../adapter/viewholder/UsersViewHolder.java | 57 - .../com/fastaccess/ui/base/BaseActivity.java | 554 - .../ui/base/BaseBottomSheetDialog.java | 137 - .../ui/base/BaseDialogFragment.java | 186 - .../com/fastaccess/ui/base/BaseFragment.java | 151 - .../BaseMvpBottomSheetDialogFragment.java | 166 - .../com/fastaccess/ui/base/MainNavDrawer.kt | 50 - .../com/fastaccess/ui/base/mvp/BaseMvp.java | 92 - .../ui/base/mvp/presenter/BasePresenter.java | 137 - .../modules/about/FastHubAboutActivity.java | 180 - .../changelog/ChangelogBottomSheetDialog.java | 82 - .../ui/modules/changelog/ChangelogMvp.java | 20 - .../modules/changelog/ChangelogPresenter.java | 24 - .../ui/modules/code/CodeViewerActivity.java | 142 - .../ui/modules/editor/EditorActivity.kt | 230 - .../fastaccess/ui/modules/editor/EditorMvp.kt | 44 - .../ui/modules/editor/EditorPresenter.kt | 157 - .../editor/comment/CommentEditorFragment.kt | 174 - .../modules/editor/emoji/EmojiBottomSheet.kt | 76 - .../ui/modules/editor/emoji/EmojiMvp.kt | 24 - .../ui/modules/editor/emoji/EmojiPresenter.kt | 29 - .../popup/EditorLinkImageDialogFragment.java | 125 - .../editor/popup/EditorLinkImageMvp.java | 27 - .../popup/EditorLinkImagePresenter.java | 36 - .../ui/modules/feeds/FeedsFragment.java | 186 - .../fastaccess/ui/modules/feeds/FeedsMvp.java | 49 - .../ui/modules/feeds/FeedsPresenter.java | 200 - .../chooser/FilterAddChooserListener.java | 12 - .../FilterChooserBottomSheetDialog.java | 52 - .../filter/issues/FilterIssuesActivity.java | 585 - .../issues/FilterIssuesActivityMvp.java | 20 - .../issues/FilterIssuesActivityPresenter.java | 52 - .../issues/fragment/FilterIssueFragment.java | 171 - .../issues/fragment/FilterIssuePresenter.java | 75 - .../issues/fragment/FilterIssuesMvp.java | 45 - .../ui/modules/gists/GistsFragment.java | 131 - .../ui/modules/gists/GistsListActivity.java | 111 - .../fastaccess/ui/modules/gists/GistsMvp.java | 35 - .../ui/modules/gists/GistsPresenter.java | 82 - .../gists/create/CreateGistActivity.java | 183 - .../modules/gists/create/CreateGistMvp.java | 36 - .../gists/create/CreateGistPresenter.java | 44 - .../create/dialog/AddGistBottomSheetDialog.kt | 130 - .../modules/gists/create/dialog/AddGistMvp.kt | 19 - .../gists/create/dialog/AddGistPresenter.kt | 8 - .../ui/modules/gists/gist/GistActivity.java | 331 - .../ui/modules/gists/gist/GistMvp.java | 59 - .../ui/modules/gists/gist/GistPresenter.java | 121 - .../gist/comments/GistCommentsFragment.java | 271 - .../gists/gist/comments/GistCommentsMvp.java | 63 - .../gist/comments/GistCommentsPresenter.java | 152 - .../gist/files/GistFilesListFragment.java | 191 - .../gists/gist/files/GistFilesListMvp.java | 39 - .../gist/files/GistFilesListPresenter.java | 48 - .../gists/starred/StarredGistsFragment.java | 145 - .../gists/starred/StarredGistsMvp.java | 37 - .../gists/starred/StarredGistsPresenter.java | 78 - .../ui/modules/login/LoginActivity.java | 262 - .../fastaccess/ui/modules/login/LoginMvp.java | 45 - .../ui/modules/login/LoginPresenter.java | 158 - .../login/chooser/LoginChooserActivity.kt | 138 - .../modules/login/chooser/LoginChooserMvp.kt | 14 - .../login/chooser/LoginChooserPresenter.kt | 12 - .../ui/modules/main/MainActivity.java | 217 - .../fastaccess/ui/modules/main/MainMvp.java | 59 - .../ui/modules/main/MainPresenter.java | 138 - .../main/donation/CheckPurchaseActivity.kt | 79 - .../modules/main/donation/DonateActivity.kt | 118 - .../main/donation/DonationActivity.java | 102 - .../main/drawer/AccountDrawerFragment.kt | 132 - .../modules/main/drawer/MainDrawerFragment.kt | 78 - .../modules/main/issues/MyIssuesFragment.java | 198 - .../ui/modules/main/issues/MyIssuesMvp.java | 43 - .../main/issues/MyIssuesPresenter.java | 104 - .../issues/pager/MyIssuesPagerFragment.java | 195 - .../main/issues/pager/MyIssuesPagerMvp.java | 15 - .../issues/pager/MyIssuesPagerPresenter.java | 9 - .../FastHubNotificationDialog.kt | 77 - .../main/orgs/OrgListDialogFragment.java | 108 - .../modules/main/orgs/OrgListDialogMvp.java | 28 - .../main/orgs/OrgListDialogPresenter.java | 47 - .../playstore/PlayStoreWarningActivity.kt | 40 - .../main/premium/GmsTaskListeners.java | 48 - .../modules/main/premium/PremiumActivity.kt | 190 - .../ui/modules/main/premium/PremiumMvp.kt | 18 - .../modules/main/premium/PremiumPresenter.kt | 71 - .../pullrequests/MyPullRequestFragment.java | 194 - .../main/pullrequests/MyPullRequestsMvp.java | 43 - .../pullrequests/MyPullRequestsPresenter.java | 104 - .../pager/MyPullsPagerFragment.java | 196 - .../pullrequests/pager/MyPullsPagerMvp.java | 15 - .../pager/MyPullsPagerPresenter.java | 9 - .../notification/NotificationActivity.java | 103 - .../all/AllNotificationsFragment.java | 201 - .../notification/all/AllNotificationsMvp.java | 51 - .../all/AllNotificationsPresenter.java | 142 - .../OnNotificationChangedListener.java | 10 - .../fasthub/FastHubNotificationsFragment.kt | 59 - .../fasthub/FastHubNotificationsMvp.kt | 20 - .../fasthub/FastHubNotificationsPresenter.kt | 22 - .../unread/UnreadNotificationMvp.java | 45 - .../unread/UnreadNotificationsFragment.java | 197 - .../unread/UnreadNotificationsPresenter.java | 93 - .../modules/parser/LinksParserActivity.java | 66 - .../modules/pinned/PinnedReposActivity.java | 65 - .../pinned/gist/PinnedGistFragment.java | 91 - .../ui/modules/pinned/gist/PinnedGistMvp.java | 30 - .../pinned/gist/PinnedGistPresenter.java | 47 - .../pinned/issue/PinnedIssueFragment.java | 91 - .../modules/pinned/issue/PinnedIssueMvp.java | 30 - .../pinned/issue/PinnedIssuePresenter.java | 47 - .../PinnedPullRequestFragment.java | 92 - .../pullrequest/PinnedPullRequestMvp.java | 30 - .../PinnedPullRequestPresenter.java | 47 - .../pinned/repo/PinnedReposFragment.java | 90 - .../modules/pinned/repo/PinnedReposMvp.java | 30 - .../pinned/repo/PinnedReposPresenter.java | 49 - .../modules/profile/ProfilePagerFragment.java | 70 - .../ui/modules/profile/ProfilePagerMvp.java | 21 - .../profile/ProfilePagerPresenter.java | 9 - .../followers/ProfileFollowersFragment.java | 131 - .../followers/ProfileFollowersMvp.java | 36 - .../followers/ProfileFollowersPresenter.java | 90 - .../following/ProfileFollowingFragment.java | 131 - .../following/ProfileFollowingMvp.java | 36 - .../following/ProfileFollowingPresenter.java | 90 - .../profile/gists/ProfileGistsFragment.java | 155 - .../profile/gists/ProfileGistsMvp.java | 37 - .../profile/gists/ProfileGistsPresenter.java | 91 - .../org/OrgProfileOverviewFragment.java | 154 - .../profile/org/OrgProfileOverviewMvp.java | 27 - .../org/OrgProfileOverviewPresenter.java | 49 - .../org/members/OrgMembersFragment.java | 130 - .../profile/org/members/OrgMembersMvp.java | 36 - .../org/members/OrgMembersPresenter.java | 76 - .../profile/org/project/OrgProjectActivity.kt | 63 - .../profile/org/repos/OrgReposFragment.java | 160 - .../profile/org/repos/OrgReposMvp.java | 38 - .../profile/org/repos/OrgReposPresenter.java | 108 - .../profile/org/teams/OrgTeamFragment.java | 130 - .../modules/profile/org/teams/OrgTeamMvp.java | 36 - .../profile/org/teams/OrgTeamPresenter.java | 81 - .../org/teams/details/TeamPagerActivity.java | 101 - .../details/members/TeamMembersFragment.java | 130 - .../teams/details/members/TeamMembersMvp.java | 36 - .../details/members/TeamMembersPresenter.java | 76 - .../details/repos/TeamReposFragment.java | 131 - .../org/teams/details/repos/TeamReposMvp.java | 35 - .../details/repos/TeamReposPresenter.java | 78 - .../overview/ProfileOverviewFragment.java | 319 - .../profile/overview/ProfileOverviewMvp.java | 63 - .../overview/ProfileOverviewPresenter.java | 197 - .../ProfileReposFilterBottomSheetDialog.java | 118 - .../profile/repos/ProfileReposFragment.java | 162 - .../profile/repos/ProfileReposMvp.java | 41 - .../profile/repos/ProfileReposPresenter.java | 127 - .../starred/ProfileStarredFragment.java | 153 - .../profile/starred/ProfileStarredMvp.java | 37 - .../starred/ProfileStarredPresenter.java | 115 - .../ui/modules/repos/DummyFragment.java | 21 - .../ui/modules/repos/RepoPagerActivity.java | 642 - .../ui/modules/repos/RepoPagerMvp.java | 127 - .../ui/modules/repos/RepoPagerPresenter.java | 316 - .../repos/code/RepoCodePagerFragment.java | 132 - .../modules/repos/code/RepoCodePagerMvp.java | 19 - .../repos/code/RepoCodePagerPresenter.java | 9 - .../code/commit/RepoCommitsFragment.java | 189 - .../repos/code/commit/RepoCommitsMvp.java | 49 - .../code/commit/RepoCommitsPresenter.java | 138 - .../commit/details/CommitPagerActivity.java | 295 - .../code/commit/details/CommitPagerMvp.java | 46 - .../commit/details/CommitPagerPresenter.java | 103 - .../comments/CommitCommentsFragment.java | 316 - .../details/comments/CommitCommentsMvp.java | 82 - .../comments/CommitCommentsPresenter.java | 214 - .../details/files/CommitFilesFragment.java | 180 - .../commit/details/files/CommitFilesMvp.java | 46 - .../details/files/CommitFilesPresenter.java | 120 - .../details/files/CommitFilesSingleton.java | 39 - .../history/FileCommitHistoryActivity.kt | 76 - .../commit/viewer/FullCommitFileActivity.java | 135 - .../RepoContributorsFragment.java | 136 - .../contributors/RepoContributorsMvp.java | 38 - .../RepoContributorsPresenter.java | 90 - .../repos/code/files/RepoFilesFragment.java | 253 - .../repos/code/files/RepoFilesMvp.java | 54 - .../repos/code/files/RepoFilesPresenter.java | 130 - .../files/activity/RepoFilesActivity.java | 167 - .../files/paths/RepoFilePathFragment.java | 289 - .../code/files/paths/RepoFilePathMvp.java | 54 - .../files/paths/RepoFilePathPresenter.java | 95 - .../repos/code/prettifier/ViewerFragment.java | 276 - .../repos/code/prettifier/ViewerMvp.java | 56 - .../code/prettifier/ViewerPresenter.java | 184 - .../code/releases/ReleasesListActivity.java | 113 - .../code/releases/RepoReleasesFragment.java | 197 - .../repos/code/releases/RepoReleasesMvp.java | 45 - .../code/releases/RepoReleasesPresenter.java | 131 - .../assignees/AssigneesDialogFragment.java | 176 - .../repos/extras/assignees/AssigneesMvp.java | 32 - .../extras/assignees/AssigneesPresenter.java | 27 - .../repos/extras/branches/BranchesFragment.kt | 120 - .../repos/extras/branches/BranchesMvp.kt | 27 - .../extras/branches/BranchesPresenter.kt | 89 - .../branches/pager/BranchesPagerFragment.kt | 77 - .../branches/pager/BranchesPagerListener.kt | 10 - .../extras/labels/LabelsDialogFragment.java | 189 - .../repos/extras/labels/LabelsMvp.java | 38 - .../repos/extras/labels/LabelsPresenter.java | 66 - .../create/CreateLabelDialogFragment.java | 106 - .../extras/labels/create/CreateLabelMvp.java | 25 - .../labels/create/CreateLabelPresenter.java | 32 - .../extras/license/RepoLicenseBottomSheet.kt | 113 - .../repos/extras/license/RepoLicenseMvp.kt | 17 - .../extras/license/RepoLicensePresenter.kt | 16 - .../locking/LockIssuePrBottomSheetDialog.kt | 46 - .../extras/locking/LockIssuePrCallback.kt | 9 - .../milestone/MilestoneDialogFragment.java | 161 - .../repos/extras/milestone/MilestoneMvp.java | 36 - .../extras/milestone/MilestonePresenter.java | 40 - .../create/CreateMilestoneDialogFragment.java | 112 - .../milestone/create/CreateMilestoneMvp.java | 29 - .../create/CreateMilestonePresenter.java | 46 - .../create/MilestoneDialogFragment.java | 90 - .../extras/misc/RepoMiscDialogFragment.java | 145 - .../repos/extras/misc/RepoMiscMVp.java | 47 - .../repos/extras/misc/RepoMiscPresenter.java | 112 - .../extras/popup/IssuePopupFragment.java | 202 - .../repos/extras/popup/IssuePopupMvp.java | 20 - .../extras/popup/IssuePopupPresenter.java | 23 - .../modules/repos/git/EditRepoFileActivity.kt | 159 - .../ui/modules/repos/git/EditRepoFileMvp.kt | 28 - .../repos/git/EditRepoFilePresenter.kt | 69 - .../git/delete/DeleteContentFileCallback.kt | 9 - .../delete/DeleteFileBottomSheetFragment.kt | 72 - .../repos/issues/RepoIssuesPagerFragment.java | 154 - .../repos/issues/RepoIssuesPagerMvp.java | 28 - .../issues/RepoIssuesPagerPresenter.java | 9 - .../issues/create/CreateIssueActivity.java | 417 - .../repos/issues/create/CreateIssueMvp.java | 57 - .../issues/create/CreateIssuePresenter.java | 179 - .../issue/RepoClosedIssuesFragment.java | 209 - .../repos/issues/issue/RepoIssuesMvp.java | 58 - .../issues/issue/RepoIssuesPresenter.java | 184 - .../issue/RepoOpenedIssuesFragment.java | 219 - .../issue/details/IssuePagerActivity.java | 462 - .../issues/issue/details/IssuePagerMvp.java | 88 - .../issue/details/IssuePagerPresenter.java | 290 - .../timeline/IssueTimelineFragment.java | 372 - .../details/timeline/IssueTimelineMvp.java | 89 - .../timeline/IssueTimelinePresenter.java | 328 - .../projects/RepoProjectsFragmentPager.kt | 85 - .../projects/columns/ProjectColumnFragment.kt | 260 - .../projects/columns/ProjectColumnMvp.kt | 36 - .../columns/ProjectColumnPresenter.kt | 180 - .../crud/ProjectCurdDialogFragment.kt | 120 - .../projects/details/ProjectPagerActivity.kt | 151 - .../repos/projects/details/ProjectPagerMvp.kt | 27 - .../projects/details/ProjectPagerPresenter.kt | 89 - .../projects/list/RepoProjectFragment.kt | 145 - .../repos/projects/list/RepoProjectMvp.kt | 29 - .../projects/list/RepoProjectPresenter.kt | 222 - .../RepoPullRequestPagerFragment.java | 128 - .../RepoPullRequestPagerMvp.java | 21 - .../RepoPullRequestPagerPresenter.java | 9 - .../pull_request/RepoPullRequestFragment.java | 201 - .../pull_request/RepoPullRequestMvp.java | 49 - .../RepoPullRequestPresenter.java | 129 - .../details/PullRequestPagerActivity.java | 593 - .../details/PullRequestPagerMvp.java | 102 - .../details/PullRequestPagerPresenter.java | 346 - .../commits/PullRequestCommitsFragment.java | 138 - .../commits/PullRequestCommitsMvp.java | 37 - .../commits/PullRequestCommitsPresenter.java | 102 - .../files/PullRequestFilesFragment.java | 270 - .../details/files/PullRequestFilesMvp.java | 61 - .../files/PullRequestFilesPresenter.java | 143 - .../FullScreenFileChangeActivity.kt | 177 - .../fullscreen/FullScreenFileChangeMvp.kt | 21 - .../FullScreenFileChangePresenter.kt | 39 - .../timeline/PullRequestTimelineFragment.java | 434 - .../timeline/PullRequestTimelineMvp.java | 103 - .../PullRequestTimelinePresenter.java | 456 - .../merge/MergePullReqeustMvp.java | 22 - .../merge/MergePullRequestDialogFragment.java | 92 - .../merge/MergePullRequestPresenter.java | 9 - .../reactions/ReactionsDialogFragment.java | 134 - .../repos/reactions/ReactionsDialogMvp.java | 31 - .../reactions/ReactionsDialogPresenter.java | 113 - .../ui/modules/repos/wiki/WikiActivity.kt | 183 - .../ui/modules/repos/wiki/WikiMvp.kt | 21 - .../ui/modules/repos/wiki/WikiPresenter.kt | 87 - .../reviews/AddReviewDialogFragment.kt | 112 - .../reviews/callback/ReviewCommentListener.kt | 11 - .../reviews/changes/ReviewChangesActivity.kt | 151 - .../reviews/changes/ReviewChangesMvp.kt | 24 - .../reviews/changes/ReviewChangesPresenter.kt | 23 - .../ui/modules/search/SearchActivity.java | 182 - .../ui/modules/search/SearchMvp.java | 33 - .../ui/modules/search/SearchPresenter.java | 66 - .../ui/modules/search/SearchUserActivity.kt | 109 - .../search/code/SearchCodeFragment.java | 188 - .../ui/modules/search/code/SearchCodeMvp.java | 44 - .../search/code/SearchCodePresenter.java | 78 - .../search/issues/SearchIssuesFragment.java | 175 - .../search/issues/SearchIssuesMvp.java | 42 - .../search/issues/SearchIssuesPresenter.java | 79 - .../search/repos/SearchReposFragment.java | 171 - .../modules/search/repos/SearchReposMvp.java | 40 - .../search/repos/SearchReposPresenter.java | 77 - .../repos/files/SearchFileActivity.java | 112 - .../search/repos/files/SearchFileMvp.java | 21 - .../repos/files/SearchFilePresenter.java | 40 - .../search/users/SearchUsersFragment.java | 169 - .../modules/search/users/SearchUsersMvp.java | 40 - .../search/users/SearchUsersPresenter.java | 76 - .../settings/LanguageBottomSheetDialog.java | 89 - .../ui/modules/settings/SettingsActivity.java | 111 - .../settings/SlackBottomSheetDialog.java | 78 - .../category/SettingsCategoryActivity.java | 70 - .../category/SettingsCategoryFragment.java | 363 - .../category/SettingsCategoryMvp.java | 13 - .../category/SettingsCategoryPresenter.java | 9 - .../sound/NotificationSoundBottomSheet.kt | 113 - .../settings/sound/NotificationSoundMvp.kt | 24 - .../sound/NotificationSoundPresenter.kt | 23 - .../ui/modules/theme/ThemeActivity.kt | 101 - .../modules/theme/code/ThemeCodeActivity.kt | 74 - .../ui/modules/theme/code/ThemeCodeMvp.kt | 18 - .../modules/theme/code/ThemeCodePresenter.kt | 19 - .../modules/theme/fragment/ThemeFragment.kt | 166 - .../theme/fragment/ThemeFragmentMvp.kt | 22 - .../theme/fragment/ThemeFragmentPresenter.kt | 9 - .../ui/modules/trending/TrendingActivity.kt | 239 - .../ui/modules/trending/TrendingMvp.kt | 21 - .../ui/modules/trending/TrendingPresenter.kt | 40 - .../trending/fragment/TrendingFragment.kt | 90 - .../trending/fragment/TrendingFragmentMvp.kt | 23 - .../fragment/TrendingFragmentPresenter.kt | 83 - .../ui/modules/user/UserPagerActivity.java | 332 - .../ui/modules/user/UserPagerMvp.java | 36 - .../ui/modules/user/UserPagerPresenter.java | 56 - .../ui/widgets/AppbarRefreshLayout.java | 24 - .../ui/widgets/AutoLinearLayout.java | 495 - .../fastaccess/ui/widgets/AvatarLayout.java | 105 - .../ui/widgets/CardsPagerTransformerBasic.kt | 17 - .../ui/widgets/ColorPickerPreference.java | 113 - .../fastaccess/ui/widgets/DiffLineSpan.java | 109 - .../widgets/FloatingActionButtonBehavior.java | 91 - .../ui/widgets/FontAutoCompleteEditText.java | 39 - .../com/fastaccess/ui/widgets/FontButton.java | 35 - .../fastaccess/ui/widgets/FontCheckbox.java | 35 - .../fastaccess/ui/widgets/FontEditText.java | 49 - .../ui/widgets/FontRadioButton.java | 35 - .../fastaccess/ui/widgets/FontSwitchView.java | 36 - .../fastaccess/ui/widgets/FontTextView.java | 109 - .../ui/widgets/ForegroundImageView.java | 32 - .../ui/widgets/ForegroundRelativeLayout.java | 102 - .../com/fastaccess/ui/widgets/LabelSpan.java | 169 - .../ui/widgets/NestedCoordinatorLayout.java | 111 - .../ui/widgets/SpannableBuilder.java | 133 - .../fastaccess/ui/widgets/StateLayout.java | 172 - .../fastaccess/ui/widgets/TabletBehavior.java | 49 - .../fastaccess/ui/widgets/ViewPagerView.java | 71 - .../ui/widgets/color/ColorGenerator.java | 68 - .../contributions/ContributionsDay.java | 25 - .../contributions/ContributionsProvider.java | 82 - .../GitHubContributionsView.java | 386 - .../contributions/utils/ColorsUtils.java | 110 - .../contributions/utils/DatesUtils.java | 99 - .../ui/widgets/dialog/ListDialogView.java | 104 - .../ui/widgets/dialog/MessageDialogView.java | 174 - .../dialog/ProgressDialogFragment.java | 69 - .../ui/widgets/markdown/MarkDownLayout.kt | 175 - .../ui/widgets/markdown/MarkdownEditText.kt | 115 - .../recyclerview/BaseRecyclerAdapter.java | 270 - .../widgets/recyclerview/BaseViewHolder.java | 63 - .../recyclerview/BottomPaddingDecoration.java | 60 - .../recyclerview/DynamicRecyclerView.java | 162 - .../recyclerview/InsetDividerDecoration.java | 69 - .../recyclerview/ProgressBarViewHolder.java | 26 - .../layout_manager/GridManager.java | 58 - .../layout_manager/LinearManager.java | 37 - .../layout_manager/StaggeredManager.java | 33 - .../recyclerview/scroll/InfiniteScroll.java | 110 - .../scroll/RecyclerViewFastScroller.java | 240 - .../com/prettifier/pretty/NestedWebView.java | 130 - .../prettifier/pretty/PrettifyWebView.java | 269 - .../MarkDownInterceptorInterface.java | 37 - .../pretty/helper/CodeThemesHelper.java | 98 - .../pretty/helper/GithubHelper.java | 156 - .../pretty/helper/PrettifyHelper.java | 94 - .../com/zzhoujay/markdown/style/CodeSpan.java | 53 - .../com/zzhoujay/markdown/style/FontSpan.java | 42 - .../com/zzhoujay/markdown/style/LinkSpan.java | 26 - .../markdown/style/MarkDownQuoteSpan.java | 41 - .../main/res/color/search_tab_highlighter.xml | 9 - .../res/drawable-nodpi/web_hi_res_512.png | Bin 121788 -> 0 bytes .../drawable-small/splash_screen_drawable.xml | 16 - .../drawable-v26/ic_app_shortcut_github.xml | 5 - .../drawable-v26/ic_app_shortcut_issues.xml | 5 - .../drawable-v26/ic_app_shortcut_pinned.xml | 5 - .../drawable-v26/ic_app_shortcut_profile.xml | 5 - .../ic_app_shortcut_pull_requests.xml | 5 - .../main/res/drawable/fastscroller_bubble.xml | 18 - app/src/main/res/drawable/ic_person.xml | 9 - .../main_layouts/layout-land/bottom_fab.xml | 15 - .../layout-land/fragment_container.xml | 11 - .../layout-land/header_title_with_toolbar.xml | 32 - .../layout-land/issues_bottom_navigation.xml | 10 - .../layout-land/main_bottom_navigation.xml | 10 - .../profile_follow_action_layout.xml | 67 - .../layout-land/repo_file_header_layout.xml | 115 - .../layout-sw600dp/bottom_fab.xml | 13 - .../layout-sw600dp/fragment_container.xml | 11 - .../header_title_with_toolbar.xml | 33 - .../issues_bottom_navigation.xml | 10 - .../layout-sw600dp/main_bottom_navigation.xml | 10 - .../repo_file_header_layout.xml | 118 - .../layout/accounts_menu_layout.xml | 230 - .../layout/activity_fragment_layout.xml | 37 - ...agment_container.xml => activity_main.xml} | 5 +- .../layout/activity_main_view.xml | 40 - .../layout/activity_search_file.xml | 82 - .../layout/activity_search_user.xml | 91 - .../main_layouts/layout/activity_settings.xml | 22 - .../layout/activity_settings_category.xml | 16 - .../main_layouts/layout/add_banner_layout.xml | 9 - .../layout/add_gist_file_layout.xml | 65 - .../main_layouts/layout/add_label_layout.xml | 71 + .../layout/add_milestone_layout.xml | 89 + .../layout/add_review_dialog_layout.xml | 23 - .../main_layouts/layout/bottom_fab.xml | 16 - .../layout/branches_tabbed_viewpager.xml | 16 - .../layout/centered_tabbed_viewpager.xml | 24 - .../layout/code_editor_activity_layout.xml | 27 + .../layout/comment_box_layout.xml | 85 - .../layout/commit_file_full_layout.xml | 81 - .../layout/commit_pager_activity.xml | 186 - .../layout/commit_with_branch_layout.xml | 49 - .../layout/create_gist_layout.xml | 114 - .../layout/create_issue_layout.xml | 226 - .../layout/create_label_layout.xml | 95 - .../layout/create_milestone_layout.xml | 101 - .../layout/delete_repo_file_layout.xml | 94 - .../main_layouts/layout/dialog_picker.xml | 10 - .../edit_project_column_note_layout.xml | 45 - .../layout/edit_repo_file_layout.xml | 142 - .../main_layouts/layout/editor_layout.xml | 91 - .../layout/emoji_popup_layout.xml | 60 - .../layout/fab_micro_grid_refresh_list.xml | 43 - .../layout/fab_simple_refresh_list_layout.xml | 31 + .../layout/filter_bottom_sheet.xml | 134 - .../layout/filter_issues_popup.xml | 45 - .../layout/filter_issues_prs_layout.xml | 210 - .../layout/fragment_activity_layout.xml} | 5 +- .../full_screen_file_changes_layout.xml | 80 - .../layout/general_viewer_layout.xml | 48 - .../layout/gists_activity_layout.xml | 62 - .../layout/gists_pager_layout.xml | 132 - .../layout/header_title_with_toolbar.xml | 34 - .../main_layouts/layout/icon_row_item.xml | 44 - .../layout/issue_pager_activity.xml | 105 - .../layout/issue_popup_layout.xml | 281 - .../layout/issue_pr_bottomsheet_layout.xml | 110 + .../layout/issue_pr_fragment_layout.xml | 160 + .../layout/issues_bottom_navigation.xml | 10 - .../layout/issues_prs_fragment_layout.xml | 30 + .../layout/license_viewer_layout.xml | 43 - .../layout/login_chooser_activity_layout.xml | 16 + .../layout/login_chooser_fragment_layout.xml | 254 + .../layout/login_chooser_layout.xml | 268 - .../main_layouts/layout/login_form_layout.xml | 327 +- .../layout/main_bottom_navigation.xml | 10 - .../layout/main_fragment_layout.xml | 116 + .../layout/main_nav_fragment_layout.xml | 14 - .../layout/markdown_buttons_layout.xml | 215 - .../markdown_link_image_dialog_layout.xml | 124 - .../layout/merge_dialog_layout.xml | 64 - .../layout/micro_grid_refresh_list.xml | 41 - .../layout/milestone_dialog_layout.xml | 13 - .../layout/notification_activity_layout.xml | 57 - .../main_layouts/layout/picker_dialog.xml | 54 - .../playstore_review_layout_warning.xml | 58 - .../layout/pro_features_layout.xml | 302 - .../layout/profile_bottom_sheet.xml | 58 + .../layout/profile_follow_action_layout.xml | 66 - .../layout/profile_fragment_layout.xml | 363 + .../layout/project_columns_layout.xml | 94 - .../layout/projects_activity_layout.xml | 41 - .../layout/pull_request_files_layout.xml | 96 - .../layout/repo_file_header_layout.xml | 113 - .../main_layouts/layout/repo_file_layout.xml | 22 - .../layout/repo_header_icons_layout.xml | 178 - .../layout/repo_pager_activity.xml | 53 - .../layout/review_changes_bottom_layout.xml | 73 - .../layout/review_comment_dialog_layout.xml | 50 - .../rounded_toolbar_fragment_list_layout.xml | 22 + .../layout/search_fragment_layout.xml | 99 + .../main_layouts/layout/search_layout.xml | 98 - .../main_layouts/layout/settings_layout.xml | 16 - .../layout/simple_refresh_list_layout.xml | 29 + .../layout/small_grid_refresh_list.xml | 43 - .../layout/submit_review_layout.xml | 10 - .../layout/support_development_layout.xml | 178 - .../layout/tabbed_pager_layout.xml | 48 - .../main_layouts/layout/tabbed_viewpager.xml | 29 - .../layout/tending_buttons_layout.xml | 90 - .../main_layouts/layout/theme_code_layout.xml | 69 - .../main_layouts/layout/theme_layout.xml | 1000 - .../main_layouts/layout/theme_viewpager.xml | 29 - .../layout/title_header_layout.xml | 140 - .../layout/toolbar_activity_layout.xml | 48 +- .../layout/toolbar_fragment_list_layout.xml | 17 + .../layout/toolbar_fragment_pager_layout.xml | 16 + ...t.xml => toolbar_tabs_activity_layout.xml} | 10 +- .../layout/trending_activity_layout.xml | 168 - .../layout/trending_fragment_layout.xml | 30 + .../layout/vertical_refresh_list.xml | 42 - .../layout/view_pager_activity_layout.xml | 25 - .../layout/wiki_activity_layout.xml | 67 - .../layout-land/appbar_start_margin.xml | 18 - .../layout-sw600dp/appbar_start_margin.xml | 19 - .../layout/appbar_center_title_layout.xml | 37 + ...appbar_center_title_layout_bottomsheet.xml | 38 + ...ppbar_center_title_layout_primary_dark.xml | 38 + ...r_center_title_round_background_layout.xml | 43 + ...t_margin.xml => appbar_default_layout.xml} | 14 +- .../layout/appbar_elevation_dark.xml | 16 - .../appbar_logo_center_title_layout.xml | 40 + .../layout/appbar_profile_title_layout.xml | 44 + .../layout/appbar_tabbed_elevation.xml | 28 - .../appbar_tabs_center_title_layout.xml | 43 + .../other_layouts/layout/avatar_layout.xml | 15 - .../layout/bottm_bar_menu_layout.xml | 47 + .../layout/dialog_guide_layout.xml | 69 - .../other_layouts/layout/drawer_header.xml | 93 - .../other_layouts/layout/empty_layout.xml | 39 - .../layout/empty_state_layout.xml | 33 + .../layout/fastscroller_layout.xml | 17 +- .../layout/filter_issue_pr_layout.xml | 227 + .../layout/filter_search_layout.xml | 484 + .../layout/filter_trending_layout.xml | 111 + .../other_layouts/layout/home_button.xml | 9 - .../layout/icon_dialog_layout.xml | 83 + .../layout/lock_issue_pr_dialog.xml | 96 - .../layout/lock_unlock_issue_pr_layout.xml | 101 + .../other_layouts/layout/message_dialog.xml | 98 - .../other_layouts/layout/nav_menu_layout.xml | 41 - ..._dialog_layout.xml => progress_layout.xml} | 7 +- .../layout/reaction_group_chip_widget.xml | 8 + .../layout/reactions_chips_layout.xml | 59 + .../layout/simple_footer_list_dialog.xml | 114 - .../layout/simple_list_dialog.xml | 41 - .../other_layouts/layout/state_layout.xml | 7 - .../layout-sw600dp/login_row_item_menu.xml | 17 - .../layout-sw600dp/repos_row_item_menu.xml | 18 - .../layout/add_filter_row_layout.xml | 33 - .../row_layouts/layout/assignees_row_item.xml | 57 + .../row_layouts/layout/branches_row_item.xml | 36 - .../layout/column_card_row_layout.xml | 63 - .../row_layouts/layout/comment_row_item.xml | 108 + .../layout/comments_dropdown_layout.xml | 99 - .../row_layouts/layout/comments_row_item.xml | 222 - .../layout/commit_file_row_item.xml | 117 - .../layout/commit_line_row_item.xml | 63 - .../row_layouts/layout/emoji_row_item.xml | 20 - .../layout/fasthub_notification_row_item.xml | 62 - .../row_layouts/layout/feeds_row_item.xml | 106 +- .../layout/feeds_row_no_image_item.xml | 55 - .../row_layouts/layout/file_path_row_item.xml | 15 - .../layout/gist_files_row_item.xml | 80 - .../layout/grouped_commit_comment_row.xml | 59 - .../grouped_review_timeline_row_item.xml | 137 - .../row_layouts/layout/icon_row_item.xml | 9 + .../layout/issue_content_row_item.xml | 60 + .../layout/issue_detail_header_row_item.xml | 235 - .../layout/issue_header_row_item.xml | 232 + .../layout/issue_no_image_row_item.xml | 78 - .../row_layouts/layout/issue_row_item.xml | 94 - .../layout/issue_timeline_row_item.xml | 83 - .../issues_prs_main_screen_row_item.xml | 78 + .../layout/label_color_row_item.xml | 11 + .../row_layouts/layout/label_row_item.xml | 49 +- .../row_layouts/layout/language_row_item.xml | 17 + .../row_layouts/layout/login_row_item.xml | 42 - .../layout/login_row_item_menu.xml | 17 - .../row_layouts/layout/milestone_row_item.xml | 65 +- .../layout/no_emojies_comments_row_item.xml | 81 - .../layout/notification_header_row_item.xml | 30 - .../notification_main_screen_row_item.xml | 78 + .../layout/notifications_row_item.xml | 134 - .../layout/org_profile_overview_layout.xml | 163 - .../layout/organization_row_item.xml | 120 + .../layout/preference_widget_color.xml | 13 - .../profile_follower_following_row_item.xml | 65 + .../layout/profile_gist_repo_row_item.xml | 88 + .../layout/profile_org_row_item.xml | 26 - .../layout/profile_overview_layout.xml | 303 - .../layout/profile_pinned_repo_row_item.xml | 147 +- .../row_layouts/layout/progress_layout.xml | 16 - .../layout/pull_status_row_item.xml | 54 - .../layout/pullrequest_file_row_item.xml | 118 - .../row_layouts/layout/releases_row_item.xml | 70 - .../layout/repo_files_row_item.xml | 70 - .../row_layouts/layout/repos_row_item.xml | 128 - .../layout/repos_row_item_menu.xml | 18 - .../layout/repos_row_no_image_item.xml | 111 - .../layout/review_comments_row_item.xml | 202 - .../layout/review_timeline_row_item.xml | 82 - .../layout/simple_color_row_item.xml | 19 - .../row_layouts/layout/simple_row_item.xml | 20 - .../layout/title_section_row_item.xml | 15 + .../row_layouts/layout/topics_row_item.xml | 14 - .../row_layouts/layout/trending_row_item.xml | 155 +- .../row_layouts/layout/unknown_row_item.xml | 4 - .../layout/users_small_row_item.xml | 70 - .../main/res/menu-land/bottom_nav_menu.xml | 38 - .../main/res/menu-sw600dp/bottom_nav_menu.xml | 38 - .../res/menu-sw600dp/repo_bottom_nav_menu.xml | 37 - .../repo_with_project_bottom_nav_menu.xml | 41 - app/src/main/res/menu/bottom_nav_menu.xml | 31 - app/src/main/res/menu/comments_menu.xml | 29 - app/src/main/res/menu/commit_row_menu.xml | 29 - .../main/res/menu/download_browser_menu.xml | 31 - app/src/main/res/menu/download_share_menu.xml | 38 - .../main/res/menu/dynamic_trending_menu.xml | 9 - app/src/main/res/menu/filter_fab_menu.xml | 14 - .../main/res/menu/filter_issue_state_menu.xml | 15 - app/src/main/res/menu/gist_menu.xml | 16 - app/src/main/res/menu/link_popup_menu.xml | 20 - app/src/main/res/menu/project_card_menu.xml | 31 - app/src/main/res/menu/pull_request_menu.xml | 101 - .../main/res/menu/repo_bottom_nav_menu.xml | 31 - app/src/main/res/menu/repo_menu.xml | 31 - .../repo_with_project_bottom_nav_menu.xml | 34 - app/src/main/res/menu/share_menu.xml | 40 - app/src/main/res/menu/trending_menu.xml | 17 - app/src/main/res/menu/wrap_menu_option.xml | 12 - .../main/res/navigation/login_navigation.xml | 35 + app/src/main/res/raw/changelog.html | 56 - app/src/main/res/values-ar/strings.xml | 389 - app/src/main/res/values-bg/strings.xml | 477 - app/src/main/res/values-cs/strings.xml | 391 - app/src/main/res/values-de/strings.xml | 472 - app/src/main/res/values-es/strings.xml | 500 - app/src/main/res/values-fr/strings.xml | 463 - app/src/main/res/values-in/strings.xml | 384 - app/src/main/res/values-it/strings.xml | 479 - app/src/main/res/values-ja/strings.xml | 466 - app/src/main/res/values-ko/strings.xml | 461 - app/src/main/res/values-lt/strings.xml | 373 - app/src/main/res/values-pl/strings.xml | 464 - app/src/main/res/values-pt-rBR/strings.xml | 473 - app/src/main/res/values-pt-rPT/strings.xml | 441 - app/src/main/res/values-ru/strings.xml | 467 - .../main/res/values-sw600dp-land/dimens.xml | 8 - app/src/main/res/values-sw600dp/dimens.xml | 6 - .../main/res/values-sw720dp-land/dimens.xml | 8 - app/src/main/res/values-sw720dp/dimens.xml | 7 - app/src/main/res/values-tr/strings.xml | 430 - .../main/res/values-w820dp-land/dimens.xml | 7 - app/src/main/res/values-w820dp/dimens.xml | 6 - app/src/main/res/values-zh-rCN/strings.xml | 508 - app/src/main/res/values-zh-rTW/strings.xml | 491 - app/src/main/res/values/attrs.xml | 96 - app/src/main/res/values/no_translate.xml | 6 + app/src/main/res/values/styles.xml | 11 - app/src/main/res/values/theme_amlod.xml | 228 - app/src/main/res/values/theme_bluish.xml | 238 - app/src/main/res/values/theme_dark.xml | 232 - app/src/main/res/values/theme_light.xml | 233 - app/src/main/res/values/theme_midnight.xml | 232 - app/src/main/res/xml/about_settings.xml | 22 - app/src/main/res/xml/backup_settings.xml | 16 - app/src/main/res/xml/behaviour_settings.xml | 45 - .../main/res/xml/customization_settings.xml | 47 - app/src/main/res/xml/fasthub_settings.xml | 110 - app/src/main/res/xml/language_settings.xml | 13 - .../main/res/xml/notification_settings.xml | 43 - .../com/fastaccess/github/ExampleUnitTest.kt | 17 + .../fastaccess/login/LoginPresenterTest.java | 40 - .../debug_keys.properties | 2 +- build-dependecies/fasthub-config.gradle | 10 + build-dependecies/fasthub-dependencies.gradle | 158 + build.gradle | 48 +- data/.gitignore | 1 + data/build.gradle | 69 + data/proguard-rules.pro | 21 + data/src/main/AndroidManifest.xml | 1 + data/src/main/assets/languages.json | 1434 + .../src/main/graphql/github/fragments.graphql | 173 + .../graphql/github/issue_prs_mutation.graphql | 23 + .../main/graphql/github/issues_prs.graphql | 266 + .../graphql/github/profile_screen.graphql | 246 + .../src/main/graphql/github/schema.json | 41477 +++++++++++----- data/src/main/graphql/github/search.graphql | 55 + .../com/fastaccess/data/model/CountModel.kt | 5 + .../data/model/EmbeddedRepoModel.kt | 10 + .../java/com/fastaccess/data/model/Errors.kt | 20 + .../data/model/FirebaseTrendingConfigModel.kt | 39 + .../data/model/GroupedNotificationsModel.kt | 18 + .../data/model/LanguageColorsModel.kt | 50 + .../fastaccess/data/model/MainScreenModel.kt | 20 + .../fastaccess/data/model/PageInfoModel.kt | 11 + .../data/model/ReactionGroupModel.kt | 77 + .../data/model/RepoLanguageModel.kt | 8 + .../com/fastaccess/data/model/SearchModel.kt | 11 + .../fastaccess/data/model/ShortRepoModel.kt | 18 + .../fastaccess/data/model/ShortUserModel.kt | 57 + .../fastaccess/data/model/SimpleUserModel.kt | 8 + .../fastaccess/data/model/TimelineModel.kt | 157 + .../fastaccess/data/model/TrendingModel.kt | 10 + .../fastaccess/data/model/ViewPagerModel.kt | 42 + .../model/parcelable/FilterIssuesPrsModel.kt | 45 + .../model/parcelable/FilterSearchModel.kt | 96 + .../model/parcelable/FilterTrendingModel.kt | 40 + .../data/model/parcelable/LabelModel.kt | 39 + .../parcelable/LoginRepoParcelableModel.kt | 41 + .../data/model/parcelable/MilestoneModel.kt | 51 + .../data/persistence/dao/BaseDao.kt | 39 + .../data/persistence/dao/FeedDao.kt | 26 + .../data/persistence/dao/IssueDao.kt | 30 + .../data/persistence/dao/LoginDao.kt | 34 + .../data/persistence/dao/MyIssuesPullsDao.kt | 31 + .../data/persistence/dao/NotificationsDao.kt | 36 + .../data/persistence/dao/OrgsDao.kt | 24 + .../data/persistence/dao/SuggestionDao.kt | 21 + .../data/persistence/dao/UserDao.kt | 23 + .../dao/UserFollowersFollowingsDao.kt | 26 + .../data/persistence/dao/UserGistsDao.kt | 22 + .../data/persistence/dao/UserReposDao.kt | 22 + .../persistence/dao/UserStarredReposDao.kt | 22 + .../data/persistence/db/Converters.kt | 106 + .../data/persistence/db/FastHubDatabase.kt | 39 + .../persistence/db/FastHubLoginDatabase.kt | 20 + .../data/persistence/models/FeedModel.kt | 160 + .../models/FollowingsFollowersModel.kt | 75 + .../data/persistence/models/GetIssueModel.kt | 58 + .../data/persistence/models/GistsModel.kt | 54 + .../data/persistence/models/LoginModel.kt | 49 + .../persistence/models/MyIssuesPullsModel.kt | 26 + .../persistence/models/NotificationModel.kt | 57 + .../persistence/models/OrganizationModel.kt | 68 + .../persistence/models/ProfileRepoModel.kt | 64 + .../models/ProfileStarredRepoModel.kt | 64 + .../persistence/models/SuggestionsModel.kt | 21 + .../data/persistence/models/UserModel.kt | 65 + .../repository/FeedsRepositoryProvider.kt | 73 + .../repository/IssueRepositoryProvider.kt | 34 + .../repository/LoginRepositoryProvider.kt | 53 + .../MyIssuesPullsRepositoryProvider.kt | 33 + .../NotificationRepositoryProvider.kt | 60 + .../data/repository/OrgRepositoryProvider.kt | 50 + .../SuggestionRepositoryProvider.kt | 28 + ...serFollowersFollowingRepositoryProvider.kt | 67 + .../repository/UserGistsRepositoryProvider.kt | 49 + .../repository/UserReposRepositoryProvider.kt | 49 + .../data/repository/UserRepositoryProvider.kt | 76 + .../UserStarredReposRepositoryProvider.kt | 48 + .../data/storage/FastHubSharedPreference.kt | 66 + .../extension/GraphqlFragmentExtension.kt | 39 + .../com/fastaccess/extension/RxExtension.kt | 39 + .../com/fastaccess/data/ExampleUnitTest.java | 17 + domain/.gitignore | 1 + domain/build.gradle | 53 + domain/proguard-rules.pro | 21 + domain/src/main/AndroidManifest.xml | 1 + .../com/fastaccess/domain/FastHubObserver.kt | 14 + .../repository/LoginRemoteRepository.kt | 19 + .../repository/services/IssuePrService.kt | 25 + .../repository/services/LoginService.kt | 24 + .../services/NotificationService.kt | 24 + .../services/OrganizationService.kt | 22 + .../repository/services/ReactionService.kt | 48 + .../domain/repository/services/RepoService.kt | 42 + .../repository/services}/ScrapService.kt | 10 +- .../domain/repository/services/UserService.kt | 44 + .../fastaccess/domain/response/AuthModel.kt | 21 + .../domain/response/FeedResponse.kt | 172 + .../domain/response/IssueRequestModel.kt | 24 + .../domain/response/NotificationResponse.kt | 27 + .../domain/response/PageableResponse.kt | 12 + .../domain/response/PostReactionModel.kt | 8 + .../domain/response/UserResponse.kt | 30 + .../response/body/AssigneesBodyModel.kt | 11 + .../domain/response/body/LabelsBodyModel.kt | 10 + .../response/body/MilestoneBodyModel.kt | 12 + .../domain/response/enums/EventsType.kt | 32 + .../fastaccess/domain/rx/FastHubSubscriber.kt | 19 + .../usecase/base/BaseCompletableUseCase.kt | 37 + .../usecase/base/BaseFlowableUseCase.kt | 39 + .../domain/usecase/base/BaseMaybeUseCase.kt | 39 + .../usecase/base/BaseObservableUseCase.kt | 46 + .../domain/usecase/base/BaseSingleUseCase.kt | 37 + .../domain/usecase/base/BaseUseCase.kt | 26 + .../usecase/base/BaseUseCaseDefaults.kt | 11 + .../fastaccess/domain/ExampleUnitTest.java | 17 + editor/.gitignore | 1 + editor/build.gradle | 39 + editor/proguard-rules.pro | 21 + editor/src/main/AndroidManifest.xml | 2 + .../github/editor/ExampleUnitTest.java | 17 + extensions/.gitignore | 1 + extensions/build.gradle | 59 + extensions/proguard-rules.pro | 21 + extensions/src/main/AndroidManifest.xml | 5 + .../extensions/ActivityFragmentExtension.kt | 126 + .../github/extensions/DatePrettifier.kt | 94 + .../github/extensions/LiveDataExtensions.kt | 196 + .../github/extensions/ObjectExtension.kt | 54 + .../github/extensions/ExampleUnitTest.java | 17 + fasthub_as_settings.jar | Bin 4729 -> 0 bytes fasthub_trending.json | 13 + gradle.properties | 3 + gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 54708 bytes gradle/wrapper/gradle-wrapper.properties | 5 +- gradlew | 72 +- gradlew.bat | 14 +- graphql.config.json | 23 + graphql.schema.json | 942 + markdown/.gitignore | 1 + markdown/build.gradle | 56 + markdown/proguard-rules.pro | 21 + markdown/src/main/AndroidManifest.xml | 2 + {app => markdown}/src/main/assets/emojis.json | 0 .../fastaccess/markdown/MarkdownProvider.kt | 136 + .../com/fastaccess/markdown/emoji/Emoji.kt | 167 + .../fastaccess/markdown/emoji/EmojiLoader.kt | 81 + .../fastaccess/markdown/emoji/EmojiManager.kt | 92 + .../fastaccess/markdown/emoji/EmojiParser.kt | 474 + .../fastaccess/markdown/emoji/EmojiTrie.kt | 102 + .../fastaccess/markdown/emoji/Fitzpatrick.kt | 37 + .../markdown/extension/TagExtension.kt | 14 + .../spans/CodeBackgroundRoundedSpan.kt | 51 + .../markdown/spans/DrawableHandler.kt | 41 + .../fastaccess/markdown/spans/EmojiHandler.kt | 28 + .../com/fastaccess/markdown/spans/FontSpan.kt | 21 + .../markdown/spans/HeaderHandler.kt | 38 + .../fastaccess/markdown/spans/HrHandler.kt | 30 + .../com/fastaccess/markdown/spans/HrSpan.kt | 34 + .../markdown/spans/ItalicHandler.kt | 17 + .../fastaccess/markdown/spans/LabelSpan.kt | 157 + .../fastaccess/markdown/spans/LinkHandler.kt | 37 + .../fastaccess/markdown/spans/ListsHandler.kt | 79 + .../markdown/spans/MarginHandler.kt | 30 + .../fastaccess/markdown/spans/MdQouteSpan.kt | 55 + .../markdown/spans/PreTagHandler.kt | 82 + .../fastaccess/markdown/spans/QuoteHandler.kt | 24 + .../markdown/spans/StrikethroughHandler.kt | 14 + .../markdown/spans/SubScriptHandler.kt | 17 + .../markdown/spans/SuperScriptHandler.kt | 18 + .../markdown/spans/UnderlineHandler.kt | 15 + .../com/fastaccess/markdown/spans/UrlSpan.kt | 18 + .../markdown/spans/drawable/DrawableGetter.kt | 68 + .../spans/drawable/GlideDrawableTarget.kt | 67 + .../markdown/spans/drawable/UrlDrawable.kt | 45 + .../markdown/widget/CenterImageSpan.kt | 50 + .../markdown/widget/HtmlTextView.kt | 21 + .../markdown/widget/SpannableBuilder.kt | 122 + markdown/src/main/res/values/ids.xml | 4 + .../fastaccess/markdown/ExampleUnitTest.java | 17 + privacy_policy.html | 39 - resources/.gitignore | 1 + resources/build.gradle | 28 + resources/proguard-rules.pro | 21 + resources/src/main/AndroidManifest.xml | 1 + .../main/res/animator/cardview_selector.xml | 0 .../src/main/res/animator/minus_to_plus.xml | 0 .../main/res/animator/plus_minus_rotate.xml | 0 .../src/main/res/animator/plus_to_minus.xml | 0 .../res/drawable-nodpi}/web_hi_res_512.png | Bin .../res/drawable/arrow_toggle_drawable.xml | 0 .../src/main/res/drawable/asl_follow.xml | 0 .../src/main/res/drawable/avd_follow.xml | 0 .../src/main/res/drawable/avd_unfollow.xml | 0 .../src/main/res/drawable/bottom_border.xml | 0 .../res/drawable/bottom_sheet_background.xml | 11 + .../src/main/res/drawable/circle_shape.xml | 10 + .../res/drawable/circle_shape_blue_small.xml | 10 + .../res/drawable/circle_shape_cardview.xml | 5 +- .../res/drawable/circle_shape_green_small.xml | 10 + .../res/drawable/circle_shape_red_small.xml | 10 + .../res/drawable/circle_shape_theme_small.xml | 10 + .../main/res/drawable/dialog_background.xml | 5 + .../main/res/drawable/fastscroller_bubble.xml | 5 + .../src/main/res/drawable/ic_add.xml | 0 .../src/main/res/drawable/ic_add_emoji.xml | 0 .../src/main/res/drawable/ic_add_small.xml | 9 + .../src/main/res/drawable/ic_announcement.xml | 0 .../res/drawable/ic_app_shortcut_github.xml | 0 .../ic_app_shortcut_github_foreground.xml | 0 .../res/drawable/ic_app_shortcut_issues.xml | 0 .../ic_app_shortcut_issues_foreground.xml | 0 .../res/drawable/ic_app_shortcut_pinned.xml | 0 .../ic_app_shortcut_pinned_foreground.xml | 0 .../res/drawable/ic_app_shortcut_profile.xml | 0 .../ic_app_shortcut_profile_foreground.xml | 0 .../ic_app_shortcut_pull_requests.xml | 0 ..._app_shortcut_pull_requests_foreground.xml | 0 .../main/res/drawable/ic_arrow_drop_down.xml | 0 .../main/res/drawable/ic_arrow_drop_up.xml | 2 + .../src/main/res/drawable/ic_arrow_right.xml | 0 .../src/main/res/drawable/ic_at.xml | 0 .../src/main/res/drawable/ic_back.xml | 0 .../src/main/res/drawable/ic_backup.xml | 0 .../src/main/res/drawable/ic_blank.xml | 0 .../src/main/res/drawable/ic_block.xml | 0 .../src/main/res/drawable/ic_book.xml | 0 .../src/main/res/drawable/ic_bookmark.xml | 0 .../src/main/res/drawable/ic_branch.xml | 0 .../src/main/res/drawable/ic_branch_small.xml | 10 + .../src/main/res/drawable/ic_brower.xml | 8 +- .../src/main/res/drawable/ic_brush.xml | 0 .../src/main/res/drawable/ic_bug.xml | 0 .../src/main/res/drawable/ic_check.xml | 0 .../src/main/res/drawable/ic_check_small.xml | 0 .../src/main/res/drawable/ic_checkbox.xml | 0 .../main/res/drawable/ic_checkbox_empty.xml | 0 .../res/drawable/ic_checkbox_empty_small.xml | 0 .../main/res/drawable/ic_checkbox_small.xml | 0 .../src/main/res/drawable/ic_chevron_down.xml | 11 + .../src/main/res/drawable/ic_chevron_up.xml | 12 + .../src/main/res/drawable/ic_circle_small.xml | 0 .../src/main/res/drawable/ic_clear.xml | 0 .../src/main/res/drawable/ic_clear_all.xml | 2 + .../src/main/res/drawable/ic_clear_black.xml | 0 .../src/main/res/drawable/ic_code.xml | 0 .../src/main/res/drawable/ic_color_lens.xml | 0 .../src/main/res/drawable/ic_comment.xml | 0 .../main/res/drawable/ic_comment_small.xml | 0 .../main/res/drawable/ic_comments_number.xml | 12 + .../src/main/res/drawable/ic_copy.xml | 0 .../src/main/res/drawable/ic_crop_square.xml | 0 .../res/drawable/ic_developer_programm.xml | 11 + .../src/main/res/drawable/ic_done.xml | 0 .../src/main/res/drawable/ic_dot.xml | 4 +- .../src/main/res/drawable/ic_dot_colored.xml | 9 + .../src/main/res/drawable/ic_download.xml | 0 .../main/res/drawable/ic_download_small.xml | 9 + .../src/main/res/drawable/ic_edit.xml | 0 .../src/main/res/drawable}/ic_edittext.9.png | Bin .../src/main/res/drawable/ic_email.xml | 0 .../src/main/res/drawable/ic_eye.xml | 0 .../src/main/res/drawable/ic_eye_off.xml | 0 .../src/main/res/drawable/ic_eye_small.xml | 9 + .../main/res/drawable/ic_fasthub_mascot.xml | 0 .../main/res/drawable/ic_file_document.xml | 0 .../src/main/res/drawable/ic_file_multi.xml | 0 .../src/main/res/drawable/ic_filter.xml | 0 .../src/main/res/drawable/ic_folder.xml | 0 .../src/main/res/drawable/ic_follow.xml | 0 .../src/main/res/drawable/ic_fork.xml | 0 .../src/main/res/drawable/ic_fork_small.xml | 0 .../src/main/res/drawable/ic_format_bold.xml | 0 .../main/res/drawable/ic_format_italic.xml | 0 .../res/drawable/ic_format_list_bulleted.xml | 0 .../src/main/res/drawable/ic_format_quote.xml | 0 .../res/drawable/ic_format_strikethrough.xml | 0 .../res/drawable/ic_format_underlined.xml | 0 .../src/main/res/drawable/ic_fullscreen.xml | 0 .../src/main/res/drawable/ic_gists.xml | 0 .../src/main/res/drawable/ic_gists_small.xml | 9 + .../src/main/res/drawable/ic_github.xml | 0 .../src/main/res/drawable/ic_github_dark.xml | 0 .../main/res/drawable/ic_github_shortcut.xml | 0 .../src/main/res/drawable/ic_group.xml | 0 .../src/main/res/drawable/ic_header_one.xml | 0 .../src/main/res/drawable/ic_header_three.xml | 0 .../src/main/res/drawable/ic_header_two.xml | 0 .../src/main/res/drawable/ic_heart.xml | 0 .../src/main/res/drawable/ic_heart_full.xml | 0 .../src/main/res/drawable/ic_home.xml | 0 .../src/main/res/drawable/ic_image.xml | 8 +- .../src/main/res/drawable/ic_incognito.xml | 0 .../main/res/drawable/ic_incognito_avatar.xml | 0 .../src/main/res/drawable/ic_info.xml | 0 .../src/main/res/drawable/ic_info_outline.xml | 2 + .../res/drawable/ic_info_outline_small.xml | 9 + .../src/main/res/drawable/ic_inline_code.xml | 0 .../src/main/res/drawable/ic_insert_link.xml | 0 .../src/main/res/drawable/ic_issue_closed.xml | 0 .../res/drawable/ic_issue_closed_small.xml | 0 .../src/main/res/drawable/ic_issue_opened.xml | 0 .../res/drawable/ic_issue_opened_small.xml | 0 .../src/main/res/drawable/ic_issues.xml | 0 .../main/res/drawable/ic_issues_shortcut.xml | 0 .../src/main/res/drawable/ic_issues_small.xml | 0 .../src/main/res/drawable/ic_label.xml | 0 .../src/main/res/drawable/ic_language.xml | 0 .../main/res/drawable/ic_language_small.xml | 0 .../src/main/res/drawable/ic_license.xml | 0 .../src/main/res/drawable/ic_lightblub.xml | 0 .../src/main/res/drawable/ic_list_numbers.xml | 0 .../src/main/res/drawable/ic_location.xml | 0 .../src/main/res/drawable/ic_lock.xml | 0 .../src/main/res/drawable/ic_logout.xml | 0 .../src/main/res/drawable/ic_menu.xml | 0 .../src/main/res/drawable/ic_merge.xml | 0 .../src/main/res/drawable/ic_merged_state.xml | 10 + .../src/main/res/drawable/ic_milestone.xml | 0 .../src/main/res/drawable/ic_minus.xml | 0 .../src/main/res/drawable/ic_money.xml | 0 .../src/main/res/drawable/ic_newline.xml | 0 .../src/main/res/drawable/ic_notification.xml | 11 + .../res/drawable/ic_notification_unread.xml | 17 + .../res/drawable/ic_notifications_none.xml | 10 +- .../src/main/res/drawable/ic_open_state.xml | 10 + .../src/main/res/drawable/ic_overflow.xml | 0 .../src/main/res/drawable/ic_people.xml | 0 .../src/main/res/drawable/ic_pin.xml | 0 .../src/main/res/drawable/ic_pin_filled.xml | 0 .../src/main/res/drawable/ic_pin_shortcut.xml | 0 .../src/main/res/drawable/ic_profile.xml | 9 + .../main/res/drawable/ic_profile_shortcut.xml | 0 .../main/res/drawable/ic_profile_small.xml | 4 +- .../src/main/res/drawable/ic_project.xml | 0 .../main/res/drawable/ic_pull_requests.xml | 0 .../drawable/ic_pull_requests_shortcut.xml | 0 .../res/drawable/ic_pull_requests_small.xml | 0 .../ic_pull_requests_uncolored_small.xml | 9 + .../src/main/res/drawable/ic_push.xml | 0 .../src/main/res/drawable/ic_push_small.xml | 9 + .../src/main/res/drawable/ic_redo.xml | 0 .../src/main/res/drawable/ic_refresh.xml | 4 +- resources/src/main/res/drawable/ic_reply.xml | 11 + .../src/main/res/drawable/ic_repo.xml | 0 .../src/main/res/drawable/ic_repo_small.xml | 11 + .../src/main/res/drawable/ic_restore.xml | 0 .../src/main/res/drawable/ic_restricted.xml | 0 .../src/main/res/drawable/ic_ring.xml | 0 .../src/main/res/drawable/ic_ring_sound.xml | 0 .../src/main/res/drawable/ic_rocket.xml | 0 .../src/main/res/drawable/ic_scroll_fast.xml | 18 + .../res/drawable/ic_scroll_fast_selected.xml | 18 + .../src/main/res/drawable/ic_search.xml | 8 +- .../src/main/res/drawable/ic_send.xml | 0 .../src/main/res/drawable/ic_settings.xml | 0 .../src/main/res/drawable/ic_share.xml | 0 .../src/main/res/drawable/ic_slack.xml | 0 .../src/main/res/drawable/ic_star.xml | 0 .../src/main/res/drawable/ic_star_filled.xml | 0 .../res/drawable/ic_star_filled_small.xml | 9 + .../src/main/res/drawable/ic_star_small.xml | 0 .../main/res/drawable/ic_storage_small.xml | 0 .../src/main/res/drawable/ic_submodule.xml | 0 .../src/main/res/drawable/ic_subscribe.xml | 0 .../src/main/res/drawable/ic_support.xml | 0 .../src/main/res/drawable/ic_sync.xml | 0 .../src/main/res/drawable/ic_time.xml | 0 .../src/main/res/drawable/ic_time_small.xml | 0 .../drawable}/ic_timeline_arrow_left.9.png | Bin .../src/main/res/drawable/ic_title.xml | 0 .../main/res/drawable/ic_track_changes.xml | 0 .../src/main/res/drawable/ic_trash.xml | 0 .../src/main/res/drawable/ic_trash_small.xml | 9 + .../src/main/res/drawable/ic_trending.xml | 0 .../src/main/res/drawable/ic_undo.xml | 0 .../src/main/res/drawable/ic_unfollow.xml | 0 .../src/main/res/drawable/ic_unlock.xml | 0 .../src/main/res/drawable/ic_unsubscribe.xml | 0 .../src/main/res/drawable/ic_update.xml | 0 .../src/main/res/drawable/ic_wrap_text.xml | 0 .../src/main/res/drawable/left_border.xml | 0 .../res/drawable/popup_window_background.xml | 18 + .../src/main/res/drawable/rect_shape.xml | 0 .../src/main/res/drawable/right_border.xml | 0 .../drawable/rounded_toolbar_shadow_up.xml | 11 + .../src/main/res/drawable/scrim.xml | 0 .../drawable/selectable_layout_background.xml | 7 + .../main/res/drawable/snackbar_background.xml | 6 + .../drawable/snackbar_background_error.xml | 6 + .../res/drawable/splash_screen_drawable.xml | 4 +- .../main/res/drawable/toolbar_shadow_up.xml | 0 .../src/main/res/drawable/top_border.xml | 0 .../main/res/drawable/top_bottom_border.xml | 16 + .../res/drawable/top_radius_background.xml | 11 + .../drawable/top_round_corner_background.xml | 11 + resources/src/main/res/font/abeezee.ttf | Bin 0 -> 46124 bytes resources/src/main/res/font/roboto_mono.ttf | Bin 0 -> 114624 bytes resources/src/main/res/font/rubik_bold.ttf | Bin 0 -> 143696 bytes resources/src/main/res/font/rubik_font.xml | 13 + resources/src/main/res/font/rubik_normal.ttf | Bin 0 -> 140732 bytes .../src/main/res/menu/edit_submit_menu.xml | 12 +- .../src/main/res/menu/issue_menu.xml | 41 +- .../main/res/menu/main_bottom_bar_menu.xml | 9 +- .../src/main/res/menu/main_menu.xml | 29 +- .../src/main/res/menu/notification_menu.xml | 7 +- .../src/main/res/menu/submit_menu.xml | 5 +- .../res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin .../src/main/res/mipmap-nodpi/foreground.png | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin resources/src/main/res/raw/shrug.json | 1 + .../src/main/res/values-land/dimens.xml | 0 .../src/main/res/values/arrays.xml | 21 +- .../src/main/res/values/colors.xml | 0 .../src/main/res/values/dimens.xml | 4 +- .../src/main/res/values/paths.xml | 0 .../src/main/res/values/strings.xml | 24 +- resources/src/main/res/values/styles.xml | 44 + resources/src/main/res/values/theme_amlod.xml | 95 + .../src/main/res/values/theme_attrs.xml | 0 .../src/main/res/values/theme_bluish.xml | 103 + resources/src/main/res/values/theme_dark.xml | 101 + resources/src/main/res/values/theme_light.xml | 93 + .../src/main/res/values/themes.xml | 24 +- settings.gradle | 2 +- 1758 files changed, 57327 insertions(+), 116962 deletions(-) delete mode 100644 .codecov.yml create mode 100644 .editorconfig delete mode 100644 .github/CONTRIBUTING.md delete mode 100644 .github/ISSUE_TEMPLATE.md delete mode 100644 .github/assets/direct-apk-download.png delete mode 100644 .github/assets/feature_graphic.png delete mode 100644 .github/assets/first.png delete mode 100644 .github/assets/fourth.png delete mode 100644 .github/assets/sec.png delete mode 100644 .github/assets/third.png delete mode 100644 .github_changelog_generator delete mode 100644 .travis.yml delete mode 100644 CODE_OF_CONDUCT.md delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 _config.yml delete mode 100644 app/src/androidTest/java/com/fastaccess/helper/TestHelper.java delete mode 100644 app/src/androidTest/java/com/fastaccess/ui/modules/login/LoginActivityTest.java delete mode 100644 app/src/androidTest/java/com/fastaccess/ui/modules/login/LoginChooserActivityTest.java delete mode 100644 app/src/androidTest/java/com/fastaccess/ui/modules/main/MainActivityTest.java delete mode 100644 app/src/main/assets/colors.json delete mode 100644 app/src/main/assets/fonts/app_font.ttf delete mode 100644 app/src/main/assets/highlight/js/prettify.js delete mode 100644 app/src/main/assets/highlight/js/prettify_line_number.js delete mode 100644 app/src/main/assets/highlight/js/scrollto.js delete mode 100644 app/src/main/assets/highlight/styles/prettify.css delete mode 100644 app/src/main/assets/highlight/styles/prettify_dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/agate.css delete mode 100644 app/src/main/assets/highlight/styles/themes/androidstudio.css delete mode 100644 app/src/main/assets/highlight/styles/themes/arduino-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/arta.css delete mode 100644 app/src/main/assets/highlight/styles/themes/ascetic.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-cave-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-cave-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-dune-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-dune-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-estuary-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-estuary-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-forest-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-forest-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-heath-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-heath-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-lakeside-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-lakeside-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-plateau-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-plateau-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-savanna-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-savanna-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-seaside-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-seaside-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-sulphurpool-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atelier-sulphurpool-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atom-one-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/atom-one-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/brown-paper.css delete mode 100644 app/src/main/assets/highlight/styles/themes/codepen-embed.css delete mode 100644 app/src/main/assets/highlight/styles/themes/color-brewer.css delete mode 100644 app/src/main/assets/highlight/styles/themes/darcula.css delete mode 100644 app/src/main/assets/highlight/styles/themes/dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/darkula.css delete mode 100644 app/src/main/assets/highlight/styles/themes/default.css delete mode 100644 app/src/main/assets/highlight/styles/themes/docco.css delete mode 100644 app/src/main/assets/highlight/styles/themes/dracula.css delete mode 100644 app/src/main/assets/highlight/styles/themes/far.css delete mode 100644 app/src/main/assets/highlight/styles/themes/foundation.css delete mode 100644 app/src/main/assets/highlight/styles/themes/github-gist.css delete mode 100644 app/src/main/assets/highlight/styles/themes/github.css delete mode 100644 app/src/main/assets/highlight/styles/themes/googlecode.css delete mode 100644 app/src/main/assets/highlight/styles/themes/grayscale.css delete mode 100644 app/src/main/assets/highlight/styles/themes/gruvbox-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/gruvbox-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/hopscotch.css delete mode 100644 app/src/main/assets/highlight/styles/themes/hybrid.css delete mode 100644 app/src/main/assets/highlight/styles/themes/idea.css delete mode 100644 app/src/main/assets/highlight/styles/themes/ir-black.css delete mode 100644 app/src/main/assets/highlight/styles/themes/kimbie.dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/kimbie.light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/magula.css delete mode 100644 app/src/main/assets/highlight/styles/themes/mono-blue.css delete mode 100644 app/src/main/assets/highlight/styles/themes/monokai-sublime.css delete mode 100644 app/src/main/assets/highlight/styles/themes/monokai.css delete mode 100644 app/src/main/assets/highlight/styles/themes/obsidian.css delete mode 100644 app/src/main/assets/highlight/styles/themes/ocean.css delete mode 100644 app/src/main/assets/highlight/styles/themes/paraiso-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/paraiso-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/pojoaque.css delete mode 100644 app/src/main/assets/highlight/styles/themes/purebasic.css delete mode 100644 app/src/main/assets/highlight/styles/themes/qtcreator_dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/qtcreator_light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/railscasts.css delete mode 100644 app/src/main/assets/highlight/styles/themes/rainbow.css delete mode 100644 app/src/main/assets/highlight/styles/themes/routeros.css delete mode 100644 app/src/main/assets/highlight/styles/themes/school-book.css delete mode 100644 app/src/main/assets/highlight/styles/themes/solarized-dark.css delete mode 100644 app/src/main/assets/highlight/styles/themes/solarized-light.css delete mode 100644 app/src/main/assets/highlight/styles/themes/sunburst.css delete mode 100644 app/src/main/assets/highlight/styles/themes/tomorrow-night-blue.css delete mode 100644 app/src/main/assets/highlight/styles/themes/tomorrow-night-bright.css delete mode 100644 app/src/main/assets/highlight/styles/themes/tomorrow-night-eighties.css delete mode 100644 app/src/main/assets/highlight/styles/themes/tomorrow-night.css delete mode 100644 app/src/main/assets/highlight/styles/themes/tomorrow.css delete mode 100644 app/src/main/assets/highlight/styles/themes/vs.css delete mode 100644 app/src/main/assets/highlight/styles/themes/vs2015.css delete mode 100644 app/src/main/assets/highlight/styles/themes/xcode.css delete mode 100644 app/src/main/assets/highlight/styles/themes/xt256.css delete mode 100644 app/src/main/assets/highlight/styles/themes/zenburn.css delete mode 100644 app/src/main/assets/lottie/bounching_ball.json delete mode 100644 app/src/main/assets/lottie/code_invite_success.json delete mode 100644 app/src/main/assets/md/github.css delete mode 100644 app/src/main/assets/md/github_dark.css delete mode 100644 app/src/main/assets/md/intercept-hash.js delete mode 100644 app/src/main/assets/md/intercept-touch.js delete mode 100644 app/src/main/graphql/github/PinnedRepos.graphql delete mode 100644 app/src/main/graphql/github/PullRequestTimeline.graphql delete mode 100644 app/src/main/graphql/github/RepoProject.graphql delete mode 100644 app/src/main/java/com/fastaccess/App.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/AccessTokenModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/AppLanguageModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/AssigneesRequestModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/AuthModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/BranchesModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/CommentRequestModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/CommitCountModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/CommitFileChanges.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/CommitFileListModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/CommitFileModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/CommitLinesModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/CommitListModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/CommitRequestModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/CreateGistModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/CreateIssueModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/CreateMilestoneModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/EditRepoFileModel.kt delete mode 100644 app/src/main/java/com/fastaccess/data/dao/EditReviewCommentModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/FilesListModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/FilterOptionsModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/FragmentPagerAdapterModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/GistHubErrorsModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/GitCommitListModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/GitCommitModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/GitHubErrorResponse.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/GitHubStatusModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/GithubFileModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/GithubState.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/GroupedNotificationModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/GroupedReviewModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/ImgurReponseModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/IssueEventAdapterModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/IssueRequestModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/IssuesPageable.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/LabelListModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/LabelModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/LanguageColorModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/LicenseModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/LockIssuePrModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/MarkdownModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/MergeRequestModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/MergeResponseModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/MilestoneModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/NameParser.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/NotificationSoundModel.kt delete mode 100644 app/src/main/java/com/fastaccess/data/dao/NotificationSubjectModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/NotificationSubscriptionBodyModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/Pageable.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/PayloadModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/PostReactionModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/ProUsersModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/ProjectCardModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/ProjectColumnModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/ProjectsModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/PullRequestAdapterModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/PullRequestStatusModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/PullsIssuesParser.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/ReactionsModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/ReleasesAssetsListModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/ReleasesAssetsModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/RenameModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/RepoPathsManager.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/RepoPermissionsModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/RepoSubscriptionModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/ReviewCommentModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/ReviewModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/ReviewRequestModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/SearchCodeModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/SettingsModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/SimpleUrlsModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/SlackInvitePostModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/SlackResponseModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/SparseBooleanArrayParcelable.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/StatusesModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/TabsCountStateModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/TeamsModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/TimelineModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/TopicsModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/TreeResponseModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/TrendingModel.kt delete mode 100644 app/src/main/java/com/fastaccess/data/dao/UsersListModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/WikiModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/BaseConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/CommitConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/CommitFilesConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/CommitsConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/GistConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/GitCommitConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/GitHubFilesConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/GitHubStateConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/IssueConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/LabelConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/LabelsListConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/LicenseConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/MilestoneConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/NotificationSubjectConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/PayloadConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/PullRequestConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/ReactionsConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/ReleasesAssetsConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/RenameConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/RepoConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/RepoPermissionConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/TeamConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/TopicsConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/UserConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/converters/UsersConverter.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractComment.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractCommit.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractEvent.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractFastHubNotification.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractGist.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractIssue.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractIssueEvent.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractLogin.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractNotification.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractNotificationQueue.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedGists.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedIssues.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedPullRequests.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedRepos.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractPullRequest.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractRelease.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractRepo.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractRepoFile.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractSearchHistory.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractUser.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/model/AbstractViewerFile.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/timeline/AuthorModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/timeline/CommentEvent.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/timeline/GenericEvent.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/timeline/ParentsModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestCommitModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestReviewModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestTimelineModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/timeline/SourceModel.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/types/EventsType.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/types/FilesType.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/types/GitEntryType.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/types/IssueEventType.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/types/IssueState.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/types/MyIssuesType.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/types/NotificationReason.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/types/NotificationType.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/types/ReactionTypes.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/types/ReviewStateType.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/types/StatusStateType.java delete mode 100644 app/src/main/java/com/fastaccess/data/dao/wiki/WikiContentModel.kt delete mode 100644 app/src/main/java/com/fastaccess/data/dao/wiki/WikiSideBarModel.kt delete mode 100644 app/src/main/java/com/fastaccess/data/service/ContentService.kt delete mode 100644 app/src/main/java/com/fastaccess/data/service/GistService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/ImgurService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/IssueService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/LoginRestService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/NotificationService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/OrganizationService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/ProjectsService.kt delete mode 100644 app/src/main/java/com/fastaccess/data/service/PullRequestService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/ReactionsService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/RepoService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/ReviewService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/SearchService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/SlackService.java delete mode 100644 app/src/main/java/com/fastaccess/data/service/UserRestService.java create mode 100644 app/src/main/java/com/fastaccess/github/App.kt create mode 100644 app/src/main/java/com/fastaccess/github/base/BaseActivity.kt create mode 100644 app/src/main/java/com/fastaccess/github/base/BaseBottomSheetDialogFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/base/BaseDialogFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/base/BaseFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/base/BasePagerFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/base/BaseViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/base/callback/UpdateTabCount.kt create mode 100644 app/src/main/java/com/fastaccess/github/base/engine/ThemeEngine.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/annotations/ForActivity.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/annotations/ForApplication.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/annotations/ForAuth.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/annotations/ForDB.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/annotations/ViewModelKey.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/annotations/WorkerKey.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/components/AppComponent.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/components/WorkerSubComponent.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/ActivityBindingModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/ActivityModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/ApplicationModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/DialogFragmentBindingModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/FastHubDatabaseModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/FragmentBindingModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/FragmentModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/NetworkModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/RepositoryModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/UseCaseModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/ViewModelModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/modules/WorkersModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/scopes/PerActivity.kt create mode 100644 app/src/main/java/com/fastaccess/github/di/scopes/PerFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/platform/deeplink/AppDeepLink.kt create mode 100644 app/src/main/java/com/fastaccess/github/platform/deeplink/RawWebDeepLink.kt create mode 100644 app/src/main/java/com/fastaccess/github/platform/deeplink/WebDeepLink.kt create mode 100644 app/src/main/java/com/fastaccess/github/platform/extension/ClickExtenion.kt rename app/src/main/java/com/fastaccess/{provider => github/platform}/fabric/FabricProvider.kt (75%) create mode 100644 app/src/main/java/com/fastaccess/github/platform/glide/GlideModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/platform/timber/LogTree.kt create mode 100644 app/src/main/java/com/fastaccess/github/platform/viewmodel/FastHubViewModelFactory.kt create mode 100644 app/src/main/java/com/fastaccess/github/platform/workmanager/DaggerWorkerFactory.kt create mode 100644 app/src/main/java/com/fastaccess/github/platform/works/MarkAsReadNotificationWorker.kt create mode 100644 app/src/main/java/com/fastaccess/github/platform/works/ReactionWorker.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/AllNotificationsAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/AssigneesAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/IssueTimelineAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/LabelColorAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/LabelsAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/LanguagesAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/LoggedInUsersAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/MainScreenAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/MilestonesAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/MyIssuesPrsAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/OrganizationsAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/PagerAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/ProfileFeedsAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/ProfileFollowingFollowersAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/ProfileGistsAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/ProfileOrgsAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/ProfilePinnedReposAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/ProfileReposAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/ProfileStarredReposAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/SearchReposAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/ShortUsersAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/TrendingsAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/UnreadNotificationsAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/base/BasePagedAdapter.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/base/BaseViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/AssigneeViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/CommentViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/FeedsViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/IssueContentViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LabelColorViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LabelViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LanguagesViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LoadingViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LoggedInUserViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/MilestoneViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/MyIssuesPrsViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/NotificationsViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/OrganizationViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileFollowerFollowingViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileGistsViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileOrgsViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ReposProfileViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ReposStarredProfileViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ShortRepoViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ShortUserViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/TitleSectionViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/TrendingViewHolder.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/auth/LoginChooserActivity.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/auth/LoginChooserViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/auth/callback/LoginChooserCallback.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/auth/chooser/LoginChooserFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/auth/login/AuthLoginFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/auth/login/LoginViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/editor/EditorWebViewActivity.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/feed/fragment/FeedsFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/feed/fragment/viewmodel/FeedsViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issue/IssueActivity.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issue/fragment/IssueFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issue/fragment/viewmodel/IssueTimelineViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/LockUnlockFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/assignees/AssigneesFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/assignees/viewmodel/AssigneesViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/LabelsFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/create/CreateLabelFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/viewmodel/LabelsViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/CreateMilestoneDialogFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/MilestoneFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/viewmodel/MilestoneViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/filter/FilterIssuesPrsBottomSheet.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/fragment/FilterIssuePullRequestsFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/fragment/viewmodel/FilterIssuePullRequestsViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/main/MainActivity.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/main/fragment/MainFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/main/fragment/viewmodel/MainFragmentViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/multipurpose/MultiPurposeActivity.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/multipurpose/MultiPurposeBottomSheetDialog.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/notifications/NotificationPagerFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/read/AllNotificationsFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/read/AllNotificationsViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/unread/UnreadNotificationsFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/unread/viewmodel/UnreadNotificationsViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/ProfileActivity.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/feeds/ProfileFeedFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/feeds/viewmodel/ProfileFeedsViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/followersandfollowings/ProfileFollowersFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/followersandfollowings/viewmodel/FollowersFollowingViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/fragment/ProfileFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/fragment/viewmodel/ProfileViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/gists/ProfileGistsFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/gists/viewmodel/ProfileGistsViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/orgs/userorgs/UserOrgsFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/orgs/userorgs/viewmodel/UserOrgsViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/repos/ProfileReposFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/repos/viewmodel/ProfileReposViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/starred/ProfileStarredReposFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/profile/starred/viewmodel/ProfileStarredReposViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/routing/RoutingActivity.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/routing/RoutingModule.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/search/filter/FilterSearchBottomSheet.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/search/fragment/SearchFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/search/fragment/viewmodel/FilterSearchViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/trending/TrendingActivity.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/trending/filter/FilterTrendingBottomSheet.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/trending/fragment/TrendingFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/modules/trending/fragment/viewmodel/TrendingViewModel.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/AnchorSheetBehavior.java create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/AppBarBottomSheetBehaviour.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/AvatarImageView.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/ParentSwipeRefreshLayout.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/ReactionsChipGroup.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/ViewPagerView.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/dialog/IconDialogFragment.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/BaseRecyclerView.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/EndlessRecyclerViewScrollListener.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/RecyclerViewFastScroller.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/SwipeToDeleteCallback.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/decoration/InsetDividerDecoration.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeGridLayoutManager.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeLinearLayoutManager.kt create mode 100644 app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeStaggeredLayoutManager.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/auth/GetAccessTokenUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/auth/LoginUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/auth/LoginWithAccessTokenUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/feed/FeedsUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/AddAssigneesUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/CloseOpenIssuePrUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/CreateLabelUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/CreateMilestoneUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/FilterIssuesUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/FilterPullRequestsUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetAssigneesUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetIssueTimelineUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetIssueUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetLabelsUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetMilestonesUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/LockUnlockIssuePrUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/MilestoneIssuePrUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/issuesprs/PutLabelsUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/main/FeedsMainScreenUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/main/IssuesMainScreenUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/main/PullRequestsMainScreenUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/notification/NotificationUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/search/FilterSearchReposUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/search/FilterSearchUsersUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/user/BlockUnblockUserUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/user/FollowUnfollowUserUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/user/IsUserBlockedUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/user/UserFeedsUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/usecase/user/UserUseCase.kt create mode 100644 app/src/main/java/com/fastaccess/github/utils/Constants.kt create mode 100644 app/src/main/java/com/fastaccess/github/utils/extensions/ActivityFragmentExtension.kt create mode 100644 app/src/main/java/com/fastaccess/github/utils/extensions/PrefExtension.kt create mode 100644 app/src/main/java/com/fastaccess/github/utils/extensions/ViewExtension.kt delete mode 100644 app/src/main/java/com/fastaccess/helper/ActivityHelper.java delete mode 100644 app/src/main/java/com/fastaccess/helper/AnimHelper.java delete mode 100644 app/src/main/java/com/fastaccess/helper/AppHelper.java delete mode 100644 app/src/main/java/com/fastaccess/helper/BundleConstant.java delete mode 100644 app/src/main/java/com/fastaccess/helper/Bundler.java delete mode 100644 app/src/main/java/com/fastaccess/helper/CustomTabsHelper.java delete mode 100644 app/src/main/java/com/fastaccess/helper/DeviceNameGetter.java delete mode 100644 app/src/main/java/com/fastaccess/helper/FileHelper.java delete mode 100644 app/src/main/java/com/fastaccess/helper/GithubConfigHelper.java delete mode 100644 app/src/main/java/com/fastaccess/helper/InputHelper.java delete mode 100644 app/src/main/java/com/fastaccess/helper/Logger.java delete mode 100644 app/src/main/java/com/fastaccess/helper/ObjectsCompat.java delete mode 100644 app/src/main/java/com/fastaccess/helper/ParcelableHelper.kt delete mode 100644 app/src/main/java/com/fastaccess/helper/ParseDateFormat.java delete mode 100644 app/src/main/java/com/fastaccess/helper/PrefGetter.java delete mode 100644 app/src/main/java/com/fastaccess/helper/PrefHelper.java delete mode 100644 app/src/main/java/com/fastaccess/helper/RxHelper.java delete mode 100644 app/src/main/java/com/fastaccess/helper/TypeFaceHelper.java delete mode 100644 app/src/main/java/com/fastaccess/helper/ViewHelper.java delete mode 100644 app/src/main/java/com/fastaccess/provider/colors/ColorsProvider.java delete mode 100644 app/src/main/java/com/fastaccess/provider/emoji/Emoji.java delete mode 100644 app/src/main/java/com/fastaccess/provider/emoji/EmojiLoader.java delete mode 100644 app/src/main/java/com/fastaccess/provider/emoji/EmojiManager.java delete mode 100644 app/src/main/java/com/fastaccess/provider/emoji/EmojiParser.java delete mode 100644 app/src/main/java/com/fastaccess/provider/emoji/EmojiTrie.java delete mode 100644 app/src/main/java/com/fastaccess/provider/emoji/Fitzpatrick.java delete mode 100644 app/src/main/java/com/fastaccess/provider/fcm/PushNotificationService.java delete mode 100644 app/src/main/java/com/fastaccess/provider/gson/ToGsonProvider.java delete mode 100644 app/src/main/java/com/fastaccess/provider/markdown/CachedComments.kt delete mode 100644 app/src/main/java/com/fastaccess/provider/markdown/MarkDownProvider.java delete mode 100644 app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/Emoji.java delete mode 100644 app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/EmojiExtension.java delete mode 100644 app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/internal/EmojiDelimiterProcessor.java delete mode 100644 app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/internal/EmojiNodeRenderer.java delete mode 100644 app/src/main/java/com/fastaccess/provider/markdown/extension/mention/Mention.java delete mode 100644 app/src/main/java/com/fastaccess/provider/markdown/extension/mention/MentionExtension.java delete mode 100644 app/src/main/java/com/fastaccess/provider/markdown/extension/mention/internal/MentionDelimiterProcessor.java delete mode 100644 app/src/main/java/com/fastaccess/provider/markdown/extension/mention/internal/MentionNodeRenderer.java delete mode 100644 app/src/main/java/com/fastaccess/provider/rest/ApolloProdivder.kt delete mode 100644 app/src/main/java/com/fastaccess/provider/rest/ImgurProvider.java delete mode 100644 app/src/main/java/com/fastaccess/provider/rest/LoginProvider.java delete mode 100644 app/src/main/java/com/fastaccess/provider/rest/RepoQueryProvider.java delete mode 100644 app/src/main/java/com/fastaccess/provider/rest/RestProvider.java delete mode 100644 app/src/main/java/com/fastaccess/provider/rest/converters/GithubResponseConverter.java delete mode 100644 app/src/main/java/com/fastaccess/provider/rest/interceptors/AuthenticationInterceptor.kt delete mode 100644 app/src/main/java/com/fastaccess/provider/rest/interceptors/ContentTypeInterceptor.kt delete mode 100644 app/src/main/java/com/fastaccess/provider/rest/interceptors/PaginationInterceptor.java delete mode 100644 app/src/main/java/com/fastaccess/provider/rest/jsoup/JsoupProvider.java delete mode 100644 app/src/main/java/com/fastaccess/provider/rest/loadmore/OnLoadMore.java delete mode 100644 app/src/main/java/com/fastaccess/provider/scheme/LinkParserHelper.java delete mode 100644 app/src/main/java/com/fastaccess/provider/scheme/SchemeParser.java delete mode 100644 app/src/main/java/com/fastaccess/provider/tasks/git/GithubActionService.java delete mode 100644 app/src/main/java/com/fastaccess/provider/tasks/git/ReactionService.java delete mode 100644 app/src/main/java/com/fastaccess/provider/tasks/notification/NotificationSchedulerJobTask.java delete mode 100644 app/src/main/java/com/fastaccess/provider/tasks/notification/ReadNotificationService.java delete mode 100644 app/src/main/java/com/fastaccess/provider/tasks/slack/SlackInvitationService.java delete mode 100644 app/src/main/java/com/fastaccess/provider/tasks/version/CheckVersionService.kt delete mode 100644 app/src/main/java/com/fastaccess/provider/theme/ThemeEngine.kt delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/CommentsHelper.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/HtmlHelper.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/ReactionsProvider.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/TimelineConverter.kt delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/TimelineProvider.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/BetterLinkMovementExtended.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/CodeBackgroundRoundedSpan.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/DrawableHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/EmojiHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/HeaderHandler.kt delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/HrHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/HrSpan.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/ItalicHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/LinkHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/ListsHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/MarginHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/PreTagHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/QuoteHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/StrikethroughHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/SubScriptHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/SuperScriptHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/TableHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/UnderlineHandler.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/DrawableGetter.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/GlideDrawableTarget.java delete mode 100644 app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/UrlDrawable.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/AssigneesAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/BranchesAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/ColumnCardAdapter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/CommentsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/CommitCommentsAdapter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/CommitFilesAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/CommitLinesAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/CommitsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/EmojiAdapter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/FastHubNotificationsAdapter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/FeedsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/FragmentsPagerAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/GistFilesAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/GistsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/IssuesAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/IssuesTimelineAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/LabelColorsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/LabelsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/LoginAdapter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/MilestonesAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/NotificationsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/PinnedReposAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/ProfileOrgsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/ProfilePinnedReposAdapter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/ProjectsAdapter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/PullRequestAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/ReleasesAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/RepoFilePathsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/RepoFilesAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/ReposAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/ReviewCommentsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/SearchCodeAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/SettingsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/SimpleListAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/SpinnerAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/TeamsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/TopicsAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/TrendingAdapter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/UsersAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/callback/OnToggleView.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/callback/ReactionsCallback.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/AssigneesViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/ColumnCardViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommentsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitCommentsViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitLinesViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitThreadViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/EmojiViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/FastHubNotificationViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/FeedsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/GistFilesViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/GistsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/GroupedReviewsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssueDetailsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssueTimelineViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssuesViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/LabelColorsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/LabelsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/LoginViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/MilestonesViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/NotificationsHeaderViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/NotificationsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/PinnedReposViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfileOrgsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProjectViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestEventViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestFilesViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullStatusViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReleasesViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/RepoFilePathsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/RepoFilesViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReposViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReviewCommentsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReviewsViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/SearchCodeViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/SimpleViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/TeamsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/TimelineCommentsViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/TrendingViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/UnknownTypeViewHolder.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/adapter/viewholder/UsersViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/base/BaseActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/base/BaseBottomSheetDialog.java delete mode 100644 app/src/main/java/com/fastaccess/ui/base/BaseDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/base/BaseFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/base/BaseMvpBottomSheetDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/base/MainNavDrawer.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/base/mvp/BaseMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/base/mvp/presenter/BasePresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/about/FastHubAboutActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogBottomSheetDialog.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/code/CodeViewerActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/editor/EditorActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/editor/EditorMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/editor/EditorPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/editor/comment/CommentEditorFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiBottomSheet.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImageDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImageMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImagePresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/filter/chooser/FilterAddChooserListener.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/filter/chooser/FilterChooserBottomSheetDialog.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivityMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivityPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssueFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssuePresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssuesMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/GistsFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/GistsListActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/GistsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/GistsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistBottomSheetDialog.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/login/LoginActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/MainActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/MainMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/MainPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/donation/CheckPurchaseActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/donation/DonateActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/donation/DonationActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/drawer/AccountDrawerFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/drawer/MainDrawerFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/notifications/FastHubNotificationDialog.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/playstore/PlayStoreWarningActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/premium/GmsTaskListeners.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/notification/NotificationActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/notification/callback/OnNotificationChangedListener.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationsFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/parser/LinksParserActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/PinnedReposActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssueFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssueMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssuePresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/project/OrgProjectActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/TeamPagerActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposFilterBottomSheetDialog.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/DummyFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesSingleton.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/history/FileCommitHistoryActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/viewer/FullCommitFileActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/files/activity/RepoFilesActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/ReleasesListActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/pager/BranchesPagerFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/pager/BranchesPagerListener.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicenseBottomSheet.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicenseMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicensePresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/locking/LockIssuePrBottomSheetDialog.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/locking/LockIssuePrCallback.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestoneDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestoneMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestonePresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestonePresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/MilestoneDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscMVp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFileActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFileMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFilePresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/git/delete/DeleteContentFileCallback.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/git/delete/DeleteFileBottomSheetFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssueActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssueMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssuePresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoClosedIssuesFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoIssuesMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoIssuesPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoOpenedIssuesFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelineFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelineMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelinePresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/RepoProjectsFragmentPager.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/crud/ProjectCurdDialogFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangeActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangeMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangePresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelineFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelineMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelinePresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullReqeustMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullRequestDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullRequestPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/reviews/AddReviewDialogFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/reviews/callback/ReviewCommentListener.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/SearchActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/SearchMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/SearchPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/SearchUserActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodeFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodeMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodePresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFileActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFileMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFilePresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/LanguageBottomSheetDialog.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/SettingsActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/SlackBottomSheetDialog.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundBottomSheet.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/theme/ThemeActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodeActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodeMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodePresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragmentMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragmentPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/trending/TrendingActivity.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/trending/TrendingMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/trending/TrendingPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragment.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragmentMvp.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragmentPresenter.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/user/UserPagerActivity.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/user/UserPagerMvp.java delete mode 100644 app/src/main/java/com/fastaccess/ui/modules/user/UserPagerPresenter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/AppbarRefreshLayout.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/AutoLinearLayout.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/AvatarLayout.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/CardsPagerTransformerBasic.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/ColorPickerPreference.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/DiffLineSpan.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FloatingActionButtonBehavior.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontAutoCompleteEditText.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontButton.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontCheckbox.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontEditText.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontRadioButton.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontSwitchView.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/FontTextView.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/ForegroundImageView.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/ForegroundRelativeLayout.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/LabelSpan.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/NestedCoordinatorLayout.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/SpannableBuilder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/StateLayout.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/TabletBehavior.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/ViewPagerView.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/color/ColorGenerator.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/contributions/ContributionsDay.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/contributions/ContributionsProvider.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/contributions/GitHubContributionsView.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/contributions/utils/ColorsUtils.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/contributions/utils/DatesUtils.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/dialog/ListDialogView.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/dialog/ProgressDialogFragment.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/markdown/MarkDownLayout.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/markdown/MarkdownEditText.kt delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BottomPaddingDecoration.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/InsetDividerDecoration.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/ProgressBarViewHolder.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/GridManager.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/LinearManager.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/StaggeredManager.java delete mode 100644 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/scroll/InfiniteScroll.java delete mode 100755 app/src/main/java/com/fastaccess/ui/widgets/recyclerview/scroll/RecyclerViewFastScroller.java delete mode 100644 app/src/main/java/com/prettifier/pretty/NestedWebView.java delete mode 100644 app/src/main/java/com/prettifier/pretty/PrettifyWebView.java delete mode 100644 app/src/main/java/com/prettifier/pretty/callback/MarkDownInterceptorInterface.java delete mode 100644 app/src/main/java/com/prettifier/pretty/helper/CodeThemesHelper.java delete mode 100644 app/src/main/java/com/prettifier/pretty/helper/GithubHelper.java delete mode 100644 app/src/main/java/com/prettifier/pretty/helper/PrettifyHelper.java delete mode 100644 app/src/main/java/com/zzhoujay/markdown/style/CodeSpan.java delete mode 100644 app/src/main/java/com/zzhoujay/markdown/style/FontSpan.java delete mode 100644 app/src/main/java/com/zzhoujay/markdown/style/LinkSpan.java delete mode 100644 app/src/main/java/com/zzhoujay/markdown/style/MarkDownQuoteSpan.java delete mode 100644 app/src/main/res/color/search_tab_highlighter.xml delete mode 100755 app/src/main/res/drawable-nodpi/web_hi_res_512.png delete mode 100644 app/src/main/res/drawable-small/splash_screen_drawable.xml delete mode 100644 app/src/main/res/drawable-v26/ic_app_shortcut_github.xml delete mode 100644 app/src/main/res/drawable-v26/ic_app_shortcut_issues.xml delete mode 100644 app/src/main/res/drawable-v26/ic_app_shortcut_pinned.xml delete mode 100644 app/src/main/res/drawable-v26/ic_app_shortcut_profile.xml delete mode 100644 app/src/main/res/drawable-v26/ic_app_shortcut_pull_requests.xml delete mode 100755 app/src/main/res/drawable/fastscroller_bubble.xml delete mode 100644 app/src/main/res/drawable/ic_person.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-land/bottom_fab.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-land/fragment_container.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-land/header_title_with_toolbar.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-land/issues_bottom_navigation.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-land/main_bottom_navigation.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-land/profile_follow_action_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-sw600dp/bottom_fab.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-sw600dp/fragment_container.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-sw600dp/header_title_with_toolbar.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-sw600dp/issues_bottom_navigation.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-sw600dp/main_bottom_navigation.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout-sw600dp/repo_file_header_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/accounts_menu_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/activity_fragment_layout.xml rename app/src/main/res/layouts/main_layouts/layout/{fragment_container.xml => activity_main.xml} (79%) delete mode 100644 app/src/main/res/layouts/main_layouts/layout/activity_main_view.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/activity_search_file.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/activity_search_user.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/activity_settings.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/activity_settings_category.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/add_banner_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/add_gist_file_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/add_label_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/add_milestone_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/add_review_dialog_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/bottom_fab.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/branches_tabbed_viewpager.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/centered_tabbed_viewpager.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/code_editor_activity_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/comment_box_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/commit_file_full_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/commit_pager_activity.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/commit_with_branch_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/create_gist_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/create_issue_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/create_label_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/create_milestone_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/delete_repo_file_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/dialog_picker.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/edit_project_column_note_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/edit_repo_file_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/editor_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/emoji_popup_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/fab_micro_grid_refresh_list.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/fab_simple_refresh_list_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/filter_bottom_sheet.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/filter_issues_popup.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/filter_issues_prs_layout.xml rename app/src/main/res/layouts/{other_layouts/layout/single_container_layout.xml => main_layouts/layout/fragment_activity_layout.xml} (65%) delete mode 100644 app/src/main/res/layouts/main_layouts/layout/full_screen_file_changes_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/general_viewer_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/gists_activity_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/gists_pager_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/header_title_with_toolbar.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/icon_row_item.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/issue_pager_activity.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/issue_popup_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/issue_pr_bottomsheet_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/issue_pr_fragment_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/issues_bottom_navigation.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/issues_prs_fragment_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/license_viewer_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/login_chooser_activity_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/login_chooser_fragment_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/login_chooser_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/main_bottom_navigation.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/main_fragment_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/main_nav_fragment_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/markdown_buttons_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/markdown_link_image_dialog_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/merge_dialog_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/micro_grid_refresh_list.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/milestone_dialog_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/notification_activity_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/picker_dialog.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/playstore_review_layout_warning.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/pro_features_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/profile_bottom_sheet.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/profile_follow_action_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/profile_fragment_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/project_columns_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/projects_activity_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/pull_request_files_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/repo_file_header_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/repo_file_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/repo_header_icons_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/repo_pager_activity.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/review_changes_bottom_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/review_comment_dialog_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/rounded_toolbar_fragment_list_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/search_fragment_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/search_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/settings_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/simple_refresh_list_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/small_grid_refresh_list.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/submit_review_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/support_development_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/tabbed_pager_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/tabbed_viewpager.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/tending_buttons_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/theme_code_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/theme_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/theme_viewpager.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/title_header_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/toolbar_fragment_list_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/toolbar_fragment_pager_layout.xml rename app/src/main/res/layouts/main_layouts/layout/{notifications_bottom_sheet_layout.xml => toolbar_tabs_activity_layout.xml} (57%) delete mode 100644 app/src/main/res/layouts/main_layouts/layout/trending_activity_layout.xml create mode 100644 app/src/main/res/layouts/main_layouts/layout/trending_fragment_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/vertical_refresh_list.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/view_pager_activity_layout.xml delete mode 100644 app/src/main/res/layouts/main_layouts/layout/wiki_activity_layout.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout-land/appbar_start_margin.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout-sw600dp/appbar_start_margin.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout_bottomsheet.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout_primary_dark.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_center_title_round_background_layout.xml rename app/src/main/res/layouts/other_layouts/layout/{appbar_start_margin.xml => appbar_default_layout.xml} (60%) delete mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_elevation_dark.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_logo_center_title_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_profile_title_layout.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_tabbed_elevation.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/appbar_tabs_center_title_layout.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/avatar_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/bottm_bar_menu_layout.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/dialog_guide_layout.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/drawer_header.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/empty_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/empty_state_layout.xml mode change 100755 => 100644 app/src/main/res/layouts/other_layouts/layout/fastscroller_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/filter_issue_pr_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/filter_search_layout.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/filter_trending_layout.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/home_button.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/icon_dialog_layout.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/lock_issue_pr_dialog.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/lock_unlock_issue_pr_layout.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/message_dialog.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/nav_menu_layout.xml rename app/src/main/res/layouts/other_layouts/layout/{progress_dialog_layout.xml => progress_layout.xml} (67%) create mode 100644 app/src/main/res/layouts/other_layouts/layout/reaction_group_chip_widget.xml create mode 100644 app/src/main/res/layouts/other_layouts/layout/reactions_chips_layout.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/simple_footer_list_dialog.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/simple_list_dialog.xml delete mode 100644 app/src/main/res/layouts/other_layouts/layout/state_layout.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout-sw600dp/login_row_item_menu.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout-sw600dp/repos_row_item_menu.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/add_filter_row_layout.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/assignees_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/branches_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/column_card_row_layout.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/comment_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/comments_dropdown_layout.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/comments_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/commit_file_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/commit_line_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/emoji_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/fasthub_notification_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/feeds_row_no_image_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/file_path_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/gist_files_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/grouped_commit_comment_row.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/grouped_review_timeline_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/icon_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/issue_content_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/issue_detail_header_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/issue_header_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/issue_no_image_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/issue_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/issue_timeline_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/issues_prs_main_screen_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/label_color_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/language_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/login_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/login_row_item_menu.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/no_emojies_comments_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/notification_header_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/notification_main_screen_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/notifications_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/org_profile_overview_layout.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/organization_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/preference_widget_color.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/profile_follower_following_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/profile_gist_repo_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/profile_org_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/profile_overview_layout.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/progress_layout.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/pull_status_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/pullrequest_file_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/releases_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/repo_files_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/repos_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/repos_row_item_menu.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/repos_row_no_image_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/review_comments_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/review_timeline_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/simple_color_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/simple_row_item.xml create mode 100644 app/src/main/res/layouts/row_layouts/layout/title_section_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/topics_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/unknown_row_item.xml delete mode 100644 app/src/main/res/layouts/row_layouts/layout/users_small_row_item.xml delete mode 100644 app/src/main/res/menu-land/bottom_nav_menu.xml delete mode 100644 app/src/main/res/menu-sw600dp/bottom_nav_menu.xml delete mode 100644 app/src/main/res/menu-sw600dp/repo_bottom_nav_menu.xml delete mode 100644 app/src/main/res/menu-sw600dp/repo_with_project_bottom_nav_menu.xml delete mode 100644 app/src/main/res/menu/bottom_nav_menu.xml delete mode 100644 app/src/main/res/menu/comments_menu.xml delete mode 100644 app/src/main/res/menu/commit_row_menu.xml delete mode 100644 app/src/main/res/menu/download_browser_menu.xml delete mode 100644 app/src/main/res/menu/download_share_menu.xml delete mode 100644 app/src/main/res/menu/dynamic_trending_menu.xml delete mode 100644 app/src/main/res/menu/filter_fab_menu.xml delete mode 100644 app/src/main/res/menu/filter_issue_state_menu.xml delete mode 100644 app/src/main/res/menu/gist_menu.xml delete mode 100644 app/src/main/res/menu/link_popup_menu.xml delete mode 100644 app/src/main/res/menu/project_card_menu.xml delete mode 100644 app/src/main/res/menu/pull_request_menu.xml delete mode 100644 app/src/main/res/menu/repo_bottom_nav_menu.xml delete mode 100644 app/src/main/res/menu/repo_menu.xml delete mode 100644 app/src/main/res/menu/repo_with_project_bottom_nav_menu.xml delete mode 100644 app/src/main/res/menu/share_menu.xml delete mode 100644 app/src/main/res/menu/trending_menu.xml delete mode 100644 app/src/main/res/menu/wrap_menu_option.xml create mode 100644 app/src/main/res/navigation/login_navigation.xml delete mode 100644 app/src/main/res/raw/changelog.html delete mode 100644 app/src/main/res/values-ar/strings.xml delete mode 100644 app/src/main/res/values-bg/strings.xml delete mode 100644 app/src/main/res/values-cs/strings.xml delete mode 100644 app/src/main/res/values-de/strings.xml delete mode 100644 app/src/main/res/values-es/strings.xml delete mode 100644 app/src/main/res/values-fr/strings.xml delete mode 100644 app/src/main/res/values-in/strings.xml delete mode 100644 app/src/main/res/values-it/strings.xml delete mode 100644 app/src/main/res/values-ja/strings.xml delete mode 100644 app/src/main/res/values-ko/strings.xml delete mode 100644 app/src/main/res/values-lt/strings.xml delete mode 100644 app/src/main/res/values-pl/strings.xml delete mode 100644 app/src/main/res/values-pt-rBR/strings.xml delete mode 100644 app/src/main/res/values-pt-rPT/strings.xml delete mode 100644 app/src/main/res/values-ru/strings.xml delete mode 100644 app/src/main/res/values-sw600dp-land/dimens.xml delete mode 100644 app/src/main/res/values-sw600dp/dimens.xml delete mode 100644 app/src/main/res/values-sw720dp-land/dimens.xml delete mode 100644 app/src/main/res/values-sw720dp/dimens.xml delete mode 100644 app/src/main/res/values-tr/strings.xml delete mode 100644 app/src/main/res/values-w820dp-land/dimens.xml delete mode 100644 app/src/main/res/values-w820dp/dimens.xml delete mode 100644 app/src/main/res/values-zh-rCN/strings.xml delete mode 100644 app/src/main/res/values-zh-rTW/strings.xml delete mode 100644 app/src/main/res/values/attrs.xml create mode 100644 app/src/main/res/values/no_translate.xml delete mode 100644 app/src/main/res/values/styles.xml delete mode 100644 app/src/main/res/values/theme_amlod.xml delete mode 100644 app/src/main/res/values/theme_bluish.xml delete mode 100644 app/src/main/res/values/theme_dark.xml delete mode 100644 app/src/main/res/values/theme_light.xml delete mode 100644 app/src/main/res/values/theme_midnight.xml delete mode 100644 app/src/main/res/xml/about_settings.xml delete mode 100644 app/src/main/res/xml/backup_settings.xml delete mode 100644 app/src/main/res/xml/behaviour_settings.xml delete mode 100644 app/src/main/res/xml/customization_settings.xml delete mode 100644 app/src/main/res/xml/fasthub_settings.xml delete mode 100644 app/src/main/res/xml/language_settings.xml delete mode 100644 app/src/main/res/xml/notification_settings.xml create mode 100644 app/src/test/java/com/fastaccess/github/ExampleUnitTest.kt delete mode 100644 app/src/test/java/com/fastaccess/login/LoginPresenterTest.java rename debug_gradle.properties => build-dependecies/debug_keys.properties (94%) create mode 100644 build-dependecies/fasthub-config.gradle create mode 100644 build-dependecies/fasthub-dependencies.gradle create mode 100644 data/.gitignore create mode 100644 data/build.gradle create mode 100644 data/proguard-rules.pro create mode 100644 data/src/main/AndroidManifest.xml create mode 100644 data/src/main/assets/languages.json create mode 100644 data/src/main/graphql/github/fragments.graphql create mode 100644 data/src/main/graphql/github/issue_prs_mutation.graphql create mode 100644 data/src/main/graphql/github/issues_prs.graphql create mode 100644 data/src/main/graphql/github/profile_screen.graphql rename {app => data}/src/main/graphql/github/schema.json (66%) create mode 100644 data/src/main/graphql/github/search.graphql create mode 100644 data/src/main/java/com/fastaccess/data/model/CountModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/EmbeddedRepoModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/Errors.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/FirebaseTrendingConfigModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/GroupedNotificationsModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/LanguageColorsModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/MainScreenModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/PageInfoModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/ReactionGroupModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/RepoLanguageModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/SearchModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/ShortRepoModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/ShortUserModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/SimpleUserModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/TimelineModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/TrendingModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/ViewPagerModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/parcelable/FilterIssuesPrsModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/parcelable/FilterSearchModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/parcelable/FilterTrendingModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/parcelable/LabelModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/parcelable/LoginRepoParcelableModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/model/parcelable/MilestoneModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/BaseDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/FeedDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/IssueDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/LoginDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/MyIssuesPullsDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/NotificationsDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/OrgsDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/SuggestionDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/UserDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/UserFollowersFollowingsDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/UserGistsDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/UserReposDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/dao/UserStarredReposDao.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/db/Converters.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/db/FastHubDatabase.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/db/FastHubLoginDatabase.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/FeedModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/FollowingsFollowersModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/GetIssueModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/GistsModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/LoginModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/MyIssuesPullsModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/NotificationModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/OrganizationModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/ProfileRepoModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/ProfileStarredRepoModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/SuggestionsModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/persistence/models/UserModel.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/FeedsRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/IssueRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/LoginRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/MyIssuesPullsRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/NotificationRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/OrgRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/SuggestionRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/UserFollowersFollowingRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/UserGistsRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/UserReposRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/UserRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/repository/UserStarredReposRepositoryProvider.kt create mode 100644 data/src/main/java/com/fastaccess/data/storage/FastHubSharedPreference.kt create mode 100644 data/src/main/java/com/fastaccess/extension/GraphqlFragmentExtension.kt create mode 100644 data/src/main/java/com/fastaccess/extension/RxExtension.kt create mode 100644 data/src/test/java/com/fastaccess/data/ExampleUnitTest.java create mode 100644 domain/.gitignore create mode 100644 domain/build.gradle create mode 100644 domain/proguard-rules.pro create mode 100644 domain/src/main/AndroidManifest.xml create mode 100644 domain/src/main/java/com/fastaccess/domain/FastHubObserver.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/repository/LoginRemoteRepository.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/repository/services/IssuePrService.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/repository/services/LoginService.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/repository/services/NotificationService.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/repository/services/OrganizationService.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/repository/services/ReactionService.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/repository/services/RepoService.kt rename {app/src/main/java/com/fastaccess/data/service => domain/src/main/java/com/fastaccess/domain/repository/services}/ScrapService.kt (58%) create mode 100644 domain/src/main/java/com/fastaccess/domain/repository/services/UserService.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/response/AuthModel.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/response/FeedResponse.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/response/IssueRequestModel.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/response/NotificationResponse.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/response/PageableResponse.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/response/PostReactionModel.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/response/UserResponse.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/response/body/AssigneesBodyModel.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/response/body/LabelsBodyModel.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/response/body/MilestoneBodyModel.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/response/enums/EventsType.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/rx/FastHubSubscriber.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/usecase/base/BaseCompletableUseCase.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/usecase/base/BaseFlowableUseCase.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/usecase/base/BaseMaybeUseCase.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/usecase/base/BaseObservableUseCase.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/usecase/base/BaseSingleUseCase.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/usecase/base/BaseUseCase.kt create mode 100644 domain/src/main/java/com/fastaccess/domain/usecase/base/BaseUseCaseDefaults.kt create mode 100644 domain/src/test/java/com/fastaccess/domain/ExampleUnitTest.java create mode 100644 editor/.gitignore create mode 100644 editor/build.gradle create mode 100644 editor/proguard-rules.pro create mode 100644 editor/src/main/AndroidManifest.xml create mode 100644 editor/src/test/java/com/fastaccess/github/editor/ExampleUnitTest.java create mode 100644 extensions/.gitignore create mode 100644 extensions/build.gradle create mode 100644 extensions/proguard-rules.pro create mode 100644 extensions/src/main/AndroidManifest.xml create mode 100644 extensions/src/main/java/com/fastaccess/github/extensions/ActivityFragmentExtension.kt create mode 100644 extensions/src/main/java/com/fastaccess/github/extensions/DatePrettifier.kt create mode 100644 extensions/src/main/java/com/fastaccess/github/extensions/LiveDataExtensions.kt create mode 100644 extensions/src/main/java/com/fastaccess/github/extensions/ObjectExtension.kt create mode 100644 extensions/src/test/java/com/fastaccess/github/extensions/ExampleUnitTest.java delete mode 100644 fasthub_as_settings.jar create mode 100644 fasthub_trending.json create mode 100644 gradle.properties create mode 100644 graphql.config.json create mode 100644 graphql.schema.json create mode 100644 markdown/.gitignore create mode 100644 markdown/build.gradle create mode 100644 markdown/proguard-rules.pro create mode 100644 markdown/src/main/AndroidManifest.xml rename {app => markdown}/src/main/assets/emojis.json (100%) create mode 100644 markdown/src/main/java/com/fastaccess/markdown/MarkdownProvider.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/emoji/Emoji.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/emoji/EmojiLoader.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/emoji/EmojiManager.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/emoji/EmojiParser.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/emoji/EmojiTrie.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/emoji/Fitzpatrick.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/extension/TagExtension.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/CodeBackgroundRoundedSpan.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/DrawableHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/EmojiHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/FontSpan.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/HeaderHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/HrHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/HrSpan.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/ItalicHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/LabelSpan.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/LinkHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/ListsHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/MarginHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/MdQouteSpan.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/PreTagHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/QuoteHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/StrikethroughHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/SubScriptHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/SuperScriptHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/UnderlineHandler.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/UrlSpan.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/drawable/DrawableGetter.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/drawable/GlideDrawableTarget.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/spans/drawable/UrlDrawable.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/widget/CenterImageSpan.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/widget/HtmlTextView.kt create mode 100644 markdown/src/main/java/com/fastaccess/markdown/widget/SpannableBuilder.kt create mode 100644 markdown/src/main/res/values/ids.xml create mode 100644 markdown/src/test/java/com/fastaccess/markdown/ExampleUnitTest.java delete mode 100644 privacy_policy.html create mode 100644 resources/.gitignore create mode 100644 resources/build.gradle create mode 100644 resources/proguard-rules.pro create mode 100644 resources/src/main/AndroidManifest.xml rename {app => resources}/src/main/res/animator/cardview_selector.xml (100%) rename {app => resources}/src/main/res/animator/minus_to_plus.xml (100%) rename {app => resources}/src/main/res/animator/plus_minus_rotate.xml (100%) rename {app => resources}/src/main/res/animator/plus_to_minus.xml (100%) rename {.github/assets => resources/src/main/res/drawable-nodpi}/web_hi_res_512.png (100%) rename {app => resources}/src/main/res/drawable/arrow_toggle_drawable.xml (100%) rename {app => resources}/src/main/res/drawable/asl_follow.xml (100%) rename {app => resources}/src/main/res/drawable/avd_follow.xml (100%) rename {app => resources}/src/main/res/drawable/avd_unfollow.xml (100%) rename {app => resources}/src/main/res/drawable/bottom_border.xml (100%) create mode 100644 resources/src/main/res/drawable/bottom_sheet_background.xml create mode 100644 resources/src/main/res/drawable/circle_shape.xml create mode 100644 resources/src/main/res/drawable/circle_shape_blue_small.xml rename app/src/main/res/drawable/circle_shape.xml => resources/src/main/res/drawable/circle_shape_cardview.xml (50%) create mode 100644 resources/src/main/res/drawable/circle_shape_green_small.xml create mode 100644 resources/src/main/res/drawable/circle_shape_red_small.xml create mode 100644 resources/src/main/res/drawable/circle_shape_theme_small.xml create mode 100644 resources/src/main/res/drawable/dialog_background.xml create mode 100755 resources/src/main/res/drawable/fastscroller_bubble.xml rename {app => resources}/src/main/res/drawable/ic_add.xml (100%) rename {app => resources}/src/main/res/drawable/ic_add_emoji.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_add_small.xml rename {app => resources}/src/main/res/drawable/ic_announcement.xml (100%) rename {app => resources}/src/main/res/drawable/ic_app_shortcut_github.xml (100%) rename {app => resources}/src/main/res/drawable/ic_app_shortcut_github_foreground.xml (100%) rename {app => resources}/src/main/res/drawable/ic_app_shortcut_issues.xml (100%) rename {app => resources}/src/main/res/drawable/ic_app_shortcut_issues_foreground.xml (100%) rename {app => resources}/src/main/res/drawable/ic_app_shortcut_pinned.xml (100%) rename {app => resources}/src/main/res/drawable/ic_app_shortcut_pinned_foreground.xml (100%) rename {app => resources}/src/main/res/drawable/ic_app_shortcut_profile.xml (100%) rename {app => resources}/src/main/res/drawable/ic_app_shortcut_profile_foreground.xml (100%) rename {app => resources}/src/main/res/drawable/ic_app_shortcut_pull_requests.xml (100%) rename {app => resources}/src/main/res/drawable/ic_app_shortcut_pull_requests_foreground.xml (100%) rename {app => resources}/src/main/res/drawable/ic_arrow_drop_down.xml (100%) rename {app => resources}/src/main/res/drawable/ic_arrow_drop_up.xml (78%) rename {app => resources}/src/main/res/drawable/ic_arrow_right.xml (100%) rename {app => resources}/src/main/res/drawable/ic_at.xml (100%) rename {app => resources}/src/main/res/drawable/ic_back.xml (100%) rename {app => resources}/src/main/res/drawable/ic_backup.xml (100%) rename {app => resources}/src/main/res/drawable/ic_blank.xml (100%) rename {app => resources}/src/main/res/drawable/ic_block.xml (100%) rename {app => resources}/src/main/res/drawable/ic_book.xml (100%) rename {app => resources}/src/main/res/drawable/ic_bookmark.xml (100%) rename {app => resources}/src/main/res/drawable/ic_branch.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_branch_small.xml rename {app => resources}/src/main/res/drawable/ic_brower.xml (69%) rename {app => resources}/src/main/res/drawable/ic_brush.xml (100%) rename {app => resources}/src/main/res/drawable/ic_bug.xml (100%) rename {app => resources}/src/main/res/drawable/ic_check.xml (100%) rename {app => resources}/src/main/res/drawable/ic_check_small.xml (100%) rename {app => resources}/src/main/res/drawable/ic_checkbox.xml (100%) rename {app => resources}/src/main/res/drawable/ic_checkbox_empty.xml (100%) rename {app => resources}/src/main/res/drawable/ic_checkbox_empty_small.xml (100%) rename {app => resources}/src/main/res/drawable/ic_checkbox_small.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_chevron_down.xml create mode 100644 resources/src/main/res/drawable/ic_chevron_up.xml rename {app => resources}/src/main/res/drawable/ic_circle_small.xml (100%) rename {app => resources}/src/main/res/drawable/ic_clear.xml (100%) rename {app => resources}/src/main/res/drawable/ic_clear_all.xml (80%) rename {app => resources}/src/main/res/drawable/ic_clear_black.xml (100%) rename {app => resources}/src/main/res/drawable/ic_code.xml (100%) rename {app => resources}/src/main/res/drawable/ic_color_lens.xml (100%) rename {app => resources}/src/main/res/drawable/ic_comment.xml (100%) rename {app => resources}/src/main/res/drawable/ic_comment_small.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_comments_number.xml rename {app => resources}/src/main/res/drawable/ic_copy.xml (100%) rename {app => resources}/src/main/res/drawable/ic_crop_square.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_developer_programm.xml rename {app => resources}/src/main/res/drawable/ic_done.xml (100%) rename app/src/main/res/drawable/ic_notification.xml => resources/src/main/res/drawable/ic_dot.xml (52%) create mode 100644 resources/src/main/res/drawable/ic_dot_colored.xml rename {app => resources}/src/main/res/drawable/ic_download.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_download_small.xml rename {app => resources}/src/main/res/drawable/ic_edit.xml (100%) rename {app/src/main/res/drawable-xxxhdpi => resources/src/main/res/drawable}/ic_edittext.9.png (100%) rename {app => resources}/src/main/res/drawable/ic_email.xml (100%) rename {app => resources}/src/main/res/drawable/ic_eye.xml (100%) rename {app => resources}/src/main/res/drawable/ic_eye_off.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_eye_small.xml rename {app => resources}/src/main/res/drawable/ic_fasthub_mascot.xml (100%) rename {app => resources}/src/main/res/drawable/ic_file_document.xml (100%) rename {app => resources}/src/main/res/drawable/ic_file_multi.xml (100%) rename {app => resources}/src/main/res/drawable/ic_filter.xml (100%) rename {app => resources}/src/main/res/drawable/ic_folder.xml (100%) rename {app => resources}/src/main/res/drawable/ic_follow.xml (100%) rename {app => resources}/src/main/res/drawable/ic_fork.xml (100%) rename {app => resources}/src/main/res/drawable/ic_fork_small.xml (100%) rename {app => resources}/src/main/res/drawable/ic_format_bold.xml (100%) rename {app => resources}/src/main/res/drawable/ic_format_italic.xml (100%) rename {app => resources}/src/main/res/drawable/ic_format_list_bulleted.xml (100%) rename {app => resources}/src/main/res/drawable/ic_format_quote.xml (100%) rename {app => resources}/src/main/res/drawable/ic_format_strikethrough.xml (100%) rename {app => resources}/src/main/res/drawable/ic_format_underlined.xml (100%) rename {app => resources}/src/main/res/drawable/ic_fullscreen.xml (100%) rename {app => resources}/src/main/res/drawable/ic_gists.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_gists_small.xml rename {app => resources}/src/main/res/drawable/ic_github.xml (100%) rename {app => resources}/src/main/res/drawable/ic_github_dark.xml (100%) rename {app => resources}/src/main/res/drawable/ic_github_shortcut.xml (100%) rename {app => resources}/src/main/res/drawable/ic_group.xml (100%) rename {app => resources}/src/main/res/drawable/ic_header_one.xml (100%) rename {app => resources}/src/main/res/drawable/ic_header_three.xml (100%) rename {app => resources}/src/main/res/drawable/ic_header_two.xml (100%) rename {app => resources}/src/main/res/drawable/ic_heart.xml (100%) rename {app => resources}/src/main/res/drawable/ic_heart_full.xml (100%) rename {app => resources}/src/main/res/drawable/ic_home.xml (100%) rename {app => resources}/src/main/res/drawable/ic_image.xml (61%) rename {app => resources}/src/main/res/drawable/ic_incognito.xml (100%) rename {app => resources}/src/main/res/drawable/ic_incognito_avatar.xml (100%) rename {app => resources}/src/main/res/drawable/ic_info.xml (100%) rename {app => resources}/src/main/res/drawable/ic_info_outline.xml (84%) create mode 100644 resources/src/main/res/drawable/ic_info_outline_small.xml rename {app => resources}/src/main/res/drawable/ic_inline_code.xml (100%) rename {app => resources}/src/main/res/drawable/ic_insert_link.xml (100%) rename {app => resources}/src/main/res/drawable/ic_issue_closed.xml (100%) rename {app => resources}/src/main/res/drawable/ic_issue_closed_small.xml (100%) rename {app => resources}/src/main/res/drawable/ic_issue_opened.xml (100%) rename {app => resources}/src/main/res/drawable/ic_issue_opened_small.xml (100%) rename {app => resources}/src/main/res/drawable/ic_issues.xml (100%) rename {app => resources}/src/main/res/drawable/ic_issues_shortcut.xml (100%) rename {app => resources}/src/main/res/drawable/ic_issues_small.xml (100%) rename {app => resources}/src/main/res/drawable/ic_label.xml (100%) rename {app => resources}/src/main/res/drawable/ic_language.xml (100%) rename {app => resources}/src/main/res/drawable/ic_language_small.xml (100%) rename {app => resources}/src/main/res/drawable/ic_license.xml (100%) rename {app => resources}/src/main/res/drawable/ic_lightblub.xml (100%) rename {app => resources}/src/main/res/drawable/ic_list_numbers.xml (100%) rename {app => resources}/src/main/res/drawable/ic_location.xml (100%) rename {app => resources}/src/main/res/drawable/ic_lock.xml (100%) rename {app => resources}/src/main/res/drawable/ic_logout.xml (100%) rename {app => resources}/src/main/res/drawable/ic_menu.xml (100%) rename {app => resources}/src/main/res/drawable/ic_merge.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_merged_state.xml rename {app => resources}/src/main/res/drawable/ic_milestone.xml (100%) rename {app => resources}/src/main/res/drawable/ic_minus.xml (100%) rename {app => resources}/src/main/res/drawable/ic_money.xml (100%) rename {app => resources}/src/main/res/drawable/ic_newline.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_notification.xml create mode 100644 resources/src/main/res/drawable/ic_notification_unread.xml rename {app => resources}/src/main/res/drawable/ic_notifications_none.xml (66%) create mode 100644 resources/src/main/res/drawable/ic_open_state.xml rename {app => resources}/src/main/res/drawable/ic_overflow.xml (100%) rename {app => resources}/src/main/res/drawable/ic_people.xml (100%) rename {app => resources}/src/main/res/drawable/ic_pin.xml (100%) rename {app => resources}/src/main/res/drawable/ic_pin_filled.xml (100%) rename {app => resources}/src/main/res/drawable/ic_pin_shortcut.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_profile.xml rename {app => resources}/src/main/res/drawable/ic_profile_shortcut.xml (100%) rename app/src/main/res/drawable/ic_profile.xml => resources/src/main/res/drawable/ic_profile_small.xml (89%) rename {app => resources}/src/main/res/drawable/ic_project.xml (100%) rename {app => resources}/src/main/res/drawable/ic_pull_requests.xml (100%) rename {app => resources}/src/main/res/drawable/ic_pull_requests_shortcut.xml (100%) rename {app => resources}/src/main/res/drawable/ic_pull_requests_small.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_pull_requests_uncolored_small.xml rename {app => resources}/src/main/res/drawable/ic_push.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_push_small.xml rename {app => resources}/src/main/res/drawable/ic_redo.xml (100%) rename app/src/main/res/drawable/ic_feedback.xml => resources/src/main/res/drawable/ic_refresh.xml (51%) create mode 100644 resources/src/main/res/drawable/ic_reply.xml rename {app => resources}/src/main/res/drawable/ic_repo.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_repo_small.xml rename {app => resources}/src/main/res/drawable/ic_restore.xml (100%) rename {app => resources}/src/main/res/drawable/ic_restricted.xml (100%) rename {app => resources}/src/main/res/drawable/ic_ring.xml (100%) rename {app => resources}/src/main/res/drawable/ic_ring_sound.xml (100%) rename {app => resources}/src/main/res/drawable/ic_rocket.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_scroll_fast.xml create mode 100644 resources/src/main/res/drawable/ic_scroll_fast_selected.xml rename {app => resources}/src/main/res/drawable/ic_search.xml (70%) rename {app => resources}/src/main/res/drawable/ic_send.xml (100%) rename {app => resources}/src/main/res/drawable/ic_settings.xml (100%) rename {app => resources}/src/main/res/drawable/ic_share.xml (100%) rename {app => resources}/src/main/res/drawable/ic_slack.xml (100%) rename {app => resources}/src/main/res/drawable/ic_star.xml (100%) rename {app => resources}/src/main/res/drawable/ic_star_filled.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_star_filled_small.xml rename {app => resources}/src/main/res/drawable/ic_star_small.xml (100%) rename {app => resources}/src/main/res/drawable/ic_storage_small.xml (100%) rename {app => resources}/src/main/res/drawable/ic_submodule.xml (100%) rename {app => resources}/src/main/res/drawable/ic_subscribe.xml (100%) rename {app => resources}/src/main/res/drawable/ic_support.xml (100%) rename {app => resources}/src/main/res/drawable/ic_sync.xml (100%) rename {app => resources}/src/main/res/drawable/ic_time.xml (100%) rename {app => resources}/src/main/res/drawable/ic_time_small.xml (100%) rename {app/src/main/res/drawable-xxxhdpi => resources/src/main/res/drawable}/ic_timeline_arrow_left.9.png (100%) rename {app => resources}/src/main/res/drawable/ic_title.xml (100%) rename {app => resources}/src/main/res/drawable/ic_track_changes.xml (100%) rename {app => resources}/src/main/res/drawable/ic_trash.xml (100%) create mode 100644 resources/src/main/res/drawable/ic_trash_small.xml rename {app => resources}/src/main/res/drawable/ic_trending.xml (100%) rename {app => resources}/src/main/res/drawable/ic_undo.xml (100%) rename {app => resources}/src/main/res/drawable/ic_unfollow.xml (100%) rename {app => resources}/src/main/res/drawable/ic_unlock.xml (100%) rename {app => resources}/src/main/res/drawable/ic_unsubscribe.xml (100%) rename {app => resources}/src/main/res/drawable/ic_update.xml (100%) rename {app => resources}/src/main/res/drawable/ic_wrap_text.xml (100%) rename {app => resources}/src/main/res/drawable/left_border.xml (100%) create mode 100644 resources/src/main/res/drawable/popup_window_background.xml rename {app => resources}/src/main/res/drawable/rect_shape.xml (100%) rename {app => resources}/src/main/res/drawable/right_border.xml (100%) create mode 100644 resources/src/main/res/drawable/rounded_toolbar_shadow_up.xml rename {app => resources}/src/main/res/drawable/scrim.xml (100%) create mode 100644 resources/src/main/res/drawable/selectable_layout_background.xml create mode 100644 resources/src/main/res/drawable/snackbar_background.xml create mode 100644 resources/src/main/res/drawable/snackbar_background_error.xml rename {app => resources}/src/main/res/drawable/splash_screen_drawable.xml (82%) rename {app => resources}/src/main/res/drawable/toolbar_shadow_up.xml (100%) rename {app => resources}/src/main/res/drawable/top_border.xml (100%) create mode 100644 resources/src/main/res/drawable/top_bottom_border.xml create mode 100644 resources/src/main/res/drawable/top_radius_background.xml create mode 100644 resources/src/main/res/drawable/top_round_corner_background.xml create mode 100644 resources/src/main/res/font/abeezee.ttf create mode 100644 resources/src/main/res/font/roboto_mono.ttf create mode 100644 resources/src/main/res/font/rubik_bold.ttf create mode 100644 resources/src/main/res/font/rubik_font.xml create mode 100644 resources/src/main/res/font/rubik_normal.ttf rename app/src/main/res/menu/add_menu.xml => resources/src/main/res/menu/edit_submit_menu.xml (50%) rename {app => resources}/src/main/res/menu/issue_menu.xml (66%) rename app/src/main/res/menu/search_menu.xml => resources/src/main/res/menu/main_bottom_bar_menu.xml (69%) rename app/src/main/res/menu/drawer_menu.xml => resources/src/main/res/menu/main_menu.xml (74%) rename {app => resources}/src/main/res/menu/notification_menu.xml (80%) rename app/src/main/res/menu/done_menu.xml => resources/src/main/res/menu/submit_menu.xml (76%) rename {app => resources}/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%) rename {app => resources}/src/main/res/mipmap-hdpi/ic_launcher.png (100%) rename {app => resources}/src/main/res/mipmap-mdpi/ic_launcher.png (100%) rename {app => resources}/src/main/res/mipmap-nodpi/foreground.png (100%) rename {app => resources}/src/main/res/mipmap-xhdpi/ic_launcher.png (100%) rename {app => resources}/src/main/res/mipmap-xxhdpi/ic_launcher.png (100%) rename {app => resources}/src/main/res/mipmap-xxxhdpi/ic_launcher.png (100%) create mode 100644 resources/src/main/res/raw/shrug.json rename {app => resources}/src/main/res/values-land/dimens.xml (100%) rename {app => resources}/src/main/res/values/arrays.xml (61%) rename {app => resources}/src/main/res/values/colors.xml (100%) rename {app => resources}/src/main/res/values/dimens.xml (84%) rename {app => resources}/src/main/res/values/paths.xml (100%) rename {app => resources}/src/main/res/values/strings.xml (97%) create mode 100644 resources/src/main/res/values/styles.xml create mode 100644 resources/src/main/res/values/theme_amlod.xml rename {app => resources}/src/main/res/values/theme_attrs.xml (100%) create mode 100644 resources/src/main/res/values/theme_bluish.xml create mode 100644 resources/src/main/res/values/theme_dark.xml create mode 100644 resources/src/main/res/values/theme_light.xml rename {app => resources}/src/main/res/values/themes.xml (67%) diff --git a/.codecov.yml b/.codecov.yml deleted file mode 100644 index 0aa829d1d..000000000 --- a/.codecov.yml +++ /dev/null @@ -1,2 +0,0 @@ -codecov: - token: b3275f76-a606-4c63-9b5c-1c58ef7acba0 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..b57caf984 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +[*.{kt,kts}] +indent_size=4 +continuation_indent_size=4 +insert_final_newline=false +max_line_length=150 \ No newline at end of file diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index 3bbc7439c..000000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,89 +0,0 @@ -# Contributing to FastHub - -**Updated: 19 Jan 2018** - -## Table of contents - -1. [Submitting Issues](#submitting-issues) -1. [How to contribute. Importing and assembling](#how-to-contribute-importing-and-assembling) - 1. [Custom keys *(optional)*](#custom-keys-optional) - 1. [Before importing into Android Studio](#before-importing-into-android-studio) - 1. [Before import](#before-importation) - 1. [Importing Android Studio project](#importing-android-studio-project) - 1. [Submitting Pull Request](#submitting-pull-request) -1. [Working with translations](#working-with-translations) -1. [Translations Contributors](#translations-contributors) - -## Submitting Issues - -- Let's keep everything clean and tidy here :) - - Make sure that similar Issues are not exist. Reopen an Issue if exists but closed. - - If things you want to submit are related to each other, submit them in one Issue. -- None of the forked Repositories' Issues will be accepted! - - Forks are developed separately from the origin Repository. -- Make sure you are running latest version (to check it out withing the FastHub head to About and tap on the section with application's version). -- Make sure the included template is filled in (submitting an Issue within FastHub will do it automatically). - -## How to contribute. Importing and assembling - -If you have any questions, feel free to join our public [Slack](http://rebrand.ly/fasthub) channel. - -### Custom keys *(optional)* - -- Please update `debug_gradle.properties` file if you want to use your own keys: - - `github_client_id=` -- your GitHub clientId; - - `github_secret=` -- your GitHub secret; - - `redirect_url=` -- the url defined in `AndroidManifest` under `LoginView`. - -### Before importation - -- Make sure you are running *Android Studio 3.0 C4* or above; -- Import *Android Studio Settings* (to follow project's code style) from [this file](https://raw.githubusercontent.com/k0shk0sh/FastHub/master/fasthub_as_settings.jar); -- Install *Lombok Plugin* from Android Studio Plugins and enable Annotations Processors in Android Studio Preferences. - -### Importing Android Studio project - -- Fork the Repository. -- Clone it to your workstation. -- Open the project in Android Studio. -- Compile the project for the first time. Then you can start coding. - -### Submitting Pull Request - -> Please use meaningful commit messages. - -- Create a new Branch with the changes you made. -- Submit your Pull Request with an explanation of what have you done and why. - -> I really appreciate your efforts on contributing to this project. - -## Working with translations - -1. Firstly, you have to fork the repository by clicking the **Fork** button. -1. Clone your own forked repository to your workstation. -1. Create and switch Branch by typing `git checkout -b ` where `` is the name of the Branch you want to work with. We recommend you to name it into the language you want to translate in. -1. Create a new directory named like `values-`, where `` is a 2 letter ISO code of the language. For example `values-es` for Spanish, `values-fr` for French. -1. Copy `values/strings.xml` into the directory you have created (`values-??`). -1. Open `values-??/strings.xml` in your editor of choice. -1. Translate and keep in mind these important things. - 1. Obey the XML format. So, `ONLY TRANSLATE HERE`. - 1. Don't translate lines which contain `translatable="false"`. - 1. Don't translate Git and GitHub terms, such as *Pull Request*, *Push*, *Commit*, *Branch*, etc. - 1. There are some escape sequences used in translations (e.g. `\n` as a line feed (new line), `\t` as a tabulator. Don't delete them! - *For the full list you can see this [Wiki article](https://en.wikipedia.org/wiki/Control_character#In_ASCII).* - 1. There are some characters which **must be escaped** in translations. - - | `"` | `"` | - |-----|----------| - | `'` | `'` | - | `&` | `&` | - | `>` | `>` | - | `<` | `<` | - 1. Don't add extra spaces or periods. Don't delete existent ones. -1. Once you finished translating, add new files to the Git index using `git add values-??/strings.xml` command and commit the changes using `git commit -m ''`, where `` is a short description of changes you made. -1. Push your local changes into your forked repository by typing `git push origin `. -1. Finally, create a Pull Request from your Branch to our main Branch *development*. - -## Translations Contributors - -- *See [README.md](https://github.com/k0shk0sh/FastHub#language-contributors)* diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 6bb31a1cd..000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,22 +0,0 @@ - - -**FastHub Version:** -**Android Version:** -**Device Information:** -- MANUFACTURER: -- BRAND: -- MODEL: ---- diff --git a/.github/assets/direct-apk-download.png b/.github/assets/direct-apk-download.png deleted file mode 100644 index 4de1b294251afd8e730b0431e25c6c415fd0724d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14310 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В3v9B)$#asg14P!bXPzfxd;BYu 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%0Ab&uGzQ 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⁣rp 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%0Aj(tu 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�c#Rq}YHwY)>i+UiC>nU;jK@09Kc1*PLWtb< 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

taDEyw-r7jBtj&_Y&cxViQj$ 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≺0!gaVZppc2{q9kE}Bk)mcB(G6o&%2%&=szWt?uVRKK?FUgFlvyrIWi zQ)clhOT)c~hlc|#AnULKVA&5&(*T5CsWj#vawY=<6$@k@RLB(iwS60QygA#NGy0pf zO2OW{u_cO6_?`%JlU*h%rnYSYL4dU$Y3X2R6!IO)FH-Yb=or+*Gi?}-feTSqFO#{C z8K#y{@?~s`L{R^xnJrEy@(u%5UkjN{;H2@ckWg-J3kNt)_1ZA4rj|&jV)o z)!0nd47hx-W59Cw0!ngy7ru(yAbweQl^>84HDK4A3RJNo!{!t~VM+qc96U^3@qtvq z()=qhG#Fp52YDOT(XG10hi33#fM?LCyxXvIcQn>>!h%Hm>&*!ZqjhlRKPZ_8qXklX zqfGsYC={_LrH1M7S}^Bv0TU*NZT`Onp6mCv7Q_F05U=2O%~Tm>$=|5uf~lx58QLDi zsWD3QP7s(AvLco6B&0E#OMkC*I(c1?D^pbqwv0yqBjLm&*GU?e(mamQ#=2>|8Nq$&Q0u_oJH{Qv9U25ME}_^m?hz> zA5Cq1TCXTQNILrDIk5$u38hwsBNT5h&tpS9@fL01sK5SDNcv|b9ILvW@AN(9D(Qtp zLA3$8B3|7{`fqOT>|YoGH+D9+3rOT9Tg()9Oo#pLK0Rt_$LfClMP$-(ESDrW!YR%e zYaJti`g?(^Z2OxvO(Fs6R?R46i9}6GU1SzE17v&Y(M}pBr%hG^g>XBz&B{>`93mUnt{k^vh^rGT?0^Oa(l%5&fHTqyo2Dvo<9AJ{PJxi1^+O7A zZ+Cs<56#VDmBV}Cb3Drz7DH+GVHc-U8`u}i7uM&;JHgYS{IgpbO7DlpAW{>RAZ-Ko zb!sXFZm7llSD2S8p>YSyLf0Pk(0XxjN=eElZ_Cx=8|tBz7C-1JU7#o+IM?#Q=SYZp zZ;PXX%cQ7^l|)~FEYYhF5PyaR-wqXu4<1CtVw574>St5mXP;yY*n0v#?yh3#NCV%LWOR!*$24M;|{Q(b#y_C-rA^`VRRkprQ5HO zg=ZMuQMS_-SbiuIx1bz+k{&uy zhu)G7;Wq1ili~x0F`hBwi)Z33M%yd5E=EBoeq^y4{;1i*?lAar*O%X8*Nj;$V<1Z^ z$og;=^gP6LSSK~L;iFr|M{XBsu%$6Qj}mD>`@kp zl;3KUm|HPvSF4cH`UKV|PJ3a~pr~DJROR3E?q2z?WCalZU4w~xZJN0KMq1h92jV;z zS?8fU@tQ=;)ftMD`J=kHwF%tOdG)uf9Xg7zAAa$U7x({}REHXZ)H6Q3yAX81frIyS zA@yc9x!c5)fBhA zb4sA4zmR_vsub5aMZ;D zw6ot)c}P+^kpSJ83Q@HyF93iHsh|&?$M^gguius=S-_4GYGc8mm`96wNR0u|_n*o1 zY)6WDz`O^q4MNPM_^7C;Kw2i6Lpq*ks4$2mW(%6=S98T~GSF=zS9_LsU-jZDEJvBV zx%6kls~=MveQsF$zpCLkPy5flgPH~xHJJfQ(H#JgsKyv*JA{Nx)q04bWWEpb%Ocqv zVh{-kK&KyD%tNDi@aM4G0EzzlX8Ak-O&(wDfY=@mNWN6t^Hf|0_BNYpev!uAro%|{=u2cgCspio!+XwOS=MNhGI|eP5LW^kg@kbx zbjcLdD85Ymtr57>T*X?2o{vA)VEHG?DHRqbpxz+os;j3fnWjk-i?-6E4k5HtLsMIr zcE3;iYMHZRZv}OoCrD*x{t3HO7*1A26A`M#k1^XY6vB@AZ+;rbWP;uqyBBe8ECGz> z2xgO;0+?FmCRb19bAG@Cthbhg3z0d+-Nh5q8LRStB$TP1dNZz9_J8E~IM8W7jU)NI zO1{33LZ4W5%Z*&$q*&f2Ptk_o-IweBhC4bAxq5B$e#uCV{DiF@06#!wAFK}Wgd6V- z@lWWZFbX>Eh0ljJti)%Yo2eMf+Su5bOhdfAS=xCgYH`q`MCo(NUA+&eaUcht3PvvM zYV`q8tY04oWHmIboCc0y*ztnA09FPjXh_uoq>$(a^uQ%BXk67lti!Yc5gtgMU&JWA zmdWPDh9XTsq=u@+JhUIGnkp4%uM@@DRDPOZLM>hMoM0-NuC9N7P-35|GdjXxi;oeJKlAjPy)fwo~EDoE&Pvi}TuNVt}{=WId5jxKc z0fn3gm|4T1!#Xr$d6cibc1U?m1_8(QaMtVN$4pI*{N7F{9?C)h1)sG3f!ifZ67?*=6@QUGjPAXK>G^s%v+H&r0aE+v zl1}zs@?7TPcv1IC3xT~tMyZ+DL%rcZDgb^)|DxSvUYLnGCL?wCtyUJAB$IyTx)*s* z6v|`8=t9stO&ot3NHzPm=7zSChq6+It^`&|S&O{6&fD?j_LHI-9kRPRUlN*+kd4<@ zR)kk&$3wyV;T?NPT_BJjTGq^iVUr{Q<2DGTNd{sAlTEzU{I(@Gv#p^ zIA835;0ntcF+d*N@yHZ%dR97E%_9Q7FVZi=R7h%9;AN+pDNbYDY?Ml+>*v)9csYJ1l!q-e!09_ds!|k0Y?}dX8(39!bvb7Xh!5EVy1Z=w zl{c@EPqvS~zd{a%dq0HU6tT8}(coP8yaX5+uMBwo2KhnVC##ustz5Wt;@;`w?0+^E z&9vIbe>y<_e!0dhorapWx)Q-$EG`lcr8cE3Fglb`qLuEmp&>7Rc={$b%lcD&tg=8- z5V3`_LhbggUyrqxvICz!Le6Eilu5byb_sKW%+k0Gor0R0D`WWBUewp-yQZDq=WJ(w zYK)ZH=h^jI(Gx)q>%Pxe_Fnan)$CC?RTYEGk3~qX)?wK1Wv`> zc^DGu7_(*JDYHjWLBTOo_evpdBqxP)Q)7!OzTjTC>9%*O&s>^WE7}+Too{Hm%Dg2G zg{PmBc?Nj<8T<$ZL@Pi+t({d(WLBkJ?qF-F>o5`qHLMLR?2qgGMspv+ z?vb3&?i{`f+wp%mF>C&)1n5>LgAeg#|s{G;p`qD($&Wyuu>3<^@Nn^1xx= z!^-O|u&#v4um1uPr-1Ed%TuTSOvknPd!xWA2+h9I<4i&fAdOVRzpoRGUrf!sIYpd( zhgKmhmNXb+G7kf!9s#S1hW^Lg`g)29H^c#lK||G3zL0wY0?x~CpE{2|WFaj9S}a2Z z#Mr9`!WRFmAL{k`(fwxtSW3pJ-wU{YH+twq-MPWxzl8Vk-(x|k1|+}R$EKUK6NGhd z@Pzebcr!do$$k|PhKy9Et?Ye!E~rdP;cHDkPH=ofJ#F+GiyZ$z&x^jqy@H#@v3I&+ z@%kMD%Rf0uBJl^n#sh0P>YPl(taJ?DH>fz8y37dNO+Fmqk*8=t9GD?vbvV;$tm_w& z#GmaSd8fY0DXM~-;>7f*q_eEQbQI6_4`*GtedET?9xgGQmxdO-)|WnlIIYyxIOJh5 z2B<+a{G^X56*4om=tJ$WYdQ6)MQaj0?7nBoV5%EDi83;U{Z{YHbrLDRD9|{-R~Y{U zo^?Sy95B7QRG(ySASA!g1InO{PH-uf#`b_5V%$yFG(qtSydlv+n4`jM!y`0+0!age zy6n)HRZ>MA1yzt`9Zj7C_=<3VW`iFF{53wc<1QnzH=V%Qp*xRmcg}lH1$++T^*BA~;yS`v>S#rJ8K^l``puiF@#j?0OM?fFDle8BP{;fKY(=09 zzK^FR1e60dffV$2cFIA(6kZP{nB3#y;zDC~gA54=FldiJQG+zWDHZf@Q1wMYvVs9+ z<@@(Y{(w>K4`%EYJvM*K(!OgyJ*|dQ?*^bG=0?er>l0#V)>WI53*!AOsM6U8%&V$F zpO>^V(9O#$3`-nY6r83BiomTaX+p=M@%%oEY zTo5Fo^`gq-Zow7}mmFsxl9nV$CmtH;)v7Z3-&JPDwfqVBHfmG7XYrqr4;)npb zkO0iSZV~-ADDoNta1Uez8Dd0t6(F#*{={akd^r{|vm*#Z+l_MYM#4l_slQ=;JYz`%B*k)^H%dR|}W=Sm@U zEQ%vI=s+>G>7C`O_y!XXBN6sPgkL*ZdH74!V!u zjbC}#6<2W%ij2i;z#o{oQe~u`F0XwK5k)Sf7 zcuyDHdiWNDDQKwkl766OTylXrr{&u)OuGX$I3f-^8Uek0peciq^E{I&9c(OjrVa%w*-g+m&56VusirVL4=Wk$i)TS` zJ(-F$oL_ggvsbt{xUlYcg#}eMP9d+sxAzA>YP2qD2y!Y<|Al$kA6+rFs4!I+B zExVxOZNOg&LgJ;L*%3>oQ27di%-r=A%|U()G@zpO1B1m#>icnE^Cb0`#=HLtbYu^$ z?Eld$Kn#pIj|yon@@L} zrB1sW2hrJJpMx1;Jr?#;dOgP8R7v65B){47kg19gT|Sz(yLR&av?2+$xYK;ujtYP(D!fyaRJIr!l-p09yjE%wQ7?W{ z;QqbNN0_m5h1Z6}VuRIKGk}em^q3&Zi0j@h-<7nfO&Dq0u>f8I_eoof{u!&+>xVRN zgO3l0P)BnoHb?J`5v|l`!4t~xHg?`GP&M56_@=}iJTOS^U_i<@T|4;<8?>uS5AeW5-G^~jBu=zgisMCZ z*mHgh+Hs*E>exU}#vxtPyoG8mncYNWub~s(fkS$$r%T0d&)G#bnSE4;Gct1!#iSh0 zL7p4UP2JeQL2hYiPFSqO?rp4$4I^fW?tB(cLWB3NT`K>Ee|U8=KNW^<5{Jql%|QgO zuS~K)_JL(g&+SwI)Jo6PQYAFax+|vIpdU^ZLmaavonZV`=wV{m{*L^xR9`@zc%RX| z`qhcON9Kkd7s;#Q-o80Sq~o3mG}1OqRtIBg63*L};ytgz=pN*L0-KIK?7ETO0u;ha zLZ^FrGN(fz+7;FYiLG6~sd$Nk^pMku4kAyGv)~fb^Y{9!4ewuVgoE4VaM|JFrX{V% zJ#gX)J}Y+MQT;XU`|$^=Ix)REBk}lx|IVxs!RIvtOt;a?$eNP``CVz1;l?*`BSggZ;Rl z`$4U=3K<9RW4s&|UfO8g!|A-EJw}6g3fyKK^pE4&mpAF6re(Ku&-r@L7s< zXK{e*2Z43eLKqH;mUHqwTeivvZ|>fjG{SQh zCqdPgx#)o55!1Fh@CKlQ)>5{c2m6_~BLnPij^4I+M74=zaHiPqFXspY(|AdIjE^Vk zC@g1<)$mBF)^e$UWye;mBJRLJzXdJ-M1sREeVJi(T@M1$71{RJ{40a+y ztiTqCv!2MI1DLo>N|1Hr1lT;V+W-=LJkJSqJ%wRl0RE`b0jQ!jfG(`L>e;_n%lvcMlOq_e1l%*QX(820i`e#5*uSJz7S; zBKN`_0}k59^HHlPtg=0{gGs`c<7&J?XXo%UTFVt+_yp!?W=ej;_J9B64{LGmSa&z;LwOhfM- zS?KzK9s6+|=u5SLFvX+a*?(I(r-awgQm>9Y!3%Q#VYL%h_Nl}VhvaSDf^#`kmupm4 z9s-Zn+~J78 zg9^*LPvscJjOeMDE-BD6Iug4Sn28 zP>>*(S$}5(lI>4Via$=jfFj00@dQ^_A||}!3eGHhp%Ui-pv1JOxdQBdWRTgyxd8st ztsMCnbmNG-H4ET`^1iy7)IS*eI=Qm};kRjHWD24h4J9IO{<+82Fs@tSTUecnQpRn5 z1~2(neHJULYHLHiI`n=NQX!HTUb9LEWzHzpj#g2bt8LA@;XvYj{84ak@Q&xtYiBn zpLOhM>pZ`Im7hv($a!0H81(XB;1o|&Lj@Yjz*5y0q8;~I;REy(g0k>N8;VUzy70-@-K2Y^WMe}0^@UuR?=CE%;TV@zAT*q|Zc+>MPq7ZW@}8c1QxM?a6dV$DURZ7I{e1Dk)zP0JeHsjd zVRfK*nFQUdGk1OlhOjNb&4(!`^9Ivh9ruU=Nv7ngpW1R1jYuNoWrLD%n_J}mU1b!Y zHF-BDg0GS9>Brk~?C)X~&^TO!RgP{oz0dru$7e`xws5oRVJX)Q zU&jL6Xx0RAhE!2iG#?V@3QLBRzVZ7GLhS;>YKLBCK_a{XwBnPlaMBO-108qXu~N_X zqecH1e(9Q<7n1e(`%%F$?XoNPYs6B1=OgO4)trTM@+_xmJ0zjSnLUEF0ni;p0w%Ic zsXWbgw;;g1(a3=^L%Si*roVgRYXv_Su(vpaPhOz>f`LV#i*H!86Rfc?D;pcrg|>iu z_wK>I0%bh-PLKf#>7B5f^*o3EpEo);=DO887th&>5P+$k?eB2-nn+dLzBy@p!TlpE zBGbM5;lWyXpi^Z#On{t^c0N~+^xVF}MWnhNjiLp2Lj6r)Hg-{FN)SB(!;O&Mst6Rp zioJJ%^Spa{_|$^;eIZoEk=JvmoPj?yi+&O9VXSlX{v z5t!gTY2Q=seRjBTaL>5Sf2!;C56J22(~L?OYgi6CljfIyZ`IgmC}*BX|Hs%0{L95# zh*9)I?74Q~=Q7POx>+|7=@0?4L-?3lK8_6jXEY}2_&Yf!X|~L$>!A{2nQWAIbXhk+q zyR8w?EN;;*nCx^Q`YpF%T)kt9EO5!D?Vith;`&S33~MKk;A}7f2djlIjawGl^#f(j z^$S-2d9ut*uX(v1YE(}+ot9~8xg85S+upaQpC}v4;=k*VjNEul6XlS`=-4LtyW6+s zsW5$x)ok#dOgoA!(#=95Mq``qsG9Dpogi4q$1RP6<`gGfvWWNL^8BQ61T?8ioZIcS z)$1ScXZ8_xF-Ztx`ajI1qFBo_v8W=vCQ@o#|`uD{V6Vno)+H zO8@K0@xvIc@vthb7dX^{EQ+- zRroReVYoGk_O`CgSkHsPcHF=RFeM6vE45~&xim`c`7>ddh|0UKT_}H^Q0Pl+)HOTg zPZRLZm$COy;>~VLS^wu*B%!@PY@wsT$~Fi57q2p1HSkcB65hXGH~mn_Uza>Uc;}?( z#(k$ttRA!4&=>?Ywn^a|TV@>Mqe_NK6-j9?B^SM~6QTG)a@#wBCa8K*LuAo?(KNnD$k%)4$gjg}A8El}?t z>bmgC31@t(PG6SVcyTN;Bego-Y1AgXX9z8YB#O4?2xe1xfy~gtbzZc5H zE4)mMN;6g^SeTh$AIhC#n`wo|!k-wQ!6o8lF*hb;c>Ji5R`7D`$A|o~hrEGX=0T!q z8!=2cKD~oRN%-S(&9=YDXSoXkjlJAkngdt+_U?9L1wI8XF@GnKt&Y0%mnK7x=WK3UGi-XRfy%%0YR_tg%lkb7&o}Pod)Cicbv|D^h4Ps{JYZ{;#g%@S zcT3PPH0IU;RtEkLObexD?_RTr*C=$Fdf(1eCch|E50|#*p5>xQSdTxEms(JuE+RDF z?Tys)LPzAh2&|U5z~w$fX>{J_{@?2peeH7kKi*9Rnrq`{)Pq9(Y%R{6 zuPFGAQ%_rau6y8FfXTIxn2<#+UbR#OdzK z_M~uf5z(ZZ#@UjgQn1;!h`z>`PxI!TxV$t}T&}42J6V8UszRwcByNHK^j>drD4RF* zLUH_Z=fl^Uio5XSGqe5O>Ak!=*+e9&S~9nLYPEY9FZS9oeeE+`sVV?{)Fv_zCvG7; z#VL-Ae|M8NPmG#4N#NFvY=uEPmzZxhFLLN#r@#`%*r?-+;7D9;#5H*QERg zR+o!RxEnz1l!z8TWzUBgN4-xnm`OD;Xx`8p8T-qjvqghjCM}rZrT&^eQ3;At&f>ax zLT@QoF*px;Q(-v&IP!WWMO*KWi(pK?KkD*Z*n~*pcx@2p=?fsP|Mx>jP3y+LH`||I zO~s?1RFDMQve@6vrN|5X+pkw_jm4!OxRaf|Z}n32fV zIVY!9?im~nfi>g9QtxtObu-wG^?5xvVhf`pfEO4>`2a(Hl`kMtN;fJfIjjBWh8V*h8r$lhX zoZBd8+D>`|-26yPSUXo?>z&9;P8d*uIMS8==Q5neLG_1><_owFvf!*(dZXWt3(VIW zZeH}U=DWav`KzDzgr237pg#VwYJ`E#?HkwM@q*Wa?MjY5J%C|;0-!KhF&lbohX}UMg zt<*jSBihd4%Z#C)>UuYBzqyk)GN`uI!N8~*_nv_-MjH6vc1@{Rhh{YP-vx4z(gwp>)c4+u0pD|@vTg@M;s;Pu1g6)IQoDV(L6C39 zFHr`=xrLKE$4{DHhjl9rTJH3&ekte+A9-t9#Pa<}0uT6=hQ%Z7$Xpwor*(LcIH@-(boaym>)z+0*fvdY8tr6)^wMzKZyt8!^_`^#AcL9MFFmAhh7b)Cf&D_&+v?q6ofNwDbPcY+;rwMm$f2B=nV z+2>cf{5W49>4oZtL~uWnt!l+~Nwr5ejGT4ih>{LP`Yc6qBkRpkd?>AFf&Av5EXnJ8 zsKSZ-e;>r<(!njikR0CWMc)}+>Vh?$?<$F2_Ub=revD?^e(nd`wx9f+9KM&$1x^et_CT7*Sh>;vQq_4c5uBFsT3Vzkkx^9qh zXn*zSOenYjtIQ-g_f7Ov{Lk8&OLsl&@AYac;BGS+`#G{9XnxgV5ZQay3-UF`3%7u< zaz5hIe{O}#>%%-q_0iZBjRAy!{GJP7FQ*V4?sS_q)PLJF0dWXmq9E}HW($VXFenE1 zzpL7s!Thyt2^NRss!iLgQbrGv=G({aKD}{b_ByX^lBo3 zn5gH>V8ZJn>g%eThvHW-fL0BRumAm#V_#qIJ~C!G6~^tzFi68OWLgaF zA6l+2Mf3-dPUsr226TO5l@4G+me9X^yaV*3u~S~X9GEc>n@|~d{asQR z7`Xp;1JUc(O_q?h%su0#gkgo*!xbmXGcO21f$hKEU|TsTu=8TVjpDwu*@~0=+5FbZ zaON=h(USVK%9j)MoWW0rQU>mA^QlsRIs*_EKCeSt7!;lfp}qjj0;R3a2>~1)z395l z|8unl{#>n#?m#qb?K(%3b9WFdn;b{8ew#bH7QB=sv@odEWAHl@zX`gN;NTO{W7-|* zp_W9I40@?H6D3h}Ns3IWVh3Z&CoxsP&&}udOA8$jCvF2uqV)$d3T!A{6KblItUiwT z_b zS;QrC5MVB>pST;>)vh=EwqeF|Y~8CrJp$&+`!K++tBsO(FD&>q$J==Ur&NNUF+=Z5*`LmiqWAJKv@l@F|8O^y<)2r!NgPB9UXU;=)THAyXyA5Q`dmY+mB6tfVvv%Jojt(y z&GOHj81$^BrnJf-;RwTK&+6lh>-RZs?9KIiPE!SBAF@fD1~7NfF{koz^b&e4m*WkX zDri}LSC@98DdSFua7#;{S-t5RyZ$LWWQ^i9=&uaIJ3+-?N#f9fOuF}hQsC%gDexHX z{(tPfhdp70+aU4(Z2`O~^UR}F*M_W5YE>gsPXboua zYkPeG^k`tK3yYsXR9pnJ5XsnFQY~HG4)C-=FW_)N3}C?JWTf{0c;UA=hK$a$u}bS{Hw~irDd{#vl-C1fs%nP3$P9yj%A@w@sfXgUdaO^VK;re^j zMr33bSpWX=^q&u?3N1q5sS)3kn-2x^qGv#z5k6p>BM~vKelWeiT<{)FtHafV;4UyS z!~dMN->Ay=dho;1_16+*a%BwH?m>5GEwgn^!!u^uH4yyhqBqHDt*xzPmvOj6 z9mnw-k$uX!N35)@h+AKVMym9cg0Vt#EU;Q&zbJa&*27dpMC1@I0rmjNaqv7pZ~g8J zZnxv$(9i}@RWT4Bnx&aZW8M;q@zYGvIRH!(-__Pit&YIuY59EZ zs9dlo`N}y)U$m)aEO(GN=nIvAQ9X5NR(p=^Cb;J*P9Fn7GD$J={QNIVCv3M@)LDoF zN#*WLB*sSXN~zr!xYw_N3oP4P6|(6IuOw1GJ%X4{f**{r5dSdQ_cvdoAEa6BZ~pw0 zeC4T^)Wn;Emx9)WvcZ~d2~mKB_GX*nzAyz|`?OE|~14cQ@F>+M$gJ>OUo+>;C#_tI+X;p>H9bjzr3 zZVob~>7s}T!h84bH4_p9GRh*))nj#nPWmtv++E%_MeO}qd^}Bwz7#FaY@=xb#&-H+ zav@KQ7UlQ-{9vEPSZGF`(**;4zMTJHf@{1yJnNi66Mha>g zeQlLv@O^P>r?x?L5^|sBGSz$aLFM%5zX9;{p94)@5vOS-16u|o0OZ$ykf)br>zqXe z)rnr7{8@+5(s0Cc513L@lne> zw;(HdcqX5iXZ zpKj5mFF@NP+x`QjPf_ndG7p(!?yU<~*+&RF- z#U)3EC_gvX3UaCbK`0URzz07o8X%NHG4(CSzUINt0kg^8*OGryWGq_4a!DH@>_ODS zZ!pEw*49QrX@1%M1Q=v)j1^BPL2ZZx@|!ToWpnjx1(`OxbnUl<)LXWC;H)7BZ}H zDIjH2NI#buQFwc+JqiQ@Z^+8Z%D~6v5-QiQf*3iUm}s!4sQ8iY>XvIXv~zx8ci z<1~WlZB~9hae)um5dVa)rn*iIN@NJL_e*}~@yx%}{dlzk%FLcoM>sMiT+yY2(R7l# zkfe*ZS9*MevTDg|d*#|Y532fHTWH%`1hCp{F9Ok4(|gmM38*dXL}CPK90C8 zr!Krh6k^l%5SV=JZ?9Bdg(e2^=@{o_XP*L50A74IV`;e=^^;G>U0q!Ub*a9h_eT&< zIg}pQK^T_bH;30GTl_}Wl9J=4<;Pei*m5s9-kUsz@G^?agS{Om>-~B~gZHRq{G~v% zl-j)h`&-H5h=>U1y$FPx2Oq{jji(a|GV9Qs7E>O_^D$_1upYV9`0O~Qt>0tV!``9! z0b;`(-CG3rM@zGtsA8@xJU?G?j{7_LNQn(etP$>_W)?g1-?UrEug9bspV0z=@+y>) zlBnnW=9tUF1x|m~jo_}L;FM+F=x{B3C2U6yJKaet;GlFUUNCNj>rgbgPefmgC-LA% z;p9Fcwz>^c`GYh#Mu8cA3(>GS)vn{l5|Q8kRvdy<3;bSdW)Q!6fJt4P-&ujJ;s=H7 zd))#Pm=fclVde3;n2wfNcX#*u6SXgTUWs9?fi!O*&rpoFaw^FAeqP?YccJf7{b|e^ zV2ZW9y?DUtm1;#OZ@|+JMR@Xo=dTg-)2tWIl8r;81J~|nAvrb`oX8I7e1_jyQj0kz z2S!|m=D8b%u=w>4WVW(3T%b~48Lp2Jp9#xdIihyOM?xE_76|wH2f<6k#x))|Q*bRm zJ#;qJ)}{=ldYJ?HFd;D!vy+e*1>#!l_@)S8H{1D6FZ8^6A@0Hq4zC3^0xR2 zRNWTJ{Z*L$Oc)sQ_g>!$mhHLK(4~}i>|^@(kVbLYE@S+SE`ReBU2g8*k8=QG{^&z| zyf!N0yHGtZfHyIAyt*B{uVjWa)Wjy(M7|=6oG8z|I>}||X7l9Y1)oV$wwW;$J3{b@)-*9>vPg7sN6Rsr+ znUyz{JB&430!xnuM3vK!OD2}3h2~$4Eqvk}%2(_evmd$As z5Mf1%|Gpg}G8KAtT60fVCybv3o!Pd3t6ET&_K(C@XRCuZkfilnDw4h|P_ z>-hH1FKqTceJNMXH4)aC-Pd}stx~D>Tuq^T0@^=H#1=7f6bxZ*40#j^s|nM5UljP~ zZ6yEmHaPyIgWEX~-Yd`tV?d{+fTZ~&wiGYsVc^bU&~@KZrlUNb^It=O@!}-zONQK! zx$K`4K1H03_5b*t_UqTLJ3=!w$H!V0&sc<+^oI-e0o&8rqrcF6t- zrsVlq0Owr4DFRtV?swq9xHsXT1~sBi2s!%r=s>LIpV}ysvUCgef28|(VjZ2o9~9CB z>YI)sXEChJ0-d>ofy6?P8(=m<6hnz48=rT(bn6GKz6KvngV8SLlvBXL#n@azB+;nt zLn-v547ypwv%KebP9gt6f$3I~-AC4}*0o-1 z4Jn-XHc<88H0n0&f4y7~u$2A2`Q${_wZ0F;6L)w1zlkq*Fu-hlh?A2Oy@~ZLCI_ohN@$k$;$AUM?>qRbQ>kk5ekuv)WkP%Uc^5TD2)IQLH?SZ@_b!)1cqk|zp z3f?PG#iZX3(pB6-LD0j59MWtFO(A@b3B;@(HBCBX7btQOvB371&h@vE)U||Y;Rvh>z;X5J#L(lJjVwD~4X+qW02j@UT5+-&2 zlo+4F8MyKDK&AUM>IpJ9ut7RBFBp5Gz}&OndDQ-3Wt0+)SYJam{`i24i)-&|fxjYb z+{`{4agr_+j$Nexp1lo=dth%Fpa6(2ruE;IQ)CZ@~E&hEVD z1aGb9_d(dDXfvSYmd%NU~7${=4SL1vG0$RC>_MHNxA(YlJ)41~ry9 zlupoctw4Qx|9w_g7-&|-d=76AEQkvIKoCD@f$>Ru9UwhGuPpcV$wKc6ytA{7tVu@A zNIhAP2es)7=sCauSk21>QUKK)elHihN`Cu`D;J_5FVV&lT?fdLd%WSnPpw37sKw<% zA_^QxN?fj`3K=Mhd8>cCxx2;jxA+Pr9DRuTKMNK-F0Q{B&$Un|cegUfG!N4Z;`hPe z-CMW%rHxbV!0!M4_i7O%SB&^>IVf3Z84q7(18hV@BaDyWZKB_lAvTyE&RoFQ1#|i5 zWkia`#&nXNzwbNWaB&epf#=tvH&k5V9kbI#B+|QS)SihRa6v?~^aP-7JzpjOuMve< zIHrJ=XrX*7pj9BT)z{GuF$(G;Lu_{Scrrw=-3}l}kg4#!CcpFUqgVy zf%Fa~4zY?(E^4ICM+^l=@SZc`gxst~exv8MpV*|Y5Xd?y5G*O4k{`l7-0F)PCSRaI zaJGwA=c_AKJo=jnIbQvRUUY`?42OrVeRM61Qr-jO4PK+Jnam^;3&6n6_7WsUQ$a_8 zSfL}p+2>j_oW`l9V2ny=wO>g4J@h()JPn0@I&=!Mu6EJjw(J6gd`!|PB`B#Zi<{Yj z6?w1!=q!ye`~8OM>X%Sw3W7=S`7$zSZCIedt%Yv%w3N8gawgDL7^x1LGZkLeY^tae z(MvrCSr{E-^4OFJ(Sqm?vFBs9!i0soZax48eW`GoENpgePNd7yv2xzLVa_#*Rbhc%ObCIn!Bw zo0+0CagbCpTIAGo$jTK+ryQ?$6rVUXZ1Jh$MgHFnW~MAst&ivxS+q$T%Ya2ndoq5tr>D(z`ua?@y=pUa&LB@=jj3KfyRP@#Dk;?@T#E<2n=&k$? z$N0z~U-$1{nb+~RU%bdeAgS=SpP#$m=<37GDNqODm;n%d{iSfY9`{hL{cwTl zAx%TWZfKwbt=gVJd$l(5G47HboDajZE3st&N1;*zj=k^M+wXy>nxOHyfF(i#Z(-C) zD=sESgC04~`_Fp2LHZ@QC%E|tEj(M>Tlo)e)hLB(zA6`MB*S8zsIi; zTp8mDa=5`3pr!*vjuJstg&+EJpSL{P-@1}?G0vbH?zs&Laod8=KPxYSb)vvjhPUBxL+7k0c6Yd}pzS)qrNY&;s)~vsO@u4D>t3{IK+eU) zJs_C50WyQ}8M+57iToBt0E$qEvn3*_@&@@y;9M~m)LGEO=JzinK0K)W`u%$np1*4Y z@c!bM89J7KakdbnrilHf$4A+a^AJ;f$d!0#u)-vZY@>N1kOdnaN!r@lWH;(eA*f2% zGVq(B0JCNSaMP}PnobnH=O@6;dl1X^M(}IyL0~7zx7NB{5Yq_KxNx{$zhAX|rdq68^{RED+0E}C}GMS7%M@A{T%ov7R z`le+8$UIx$^e=Y!z)SG7jkq=nrCW0Wa_m4+ff29nR+?!>9gnzyc4o>A6__$a53^GL z{Sa7wem492C`zFQ!{B!u7l)qmdwFnYI$+$WaY(1g!Wr6v|BOK-gem?Xl_Qe_oFj*; zkM2rRaozj3zoD@?oss-|7Bi$yJG_7YlV$$j*6;8C;UGChC;pQmy-%y||NLiH%jxC% z=cTJ^LAw3-*T~mwoOZ?k`9BGd|MQ}e-~FGz8hJAR^T6RD{Le8%uG{}yE_ew4e<6ka zK7!R`yyG#hr9iJ3Run_O^{w7P61Cb;5qK#Y1rTXe0LFQ z`0i2DiTAW<=tG1y&t1Dx4#KX7bd&Zn<5B-csDbp;c!n3}?Y1c3*=uAHV9AS;Ecb6c z$eARGQC@n@5TyhrH$N}k@GW+lNRWI`bbq~gZ6{#=Xf=DBOx=+sO`}1Y!krg$YVNki z%;2p{)b0z^Jk@`TMI_=~JDpyS{sl5C&6u2c9!9c8Cb5vTGM$f zu5Qw*wBcUchqax^^S$#$1SF5gupYnu6!t}le`7NamF$ujc;;`2M&MPB{|aCYV5~L& z;X|!K6OA|;hqAF~se7|<28svcCSn!3+b4g0mXqBus4TUMU7$)ILE7iY_IW^KAG>w- zg=GB2^(TbqsGPG| z6kOiYhwX-E(56SfE+l)jUr7#_-a{n|E+q`nWc}yk!9bEzh7JM&qD*{`6;1ZWxbBY@ za(FYYvN@3IXI*%j6@D&CiG5W&QHrMEkwUVHIm__31LY@HdcjuKPwEJCu|2d`X3BI; zX5lAR8k`N^r9-#fPplU(KEJi;^ShYypTEmr=kpL2OskMgb^1dBdT#jJ{nn00clN$J z`FE(_Ho;`1iMkt5{f<*cct89VTJIhiX_!!!4YhS!cHSFy7S443tczrJ&JJ&v82COF zHN-k|#CsLystBDtBGr&(8Lrabd7WQUCu@oS zGutKRM-p+_=lC{tuNe{z)Y`^i(ku5HEUQ5@WHYTyiNp*P7cN|5cK2r?=f#Sb@;SkO z7}I9aI=hY=7+W}LCb=atai{Q-hH25uxz*GFf6hJ`nP=*})MpyECM#deYKW)LNBsrX z;N7mUA!+%O1k{A_8K1C1%{XrB^Pi9TAQCB3T)p`x}c~rU!(m3&sy`&940C$dw5q zpSiW(#x}YC_S4iN_!RD%o@1lKwk^VLwfuSSymcn4LImT@4?zk{3K8fVTS4U0Y+fl# z6kD7|b4f%Nnor-qQM#==e8%e0CA-`c>^&|U?2a>EX1{6U>>T})Mwz_WCKQ`^cnJ%S zWISj6KOcYDo&V0OLHqc-kf36ucJbXs+<#()$TI7SJpRQ=<}#CA=gp~WrDMy^BE@#` z=D%EkEakY`52RsiI|)1V*a|H=Gp+IJQP`I3*NvYFMCjdUkEach<;Lyb9ANA$p~+T> z3$wnH5_Zjoor4!EZR4m5_x*5zR)1mL+;bFj+^-0lb%kWAqQkeUEcWgS%>57X;&r)w ze3(vLj&2xv_jsY|egB-jL8SEW=V&*HRH}Zt4rA3(V-4PtZVNpGJBrL?KVlF4e3dz= zNV#v2;Sqk33$(II51+yuJZSB~SHs45G`KEz)cv$OnBv`=3*ojOl9Uo@I`Ji1U)5o& z7?1|xkJ1d5JdtA~!802;7ofhCY!bmj6g;>rY3K}i8us*6yyD;7arY%FW9DjGTl{AT z!W5>mJ5KN$4{@B<8v?c)ICyz`#Yq4CgfsjsAfRm)2_G<&VC?>0nY3OU>e0st+&G^1 z1&Rx*^~|gSArs9F>B@rZ_rG`3FXLPyrxxKNcj@wByqY`#F&07vG8f>zK{-UAuVRDmFSl0d-7Dqj#S8Pi# z+a5jJ5U@XqO7`x3aWGKwZ?MzC`tJ=ZgQU#Sy2gvmRu&X66STgP#-H$TaJ1EiTOFM4H~FRn_Lvurgt~V2Tvm`GSnfEGj}V zmIM3WS`0i=e0mWqG~u6XYLnydbcV}aRews!r8U#^yk%ZK+&%QC$;=_ zHo>Rg5*PkKWZ?A=V#BS;hzVI4D+iO89+t6!6p&)GG)i07#Y+9@KQdf!5dWFs^t^uni)(HxX|BTzqol~TYadaq$86e)Q(>WN&r%K5r{NZfubz~V+Q++FCmlH{b$AgK z5gGYvI32=c5!ifS7Q!}yq>zQDO1HVdvsu)xysi&bzrK6ZVZurzCwN z*owpsSvWI(QM#?XIHxexSw zZ1yC556Z`OZO0boqOoPAj4|Hu-((@QzWP+%NdfI;t`ri|j31}+$V;lM;8^QI&$AD% zWa_fDmn{RMRUXM5J-lXaeNRK!(wvx`H$uzEfG9^SW2{pzlqE$)XD|%!8RtDTaTEz_ zib@_zUNexHIOOMnVV&c(%0pHC3Ub`D+?Fk$tZ*V#nDvjCatq@2pDJV=r?LxHoTHvS zlPFK{!Jk4&OPhx#nv9Vq`JxGfMs%H(Z3>jS4>TIl8gS$3>~_o}N}%`?r>JQnYpO3uvW;Z_dH!Jp-W#xWwBX&VGt zEwVGk;v3%FV&~#JQ*pbFRQ2c$KRypjUl;{0(XU zLd9(z10{VsYSP6g(=9DS%&lM41F&~=o_{yJTd;+7;ns#qtlLe?t>AN8eI)yS?*a_Gp%_DV^*B{n~C8&3}oe($5wT&>%06$DU`4_ z*Qjw_XRuGZoS09A5u24!E39AimPPARTFSfvd6P;y#G{Sl&e`sXV@7SJOO~Gq1}OPl zpYZ%q;U?2?RE{6+m~~+ei7VVtyaqmEwk-!a6>J92{rxNz26l9@YRXq<@=p$lQDR3j zlXFiO{RK^JBt9Yoc|bsm@9PUvlt2Lra9z{y?=^u|YuPZ#7#Pq(-IVyrf*{1Og5}Fy z%ZZDpEKb1QW?=4kceXtW^=rK9DG<#7gvOQy8Y9B3L0mUa_1^5<_m5F5kC&DwRH+LQq24V(jrHDr#2QNT5k znzD>zK?9kQ-@1zeD4Sta&c3CKa*OMl)%^}~mLwF$Owk-U z<@(_ET3`zYZv?q2_H0!D#~|vT0=VvsLDuquTq+N;#8RFtQB1E2CiX+aMzoZat0Iu4 zs~G|HNAfme?_gI_y} zxnJd3%qK$T>27`E=VksLoZmh|M`o|GQ*YPcr^j-%7aY8f*au12L8YHKS3Ye;W; z8Z0m@;2xb$h4}n_s-KbtJR1+pCThJ8VO`W=^;e>2(cti( ziZI%d)lhk&DTrG0_3@F6Doj%azw!{<&)VdyrI+<~m2LU7k5EYZt9ohc&QnpaDZDfvmNVj$qSFq+<8 zJ26EzL;y*0T0?l!wVUU`uMw9M5(B&^t1;J1*IwR$y({(s05Sj3$w4}!2VMezZ%S}; z8@@E+G;0oyAFznRk;z4U{RJbT!aMWo!T&hOi7?|rruAV((`|87fo zzwoxSk|pN^zw=Kp-d9$kyXSJAeBqbx5Bs!!US4&FeIBxbSZ=;vVo6@^RT1h2jX8bS zjP>)yLFZ$>pYYEg9boc1uch5Be}9yXfb})Mt0SRPo%c(dG-?`PLiU*>6c3-t1Ny=f z`pt?#@I1wBggu~cGwTcW?=Ox5aT6B)T>wuS%qe7-^R}H7Fe*LYl01A#9@*vvGrZ?A z0n)MDS7{RjoX&zfwk60A%ztj0sZxpLS69=hBy#jw162v#L}+IUlw*X%h%j@0yI+Ly z;GAc}0UZj)%kyFldr>5PBc-$Su2t9MDaXd{es`LyufoIQ}WU@ra z_*G(s9+6>Fc13iDvCQbFe&q4VrDjX%_t$e^zN8|{G<~J$rJj!BV|;$wDaNjctXx_O zX95+HZOtE2tScl8ICf4cy0|P&2yvPSv;OgCZsj-)%)(`K>MK1d9fg=m%m-h?+2Ser zHhOQFC)f%r4V6q|>ys4B*368%cLZQM5BK>ug=66f`<)wg0xr)-n3xj@8>hd4F)9$H zLI9z`>Kt}QW{byxlE72%fDqRbaUQ0nj3FTo2OX1eaDxy#3=~jhMaAjE6_8kp@nf`% z3kL_se9a16)b5X!^DG}ixCK%jwk(XyCii+h4TMvmz}i5zVc*X|IHIuDj)77C8?^DE zmR@j`Xr8c9u{8n<#2u^zWi++42HptZAPBuqCi+1pp{m3PVrhGCGu_+Hj-$?J=N&Kw zRdiSouF5Mhr(W-4WT|Yx(QtqZxFr8dT3>41ICAlNE@-VbzjLjW5`24)0u7!U=D0kCzh5osa!9=q0|iNvk0E;cjbiz1E6?q_X&*QnH_F7q*g! znXV|ywLRWQvA(ZYC*sY33RfB04eFwb`?UVm>WL)T`%)X~y6*0h-yB(_@wL*#O&<9* z4u!NTj~*C5v5l^JLdHguLO?oJe+GTB2m7;4PkzfqOAVwh-8%yr4%sLD(J=cBaKu2d z5E^h$5rBm(R`1bwv4D7qI{c{-U;#WQ7V>Y_7D1Vp>W@~O{(MP2E){V~R|JJc7qadQ z_ZjCXP##bBz&lp|yo|7j{_HO;-J=gUbnypUN6bQ)Kj+Q@9eNJ7gf5nTxoJP-1(WFx z#MB)AG$CR9w`CZ9C!AVXyVAo8gEg~(z@SG7>kVbRc@t!Mypc5SK5X1WL(&LeNTD+Y z>%?>_pM*7$wF;uHg(yZd3Hz8B)Q|a}IwBmIk zr(KQplQNOXioX)tY{e(X&oWRSeIdm+K|Oz;9CfREfnHN)zdr_9$V&5zBr$pyw$pzE z+r(ij$tIcmsUD+tMqbk)h>;@dY+^PtL4-AV(k(D(-FE-sGY?PMj#L^3_E%-V#1o?u zD2Ny9>fv+so#!$&Z$!^+h?pLX4i^XE0Z#}%z4UKQ5r}!)+4kF-nvFa4J69R0H*N1p zA)aR9DNcUNhOp4X>a`H~PaVB9v=wgd|6K@F7*3qpO8jW3jfGa}z^1>^JAPNwCmQTNM-WxgTkAN1Y| zK6|4JpF}~Z{F1EHEtxqoHm&C$WczD8>txO~r z2b248n%sOs!uiL#K*=mhcXi*dme+E7nW%ll>{V8RdXYj%!Q^X?b^3CMu?%eb-k7aI+4R|as_rJvh{tK_Ji8pI(Z4Ba{ zbTIgiWhL*5+XA?7eMs&=)-j3heU|zHLAMeJtcXzWX;}bpbWz;;#g9Py^XtgWy>ahY zycQw3>W_V|c0a@Q0cpkeciI0d)-Ex3csxD%XJYgTC!WI6>$qEaX`~UC`mL;SwVqLt z|BRrhk|wasNWu)9+aQU|s8 zXWB&$j!Qj*2EJ}3MWJ>V#2Tt}pK%I;a_zhd?==D7d*oUI|IiW%!#yT~mZpeS67_4M zuBNF7sOYQiH6YY;)GV?9S{P{hE}+4;sic2>@atFWmDSJbSYi`ivnDZ%lP5=$-eB2W z{Na(TYwwPdFwH#B35WuiH^J%bqeO~5^^0pgK;71>^%96Rs=iDg<2HCp8KW~b6zMsB z0{f_B4B<}O59M}_>Yi+6Il+rUjRUjhY&0TU@G+jYhKlP`s!S>}Ht)K!3J5A!V&M0qU|TP5?i4~f1CCfP)Eg~sz(j9)FLPvvlE_R9dI;znhHLr7 zQUajlG>Zlneg}pMY7Nqm#Ql;gpik@`83M5f7`o!X&JUa$z<_)_doFcXA#(J7cG{cI zK+PVhbg|q$2?r_MEdv8E-bluj1vTN$vN$mgG!1rz1yJjuj38m~IIaS9MGy*fDj*5s z{5fep!>1QFMLK&hyM~Yqj-lqaUXg@d2Y+;MpF$jYu)E=e0YzX}?G?A@LiV_A-{YIm zB%)3Zn};e)2|K)*mFy!=iP#n1#0{=Lj z9FDZuexW~bK0)JDqG*W}{U{QtHQ8Xx*^U?|k3#12k?YWUJyLH#nC)kW-WC)<`wzV| zoH+}`8$6NdHNruq4M2n$trkUVa#rN?)B(&d8e31CAJ$R73ST{>w?YaD@&;AUT8gs@zExYrovs?fgy`qM4 z2@LK#$~`Gb#;!dYUVpqcvb4R5_AF?oISuby%`(5sBjP=|kwI<*U zmmE>tO@qj|-#=q(-wnu&4Bf&@q zR%>H%ft)bz&XG5v#wXvi=uu<_Fu%x|bKIzwGI*St8}oG$2gP#RIF<-w<{*fH}BkAYeNL z>gg2hLd8Uc%{fWpIo+_0g|HE1%3l;jp54;XS&+y=f+etOUx1t+^{vBGTff2oDzsQ; zFNM@OzgE%TOpX1$s|6Yir^#N}AwPZj7p+ZHm$QEo@TXfqN8Np@9e$>3qMx~P?gezd zznn{Yk ziQ0|i0w9Jd9bJ)s4H-KGc&suYb{9h_Fq3h2yT)`bZ^gfQwJh-ltOpW7t^3tBReKr; zpYyN^CmhaBWSQ0Sphxd+Y z;(>%;voi~XXQ*G6qGN!&Tx(LWT2>qc#>oP>?8g49k5Kk$ zK znxTcC|Hf0Jv7!gi`6DWiv#um$*m9)U=93xT*YFtegZ}G}&w6AXgz#1As?L8hE@F(7 z`AJd{T5D|Tbh*4Lv20?e;^ZCTFkKKLOI3f$L3VfZ-e+6jEo?HBm{L&+xOWrRwSRBvX z8mnqr>EXRaUZ@`UV*e2lvxhgtQ)Ht%$&;y9rRhqR<>R!-an58i7I?;9XXo3k z!G)+?9;3|A(2(OXi2u0d;ZVUjORaAS_w_h3Wyy`CEz+)&ba_Y>S+HEOHIsYL;o(@n zErFu^()V8_%9zYeK{qj|=D;@cif+b|B zd-?ru@j4N+5Jffi4RvAQZDTY6m@Hw1+uacfR#IAj;D8QEyu0p51tBosz2U|)_;>Y9 z%olehb(0|PyR=d2qMW;VDx62{-hZv`8|6pR>;7;9<}*q0JM94Hdc)27K5zxb7T5E} zNxQncxlFS$U}H|ADO}z|kb>uEn@W28Lc%vzT1Lhr08C4|#_EAajL5tYnRNTXWSPBg zUbzzylE`EiR&D(K>wWxhcg%pOB1~bRyZ?%imAzWI{xHabLD7|IAmqpZ9qP`(i@eq+ zZbt~N3{tB-5d5Hwm%y#&7En|Pvg(3~eoVGNlE6m8vYzbbB1`@A(D(Vm;ztxB$87+= zTtu-_7X4P@WJIXow`2Sw<>qYZwy>^sr2Y*gF&6`7UcO{U zXAbXBo%e5uI73IPCC%2QOo%xH;>TGhC8u>sne)`u0a8AIj_A{)1!ZZ`Szk9k3?tbvd_f zfDCQqNVOGw@U*bPP_>)3=o3_vInOG;7h9i!aAs`~9vjMh`%TB}x>f0)8*|mm`8i2m zusaP8Lc#med3UA}+YboQ)txy@rB(I!DeAg1`n61catwhCq@e0^pD1|BUIi-(#sw)4 z2mxkVfLnoE`qj@^5X?pn{R1*t<&x*VA^Pw+MY6Ja*pD@jm@JPB0l0;jP36uD&nn#cJI5-E?gx0 z!N=1yJ39Yz0WMM0!d4t)zu0cT$?A!={Xx3~eMq}994};V7YeHRobBy&&5xAru#e*f z%ry#c&YnAslPB_zDB+~Zzg@_AQ{eR{GwJ(_!u;#aWGWf>6xRzLo8>da)QLa!m7`93 z;)SWp5%b!t51oGC{D^9FTCOVGCnj!5ldOD)#?yJtivs5wZq>TglTKsFdQ--xs5kfI ziDV-=Ep*yN=L2U$qgb>)*i>IAI5WLU!+5V?mFYt!LD3+#=eR)gus|&11I=pI1$>R% zQkCE;x$6aNdzIwT;v+mLhq7XM#X#3?5sJ?)kc~akPUJgy@$CGC~C3L z;5uSPg$ri|*9-;=b|qHlkdGGuP+=1!lN5~_s+L5SE5<&EidIjsEQz7|S^v3Y<0`Z$afWPKNG6zAsVDx-zqc)cqv74E^v z%63JzyFjh`j>q%2GGMarfvc@w(dTjOTR&*?WGRm47Rfgo7dAndXff7Yi~i#W4X7l@ z?mXH=OaqQYAd=cGOHK}}^Hx2AOPAS>`4Oq7c#eU0UESFS1v6QclCg63^~DOX7lD27 zSZK@WE4VFL4a53^(pJ7uwXxad%lEF@I}})6Lq;kaFva4rubEs$WVOFtevg(#0_>xc zXMmHDdIB&d0`FEvb0cEuXEP&Xvo7$|Wviz=0okBVjY|%Y+5G)oGA}PXCh%SR#(eje z6l%j#TMXOx^)Oe9)w|x1hIEHYcvlxE*^yOxbP^9p7m+Y3M|$u2pHO01#hm#$ z+>o>-g4OX{j9BcsMjKA{FJqrh9`aDpZyex!-<49b(4Z$@+*i2uybDjsVw`}OPQbe2 z%CLIeuwyzSTQZJi)4{NLh2&-zvti|j}?e%#i;SSKf!?_uZVz3C>5LNwV} z3b*~VzH<^^-P8o_2gve%V*a3h2J?T=N(~tjr3M^dLDpEtN=trS{8P0xwR8CK#LjTpD)0UDDeD2gZs_9yxC9O zJqvo~FRSl-0U=tvyG*z^G4;3TJg5#)NY)3*Ag8^|DhPR?uV;e!`+Yt>J{$1XD)Y#7 zzAFrvaRaigd-up+wlDPf=lj$TbK|jjrtdXA3;Dj5X7W>71-lEbG6@FIIw7V8vPu{K zKrQ_WYKwE9g#>RGad($_1i+fZfl**_{)|q#FP{10^7ZGj{VO)$>w%JjaN!GDC(7-w zR7jdY8B4G}gAk1PLtuSV=M{&>-rC5-up=#kmY~>AmlkZw8WESSCk|CrRpVZ>QIx$b z0WeiQbyXP{&m79tZvj7$=fZYcAp%w{RT|<#ACZcv7nTT?{`vJu+#ei)yuc-9q};(! zt7djo5MI|4Udb}W_Qy|19$(KlyWtml097-|k3UIj01UkVF+2(s=MURgUN8FtoVo!c zOt!K%3xS<0Z#knW&kE2BUA+`oZ))>U$u*@9QM3HQWBx@+{+-jH>|Pr@vR-h}LVxOg z?9^~1iU1{P9oLwllbs2~qj#pW<#c5rKfNs@8ZjEE6HD<*Qw=JZWfhJHAxK6v~Jl9ciVu`{@yM zrh@|~3~S5l6rACO8<8T1ZeW>ybN~BlF>RP8CHQ2$bn#XU4{8qumV^Cfic357RyAM8 z_CDYnr>ah05bW5^GbJmuI#hhuS>9g}F^75&b$_Ig$*#)orQ_APBeIToiHk51wb8kS z^MjlY(Xj%?j$;NUWz@q5FdoCvG&gk*7osnjX1UCj<06Bsd~*E03O@Ba{j9E>jav5GGsQnO>R*3Ke4Hpy`e0=r07VYJ-j7U3s1-3=z3=TulwJa!n zK^gzfQ$P5%SPy3%qUJ@M6!P=@MImEeOO>wP{DyPEC^j)GRm{mG>f9m<7B!{$H0%Pt z_S%I`Im{ET{g+Jj3yAm$}XeRgi440Mf$6aTT=-bIxBHJ}#LYLp}CyI+WwqRA4 z-e!Jhw*e2NOv}8`%@kbeITNkdVQV!@nPjGXJ%Gn*ig8hXNLj6n?+fxg-F;(P0gFcm zv=5<0{sZDZmNKW2!axwZK9-l4L#LY_dFyyWumzF0Fp~Q;$_=Qi-sDprf2rDGy=N9RY4}G_875(lmp5f~t zjFyb1UcUA)U|zpg%IImRFSSRTv8R^*rO*EL3AQYjo52A<^1F z?@8-0R@O}$tjW=DD?GdLjyczMD3=UuQx3q;n5{?!}-i+u8N`@befwA(KBzUHF5!{Q1JUlrK8 zuYGgyEbBaJ{ z`n?o;fco!P1S5VFrAsbSj?mEYNgpsv7JrrU{LcAH>mr)1BWWs`^hQGstAzB3gQ_%H zM26O-aEGoO{yLWqf|&GpbyF%r4MRooU*ej!7jR>gcLvzRND`Dga7F`}1;9S*4A)hO z+~*w%@$bW^cip_pnsAW^fO(RGoRjkACFJN&n?hB7KE0QD_JzbNRVYYej)) zB&N+Gx{XlMqIQ?v`rO*Ibt{E>LzdzkaBXg1Nd-OXow_RR!AF4puEXe{v+U-?7<{a* z;1iaiuZElg)Ds4odZy-k!n?lpPr6^PHr){W-U@UulkA+wLYKZQZ{0;|g}%z#dM^md zfuAN9Usm>s5B0vF~&DR^ar9(R^iot?Kct#%t%eg1xs=^x--QLYX`o zJbQPv{da06wY#GloA!>>-B|#^5sA1&NzEWAEw~ONOrf7{(3~yT9ga;*fhj2FfO_EE z!h%js0kV`1h8q|^hwCyjGL+Uu64%*@Xf+w3dmv_oldm$ z{ttr=cI3dpPAhyaI8l$3+D_{C8CL7J93KYXZf^N3kHuENz^eAyMyr^E*0fLMMll;9 z@f!n*sd0?6uSYzG3uRwiPUIQH_c$|}DVe+#s3)A#F4nlYkMC46z9QhPZa23@w3Kqr z{x%D(#!HIk&w{A#f$qp5irbs+?B_vFeY3XE>TKhuN`E5@bu&uhmSn;gseTkd2%f5EsAR@o*aoAg~%w&|Al{^1Kw z#gTZ|S`Wj*R}83BWwHreb4h7yj(XB>40pSb69MkzD z(_@yrMV4sjgmeO$bb>!zZh)y3(v$3g-z>&Ry`Ln^AZ(yvQ(exCPFJ{R`QDTvDDUNF z6?jw;9vncShJjFg|y8 z*@pnA<&R>BFd=)Up^ijv77f0;aS^~K>79cLKIhMJc$vnF&=?YZ-idsAQzE;|?<^I6 z+RXqrkYX6UT`4B$U~6%wN=nfZ>;j^*zZ@qY+~yoBxe=?9 zCJ>{Xz8>e0tNjeNlSd)0MvN<09zdPKd>XN^(+$E3<&lE$j?~Va8|7s!Zj~Azj!ga) z1uv`HtU?JyX{_t5KA+Uowv{b!T`#?jllGc|h_Q*XnVG4A;mb1TSbS46X1B$ZxdDD! zt-+79U(c`RKMgw0vA7w~wNg+iEPrd76BRL(L|Tk~wB1!$Xry~4wa@Bv0bzW!DF=!4 z?FwaPK%ruSW;Z3$2l&-xcvxur7X^%H?y9!F`H^FR3c4D!i{&pr9rit)Ct0QPa-gIC zMnLAdS{-ixU&Ps|JdIA0I=e?0&0`Va3bg4@5+mkz1{dAJs~&wWSE-i0R1{F5d!$O; z<({_o;<)q(>-Re6HS>pl&rKG6mA^ca=(~E%;;8{{rxG{MM1?H$WD*)H(gKR0Dzxbd z9xZSZ#;H9)rgg)W4e_*s*2f5R%qWC7F=5QCrml`SlA!QIySXJA~yX> z#a0#=H7|VkEEE6co#^qK8fozmdnAO#cxvU!U-5S7GdN5F&~-4zJbSHO`7)%wXD$a2 zpuc7{bp3$Sit=x081fU@ws~}CyKP;M+TFYEHo@Z-KtqSU8x9D;DakXnfbKov;}dX{ zIZGCQiq7Al@~+|ee<1a-IRE5E9Q*nKAsn3xc{lBf3WHNK^w zm;7Ihy#-WNTi-9d=~TKK=`N*HP#UBpq`N_BB$N*6mQ+Acq)Qs4K|s12k?yWLm*+Xp zId|Om`^LM6`>?DXo7^?qmKtU6=!CW>PpwsZ3(H8CWt!OQ{0##}R^?qXXqZvshG{gZiN@&C=9V8!0HKUaOv{p`^gW=4v-Q$|Io)fs z5C%2Qy#Youn494WC{F#xZAUPEl~^0}JNW@HhN=9Hl%U%7gPjB03$!4qT^~Bq zcjFf~K7QoUC!USKfl(0Xd+M&=>?*kIe7>8@+|6~ zih)LEn4(WEE1-)|G)1s(G(g7cP?rpFsQrR;w9mN}o_lVI-m7oYbVu5KSA2FADj3Ijf7g+f3=AhYiCNX>jh>5$%{RidBF z2j{QDjkr?i6kAjePT2HLV;H)Jwy-GqQal|88Og`4Q0>uI_DI`fn*c02ls=37Q!QUy z!(EXSmQSP4>A7kzf)<~#uxL`-X~e0-#0!m?^Yh^k$;WBMoZ@%zFuYHSaWARIvO(L0 zBsrq=gAIga2UE>yrE^F^)eIo)9j<^NmIn~LK8KXIRV_KwO}TH7pyZgDjZM+E8JO+D z1VF=j)6DM*7jz|;KnO%x1l3wDP<)*B5ok*V@_OY!Imp06^6nO>>E%hrFJ-+xL<5*X zMbZE%NK?_hS={^mXs$C~+Qn3N*>H*d&0%L-Zz3zJogZjo0(XSfct`~0-Ps7hfJF8I zFXMI6Gqh6gv)v+lgOZxzoxR$X`!L0kRiGu;&qN8E1bta(W;i$j1~yh>p9vsM%gRzC zpz?6lU+WZeK(q3I3``wY0IEPy*9{0jz!?!=&3_pI!hT1SrqOU-v(GiJb&|V1@J|_l z0%%X|i(866OGnCe>g?7P+Q9e(rNnPrmXR=aR8kG4^OuC4XnX9}-bZR8r;2q#s(5T4 zg7H)vmfgVc>`Er8d?r920c|FR&M1_j_Nm8EF@Z9z*j}l~^&C72?oICvc{Lb(A^I=7 z(zL~vUeU^V61+)=eVeNsf-CuO{)IN7LgfLayU88PvmIk?Ofgz4*oX$xM|he*Yhioo zV@&IjlIR)By{_b~2a{tV=4VtaL3t5L>UNV4UzkSe1@4^3;DL46TJGXa-4&8*S{Fqr zFF4Vwyx*R#{?RZH>00dY@R0dhjnVP3IpIa{%kj>SMysK*{T^!%sh`#2_{Ao91hZ8V z)2G;GseG`W;Kd!|U>vwjTXjmWBjFF#MpX$Ej~wS` zC2$@prIUE`&$-}%ZAMlo3mUZmlrc(n5Rq#ufPJF0fNPLGehP$!AsF#^kMF4_6y#t~ zM;ugfg3woq2^ZxX4vio{*MWm@+ebi3l?P;Rbr{v?(8lCXINi-6^slmS%4&WH?*AjmQS)iFm;FhjoGcpm&jNMo-3miLn+W8IZVwaY zhi#}!xApL1X|!Duqpb;;)XhF^cjMY;!dpARF3ljTte50##i99Z`A}d0hugCG(($$g zdHIN?el^HVL6s@psc0CrV@oP9J#DLuiHWK;n?n<9Gc9~dowBjO7miKDyM^d?1C750|YQKl87o)D20iYNRd#UF_pRq#z@U@G<*1P7X(gCY9+jB zJYo`)=X`&+M{nH~FZ5PK-kJ!fg+(D%p90}a|H};Fgr_-}LFU4N0yhPLCwK~}4TsBp zFPv{4s@=~Gue2FMZ(hiH^mrFQ6u#E@_=3p-xUU&ZXFwA(bF8?Y*$JTFUIKVo1*q+E z*9I_~>YR#dL1qM^gh6LDM9Km4=}|ALD?FkXPH@l@X6SoCPxX2qjui-c83A$sv6qfv z(zFo1q8Q-`K$UNbEn*6c&n14-1eMuKfSUtgPe&LiBd8TeT)x)5=bs?GgW$^4_T+mQ zmG(2^jSJ>!I2%V7=goIl&0bUPHah-x=J4riz#`gl&?bIP11!uS;afEY2}orY;6os` z$!NizU0xFC^67rOC5I;QRbRm%WNh<`<3bbE`*3K6b}8|@pHX@;GBQByCkni6J_pSW z0f~iZ=xi9UEq2tkuAsbL0CXGQ_}yJC$n^m+!S6snnw06or7=LRz<~QFJxN!bdifss zM{~h1ci9@h=bxTVu3O`fp@o~rvA4iO8Fb0;o>xZwwkG>ef_Cpe)g-d{_fFi~Ml0hs z+`J&fsZcm=v<~rOhA5|&Pxv?`a&$!s_S$Y!D1A7{#4yUDln40x{sb~pQb?>8+*~Ok z)>b*NU?lmRZNE@G4?FIlwQ4pL!Y28~H5t>Yvr=lTgCz z-yquMJn6YK@%gc{h4)azBf(^`1Q|~CSQCdn)~U^EKO0x9keDeCHAV93oQ>@hIjT@~ z0fDPR5EH^{15|pA_-EN&aFbH+YlqBx7$eSaf}LFsuPV|xX%d0XzBz#w*i0%03>|=6 zv^tw^C6jfk>5izwY^~7T^T&{DKqb+%tND%ykj*ymy;!SU10)OBEa1MlmS^200x|TT zC5Fwp=AiLl(u2!RtOuY1S-zLdfYj1I-371=o}h&RR||%RTb$bOLGu6Yz`TtMvxYD7 z0d--dPos3u1FP<1sfCpTAk1Cai2KxBZUP{5oIpopFH!pxnO(PX5zNg^!H5k8fq<5m zmvdbq{{SG6N0NOxegM|l5AEsR3(;F3%BAzMw&KRO2CPpo0+}dK89HkOkkoka9MRVT zK+NTi2)J_quKxjEOqCix?%W{);}FQP7|4Zct`L*r@rcDuE&Rbx4Euh33PjW;evVQ> z31AGzkl>;}LhWjt!XMf6VMP3?f|9GVTQRU6Y4n)$eUvo*io7=u{sKiv>Ksg&=n*f{ zsmB}IKtX19Zzv$t$d3P|)&G(LU2#OE^r^vY zY}?c$>rU$zlh{>wXP!5QJKC?MO=#NkwAwByC%9=Au_ih0F?X#C(M`e!rgY8Chd)s* zL!^-luCFOq2#yjdYav9_&|>Aw6Tk965QMA0>o2BxhS3(w6=v>;LKUlWi!*RAGtoM4 zkVyq0W zzj~gtUu)VOuH(@_sc3lZ#aaTte%YZm5GZ`Qtnl2oDP8&2XK&5c$9d8?={Ja!I;?C`X_fAeh>cmp=7%?@(Ii5(yA*5#6i$6 zUf=?_ewf(Z^-<&vyMA3|HO=!>P^s46M@ba`db6L|3MLI9!M*HwsX|asxaYqHP1>!8 zQJ}R&w^PF(3*zMtUK@Isqz!;bq=Qs$_Yh)@VQ|#?1EeM0*F6E;d)d4I6tRm&v`-0n z#6Az)@`=p@ICJhGxCfRXZVCw4Awbji0O)|4+tnWrD|`d%?)0Vfn5iFWwA2k`LJ-+k zrC0E01C$!G{@+Az)kpT{QKIa+Z&nh>`c|uARJ|S`w|@|bf{Qu|*rGD>@A`u3G8%;p zqOq6WjJ1T|eSEb0$Uk}3l8}40Cc4}nJ9$-Bl1YDCq08xuVEVr9O9`&VMf33Zd6N0k z0W#N*TFnx*{F#iw`5H3EetBjelX_->C_?jRY^<9?V!48HlU)zF424B7NfT6F7A7bT z5cD_@$ccVN{1k<`^^}%gx|jC!p}z#RL~Cj6`S$RG&w23QS30-2@v~oqU~A+z;h9uM zTMl9Sh$X+)LhYrS@O}ZATe6Ch+13-)B^)ZjLfnd zAZdumBdnGC5_I2c@6!NvZk4M6n9kSIEnp20hdy(4w%43YYb`_$eg;;|D?{sjy1fKe zGr}UM5KErjfiR46EC7bnzR#@5r_T4kV|@cPj4l3S(>7-UC$=4m!=s~bpw&_f25fM% zxc8!N?x4mpfNX6H6P4(Ya^otc*K^YQ~=&yPS+P`OfDW>kkaOQtpJLW zvUjoisd&t3^+-ZwSEmdB)$=BCgfr-BJaPt;)Yt#n%l)w@WB)_ z!4}I}7{e_{2=p=g!IH34(Uv`5<_l!1VKZL?b>4yb%s&3ea_y5H^Tt51or6lk4L#(ir-jFe6#ZCU5p0 zsao~JVtefB`uft*<+i51@mrtygq*mm{`1w?S%(fbWJ)n&nBf2>x;Xo4%>&;rGp7Da zG)B+GQO^TjIQf)W(eus zPM3pP#TgI@M&<4_=@}UrR}M#sE*?Ty*sq7TEGu9y_qpY`t757tM_iaxOhIE4>?tM|~EeGUaO zw&T;J&1J8^j30g95FzgCw2us<|B38nE@C12jFE^+%{1F^Oj1-g-p;Q z1lR`_mSs@du7de(@!>5HOI;DVp!lMI`QVB*3NrSAG~9K&le+=zWe_adgfc|6M__0G zS-{6735FdF4-ebi5juh>@DYXrNemM>Kk$3NP{grwlhz2%JmC8Rb+| zNW1bNDiSM2)Z49d&HGBw*%1=Zs5Dm={Fa7p0s5SpA9u_|9&uoP&j!gyvFb?9qqezG zKZVhx>2MKHvYiwS)+gThqW>v_a{mKol$^Z$J^?$QsrjJd5VLkS##_qvpdyBrd(JVh zim|ejnzUk8IKBC6kM5Ut{Vp~11T6DGsY6etaD{Nx)1fw0zd`EWEoZ!q9$GBaE;d!? z*0x2-0JIb_T+w@6Etb=V!J*JFm0g-E5&pZBX9lHGDci)G)^ZUeX?>!I<&#tk6vl34 z5w4fgaFWgJ{anX_vWZX4@YT(zcdwUF@m*$WZ4%Py#iLh> zAIu4pc4~9f0*UjVD?I;TKF~*ov7al-oti(-Audie@@2AdPT8$m7`s5Ahq(pP*8ELk zTgYh+fE)(=v4$fg7EzDeft6^?IAF?(gS}}aX@YS8Q-?8U7r?B00i{!5tEj?ebPsUD zAOW1Z=Fgxk%7TIDyjt0Q!RdQ|0dX|_ZGMc-WjPPrLHSzQ&CS^Yip$L&G$0th1(?_wMr#!l1iH8t~XWtOc~Ak7gEZXkJwB?SbJFoX0hgg$IeJ zZF-6|i$GgAK!97Of88a&gA`N&u$M&C%O&v=@?`?39cR4O?B?&vwC;fTA=gv>$bQ-h z{J5nO9Xyog?s|{{23ye89RSn-XN{Lnh!Q*dfsGZs6-_TBdO!LIbiU8d25^cr+93g3 zQ1!p5m9PfD7ysK^l{CIW-7+Y%wqCCQ@H|-Jt(MtKRvl2xTwNK=UBR0Xn(u5y$$%U{ zS)Gas8pZ(SZMnYt0ErI+Hbu~`OFwdg9#S>=8qm-Z>oRj8l#apGOQdnc3Nu@IH+t0hGjB&{2SM0%JH0+Zk1+cF-(Kt8M_DC>Rh;u04hO zv*Jq)pB)_2|Bq-hFrK?1{!e#1kV1S)88f&#)t#JmSV3PvU;rgak3-tAWR{0a*-wms zQ)Wr9|EXEW%XD~>d^Hb6aj|-r5H~g^+8WEu`o=56U~O7+oW|&=>1Q|tjoVH!m#enEYqPK9v1lmN-@Ux~w3s5fN|Cg_%m2+u zj({70Y*t90p_nJWU2B>spe>O1X#17W6E(Q8B?0*hC=~JMao~2)g?6Imj6V=PBTgG<^sl<~Tzu8<4iZmM(}S zq|=qw-%~9!H;N(q7haHb7F_{M;z!|lC%~`*z?v@CZ$Ld30l*&IY%?uiEz0ILG&IO} zjpGvoM-|AeM~ih6B*9J)aubY+@rIhoz{lYOfP3WQ3uwoFadixVb#{ayM-}%c>wv>I zQalE-oUPNW!XgDeQgfh>;miheZU!J|H4Y7VPH~J_O1&+L7{=@#IrtQKNk97aGLnK&_5jyLBtr~ z7R0*q{o<^rJq*uQ^9daul-_~(g>-ymr@8E$`KjdFue8WrAZ_7clF|8p&%+y)H_pCH zj=W$@67i;<9HSe0NaVj2l`SIFYqA*vD^35!D&T#0>lr#xk zjb$Fb7UtV;)upugaqV!uE$n@8*c@SRbBJ9Mlt-^#!fWRyHHZ3D<6|p`y{%Lu33E5i zQw?ql|IOYuLp!9FQ>x%2EosbMnx(uQO=ixhYHu7g^XkK^LSy>ZT5?iw{2WhZO(NtI zyl=Og?d@A7Q#*o)^d+df)*U{{;;5U^eOrAJWJ`+PC$`>dM0pXiu5O0mczL}2(Odp^ zSGW#h-DZ1<8bgwK$BGtq6-=e=7SA;FO*z}^e6dV_wLnustyKLqqp~Q3zg&D?WJxmA2*qxhWU*ePefWWoCGJF)J=yX-5J1%}9n|>Ys zkU1(ap~)!fnFPdDjWpCkEFrg1(`Ar~xW)6_2l!BcE64Va;HV1)(E16bZ8H;q(u689 z|7s;=a|p!mG9;-Pz6CDgN;qq=tb&vK<|vv!aO|^ujl-$&4#F1$F=}%qu67gd`PWBE z&=Z#S&^Ae<_+xoH;%{$lP4-wU!PS_^HuMmngX4I;(++GNQcG>><|{w{mXTv zg|*H=SEaagTUrx1dhAAct$UAZkN^T7;Qa4-UaTco6odCE#ct0{VP_?#Cx&Bj%myXJ zKCa;C@~TdD=VtV80kFbs))y2Z{v6(5@_Nm(Q^5>58UeGC{&)QIsO`}+az(%l%x@XA zu%G6w?3VX&ARM2~Z6H)St%2L~7dSxJVo}9FuND7ZCh2?VTtKiIH>Gvs9iLU#QiD`*>ib}~#1qa|DMfcj9t z8Xo0ow+Bdcw@-N9dcOyFhEMuf>w+#IHiMs{-#Rmen7*mJAwcyA{)AE1xjpwk7I*1B zr&Ip7jmqYLttTLF;(s?noAdX=(XAI zaWGwF^&FiMCsRkmcuERxMAfZVY`4_^&3oDB22`Gn1WN=$+$xyt38i>zNk~jG)CEE4 zlqFb+47jS&Z0!A^2{Ne20hs+GQka@O85+zoqv82zoWtV^g2l@ZI}SYbrtfl0v5*lW z#m0(Ti$$;%e1D?1Q;>yXz<&EO!gO91PbIt5S3)cE|5B%YIyIjsJb=qh2 zE%C1$F<)D}jp_1Nl|$`oLe9VvlL#aj%LW|QH?ke6Z+?#|J2F8N*;_F5CWUJmj@buYoloD& z%^*2|F*mF8?^L&oLYW$!z%yX>a;<6!@K}&4v6XMAB$dV4gX>3N%;VkLTlv6HfV_CTkttqSf(3A|?h|uSvqyo}DVjfUat;9% z`?nkW+1gmJ9o6?n@hZImaP-4bfQN_BilfzlI0`J(#lICZfH@X8l3ETLzz93pH5voC z!*gs61A_rzoY!Vs(uiy&c@B`$zr!a0>xV}uMSwWC^<=_u?{@yLqDLe7*F6gVKaHgS z7Xm0{DntGUs@15>rxsVw28KYRO@y?fCqwzM&4-(%&# z{8h1RhNJrVg4B&TWunIYju9yL49S&5*(`(U0f>?qP{L&3K{j{#QMUzrjbsd!pS+h3x?UO za<{UBL$RLkB3O~;zz5NKOF*jI1T_3IV93s|dh(@>xR=o{n~ zK)Tm77Kc=>z*gO-E0$MTSt-?(qv3n>e!&SOmRg=ZLu)Sqrtto658kOP;V9;Tg8S+pV(he34RI29u@vd&4;-uO z@8cHkQst;JjWEdZRUZfdvjflr)%WK+3j)mCCSV_vYaW*8b4oyN*$hHA*GIDK6_4l7 zbOeV6NdWw94MId#Oahln4Zv>`rZ!;tadAIHDu?BrAn=_4?B`_=B#SC0|4;)a@38;c z^`B2&ueeL_QVYf!O;-`T)xW_{0&earXl|tnj_odC_h8X#LNhx_#az$qeVEi4YZHgt z0*zGkHy>1rDUOEMt??!-wNiziC9|x;T2!UkZ(cG_K9DttrZ&S9z>}Po1r7M7ze<{T5It*zy;hZMYRo)~S7L%aL)mE+&vA=gzM_3I zkis1R@aCOgQ(q(|n-%go&Zk4dMi5qYzG}&V4VZ$S$sB_7-2$?t=W9frg}?_Y49b|; z^Jw{$Aw4ZC$+nNtV!fbPu^m+bnsL7;O0x8J^U4vuSitgL23KPRN;jMgRVNZa&*>*% z#6p5d{x($4fqWWd>H`W^_->oRW{(3C7=*@-up*;^ykr7Uu-p`Oq0Z&l?nltBao}+R zMHDbb%ITe{wjK!vA3PXX7ZXEXD`nHPsbI(xZ<+k$6|S1ny{A?@fX@pmvgD*$x8gxC zRAgz$0$UyUsAOyX#7MKKv1fx=##?HF*r-Xq( zG(3<5y0R1jRinnME67m#2IMRK$mi zNOF~jjwjLVvPfWR7P(z)&(Do?2#x!~>$N;G5bHC3pL*=4=3h<0hf22WP25~j)F5TZ zVy&iVr=%hgoK_PiU16O858)zWrUzfv11MCy#5LPWQ4<48d$(_QOq=(wonet8CpCc+ zA*F3On)^oAC$7JXE&)FW4^Yv#^SOhTwR~??Ql%3Jdka$9_W1G0dD^ti4@h*AzNTRT?1yiHvQ)ZD|79wpcAT7X%)Lw1abppcQ z7zp@xk{s{MOt`9gf_4!v0}so4lBop2r9eEOV}b|Mu63dTE^JN|LZDyJ4&gLYD^SRt zU|_%mS^z{qCV%rel<5Er)VIzn$Fa|e!T}dxY6PnBd8Z&Y5S)N~!o;)hBxJ4GghCL- z{TGlEaiD0shVvBQ zwCmm2!3m@%9c!EaQ^V^EpWQwL7NkJ$G*=!kRx=M&#(;h9=d5pU;B%r0NgsqqR1LWR zIKVZi>g5&&C8!q}ghK9-{fbhO?Cfgd5rgU`YW-SaAh~d+eTD)^5MaQ&0s^0CcF+$1 z6$P*ZLjUq|9uOjbp)&&|w*kmO4tS-)S%uJrGA^(8r^b)oL0~VyD}rXRU+`5-NuoiL zkFp5N10mrki1+I6w$Fw6U6iWTXow(aHv$tt_W)uQ)P|Tahyw?H`y`-gXZxK20S=&n ziIVNUHxK!Vf&T;M^%`)fyHcLx6s-jT+{|g^O24 z&uxAvM-+%IHP^PA%wH*lN*Cq2b)~knwP}RE39)_p_S$d_um4_M6k$^ooZ?9GqIOQ@ zR=}M4!6i00gR5Aih!Ul?FxJ)+>Udz{Q-S*QcyixElnI~3z9VoLKeeD;hqf%RDw!?jntQ4r4uETD;OIs zZ~T5dmB+uVeE(o)WbhgLEGx@<@}y;A+^9gbls6t5gk)VhCKsRjzTLH6k%-#x!2&`s zEjn3C%6c;;eU?%!myTH4=sR}Z;F>vo)3s8t7P1B#u#zUh_Wa<^X~!QM6S;dUEn;xK zkwYnd(Q248>laGpC!NJ1(k$G+Ta}xHU6RJFZ;|{t%8>SfWiUTU4KMUwK`5Avj_ECk z8LkZ!eTDb?Tyq1I3it?5sY-;w`#I0B=Nr(nQsY9SC3E@UTUx#!YS-td&}Uh*+9k-V zQcN;mr^t*F3Z=*sl{tB7OXU@bjRi2Mu z!u~P{=glk(uOz(yiNL?D?eJ37V2*N%uq^)S=V}VBLSlPpRzQMqGg94k2o6#3xuV~+ z^XJBk_LxHQPzse6%v^rbx?Gg@uht0qJI%K+%M773%NkJ(iGvB5f_cx&6gYJxuEg-< zq}HdCY7Us_`|Bx)!kf1Nf(&p-Nj_q1-#-o(hG#V+q}?fc{)jdJrvUmBC`5;kegK-? zjMh3}nhulJp!pBDODgd{_3!g@&-cZ##gP`$>=-I$N<7xu%s*lG*GahWvAs6~Fuy<{?TkkN1wsi?*f1?SbxQ{Z~w*JnR z?+_NhUrpQyV zuO#0065RY<=8RH-?BylJFLGtTqD2mW^7qNhm;Ya|u-gob-CbB=C~kZgWdea+S=*P3 z2dTSH4WqEKb}+HSiaMn7zR7D>Kb9!yZ;RA+C`4B6akyt4%k)~X$%bHG6&cOF-=hbG z+H@*>8k+;-F(ya-B@du*|1uBjiN}80a2yg&e`T-nWYcp%-fZ_*EOM<;-o_ zGyzP+8rej|$_>mf(bivA9s6riFw0oXzWUIgFifMo@viX&d@e1Er&rHbMzWSohkak) z19G(btiUM8}39SU;0Ja z<$ZqP$Sj)Yof(>cVx@-W#y~O)?WFey_%W?#Tt%=vmibQ)d{qr(%=AnGDL=33Je%@# z3S>LI`%>rft6;gQB9`r1c7b7%SC$UfIhpYygBTkXab=~&?SV6*@c1KGgb@~d0;=1| zN6dZt-Qm#a2S`Rb9%@oH)t2rZD1YCVf3HbYsra1#g*1?H$&ks}AWWMZ)$JZO%e`;* z`TV=g*kOU7e`@{wbblQYHSx);E5S2BubcXbBGE$C5+1u0b$T~dKSM3}S$OblA*nns zz5p>*4Wllmg(cFC)Q-@Yj7@|WdB=ov+siG|vdf$MRC+tA%iEM8v=*m=n{&6*r;PKF z$-;KTL6de!vTf(1%n(~sH&McQW44w^9BPGkL8`p6s`gg-=%X(As&by$>c5)=Qgu?t z##Gd5>ROvs5DShr(&Im=na!*l-rZd!cWI-Y*q?ZoYZBWXIPP<|7k2z25hV0l@I(%O zX@O4Np0(a~0c@MLDP^j|1$_ewQC!>7yv2U|JW@l2R~NmXqI=qMfqfr|uev^xSyGg) zh$N2fV~`{;zkai2tyoqD%+5q;%iN^tkMl(4oY^@qG5F_D|9?|1!LDa!Rhk9^&_4^JJn zADgj%joL~2T#CjUku$m5Br=qJ#_!MOL@oYxSY^6o9ixDe%Y-IR+9K<51l4)oOIkv; z0>dSFKjJ~8BSanhXxo~50VrWr9T#iWUy&A4Y{F892R{ipmgTq|h#(N+{Pz(%ruc?{ zmbQFbx!E=Dho?p0C=ym+mB@FgQ1MCqf=31tCU*Ss{@kMhFtT+WR$N*3YCQ9adWp#P zx)r#S?Hw&$0Zu)8$EM774=N$a1JAKK9MRc8b4U*GuivPkR8j(0sR z?V;FlH0Qf#U#=Whw!M;NS_hjh_5xVDV$977F3u@r%WZ#9kJgNZ3E9Jz1ztLqRO$&K zcFP<2??}s};w<`HkM36BJuaC>%ZQmsbzMW0f3xmSs9N@O%77)>N}g^i2W z!PFjps;w!bn#;;a2&28l1X<~T%%3~Bl#oY6V{p1AW?D@Sw=aBP>LQ77!(9{~PH_B5 z;xLnkgTq@crjxbDq|Yy_$Mw~zKAXzFA@tCRQ5e5%nSLXKsrAnxNNYWSu1t6NR;6CL z&?|WV%hTY#7*!M4%(@V4;hfkME#w7ZxK{l==Jt%2*>5^lBkmXr6z(@w&-dDY7;kuNtUuh#)Q=*= z{_ib-6N_Q>Lmo@wUxxs_G^wRqo9OfGhnZs3$7swBIMeg4JzfdPA7Tu-k{`*@-ncOep6 zrxK$xx%z_IC((ICYVvP{c5kypa~S$c;@0oLCosa>e}OO_(9SUDsq1a*pzyEbNQ#DM z1xIr6RsT8LbuBq>3Su!uCI#`F} zTSU&i_vCkWYs%8Lvk9AaxSh0kv5{nQJA1Au81umPmCWi&%11wi8jVQScwE;{g5Cyp zadXKiCprGV+67<_9^9L7`x)J#yC1N9p@iq&;9=o2-DMitleOo%?h`@#&!fB?Uz>)O zw$EXITjzTF-H2CJN37-3Z)^OH2z6UC`NvOq&L>44KTg9=f!XY)>`7{4L`WdagtdNI zAxdSw?v?Twb-+P}8!gAgGPv`P(!6@2==|n>SzoEq0|hQw?kr?}_iFwY>YZR^Haa@G zEWfP)xqHsb@JJteQZ8e#szkUzeV)ShPGsci>8E$)i}AzE%SE8W0<~v zeo8agVpLH?C>X#RwB&lFH${$FeeB4ULR$~-|L(yD<=IAYs@I(D9(i#z)-^8SGX~d8 z;prF#kJ9XX?eKB(u%Egztw+;9rY7^hZ>lq)zqSGItyMBrmM|lAD=}eY3DE-6HXEaWJ(9OY zl~2_$td#i*E%S($3*Mo_c3gPH+9%mQ`Y-GZR%smT$JPy#d0JqIl)CU*ES~hVE~bjnb6zIj zmgXsvcVs>4%Z1TBVm*sZ=yg9YHj@!^d#tfJXjyznWihTs^2)NfG_Rhm_s!~z!7?%u z-J@0pG@1LMY{HMV`xHzAkCLbaIdwMP$y-EK@(n(6Hf7nR7cY518MM1@iua-C(L4Ly ziwGfZV;CY_jL-e5(uCHJXY;Q=#K-mp!Xx^Io(wr^|MvvY((XODY`&3^UVSSYj&#Sy zMD2|*g@1Z&h2=h9M&|Ej+K%+(+`)Kel&w?B)EmKHOZcVj>eOZRfmBUFW{u;Uw1qhi zB&OP1FL(;B-4EB-_(XI+H;`$y?U<=svq+?$Sx4Ip$)p)o96oTMe6bUHC=h9BWcu?m zvISYsW)NSJz;h!$^>M2DwB@#WCbNp;PxWWFZRh6YJNNmsY%N1)Y=_8@Rwr?uvz8MEu1QwG~(-+7w zw5B0hC+~wejuE}I9W9uGJ4}v7hMBH-$^6`&tc4$1j$Sc(Qa?#rGUIufLp&w$0vj`h z7UAi)EV~ASny&GKP{aW4{Mz{ho-|C%e_dGGJ!e}jFWA4o1HJx|$nz(o(evvey=MFA z--l-uu87pC8ldN}pl=2v79L+sDm5?@;A)~Nqmg8{_4n_twyt>(!^9d3lMBa$8`mv* zC!Z%=*C-?wjQIXn9&7nrVn5oL6tSmPU~k#7(C3*(afJMu%Z|ux9GqNFh7g@{h1HcG zJRB(`9YVh>O~iA5 z2!T_yZdQuV9HzSQa$bL$L2QaC_sOLZMe?glv`=v)uDkD-xevZ4Ra}!4wqsMi84>@a z%-!Chf3k(CuT;cL^8$}pzZwUV0cR;sj1({TgK1mm{cjIu4}U&!ZfwS>!?;S~LM@Hg zVGdF5V-F{yr^2QFO|=hmK|t!wdw5OK!DunVlZQ)FVaOdX_XQ4>w`8y@K6(DPU^C#V zaYcLnAXNS7IQxh_alBihc*swL*DO!!GaN}pf?jGzq(pF~kQ$N3@ZBqawgQuZtE!II z?aqomRw-JacBUV7CfZD;EV%pX^JjOOSXb-80>9H(4E0}LU}0kRzx-G7BR$XhSEjH_ zLEQt7#3p9JWVFuchJfwxrM~0JE@uXF%$kC1Wih2s)_FztJG-@`OV?M|DUQv@uCNaR z$ZTQn=1v~9Fc8MmlXDfeCM~!%V(c1F@-6bdM?&K4PewDzd{ytm#^s;G7 z&GWO=62YrfoFTRQMm=Zmn^GAq?Bm5&wkam0*2P`lkp6T&YgmP2d)8$xZH@Vmt5f6G zm)RO5-LAP;nApMh+-J8u<&Vk6ui8dO@tgKmt}5=%B>y>{`MdF=W7t1`|Lc_&t524i zv^0nRNeBORA=2#2nT!-_mzm5rk^$`DeE#AuEbZFNi%>&0`8M;re`6!lpowuma}$A4 zM^)_TN(`5!v^s1A`-We`TQ|SDG=GUPlz%2+sXHZxW&BiZ;C;Y^+C1p zj<$v=mdmPH_MTReSHF23$FT;v9_?mwu3S_y%$#?gV2@+IIr!q^F;^e0);H-9(fM#f z>q+(Epy9lFrthUSY!?Vd6HtQc=I=)l-Cw)Qmoae|JJEURs|og$93f1tF7_7tto`Q=(yal?yyQ2jk)zzs*aQ%d_ps72YSKddMI5F24EZNqPo8%1P%!di^<5F?#9awE~t9Sx~65$5C zPc?daobFEyy5?tyKaknDB^1>w%n+{qAd)ukxy@hVbLxs9iYu!y^;m>@2M=Ez9mX8p zul!hq#2Al=$(S94+N_%=_=vvrT=3LFXx_KJnEnAPNqU_Ci$3M`5uX9k%qOlp(jw2hrb(r_m5 z3x%$rE)bK>yr7N(y#OuFOnzLeywdf(Gq~Dp^lREul-Fm2E-F-0*D0AhCtE17XGs8% z>oQ;pB!mZ%$lv{Ir6BjJu>ZaM|MQh6Li6ZG9S6tL5A@7n{y-%bzWVsxo$nMKW@9QE zo6ZK-AfvMBsmK~Hr{*)shyk9%|+5DgLYV3ME zEmqDS8i|A|*R9ip&k&n(b^g!;b%o8GV5HjleDrDgI?+d1{q4Ld)^kyz9zvJ9;V+GYCjma7~VQWrFCrkKK>&PdoVQig)e0!LJRHu<7qdwZ(a zKG**_i#3m-w~zMV0B_T9Cf`hbH~(t`7SktF2^~o|8zijr-zxc4zD0lAW#?>F+vTr{ zsZ--FQ!2m;8V$gP;ni8P_Fi85-7R}xFBV$hG@01a%yFT2seCyz{*C;6Rpkpj>->AL zvu+?|yaK~Yjyt3OE_-RSG1Wii2zHh0?qJOViNB3 zdWa=v;lv#9wP1bC-_Lhl&Kq@g*q+x zm)ZNh8!Jwjir7r<&OP_87~SNrv@^;g3d{6k-1i5_kLo0E!cPp2f#?MLZ*nLo{QbE0 z(y16m_*Y%|Cpp#mdh99>wpQx#t7806(NuH2-#3W}zelRIBYJ9J zU-3#$yVCOOj)jYM4u2MNVofP;xog6}dy8MQ33=EZIA!nPhzsBK``k*=4cXMZdDWx+ zQ@#4Zk8vN1o0JMR(R1g?XYIzxqZuu}8zok4`Ba4i~?BlTf&yMO(_k)Tm$! zDMdx0SrnF;mfcnLz61EQ<5?VL7yQqQF#7o#KXEGvsno z16oSf$OU@QKNsNQ%4wNanwvu3_g`fFrUn+4;-fVr0DA#sZt#=M-$(Bowi z-7@;9xf8j2A3!&qup36qc^6isuXk_z_q|+!?~&B_y593K>LNZ&e)fQz z(!zs@4IW3z&*DkM%hJG9xAhJkPBmJf1SH0$_n!$!20D}Al1-Sy3n3))%n$cV;Gqo+Bw}Lrk zxLJ<rLsat593kW-IJubE9$o#s2d9>$HQat$flMp+CQKn6~|Xr37*t+44x- z18Kzy3cS%5%;8{TUwWdBIiaYxUCI8d3*MIm#h6{&7R{#k?ou^_%SrTkZU@B= zVRr?ZJ$AVJl(yWDmO5un;rY)Jhk5lGe#jS@>9D*mQ6Wk7^!3)QQEoP9Oa@Sx^@id` zz?4pM;``_9l#_1UT@Zn$s?CkeR@o;D!ZarI=N?9pt*1}4GzNBbFtf_ct(7awPu)yL zfJs;ikuk9-#!cd4fahD*Uo4tGzw0WzdY%3&mrO+!qtI|JyUD)&#No9G+0WO;nEpR4 zyHIU{FCP(EJ;S=*lvPu}M#RM8hgqrckqC=)zN7laZCkQ%lb~3i9p2DfR>tix<*M*( zw@uky!3su~5$eXs&?EnaPq^4#yd-^z#11`r*L~+5pNX46MTS!ZtLyNUjy^VJ$4ys8 zsE?^>`;-9fTe}y^2XaL8qMrvd4uX%ePjCo@z=IZp73{a|J|FDlAw%a_3gCB!4qY2@n=)(QZzgP z$P0n(7w|PzF;XdYNY3y74|``BRR!Ai`%NP)-65TVbeEJMFSXJEgmO6X)K}1&Bo_b*$Hk zxYU2TnSIuZE2+e6eW6;Oi-y3|gMOcsMn$mL^kNHj_mBxKiVE3ed_Hp>h@bcG++sSYEAb1$-7f;Xdj-% z`rC2**K=sVDL>TyrubbA?0go=Tg zPfAfYEPv3B;|xanm#X(+aQRy>UxDPma8rXGhZ=(U$$toL- z_TQ8G`=e4lR&#jX&T(EO>LhLInG9)>{_xMQx@Q5y6g}rE8fFigHJ^m3#|IQsRSEl+ zD=ibahWGJu``6$lkcT3Z6Fcl$p(zKAPFkm+C5*&=pmLwo#BPVURQVf)>^b&$ z5g9Jj?RxQboS`TMmlTpBG%)XL$>VHRtL0U5Yy%T%qmK_F7hlAIMn^5xqHreH354Vy zbd#D7aoRK<^Gz}JBa$o$6_$@c+aJe$;VZN!gh45J$6W%5niEBSslV$BMA9p1J2!d# zS`>2nOGLUpGJ{G@Gi?9E1NBeI?hkQi6;1H;2<#x&dj7_|d}W9HSlN0 zmJ|H-qY#9E^u_8V;IYe)hP0i5?ktUabsH`sVh2q~SXkANuTefb<|HPq|DGebd5j^# zv&Rv3U5cOS93SiMnRF{oK?u;35{;nSN=tNY!z`8q8pVhoKu0miEE!43i{_e&a8&$ieYD>_g zXYV0$%FEA2cH+AmXkkJ|>_@ySx;8eFXU?#9wZbyfQLK~kQpiKf!U-etwz=r#1kxEW z%{HyFI|JE{W|R%j&{8aCU(`>3z5FTNaGnN(RKtuHx;n=qmX1r9>3iFYMIR>A=!sOG zJafVSs9V>yQIc5u_Bv>%hI=Y?nownRYsZfIMDZ82D z94%zTL2W?DDiap+NTNNAT^Pk6H+tAjaPG~rMm)NWD@Wh^cP6zxlP2QDN{9^$yS7Sw z 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 WckQjOfmMhTN=w`q&%CAg$NvCkSm`|g diff --git a/.github/assets/fourth.png b/.github/assets/fourth.png deleted file mode 100644 index 9465ff803cd7b90e0b38c9e890544f83bedf6e33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 307540 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 eQ91owwRcD9jofvACr|!K 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�aP`DVP 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 diff --git a/.github/assets/sec.png b/.github/assets/sec.png deleted file mode 100644 index b47c18f9250842dedcf6f20356574e7dc188b880..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 188798 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 z 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 z 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 R4nna>&@fQX{oVf0{{hzXdl~=$ diff --git a/.github/assets/third.png b/.github/assets/third.png deleted file mode 100644 index e2510482972ac951d0b1463be8fe7e35d0e998c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 802310 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 eQ91owwRcD9jofvACr|!K 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 PYiU~g!20Z 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

M{|pK&O| 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Ƕ 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⪙UgH2FcM_^!2*2c;0KH-S{vOOwYx>oTOq==>D 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

  • >AJu+K!*j})J9CxPiGI@J{{8koQ~i4 z@9>ZNx5&!&6N5z47xamZ1E<-@w66G7PPtD0=DI@nUgzWM_-ol**AH_0QYGFJk2;|D z`@&>o|0d1ZpG6dnl$4yOHvr!YjeyF)kaN90Y%0Ea0BW`eSJrVU zLXbNVXzDNY#ecA=d*pWYm?t>&4FVfm;~zi0;7YLUEA$2PP2q`J^H8%o-G?1t?uH^i z3lSK(4Xh4of&KFRJ9}#mtPMC{@7Kh8dk|Ht8p)x{FwSHb#=%}BEm=dJMt~$M4HsJPm zmlRp)dTo21GqK@p>_mosF!qX~@neFi@u@`hlb0jX17lkQXkw}23vA_V#l-_c6jFLY zfEY7Km~}L>uownZm`Wd%X`w{$m^EAxkd^?Li0IB5?qzfNU<>8F{HnPA{(jW z7rwoucq{}JoiGUB{{|d)bQmx|Qz472W~>H~7@esNH8RKveoQ477KR!L9=M0%PDBPp z{7ei27@QyNX*7b-a}FZk=XB`D*Y@~QB2jz{0*w()54qKkbNO*`(^diFQy-uL0&e;8 zyZ72F^u|V#|4UaFbu|cbeavxR<_Fpm z)#sdA>FjkTS7Ls>kINPqHw^M;uk4z5b!=;yt6z6}D7`k;9}REZAk1xK&uzd~9h!n{ zAaK;hG%puroBz7!`oxh#x1YM_4qeo(ko6; z-?Aho4sn_j2Hwb&=!PE9n|IJFO|W)P^xbv%dx_7`Qr^M2!#M99x;q6~IZQpK_p`*^ zXI|hrN0Gbq`USS1X=N}RTWc=jRApn`k~E{ z&2vWHENM>GwqhP%T`%vrT3Av7_C9w0DhUSOsz5bsLoK}Vws@HA?!fxV*;&Rajz%K% zsW(F5i8+8X&5N0TamE9jiSXI8%NeOb3Mrdvviql&s$l8~xWZilG~-sn{ev(?6uLwo zRM`i~CeaZ$Xa_#@_w_kJFE6TxlclDnUYIU>0hVTA<@fK;ot@0Fb6=)OP_i0>rmC5e zz@byK!5n%}or2771iGd~re9r6R+c{FP7?VW>x(#f>~y~kX&CP+iRWLlvLwL$AE6Ik zSX3(ya$f!POHb`BFzk2O-?6T$sF&lzR z*M{%K#6i)xhAmUU;k>RhIZ9_bE=aKA1_DhgQ&wX%-+M<#s8l2{daibh$(epF{^>?! z;{gbO`8a}_?~|_Ff8u+YXe4+so0*ULkT{->p?A2^$nGkiD*f4k{{BN8gV3r`??y^f z<#QE3;6Fn%?vT(L2N~q7(~8rB+E@A)8@2|`(g~zSu!!5XavL83a8vB`7ZoKkV1BW$ z^h8wtPNIF;sQRE$N-@4lUxc*!xD^1tKllCug1r9>a*paF@bBN}!b|h#asBg?i~CX4 z_}^b>+ODbo`&VT~2vz>$U-5RQQK9PJpM*a8vxEQs>Xa`nV*bVaAuU%c&U0g0q%y6+|JPLbzw>ZF&UW=)&Kv)&6p)_Z~Er9dv%_AX$1dpn!s$WeW=nEfAXm zAqqxJo~EV4UZ8_Wnp;`HjIy&BU=q;AzJN;8onAVr|Jac5v=O8a7ngYEYkT`uL&GCb z%cknrlat%IUD*bLny|2N51$nL!amiETxD>GQQ4>ff?ji^9efHPQY`Lb!QkA@?%iX2 z1gi3xr;QHdq8x7Bx^>swJRvKKp@H%c2H1QU&2pzR%gf8dL=M*JZYA_qv;Vx+ZVPK` z8hxOSQe`Nd*>k1Z5OlbK@lgPX2gV?;M@m5spZMyQwzgKuJ@%kWsrxC};V)+9=5+9Z z8rk%ctcDlkpuCOQpAN_K>+S!(Vhq=OJuxkfxBSfm!EZHv9Uc4BJ4?r+ET9k)J#+wv z@6c0XH%OezxMJ)N?_~pB`vF>=eqUOp0eVgsL`OL}Gfq^yX{UCAE8%S{Z7+#Lym_(u z@r)imF>jxaCb~Ev-@%F)8y|%sFiGj@be=Fk73H}1?=QzUmz0!z{qm&-SjuD*6B9$w zeDgXZ!$Nhb3LLB1-Mc%qAIac_gT1>rqz@VZo8(R@`TqOW2AN~9{=%KxmPe(vEw*LL zZ!hH`@+Wi`C^s3#ZcY&7@WNf*{%36_yqj&*)YX;s^c3CPL{Bg76oqXCj7uNUk;5wY zxnD}FsO*L7J3@C$_}satQ-jbl_t7A4cMB|Ko?tk0{Lcla(h8tPy>KGL%hqbPp!??g z?@N~Lp^F8ka!eVj!MYa>$}_HS&2ffts;4CcZAM_tGO0TGt}CY{q^J8meM*giYEFF; zx0KR)0+iZde>|SS9Xxbsa$=(49kDw0w|Z6(mid;PoZOnbaCkqxn2Cl<6Hlu8oh0z~ z+kiI~r&6c?+RtnFwEK^zHCLIRe5=CZ40%g)1>2QsjU#lgOG-*!c|@0|nW-1_CND1- zdfJ#Qz7Jhh{v0yk`2?G$|v#Vg6984_iAV7#V8eNh+@=udgzDbr1Ts9|**pz7)<8LZIn)A;fIyc4gj%O-}F4 z$6TFzmD!(F0QONf8KbU5&Z8?pR}(fHB~8H%|9fiNg}3Wd z^5$1I1AnMyTqrtLD_Y_p1Q%Ce&MZ+{;c{Ae7SPs0W{X*#-m5o~k{(JYi1)^^Se|51{a#LwB}gQ=@XV*tMTAT@7r9 zZH9WVMckDzdRURhkLp~oFWL{@yKs2NCCb-+3ws{(SI*DSVa}B>#@u1(^X}Org;%`+ zpYXJENwhS6Zy|XH?RkR#(}v2<`~lhgEuaOTlcS1s_|ps<8?o$GhdP0g`VYm zM9GR0etIY!mXYf8;n#kaSG0o!T;GxF_mJ)Uz>H74YGG#fx~$B(!5E~g>8oLOTfHj@ z^@auwLrOaSa@HD#2S(l4z|`t#oI|j z>3DAP`8&-Mb88dQOpG}icx@iV0 zXLw7O?`0cIyC6gM1fMMW*B}4gjidUtV2D&zueTEo1Pe*~Z=4>4<6Uh21Z(zwBtvy~ zC@C8b!AFNDJ+2174P9jQ|#-#K&=8-&LOA+Hvo==P;*^nwEphLr;ftaAK89Rw5+N||2(H-_fxrdJ?6(`XvpB{`1Iyh zCY92-`@zt9Nrv%KAH0|20xwJ8(%G&0CHEmZ3-`9UUH=}&Q1I_y4;~-Hx%j7jCK{fu zS@>ozSE2?#qzcYSx(1FGb~RO$yzP#FlKgzThIcmFw{FoXKh(u18thfg!n|)nnZeg5 z+ix?nJ92_{U-gavTk~2uEbd7M*u;@FfOB>Vhx{ynQCx@Xp*QMQe54Fs)fM)`2Gt3) z{5${L*7Ab=-XG)Zd>WSSJWZ^`B5#*_v(zsI!}vvpBZX_x4_f9%+A41MI<^wOn8Vq< z`DQhDG7PQKp7J`^X7lFi$PkuD1-V3Gezj@0)w+k{PkbKCOet`=w9Uq&; z=@lgianJ^umUi-GsvgFPC_~&R8K5}+PATGq)_b5m+Xswaa@=+eX21Sy|AU<3=WDus zb|387QV^!sq_h$~_J&J!H=Cl^Q$E;&NA)iG!>%W9Nn9Jb^x$vqBTU%-VCJwdsyXnv z_dIbb72G=>fpK@up1#EM_l2EL0Qda+!oS<}?+gDu+<)T9!~~(JbY{%zw{N#A>)pI^T7nC@KFUIq%5E730u_C4nFULP||{U`rQ^fley{TpH!TpU_qPaf(q++g#p%J!DhO_U@i|k!(&?EqdNj(W%of zo?2*V*fqIz|6;jXncr(HQb6$zm~B%j*9cG=sr*5*C4L=THm z!h7Z`sRkFk=uX2j@V$ZuarhB4puAKJ>S!PsRlkOqWDKi*AGN~vMMbq*QbBTkEG#fC zdT6S98Sa#Fm-jE`n1vlN3o>LT5xb|YOJDo(x5=Y`m07jYMgrn@FB4@~82BSHQu;Sf zOy>L_vd^U9LWoyvJwSA@ zEM)tNR06k8Kq7M?Rio+Br7!MQSL);*Y%)p0J~b%b-ulte(dZmNA|N>8RB6w%{dAK# zwl_b{O1P7MmgMoS&iK@oRPH$b%`r<@DB+vt78X8if%U_M#l_@GDk>_^c;!onoQ4(2aldHzzbLk48h)pa(5KL!m;|LhCIF3t|FaKgpxR=wTOxsi~TM*C8XnIB-1 z(<7x}f7Uvxa@$)$a-=yzcOJ#y?uVaWog0K)BJCwW*JNdnm{BoXABr~++1kc5BRFJa z4V6%{H{mKF17j+?VN(f##$%niHi`(|uAxDrI0&!WCAI^PP(jUQzns-42kL}W&vX!T zrd>X5zd7X5&`So_qw#ey4!(e=?V9ofyx z^PPyd~9_G*Hquw@2YBgLs8XuiBuNaUb3(+C6euGm8?#~?Mr|O zE-j&mJig#`+0q3sr>pxtRMZ`(Yzrj_l-xPZ&KI;aUpR|k&ikE_pcxqOwt{gq_5xbgo z@U)kalN)+=mDbDYGRHk@=qQjbulVujst%s|YdZcO-aj4={*qh

    Qq?ggP9tz7Xg^ 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 - echo "$TRAVIS_COMMIT_MESSAGE" - | grep -E '\[(skip travis|travis skip)\]' - && echo "[skip travis] has been found, exiting." - && exit 0 || true - -before_script: - - mkdir -p $ANDROID_HOME/licenses - - echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > $ANDROID_HOME/licenses/android-sdk-license - - echo -e "d56f5187479451eabf01fb78af6dfcb131a6481e" >> $ANDROID_HOME/licenses/android-sdk-license - - echo -e "\n504667f4c0de7af1a06de9f4b1727b84351f2910" > $ANDROID_HOME/licenses/android-sdk-preview-license - -script: - - ./gradlew clean assembleDebug --no-daemon --stacktrace - -before_cache: - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ - -cache: - directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ - - $HOME/.android/build-cache - -after_success: - - bash <(curl -s https://codecov.io/bash) - -notifications: - email: false - webhooks: https://www.travisbuddy.com/ - on_success: never diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 3baf58318..000000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,46 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at kosh20111@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 9cecc1d46..000000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {one line to give the program's name and a brief idea of what it does.} - Copyright (C) {year} {name of author} - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - {project} Copyright (C) {year} {fullname} - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/README.md b/README.md deleted file mode 100644 index 9c8516e62..000000000 --- a/README.md +++ /dev/null @@ -1,199 +0,0 @@ -#### FastHub is currently under a huge refactoring, please make sure to submit an issue only if necessary. -##### Any Pull requests that are not directed to fasthub/fasthub-v5 branch will be ignored. You could follow the development on this branch: [fasthub/fasthub-v5](https://github.com/k0shk0sh/FastHub/tree/fasthub/fasthub-v5) - -[![Build Status](https://travis-ci.org/k0shk0sh/FastHub.svg?branch=master)](https://travis-ci.org/k0shk0sh/FastHub) -[![Releases](https://img.shields.io/github/release/k0shk0sh/FastHub.svg)](https://github.com/k0shk0sh/FastHub/releases/latest) [![Slack](https://img.shields.io/badge/slack-join-e01563.svg)](http://rebrand.ly/fasthub) -[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) - - -![Logo](/.github/assets/feature_graphic.png?raw=true "Logo") - -# FastHub - -Yet another **open-source** GitHub client app but unlike any other app, FastHub was built from scratch. - -[Download from Google Play](https://play.google.com/store/apps/details?id=com.fastaccess.github) -[Direct apk download](https://github.com/k0shk0sh/FastHub/releases/latest) - -## Features -- **App** - - Three login types (Basic Auth), (Access Token) or via (OAuth) - - Multiple Accounts - - Enterprise Accounts - - Themes mode - - Offline-mode - - Markdown and code highlighting support - - Notifications overview and "Mark all as read" - - Search Users/Orgs, Repos, Issues/PRs & Code. - - FastHub & GitHub Pinned Repos - - Trending - - Wiki - - Projects -- **Repositories** - - Browse & Read Wiki - - Edit, Create & Delete files (commit) - - Edit, Create & Delete files (Project Columns Cards) - - Search Repos - - Browse and search Repos - - See your public, private and forked Repos - - Filter Branches and Commits - - Watch, star and fork Repos - - Download releases, files and branches -- **Issues and Pull Requests** - - Search Issues/PRs - - Filter Issues/PRs - - Long click to peak Issues/PRs & add comments otg. - - Open/close Issues/PRs - - Comment on Issues/PRs - - Manage Issue/PR comments - - React to comments with reactions - - Edit Issues/PRs - - Lock/unlock conversation in Issues/PRs - - Assign people and add Labels and Milestones to Issues/PRs - - Manage Milestones - - Merge PRs - - PRs reviews (reply, react with emojies, delete & edit comment) - - PRs request review changes/approve & comment. - - PRs statuses -- **Commits and Gists** - - Search Code/Gists - - View Gists and their files - - Comment on Commits/Gists - - Manage Commit/Gist comments - - Create/Delete Gists - - Edit Gist & Gist Files - - React to Commit comments with reactions - - Comment on line number in Files/Code changes. -- **Organisations** - - Overview - - Feeds - - Teams & Teams repos - - Repos -- **Users** - - GitHub Pinned Repos - - Follow/Unfollow users - - View user feeds - - Contribution graph. - - Search Users, Repos, Issues,Pull Requests and Code -- _**Much more...**_ - - _FastHub is actively developed. More features will come!_ - -~~> **FastHub** contain Ads, which are disabled by default. You could enable them if you'd like to support the development.~~ -_Ads currently not available._ - -## Specs / Open-source libraries: - -- Minimum **SDK 21**, _but AppCompat is used all the way ;-)_ -- [**Kotlin**](https://github.com/JetBrains/kotlin) all new modules starting from 2.5.3 will be written in **#Kotlin**. -- **MVP**-architecture: [**ThirtyInch**](https://github.com/grandcentrix/ThirtyInch) because its ThirtyInch. -- [**RxJava2**](https://github.com/ReactiveX/RxJava) & [**RxAndroid**](https://github.com/ReactiveX/RxAndroid) for Retrofit & background threads -- [**Retrofit**](https://github.com/square/retrofit) for constructing the REST API -- [**Requery**](https://github.com/requery/requery/) for offline-mode -- [**Stream API**](https://github.com/aNNiMON/Lightweight-Stream-API) for dealing with `Collections` -- [**ButterKnife**](https://github.com/JakeWharton/butterknife) for view binding -- [**Android State**](https://github.com/evernote/android-state) for saving instance states -- [**Lombok**](https://projectlombok.org/) for getters and setters -- [**Material-BottomNavigation**](https://github.com/sephiroth74/Material-BottomNavigation) for `BottomBar` tabs -- [**Glide**](https://github.com/bumptech/glide) for loading images -- [**commonmark**](https://github.com/atlassian/commonmark-java) for _Markdown_ conversion to html -- [**Toasty**](https://github.com/GrenderG/Toasty) for displaying error/success messages -- [**ShapedImageView**](https://github.com/gavinliu/ShapedImageView) for round avatars -- [**Material-About-Library**](https://github.com/daniel-stoneuk/material-about-library) for the about screen -- [**Fabric**](https://fabric.io/kits/android/crashlytics) analytics & crash reporting. -- [**Lottie**](https://github.com/airbnb/lottie-android) for animations -- **Android Support Libraries**, the almighty ;-) - -## Contribution - -You love FastHub? You want new features or bug fixes? -Please **contribute** to the project either by [_creating a PR_](https://github.com/k0shk0sh/FastHub/compare) or [_submitting an issue_](https://github.com/k0shk0sh/FastHub/issues/new) on GitHub. -Read the [**contribution guide**](.github/CONTRIBUTING.md) for more detailed information. - -## Language Contributors - -

    - -## FAQ - -
    - Why can't I see my Organizations either Private or Public ones? -

    Open up https://github.com/settings/applications and look for FastHub, open it then scroll to Organization access and click on Grant Button, - alternatively login via Access Token which will ease this setup.

    -
    - -
    - I tried to login via Access Token & OTP but why isn't it working? -

    You can't login via Access Token & OTP all together due to the lifetime of the OTP code, you'll be required to login in every few seconds.

    -
    - -
    - Why are my Private Repo and Enterprise Wiki not showing up? -

    It's due to FastHub scraping GitHub Wiki page & Private Repos require session token that FastHub doesn't have.

    -
    - -
    - I login with Enterprise account but can't interact with anything other than my Enterprise GitHub. -

    Well, logically, you can't access anything else other than your Enterprise, but FastHub made that possible but can't do much about it, in most cases since your login credential doesn't exists in GitHub server. But in few cases your GitHub account Oauth token will do the trick.

    -
    - -
    - Why am I having problems editing Issues/PRs? -

    If you are unable to edit an issue in a public organization, please contact your Organization Admin to grant access to FastHub. Alternatively you can login using an Access Token with the correct permissions granted.

    -
    - -
    - I'm having this issue! / I want this and that! -

    Head to https://github.com/k0shk0sh/FastHub/issues/new and create new issue for bugs or feature requests. I really encourage you to search before opening a ticket. Any duplicate request will result in it being closed immediately.

    -
    - -## License - -> Copyright (C) 2017 Kosh. -> Licensed under the [GPL-3.0](https://www.gnu.org/licenses/gpl.html) license. -> (See the [LICENSE](https://github.com/k0shk0sh/FastHub/blob/master/LICENSE) file for the whole license text.) - -## Screenshots - -| Feeds | Drawer | -|:-:|:-:| -| ![First](/.github/assets/first.png?raw=true) | ![Sec](/.github/assets/sec.png?raw=true) | - -| Repo | Profile | -|:-:|:-:| -| ![Third](/.github/assets/third.png?raw=true) | ![Fourth](/.github/assets/fourth.png?raw=true) | - -## FastHub Logo - -**FastHub** logo is designed by **Cookicons**. -[Google+](https://plus.google.com/+CookiconsDesign) | [Twitter](https://twitter.com/mcookie) -Designer website [Cookicons](https://cookicons.co/). - -**OLD FastHub** logo was designed by **Kevin Aguilar**. -[Google+](https://plus.google.com/+KevinAguilarC) | [Twitter](https://twitter.com/kevttob) -Designer at [Kevin Aguilar](http://kevaguilar.com/). -Laus Deo Semper diff --git a/_config.yml b/_config.yml deleted file mode 100644 index 259a24e4d..000000000 --- a/_config.yml +++ /dev/null @@ -1 +0,0 @@ -theme: jekyll-theme-tactile \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 954282a8f..7a9c5f281 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,20 +1,31 @@ apply plugin: 'com.android.application' -apply plugin: 'com.apollographql.android' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' -apply plugin: 'com.novoda.build-properties' -apply plugin: 'jacoco-android' +apply plugin: 'kotlin-kapt' +apply plugin: 'androidx.navigation.safeargs' apply plugin: 'io.fabric' +apply plugin: 'com.novoda.build-properties' +apply plugin: "org.jlleitschuh.gradle.ktlint" +apply plugin: "com.github.ben-manes.versions" buildProperties { notThere { - file rootProject.file('debug_gradle.properties') + file rootProject.file('build-dependecies/debug_keys.properties') } secrets { - file rootProject.file('gradle.properties') + file rootProject.file('build-dependecies/secret_keys.properties') } } +ktlint { + version = "0.28.0" + debug = true + verbose = true + android = true + reporter = "checkstyle" + ignoreFailures = true +} + android { signingConfigs { signing { @@ -24,45 +35,44 @@ android { storePassword((buildProperties.secrets['android_store_password'] | buildProperties.notThere['android_store_password']).string) } } - compileSdkVersion 27 - buildToolsVersion '27.0.3' + + def conf = rootProject.ext.android + + compileSdkVersion conf.compileSdkVersion + defaultConfig { - applicationId "com.fastaccess.github" - minSdkVersion 21 - targetSdkVersion 27 - versionCode 467 - versionName "4.6.7" - buildConfigString "GITHUB_CLIENT_ID", (buildProperties.secrets['github_client_id'] | buildProperties.notThere['github_client_id']).string - buildConfigString "GITHUB_SECRET", (buildProperties.secrets['github_secret'] | buildProperties.notThere['github_secret']).string - buildConfigString "IMGUR_CLIENT_ID", (buildProperties.secrets['imgur_client_id'] | buildProperties.notThere['imgur_client_id']).string - buildConfigString "IMGUR_SECRET", (buildProperties.secrets['imgur_secret'] | buildProperties.notThere['imgur_secret']).string - buildConfigField "String", "REST_URL", '"https://api.github.com/"' - buildConfigField "String", "IMGUR_URL", '"https://api.imgur.com/3/"' + applicationId conf.applicationId + minSdkVersion conf.minSdkVersion + targetSdkVersion conf.targetSdkVersion + versionCode conf.versionCode + versionName conf.versionName multiDexEnabled true - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" javaCompileOptions { annotationProcessorOptions { - includeCompileClasspath true + includeCompileClasspath = true } } + buildConfigString "REST_URL", "https://api.github.com/" + buildConfigString "GRAPHQL_REST_URL", "https://api.github.com/graphql" + buildConfigString "IMGUR_URL", "https://api.imgur.com/3/" + buildConfigString "GITHUB_CLIENT_ID", (buildProperties.secrets['github_client_id'] | buildProperties.notThere['github_client_id']).string + buildConfigString "GITHUB_SECRET", (buildProperties.secrets['github_secret'] | buildProperties.notThere['github_secret']).string + buildConfigString "IMGUR_CLIENT_ID", (buildProperties.secrets['imgur_client_id'] | buildProperties.notThere['imgur_client_id']).string + buildConfigString "IMGUR_SECRET", (buildProperties.secrets['imgur_secret'] | buildProperties.notThere['imgur_secret']).string } buildTypes { release { - minifyEnabled true - shrinkResources true - signingConfig signingConfigs.signing + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } + debug { - if (!rootProject.file('gradle.properties').exists()) { - signingConfig signingConfigs.signing - } applicationIdSuffix ".debug" versionNameSuffix "-debug" ext.alwaysUpdateBuildId = false } - } sourceSets { @@ -72,7 +82,6 @@ android { "src/main/res/layouts/main_layouts", "src/main/res/layouts/row_layouts", "src/main/res/layouts/other_layouts", - "src/main/res/translations", "src/main/res" ] } @@ -83,18 +92,14 @@ android { htmlReport true xmlReport true disable 'InvalidPackage' + check 'Interoperability' } + compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - configurations { - all*.exclude module: 'annotations' - } - - packagingOptions { exclude 'META-INF/rxjava.properties' } - dexOptions { jumboMode true javaMaxHeapSize "4g" @@ -103,89 +108,38 @@ android { testOptions { unitTests.returnDefaultValues = true } -} -kapt { - generateStubs = true -} - -repositories { - maven { url "https://clojars.org/repo/" } - maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } - maven { url "https://jitpack.io" } - maven { url 'https://maven.fabric.io/public' } + configurations { + all*.exclude module: 'javax.annotation' + } } dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation "com.android.support:appcompat-v7:${supportVersion}" - implementation "com.android.support:design:${supportVersion}" - implementation "com.android.support:cardview-v7:${supportVersion}" - implementation "com.android.support:recyclerview-v7:${supportVersion}" - implementation "com.android.support:preference-v14:${supportVersion}" - implementation "com.android.support:customtabs:${supportVersion}" - implementation "com.android.support:palette-v7:${supportVersion}" - implementation "net.grandcentrix.thirtyinch:thirtyinch:${thirtyinchVersion}" - implementation "net.grandcentrix.thirtyinch:thirtyinch-rx2:${thirtyinchVersion}" - implementation "com.squareup.retrofit2:retrofit:${retrofit}" - implementation "com.squareup.retrofit2:converter-gson:${retrofit}" - implementation "com.squareup.retrofit2:adapter-rxjava2:${retrofit}" - implementation "com.github.bumptech.glide:glide:${glideVersion}" - implementation 'cn.gavinliu.android.lib:ShapedImageView:0.8.3' - implementation "com.jakewharton:butterknife:${butterKnifeVersion}" - implementation 'it.sephiroth.android.library.bottomnavigation:bottom-navigation:2.0.2' - implementation 'io.reactivex.rxjava2:rxjava:2.1.10' - implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' - implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0' - implementation 'com.annimon:stream:1.1.9' - implementation 'com.github.GrenderG:Toasty:1.1.3' - implementation 'com.github.k0shk0sh:RetainedDateTimePickers:1.0.2' - implementation 'com.github.daniel-stoneuk:material-about-library:2.1.0' - implementation "io.requery:requery:${requery}" - implementation "io.requery:requery-android:${requery}" - implementation('com.mikepenz:aboutlibraries:5.9.7@aar') { transitive = true } - implementation 'com.github.nightwhistler:HtmlSpanner:0.4' - implementation 'net.sourceforge.htmlcleaner:htmlcleaner:2.2' - implementation 'com.github.matthiasrobbers:shortbread:1.0.1' - implementation "com.atlassian.commonmark:commonmark:${commonmark}" - implementation "com.atlassian.commonmark:commonmark-ext-autolink:${commonmark}" - implementation "com.atlassian.commonmark:commonmark-ext-gfm-strikethrough:${commonmark}" - implementation "com.atlassian.commonmark:commonmark-ext-gfm-tables:${commonmark}" - implementation "com.atlassian.commonmark:commonmark-ext-ins:${commonmark}" - implementation "com.atlassian.commonmark:commonmark-ext-yaml-front-matter:${commonmark}" - implementation "com.google.firebase:firebase-core:${gms}" - implementation "com.google.firebase:firebase-messaging:${gms}" - implementation "com.google.firebase:firebase-database:${gms}" - implementation "com.google.android.gms:play-services-base:${gms}" - implementation('com.github.b3er.rxfirebase:firebase-database-kotlin:11.2.0') { transitive = false } - implementation('com.github.b3er.rxfirebase:firebase-database:11.2.0') { transitive = false } - implementation('com.crashlytics.sdk.android:crashlytics:2.9.0@aar') { transitive = true } - implementation "com.github.miguelbcr:RxBillingService:0.0.3" - implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:${kotlin_version}" - implementation 'org.jsoup:jsoup:1.10.3' - implementation "com.evernote:android-state:${state_version}" - implementation "petrov.kristiyan:colorpicker-library:1.1.4" - implementation 'com.apollographql.apollo:apollo-rx2-support:0.4.1' - implementation 'com.jaredrummler:android-device-names:1.1.5' - implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:2.1.0' - implementation 'com.airbnb.android:lottie:2.2.5' - implementation 'com.firebase:firebase-jobdispatcher:0.8.2' - compileOnly "org.projectlombok:lombok:${lombokVersion}" - kapt "org.projectlombok:lombok:${lombokVersion}" - kapt "com.evernote:android-state-processor:${state_version}" - kapt "com.jakewharton:butterknife-compiler:${butterKnifeVersion}" - kapt 'com.github.matthiasrobbers:shortbread-compiler:1.0.1' - kapt "io.requery:requery-processor:${requery}" -// testImplementation "net.grandcentrix.thirtyinch:thirtyinch-test:$thirtyinchVersion" - testImplementation "junit:junit:${junitVersion}" - testImplementation "org.mockito:mockito-core:${mockitoVersion}" - testImplementation "org.assertj:assertj-core:${assertjVersion}" - androidTestImplementation "com.android.support:support-annotations:${supportVersion}" - androidTestImplementation "org.mockito:mockito-core:${mockitoVersion}" - androidTestImplementation 'com.android.support.test:runner:1.0.1' - androidTestImplementation 'com.android.support.test:rules:1.0.1' - androidTestImplementation "com.android.support.test.espresso:espresso-intents:${espresseVersion}" - androidTestImplementation "com.android.support.test.espresso:espresso-core:${espresseVersion}" + + def dependency = rootProject.ext + + implementation project(':data') + implementation project(':domain') + implementation project(':resources') + implementation project(':extensions') + implementation project(':markdown') + implementation project(':editor') + implementation dependency.kotlin + implementation dependency.supportLibraries + implementation dependency.extrasLibraries + implementation dependency.networking + implementation dependency.rxJava + implementation dependency.extrasLibraries + implementation dependency.dagger + implementation dependency.archs + implementation dependency.firebase + api 'com.google.guava:guava:28.0-jre' // for the sake of listenablefuture + debugImplementation dependency.developmentDependencies + releaseImplementation dependency.releaseDevelopmentDependencies + + testImplementation dependency.testing + + kapt dependency.processing } apply plugin: 'com.google.gms.google-services' \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 2ce4dd23d..f1b424510 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,140 +1,21 @@ --keepattributes SourceFile,LineNumberTable --dontobfuscate --optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable --keepattributes *Annotation*,Signature --keepclassmembers class * implements java.io.Serializable { - static final long serialVersionUID; - private static final java.io.ObjectStreamField[] serialPersistentFields; - private void writeObject(java.io.ObjectOutputStream); - private void readObject(java.io.ObjectInputStream); - java.lang.Object writeReplace(); - java.lang.Object readResolve(); -} --keepclassmembers class **.R$* { - public static ; -} --keep class * implements android.os.Parcelable { - public static final android.os.Parcelable$Creator *; -} --keep public class * implements butterknife.Unbinder { public (**, android.view.View); } --keep class butterknife.* --keepclasseswithmembernames class * { @butterknife.* ; } --keepclasseswithmembernames class * { @butterknife.* ; } --keep class retrofit.** { *; } --keepattributes Signature --keepattributes Exceptions --keepclasseswithmembers class * { - @retrofit.http.* ; -} --keep class com.google.gson.** { *; } --keep class com.google.inject.** { *; } --keep class org.apache.** { *; } --keep class javax.inject.** { *; } --keep class retrofit.** { *; } --keep class com.squareup.okhttp.** { *; } --keep interface com.squareup.okhttp.** { *; } --keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* { - long producerIndex; - long consumerIndex; -} --keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef { - long producerNode; - long consumerNode; -} --keepclasseswithmembernames class * { - native ; -} --keepclassmembers enum * { *; } --keepclassmembers enum * { - public static **[] values(); - public static ** valueOf(java.lang.String); -} --keep class **$$Icepick { *; } --keepclasseswithmembernames class * { - @icepick.* ; -} --keep class com.fastaccess.data.** { *; } --keep class com.fastaccess.provider.rest.** { *; } --keepclassmembers class com.prettifier.pretty.callback.MarkDownInterceptorInterface { - public *; -} --keepclassmembers enum io.requery.** { - public static **[] values(); - public static ** valueOf(java.lang.String); -} --keep class .R --keep class **.R$* { - ; -} --keep class net.nightwhistler.** { *; } --keep class org.htmlcleaner.** { *; } --keeppackagenames org.jsoup.nodes --keep class com.github.b3er.** { *; } --keep class com.memoizrlabs.** { *; } --keep public class * implements com.bumptech.glide.module.GlideModule --keep public class * extends com.bumptech.glide.AppGlideModule --keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { - **[] $VALUES; - public *; -} +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html --keep class com.google.android.gms.** { *; } +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} --dontwarn com.github.b3er.** --dontwarn com.memoizrlabs.** --dontwarn java.lang.FunctionalInterface --dontwarn java.util.** --dontwarn java.time.** --dontwarn javax.annotation.** --dontwarn org.jetbrains.annotations.** --dontwarn javax.cache.** --dontwarn javax.naming.** --dontwarn javax.transaction.** --dontwarn java.sql.** --dontwarn android.support.** --dontwarn io.requery.cache.** --dontwarn io.requery.rx.** --dontwarn io.requery.reactivex.** --dontwarn io.requery.reactor.** --dontwarn io.requery.query.** --dontwarn io.requery.android.sqlcipher.** --dontwarn io.requery.android.sqlitex.** --dontwarn org.jaxen.** --dontwarn org.jdom.** --dontwarn com.google.android.gms.** --dontwarn android.animation.** --dontwarn java.io.** --dontwarn android.content.** --dontwarn org.jdom.** --dontwarn kotlin.reflect.jvm.internal.impl.descriptors.CallableDescriptor --dontwarn kotlin.reflect.jvm.internal.impl.descriptors.ClassDescriptor --dontwarn kotlin.reflect.jvm.internal.impl.descriptors.ClassifierDescriptorWithTypeParameters --dontwarn kotlin.reflect.jvm.internal.impl.descriptors.annotations.AnnotationDescriptor --dontwarn kotlin.reflect.jvm.internal.impl.descriptors.impl.PropertyDescriptorImpl --dontwarn kotlin.reflect.jvm.internal.impl.load.java.JavaClassFinder --dontwarn kotlin.reflect.jvm.internal.impl.resolve.OverridingUtil --dontwarn kotlin.reflect.jvm.internal.impl.types.DescriptorSubstitutor --dontwarn kotlin.reflect.jvm.internal.impl.types.DescriptorSubstitutor --dontwarn kotlin.reflect.jvm.internal.impl.types.TypeConstructor --dontwarn java.beans.** --dontwarn javax.** --dontwarn lombok.** --dontwarn java.lang.invoke.* --dontwarn rx.** --dontwarn com.squareup.okhttp.** --dontwarn okio.** --dontwarn org.apache.** --dontwarn android.net.http.AndroidHttpClient --dontwarn retrofit.** --dontwarn retrofit2.adapter.rxjava.CompletableHelper$** --dontwarn retrofit2.Platform$Java8 --dontwarn sun.misc.** --dontwarn sun.misc.Unsafe --dontwarn com.octo.android.robospice.retrofit.RetrofitJackson** --dontwarn retrofit.appengine.UrlFetchClient --dontwarn icepick.** --dontwarn com.fastaccess.ui.modules.repos.** --dontwarn org.apache.xerces.parsers.** --dontwarn oracle.xml.** --dontwarn org.jdom.** --dontwarn okhttp3.internal.** \ No newline at end of file +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/fastaccess/helper/TestHelper.java b/app/src/androidTest/java/com/fastaccess/helper/TestHelper.java deleted file mode 100644 index 1bf730f69..000000000 --- a/app/src/androidTest/java/com/fastaccess/helper/TestHelper.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.fastaccess.helper; - -import android.support.annotation.IntRange; -import android.support.design.widget.TextInputLayout; -import android.support.test.espresso.UiController; -import android.support.test.espresso.ViewAction; -import android.view.View; - -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; - -import it.sephiroth.android.library.bottomnavigation.BottomNavigation; - -import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; - -/** - * Created by Kosh on 05 May 2017, 9:23 PM - */ - -public class TestHelper { - - public static Matcher textInputLayoutHasHint(final String expectedErrorText) { - return new TypeSafeMatcher() { - @Override public boolean matchesSafely(View view) { - if (!(view instanceof TextInputLayout)) { - return false; - } - CharSequence error = ((TextInputLayout) view).getHint(); - return error != null && expectedErrorText.equals(error.toString()); - } - - @Override public void describeTo(Description description) {} - }; - } - - public static Matcher textInputLayoutHasError(final String expectedErrorText) { - return new TypeSafeMatcher() { - @Override public boolean matchesSafely(View view) { - if (!(view instanceof TextInputLayout)) { - return false; - } - CharSequence error = ((TextInputLayout) view).getError(); - return error != null && expectedErrorText.equals(error.toString()); - } - - @Override public void describeTo(Description description) {} - }; - } - - public static Matcher bottomNavSelection(@IntRange(from = 0, to = 3) final int position) { - return new TypeSafeMatcher() { - @Override public boolean matchesSafely(View view) { - return view instanceof BottomNavigation && position == ((BottomNavigation) view).getSelectedIndex(); - } - - @Override public void describeTo(Description description) {} - }; - } - - public static ViewAction bottomNavAction(@IntRange(from = 0, to = 3) final int index) { - return new ViewAction() { - - @Override public Matcher getConstraints() { - return isAssignableFrom(BottomNavigation.class); - } - - @Override public String getDescription() { - return "BottomNavigation"; - } - - @Override public void perform(UiController uiController, View view) { - ((BottomNavigation) view).setSelectedIndex(index, false); - } - }; - } -} diff --git a/app/src/androidTest/java/com/fastaccess/ui/modules/login/LoginActivityTest.java b/app/src/androidTest/java/com/fastaccess/ui/modules/login/LoginActivityTest.java deleted file mode 100644 index e10fd0931..000000000 --- a/app/src/androidTest/java/com/fastaccess/ui/modules/login/LoginActivityTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.fastaccess.ui.modules.login; - - -import android.support.test.filters.LargeTest; -import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; - -import com.fastaccess.R; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard; -import static android.support.test.espresso.action.ViewActions.typeText; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static com.fastaccess.helper.TestHelper.textInputLayoutHasError; -import static org.hamcrest.core.IsNot.not; - -@RunWith(AndroidJUnit4.class) @LargeTest -public class LoginActivityTest { - - @Rule public ActivityTestRule testRule = new ActivityTestRule<>(LoginActivity.class); - - @Test public void successLoginClickSuccessTest() { - String username = "username"; - String password = "password"; - onView(withId(R.id.usernameEditText)).perform(typeText(username), closeSoftKeyboard()); - onView(withId(R.id.passwordEditText)).perform(typeText(password), closeSoftKeyboard()); - onView(withId(R.id.login)).perform(click()); - onView(withId(R.id.progress)).check(matches(isDisplayed())); - } - - @Test public void usernameErrorTest() { - String password = "password"; - onView(withId(R.id.passwordEditText)).perform(typeText(password), closeSoftKeyboard()); - onView(withId(R.id.login)).perform(click()); - onView(withId(R.id.progress)).check(matches(not(isDisplayed()))); - onView(withId(R.id.username)).check(matches(textInputLayoutHasError(testRule.getActivity().getString(R.string.required_field)))); - } - - @Test public void passwordErrorTest() { - String username = "username"; - onView(withId(R.id.usernameEditText)).perform(typeText(username), closeSoftKeyboard()); - onView(withId(R.id.login)).perform(click()); - onView(withId(R.id.progress)).check(matches(not(isDisplayed()))); - onView(withId(R.id.password)).check(matches(textInputLayoutHasError(testRule.getActivity().getString(R.string.required_field)))); - } - -} \ No newline at end of file diff --git a/app/src/androidTest/java/com/fastaccess/ui/modules/login/LoginChooserActivityTest.java b/app/src/androidTest/java/com/fastaccess/ui/modules/login/LoginChooserActivityTest.java deleted file mode 100644 index 940fb3d8b..000000000 --- a/app/src/androidTest/java/com/fastaccess/ui/modules/login/LoginChooserActivityTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fastaccess.ui.modules.login; - - -import android.support.test.espresso.intent.rule.IntentsTestRule; -import android.support.test.filters.LargeTest; -import android.support.test.runner.AndroidJUnit4; - -import com.fastaccess.R; -import com.fastaccess.ui.modules.login.chooser.LoginChooserActivity; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.intent.Intents.intended; -import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static com.fastaccess.helper.TestHelper.textInputLayoutHasHint; - -@RunWith(AndroidJUnit4.class) @LargeTest -public class LoginChooserActivityTest { - - @Rule public IntentsTestRule intentTestRule = new IntentsTestRule<>(LoginChooserActivity.class); - - @Test public void basicAuthButtonTest() { - onView(withId(R.id.basicAuth)).perform(click()); - intended(hasComponent(LoginActivity.class.getName())); - onView(withId(R.id.password)).check(matches(textInputLayoutHasHint(intentTestRule.getActivity().getString(R.string.password)))); - } - - @Test public void accessTokenButtonTest() { - onView(withId(R.id.accessToken)).perform(click()); - intended(hasComponent(LoginActivity.class.getName())); - onView(withId(R.id.password)).check(matches(textInputLayoutHasHint(intentTestRule.getActivity().getString(R.string.access_token)))); - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/com/fastaccess/ui/modules/main/MainActivityTest.java b/app/src/androidTest/java/com/fastaccess/ui/modules/main/MainActivityTest.java deleted file mode 100644 index c51e7b5a7..000000000 --- a/app/src/androidTest/java/com/fastaccess/ui/modules/main/MainActivityTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.fastaccess.ui.modules.main; - -import android.support.test.espresso.intent.rule.IntentsTestRule; - -import com.fastaccess.R; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.ui.modules.feeds.FeedsFragment; -import com.fastaccess.ui.modules.login.chooser.LoginChooserActivity; -import com.fastaccess.ui.modules.main.issues.pager.MyIssuesPagerFragment; -import com.fastaccess.ui.modules.main.pullrequests.pager.MyPullsPagerFragment; -import com.fastaccess.ui.modules.notification.NotificationActivity; -import com.fastaccess.ui.modules.search.SearchActivity; - -import org.junit.Rule; -import org.junit.Test; - -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.assertion.ViewAssertions.matches; -import static android.support.test.espresso.intent.Intents.intended; -import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static com.fastaccess.helper.TestHelper.bottomNavAction; -import static com.fastaccess.helper.TestHelper.bottomNavSelection; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -/** - * Created by Kosh on 06 May 2017, 2:11 AM - */ - -public class MainActivityTest { - @Rule public IntentsTestRule testRule = new IntentsTestRule<>(MainActivity.class); - - @Test public void noUserTest() { - assertEquals(testRule.getActivity().isLoggedIn(), false); - intended(hasComponent(LoginChooserActivity.class.getName())); - } - - @Test public void onInitTest() { - assertEquals(testRule.getActivity().isLoggedIn(), true); - onView(withId(R.id.bottomNavigation)).check(matches(bottomNavSelection(0))); - assertNotNull(AppHelper.getFragmentByTag(testRule.getActivity().getSupportFragmentManager(), FeedsFragment.TAG)); - } - - @Test public void onSelectIssuesTabTest() { - assertEquals(testRule.getActivity().isLoggedIn(), true); - onView(withId(R.id.bottomNavigation)).perform(bottomNavAction(1)) - .check(matches(bottomNavSelection(1))); - assertNotNull(AppHelper.getFragmentByTag(testRule.getActivity().getSupportFragmentManager(), MyIssuesPagerFragment.TAG)); - } - - @Test public void onSelectPullRequestsTabTest() { - assertEquals(testRule.getActivity().isLoggedIn(), true); - onView(withId(R.id.bottomNavigation)).perform(bottomNavAction(2)) - .check(matches(bottomNavSelection(2))); - assertNotNull(AppHelper.getFragmentByTag(testRule.getActivity().getSupportFragmentManager(), MyPullsPagerFragment.TAG)); - } - - @Test public void startNotificationsIntentTest() { - onView(withId(R.id.notifications)).perform(click()); - intended(hasComponent(NotificationActivity.class.getName())); - } - - @Test public void startSearchIntentTest() { - onView(withId(R.id.search)).perform(click()); - intended(hasComponent(SearchActivity.class.getName())); - } -} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cc5ddefb3..ac143765d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,329 +1,135 @@ - + - - - - - - - - - + + + + + + - - - - - + + + + + + - + - - + + + android:scheme="fasthub" /> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:name=".ui.modules.profile.ProfileActivity" + android:parentActivityName=".ui.modules.main.MainActivity" /> + - - - - - - - - - - - - - - - - + android:parentActivityName=".ui.modules.main.MainActivity" /> + - - + android:name="com.fastaccess.github.ui.modules.multipurpose.MultiPurposeActivity" + android:parentActivityName=".ui.modules.main.MainActivity" /> - + - - + android:name=".ui.modules.editor.EditorWebViewActivity" + android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation" /> + - + + + + + + android:scheme="http" /> + android:scheme="https" /> + android:scheme="http" /> + android:scheme="https" /> + android:scheme="https" /> - + android:scheme="https" /> + + - - + + - + - + - + - - - - - - - - - - - - - - - + + + + android:value="6ed82b6e0756853d7d782a3f547f84f9ecba217e" /> + \ No newline at end of file diff --git a/app/src/main/assets/colors.json b/app/src/main/assets/colors.json deleted file mode 100644 index feea8cf8f..000000000 --- a/app/src/main/assets/colors.json +++ /dev/null @@ -1,1394 +0,0 @@ -{ - "1C Enterprise": { - "color": "#814CCC", - "url": "https://github.com/trending?l=1C-Enterprise" - }, - "ABAP": { - "color": "#E8274B", - "url": "https://github.com/trending?l=ABAP" - }, - "ActionScript": { - "color": "#882B0F", - "url": "https://github.com/trending?l=ActionScript" - }, - "Ada": { - "color": "#02f88c", - "url": "https://github.com/trending?l=Ada" - }, - "Agda": { - "color": "#315665", - "url": "https://github.com/trending?l=Agda" - }, - "AGS Script": { - "color": "#B9D9FF", - "url": "https://github.com/trending?l=AGS-Script" - }, - "Alloy": { - "color": "#64C800", - "url": "https://github.com/trending?l=Alloy" - }, - "Alpine Abuild": { - "color": null, - "url": "https://github.com/trending?l=Alpine-Abuild" - }, - "AMPL": { - "color": "#E6EFBB", - "url": "https://github.com/trending?l=AMPL" - }, - "ANTLR": { - "color": "#9DC3FF", - "url": "https://github.com/trending?l=ANTLR" - }, - "Apex": { - "color": null, - "url": "https://github.com/trending?l=Apex" - }, - "API Blueprint": { - "color": "#2ACCA8", - "url": "https://github.com/trending?l=API-Blueprint" - }, - "APL": { - "color": "#5A8164", - "url": "https://github.com/trending?l=APL" - }, - "Apollo Guidance Computer": { - "color": null, - "url": "https://github.com/trending?l=Apollo-Guidance-Computer" - }, - "AppleScript": { - "color": "#101F1F", - "url": "https://github.com/trending?l=AppleScript" - }, - "Arc": { - "color": "#aa2afe", - "url": "https://github.com/trending?l=Arc" - }, - "Arduino": { - "color": "#bd79d1", - "url": "https://github.com/trending?l=Arduino" - }, - "ASP": { - "color": "#6a40fd", - "url": "https://github.com/trending?l=ASP" - }, - "AspectJ": { - "color": "#a957b0", - "url": "https://github.com/trending?l=AspectJ" - }, - "Assembly": { - "color": "#6E4C13", - "url": "https://github.com/trending?l=Assembly" - }, - "ATS": { - "color": "#1ac620", - "url": "https://github.com/trending?l=ATS" - }, - "Augeas": { - "color": null, - "url": "https://github.com/trending?l=Augeas" - }, - "AutoHotkey": { - "color": "#6594b9", - "url": "https://github.com/trending?l=AutoHotkey" - }, - "AutoIt": { - "color": "#1C3552", - "url": "https://github.com/trending?l=AutoIt" - }, - "Awk": { - "color": null, - "url": "https://github.com/trending?l=Awk" - }, - "Batchfile": { - "color": "#C1F12E", - "url": "https://github.com/trending?l=Batchfile" - }, - "Befunge": { - "color": null, - "url": "https://github.com/trending?l=Befunge" - }, - "Bison": { - "color": null, - "url": "https://github.com/trending?l=Bison" - }, - "BitBake": { - "color": null, - "url": "https://github.com/trending?l=BitBake" - }, - "BlitzBasic": { - "color": null, - "url": "https://github.com/trending?l=BlitzBasic" - }, - "BlitzMax": { - "color": "#cd6400", - "url": "https://github.com/trending?l=BlitzMax" - }, - "Bluespec": { - "color": null, - "url": "https://github.com/trending?l=Bluespec" - }, - "Boo": { - "color": "#d4bec1", - "url": "https://github.com/trending?l=Boo" - }, - "Brainfuck": { - "color": "#2F2530", - "url": "https://github.com/trending?l=Brainfuck" - }, - "Brightscript": { - "color": null, - "url": "https://github.com/trending?l=Brightscript" - }, - "Bro": { - "color": null, - "url": "https://github.com/trending?l=Bro" - }, - "C": { - "color": "#555555", - "url": "https://github.com/trending?l=C" - }, - "C#": { - "color": "#178600", - "url": "https://github.com/trending?l=C#" - }, - "C++": { - "color": "#f34b7d", - "url": "https://github.com/trending?l=C++" - }, - "C2hs Haskell": { - "color": null, - "url": "https://github.com/trending?l=C2hs-Haskell" - }, - "Cap'n Proto": { - "color": null, - "url": "https://github.com/trending?l=Cap'n-Proto" - }, - "CartoCSS": { - "color": null, - "url": "https://github.com/trending?l=CartoCSS" - }, - "Ceylon": { - "color": null, - "url": "https://github.com/trending?l=Ceylon" - }, - "Chapel": { - "color": "#8dc63f", - "url": "https://github.com/trending?l=Chapel" - }, - "Charity": { - "color": null, - "url": "https://github.com/trending?l=Charity" - }, - "ChucK": { - "color": null, - "url": "https://github.com/trending?l=ChucK" - }, - "Cirru": { - "color": "#ccccff", - "url": "https://github.com/trending?l=Cirru" - }, - "Clarion": { - "color": "#db901e", - "url": "https://github.com/trending?l=Clarion" - }, - "Clean": { - "color": "#3F85AF", - "url": "https://github.com/trending?l=Clean" - }, - "Click": { - "color": "#E4E6F3", - "url": "https://github.com/trending?l=Click" - }, - "CLIPS": { - "color": null, - "url": "https://github.com/trending?l=CLIPS" - }, - "Clojure": { - "color": "#db5855", - "url": "https://github.com/trending?l=Clojure" - }, - "CMake": { - "color": null, - "url": "https://github.com/trending?l=CMake" - }, - "COBOL": { - "color": null, - "url": "https://github.com/trending?l=COBOL" - }, - "CoffeeScript": { - "color": "#244776", - "url": "https://github.com/trending?l=CoffeeScript" - }, - "ColdFusion": { - "color": "#ed2cd6", - "url": "https://github.com/trending?l=ColdFusion" - }, - "ColdFusion CFC": { - "color": null, - "url": "https://github.com/trending?l=ColdFusion-CFC" - }, - "Common Lisp": { - "color": "#3fb68b", - "url": "https://github.com/trending?l=Common-Lisp" - }, - "Component Pascal": { - "color": "#B0CE4E", - "url": "https://github.com/trending?l=Component-Pascal" - }, - "Cool": { - "color": null, - "url": "https://github.com/trending?l=Cool" - }, - "Coq": { - "color": null, - "url": "https://github.com/trending?l=Coq" - }, - "Crystal": { - "color": "#776791", - "url": "https://github.com/trending?l=Crystal" - }, - "Csound": { - "color": null, - "url": "https://github.com/trending?l=Csound" - }, - "Csound Document": { - "color": null, - "url": "https://github.com/trending?l=Csound-Document" - }, - "Csound Score": { - "color": null, - "url": "https://github.com/trending?l=Csound-Score" - }, - "CSS": { - "color": "#563d7c", - "url": "https://github.com/trending?l=CSS" - }, - "Cuda": { - "color": "#3A4E3A", - "url": "https://github.com/trending?l=Cuda" - }, - "Cycript": { - "color": null, - "url": "https://github.com/trending?l=Cycript" - }, - "Cython": { - "color": null, - "url": "https://github.com/trending?l=Cython" - }, - "D": { - "color": "#ba595e", - "url": "https://github.com/trending?l=D" - }, - "Dart": { - "color": "#00B4AB", - "url": "https://github.com/trending?l=Dart" - }, - "DIGITAL Command Language": { - "color": null, - "url": "https://github.com/trending?l=DIGITAL-Command-Language" - }, - "DM": { - "color": "#447265", - "url": "https://github.com/trending?l=DM" - }, - "Dogescript": { - "color": "#cca760", - "url": "https://github.com/trending?l=Dogescript" - }, - "DTrace": { - "color": null, - "url": "https://github.com/trending?l=DTrace" - }, - "Dylan": { - "color": "#6c616e", - "url": "https://github.com/trending?l=Dylan" - }, - "E": { - "color": "#ccce35", - "url": "https://github.com/trending?l=E" - }, - "Eagle": { - "color": "#814C05", - "url": "https://github.com/trending?l=Eagle" - }, - "eC": { - "color": "#913960", - "url": "https://github.com/trending?l=eC" - }, - "ECL": { - "color": "#8a1267", - "url": "https://github.com/trending?l=ECL" - }, - "ECLiPSe": { - "color": null, - "url": "https://github.com/trending?l=ECLiPSe" - }, - "Eiffel": { - "color": "#946d57", - "url": "https://github.com/trending?l=Eiffel" - }, - "Elixir": { - "color": "#6e4a7e", - "url": "https://github.com/trending?l=Elixir" - }, - "Elm": { - "color": "#60B5CC", - "url": "https://github.com/trending?l=Elm" - }, - "Emacs Lisp": { - "color": "#c065db", - "url": "https://github.com/trending?l=Emacs-Lisp" - }, - "EmberScript": { - "color": "#FFF4F3", - "url": "https://github.com/trending?l=EmberScript" - }, - "EQ": { - "color": "#a78649", - "url": "https://github.com/trending?l=EQ" - }, - "Erlang": { - "color": "#B83998", - "url": "https://github.com/trending?l=Erlang" - }, - "F#": { - "color": "#b845fc", - "url": "https://github.com/trending?l=F#" - }, - "Factor": { - "color": "#636746", - "url": "https://github.com/trending?l=Factor" - }, - "Fancy": { - "color": "#7b9db4", - "url": "https://github.com/trending?l=Fancy" - }, - "Fantom": { - "color": "#14253c", - "url": "https://github.com/trending?l=Fantom" - }, - "Filebench WML": { - "color": null, - "url": "https://github.com/trending?l=Filebench-WML" - }, - "Filterscript": { - "color": null, - "url": "https://github.com/trending?l=Filterscript" - }, - "fish": { - "color": null, - "url": "https://github.com/trending?l=fish" - }, - "FLUX": { - "color": "#88ccff", - "url": "https://github.com/trending?l=FLUX" - }, - "Forth": { - "color": "#341708", - "url": "https://github.com/trending?l=Forth" - }, - "Fortran": { - "color": "#4d41b1", - "url": "https://github.com/trending?l=Fortran" - }, - "FreeMarker": { - "color": "#0050b2", - "url": "https://github.com/trending?l=FreeMarker" - }, - "Frege": { - "color": "#00cafe", - "url": "https://github.com/trending?l=Frege" - }, - "Game Maker Language": { - "color": "#8fb200", - "url": "https://github.com/trending?l=Game-Maker-Language" - }, - "GAMS": { - "color": null, - "url": "https://github.com/trending?l=GAMS" - }, - "GAP": { - "color": null, - "url": "https://github.com/trending?l=GAP" - }, - "GCC Machine Description": { - "color": null, - "url": "https://github.com/trending?l=GCC-Machine-Description" - }, - "GDB": { - "color": null, - "url": "https://github.com/trending?l=GDB" - }, - "GDScript": { - "color": null, - "url": "https://github.com/trending?l=GDScript" - }, - "Genie": { - "color": "#fb855d", - "url": "https://github.com/trending?l=Genie" - }, - "Genshi": { - "color": null, - "url": "https://github.com/trending?l=Genshi" - }, - "Gentoo Ebuild": { - "color": null, - "url": "https://github.com/trending?l=Gentoo-Ebuild" - }, - "Gentoo Eclass": { - "color": null, - "url": "https://github.com/trending?l=Gentoo-Eclass" - }, - "Gherkin": { - "color": "#5B2063", - "url": "https://github.com/trending?l=Gherkin" - }, - "GLSL": { - "color": null, - "url": "https://github.com/trending?l=GLSL" - }, - "Glyph": { - "color": "#e4cc98", - "url": "https://github.com/trending?l=Glyph" - }, - "Gnuplot": { - "color": "#f0a9f0", - "url": "https://github.com/trending?l=Gnuplot" - }, - "Go": { - "color": "#375eab", - "url": "https://github.com/trending?l=Go" - }, - "Golo": { - "color": "#88562A", - "url": "https://github.com/trending?l=Golo" - }, - "Gosu": { - "color": "#82937f", - "url": "https://github.com/trending?l=Gosu" - }, - "Grace": { - "color": null, - "url": "https://github.com/trending?l=Grace" - }, - "Grammatical Framework": { - "color": "#79aa7a", - "url": "https://github.com/trending?l=Grammatical-Framework" - }, - "Groovy": { - "color": "#e69f56", - "url": "https://github.com/trending?l=Groovy" - }, - "Groovy Server Pages": { - "color": null, - "url": "https://github.com/trending?l=Groovy-Server-Pages" - }, - "Hack": { - "color": "#878787", - "url": "https://github.com/trending?l=Hack" - }, - "Harbour": { - "color": "#0e60e3", - "url": "https://github.com/trending?l=Harbour" - }, - "Haskell": { - "color": "#5e5086", - "url": "https://github.com/trending?l=Haskell" - }, - "Haxe": { - "color": "#df7900", - "url": "https://github.com/trending?l=Haxe" - }, - "HCL": { - "color": null, - "url": "https://github.com/trending?l=HCL" - }, - "HLSL": { - "color": null, - "url": "https://github.com/trending?l=HLSL" - }, - "HTML": { - "color": "#e34c26", - "url": "https://github.com/trending?l=HTML" - }, - "Hy": { - "color": "#7790B2", - "url": "https://github.com/trending?l=Hy" - }, - "HyPhy": { - "color": null, - "url": "https://github.com/trending?l=HyPhy" - }, - "IDL": { - "color": "#a3522f", - "url": "https://github.com/trending?l=IDL" - }, - "Idris": { - "color": null, - "url": "https://github.com/trending?l=Idris" - }, - "IGOR Pro": { - "color": null, - "url": "https://github.com/trending?l=IGOR-Pro" - }, - "Inform 7": { - "color": null, - "url": "https://github.com/trending?l=Inform-7" - }, - "Inno Setup": { - "color": null, - "url": "https://github.com/trending?l=Inno-Setup" - }, - "Io": { - "color": "#a9188d", - "url": "https://github.com/trending?l=Io" - }, - "Ioke": { - "color": "#078193", - "url": "https://github.com/trending?l=Ioke" - }, - "Isabelle": { - "color": "#FEFE00", - "url": "https://github.com/trending?l=Isabelle" - }, - "Isabelle ROOT": { - "color": null, - "url": "https://github.com/trending?l=Isabelle-ROOT" - }, - "J": { - "color": "#9EEDFF", - "url": "https://github.com/trending?l=J" - }, - "Jasmin": { - "color": null, - "url": "https://github.com/trending?l=Jasmin" - }, - "Java": { - "color": "#b07219", - "url": "https://github.com/trending?l=Java" - }, - "Java Server Pages": { - "color": null, - "url": "https://github.com/trending?l=Java-Server-Pages" - }, - "JavaScript": { - "color": "#f1e05a", - "url": "https://github.com/trending?l=JavaScript" - }, - "JFlex": { - "color": null, - "url": "https://github.com/trending?l=JFlex" - }, - "Jison": { - "color": null, - "url": "https://github.com/trending?l=Jison" - }, - "Jison Lex": { - "color": null, - "url": "https://github.com/trending?l=Jison-Lex" - }, - "Jolie": { - "color": "#843179", - "url": "https://github.com/trending?l=Jolie" - }, - "JSONiq": { - "color": "#40d47e", - "url": "https://github.com/trending?l=JSONiq" - }, - "JSX": { - "color": null, - "url": "https://github.com/trending?l=JSX" - }, - "Julia": { - "color": "#a270ba", - "url": "https://github.com/trending?l=Julia" - }, - "Jupyter Notebook": { - "color": "#DA5B0B", - "url": "https://github.com/trending?l=Jupyter-Notebook" - }, - "KiCad": { - "color": null, - "url": "https://github.com/trending?l=KiCad" - }, - "Kotlin": { - "color": "#F18E33", - "url": "https://github.com/trending?l=Kotlin" - }, - "KRL": { - "color": "#28431f", - "url": "https://github.com/trending?l=KRL" - }, - "LabVIEW": { - "color": null, - "url": "https://github.com/trending?l=LabVIEW" - }, - "Lasso": { - "color": "#999999", - "url": "https://github.com/trending?l=Lasso" - }, - "Lean": { - "color": null, - "url": "https://github.com/trending?l=Lean" - }, - "Lex": { - "color": "#DBCA00", - "url": "https://github.com/trending?l=Lex" - }, - "LFE": { - "color": null, - "url": "https://github.com/trending?l=LFE" - }, - "LilyPond": { - "color": null, - "url": "https://github.com/trending?l=LilyPond" - }, - "Limbo": { - "color": null, - "url": "https://github.com/trending?l=Limbo" - }, - "Literate Agda": { - "color": null, - "url": "https://github.com/trending?l=Literate-Agda" - }, - "Literate CoffeeScript": { - "color": null, - "url": "https://github.com/trending?l=Literate-CoffeeScript" - }, - "Literate Haskell": { - "color": null, - "url": "https://github.com/trending?l=Literate-Haskell" - }, - "LiveScript": { - "color": "#499886", - "url": "https://github.com/trending?l=LiveScript" - }, - "LLVM": { - "color": "#185619", - "url": "https://github.com/trending?l=LLVM" - }, - "Logos": { - "color": null, - "url": "https://github.com/trending?l=Logos" - }, - "Logtalk": { - "color": null, - "url": "https://github.com/trending?l=Logtalk" - }, - "LOLCODE": { - "color": "#cc9900", - "url": "https://github.com/trending?l=LOLCODE" - }, - "LookML": { - "color": "#652B81", - "url": "https://github.com/trending?l=LookML" - }, - "LoomScript": { - "color": null, - "url": "https://github.com/trending?l=LoomScript" - }, - "LSL": { - "color": "#3d9970", - "url": "https://github.com/trending?l=LSL" - }, - "Lua": { - "color": "#000080", - "url": "https://github.com/trending?l=Lua" - }, - "M": { - "color": null, - "url": "https://github.com/trending?l=M" - }, - "M4": { - "color": null, - "url": "https://github.com/trending?l=M4" - }, - "M4Sugar": { - "color": null, - "url": "https://github.com/trending?l=M4Sugar" - }, - "Makefile": { - "color": "#427819", - "url": "https://github.com/trending?l=Makefile" - }, - "Mako": { - "color": null, - "url": "https://github.com/trending?l=Mako" - }, - "Mask": { - "color": "#f97732", - "url": "https://github.com/trending?l=Mask" - }, - "Mathematica": { - "color": null, - "url": "https://github.com/trending?l=Mathematica" - }, - "Matlab": { - "color": "#bb92ac", - "url": "https://github.com/trending?l=Matlab" - }, - "Max": { - "color": "#c4a79c", - "url": "https://github.com/trending?l=Max" - }, - "MAXScript": { - "color": "#00a6a6", - "url": "https://github.com/trending?l=MAXScript" - }, - "Mercury": { - "color": "#ff2b2b", - "url": "https://github.com/trending?l=Mercury" - }, - "Meson": { - "color": "#007800", - "url": "https://github.com/trending?l=Meson" - }, - "Metal": { - "color": "#8f14e9", - "url": "https://github.com/trending?l=Metal" - }, - "MiniD": { - "color": null, - "url": "https://github.com/trending?l=MiniD" - }, - "Mirah": { - "color": "#c7a938", - "url": "https://github.com/trending?l=Mirah" - }, - "Modelica": { - "color": null, - "url": "https://github.com/trending?l=Modelica" - }, - "Modula-2": { - "color": null, - "url": "https://github.com/trending?l=Modula-2" - }, - "Module Management System": { - "color": null, - "url": "https://github.com/trending?l=Module-Management-System" - }, - "Monkey": { - "color": null, - "url": "https://github.com/trending?l=Monkey" - }, - "Moocode": { - "color": null, - "url": "https://github.com/trending?l=Moocode" - }, - "MoonScript": { - "color": null, - "url": "https://github.com/trending?l=MoonScript" - }, - "MQL4": { - "color": "#62A8D6", - "url": "https://github.com/trending?l=MQL4" - }, - "MQL5": { - "color": "#4A76B8", - "url": "https://github.com/trending?l=MQL5" - }, - "MTML": { - "color": "#b7e1f4", - "url": "https://github.com/trending?l=MTML" - }, - "MUF": { - "color": null, - "url": "https://github.com/trending?l=MUF" - }, - "mupad": { - "color": null, - "url": "https://github.com/trending?l=mupad" - }, - "Myghty": { - "color": null, - "url": "https://github.com/trending?l=Myghty" - }, - "NCL": { - "color": "#28431f", - "url": "https://github.com/trending?l=NCL" - }, - "Nemerle": { - "color": "#3d3c6e", - "url": "https://github.com/trending?l=Nemerle" - }, - "nesC": { - "color": "#94B0C7", - "url": "https://github.com/trending?l=nesC" - }, - "NetLinx": { - "color": "#0aa0ff", - "url": "https://github.com/trending?l=NetLinx" - }, - "NetLinx+ERB": { - "color": "#747faa", - "url": "https://github.com/trending?l=NetLinx+ERB" - }, - "NetLogo": { - "color": "#ff6375", - "url": "https://github.com/trending?l=NetLogo" - }, - "NewLisp": { - "color": "#87AED7", - "url": "https://github.com/trending?l=NewLisp" - }, - "Nginx": { - "color": "#9469E9", - "url": "https://github.com/trending?l=Nginx" - }, - "Nim": { - "color": "#37775b", - "url": "https://github.com/trending?l=Nim" - }, - "Nit": { - "color": "#009917", - "url": "https://github.com/trending?l=Nit" - }, - "Nix": { - "color": "#7e7eff", - "url": "https://github.com/trending?l=Nix" - }, - "NSIS": { - "color": null, - "url": "https://github.com/trending?l=NSIS" - }, - "Nu": { - "color": "#c9df40", - "url": "https://github.com/trending?l=Nu" - }, - "NumPy": { - "color": null, - "url": "https://github.com/trending?l=NumPy" - }, - "Objective-C": { - "color": "#438eff", - "url": "https://github.com/trending?l=Objective-C" - }, - "Objective-C++": { - "color": "#6866fb", - "url": "https://github.com/trending?l=Objective-C++" - }, - "Objective-J": { - "color": "#ff0c5a", - "url": "https://github.com/trending?l=Objective-J" - }, - "OCaml": { - "color": "#3be133", - "url": "https://github.com/trending?l=OCaml" - }, - "Omgrofl": { - "color": "#cabbff", - "url": "https://github.com/trending?l=Omgrofl" - }, - "ooc": { - "color": "#b0b77e", - "url": "https://github.com/trending?l=ooc" - }, - "Opa": { - "color": null, - "url": "https://github.com/trending?l=Opa" - }, - "Opal": { - "color": "#f7ede0", - "url": "https://github.com/trending?l=Opal" - }, - "OpenCL": { - "color": null, - "url": "https://github.com/trending?l=OpenCL" - }, - "OpenEdge ABL": { - "color": null, - "url": "https://github.com/trending?l=OpenEdge-ABL" - }, - "OpenRC runscript": { - "color": null, - "url": "https://github.com/trending?l=OpenRC-runscript" - }, - "OpenSCAD": { - "color": null, - "url": "https://github.com/trending?l=OpenSCAD" - }, - "Ox": { - "color": null, - "url": "https://github.com/trending?l=Ox" - }, - "Oxygene": { - "color": "#cdd0e3", - "url": "https://github.com/trending?l=Oxygene" - }, - "Oz": { - "color": "#fab738", - "url": "https://github.com/trending?l=Oz" - }, - "P4": { - "color": "#7055b5", - "url": "https://github.com/trending?l=P4" - }, - "Pan": { - "color": "#cc0000", - "url": "https://github.com/trending?l=Pan" - }, - "Papyrus": { - "color": "#6600cc", - "url": "https://github.com/trending?l=Papyrus" - }, - "Parrot": { - "color": "#f3ca0a", - "url": "https://github.com/trending?l=Parrot" - }, - "Parrot Assembly": { - "color": null, - "url": "https://github.com/trending?l=Parrot-Assembly" - }, - "Parrot Internal Representation": { - "color": null, - "url": "https://github.com/trending?l=Parrot-Internal-Representation" - }, - "Pascal": { - "color": "#E3F171", - "url": "https://github.com/trending?l=Pascal" - }, - "PAWN": { - "color": "#dbb284", - "url": "https://github.com/trending?l=PAWN" - }, - "Perl": { - "color": "#0298c3", - "url": "https://github.com/trending?l=Perl" - }, - "Perl6": { - "color": "#0000fb", - "url": "https://github.com/trending?l=Perl6" - }, - "PHP": { - "color": "#4F5D95", - "url": "https://github.com/trending?l=PHP" - }, - "PicoLisp": { - "color": null, - "url": "https://github.com/trending?l=PicoLisp" - }, - "PigLatin": { - "color": "#fcd7de", - "url": "https://github.com/trending?l=PigLatin" - }, - "Pike": { - "color": "#005390", - "url": "https://github.com/trending?l=Pike" - }, - "PLpgSQL": { - "color": null, - "url": "https://github.com/trending?l=PLpgSQL" - }, - "PLSQL": { - "color": "#dad8d8", - "url": "https://github.com/trending?l=PLSQL" - }, - "PogoScript": { - "color": "#d80074", - "url": "https://github.com/trending?l=PogoScript" - }, - "Pony": { - "color": null, - "url": "https://github.com/trending?l=Pony" - }, - "PostScript": { - "color": "#da291c", - "url": "https://github.com/trending?l=PostScript" - }, - "POV-Ray SDL": { - "color": null, - "url": "https://github.com/trending?l=POV-Ray-SDL" - }, - "PowerBuilder": { - "color": "#8f0f8d", - "url": "https://github.com/trending?l=PowerBuilder" - }, - "PowerShell": { - "color": "#012456", - "url": "https://github.com/trending?l=PowerShell" - }, - "Processing": { - "color": "#0096D8", - "url": "https://github.com/trending?l=Processing" - }, - "Prolog": { - "color": "#74283c", - "url": "https://github.com/trending?l=Prolog" - }, - "Propeller Spin": { - "color": "#7fa2a7", - "url": "https://github.com/trending?l=Propeller-Spin" - }, - "Puppet": { - "color": "#302B6D", - "url": "https://github.com/trending?l=Puppet" - }, - "Pure Data": { - "color": "#91de79", - "url": "https://github.com/trending?l=Pure-Data" - }, - "PureBasic": { - "color": "#5a6986", - "url": "https://github.com/trending?l=PureBasic" - }, - "PureScript": { - "color": "#1D222D", - "url": "https://github.com/trending?l=PureScript" - }, - "Python": { - "color": "#3572A5", - "url": "https://github.com/trending?l=Python" - }, - "Python console": { - "color": null, - "url": "https://github.com/trending?l=Python-console" - }, - "QMake": { - "color": null, - "url": "https://github.com/trending?l=QMake" - }, - "QML": { - "color": "#44a51c", - "url": "https://github.com/trending?l=QML" - }, - "R": { - "color": "#198CE7", - "url": "https://github.com/trending?l=R" - }, - "Racket": { - "color": "#22228f", - "url": "https://github.com/trending?l=Racket" - }, - "Ragel": { - "color": "#9d5200", - "url": "https://github.com/trending?l=Ragel" - }, - "RAML": { - "color": "#77d9fb", - "url": "https://github.com/trending?l=RAML" - }, - "Rascal": { - "color": "#fffaa0", - "url": "https://github.com/trending?l=Rascal" - }, - "REALbasic": { - "color": null, - "url": "https://github.com/trending?l=REALbasic" - }, - "Reason": { - "color": null, - "url": "https://github.com/trending?l=Reason" - }, - "Rebol": { - "color": "#358a5b", - "url": "https://github.com/trending?l=Rebol" - }, - "Red": { - "color": "#f50000", - "url": "https://github.com/trending?l=Red" - }, - "Redcode": { - "color": null, - "url": "https://github.com/trending?l=Redcode" - }, - "Ren'Py": { - "color": "#ff7f7f", - "url": "https://github.com/trending?l=Ren'Py" - }, - "RenderScript": { - "color": null, - "url": "https://github.com/trending?l=RenderScript" - }, - "REXX": { - "color": null, - "url": "https://github.com/trending?l=REXX" - }, - "RobotFramework": { - "color": null, - "url": "https://github.com/trending?l=RobotFramework" - }, - "Roff": { - "color": "#ecdebe", - "url": "https://github.com/trending?l=Roff" - }, - "Rouge": { - "color": "#cc0088", - "url": "https://github.com/trending?l=Rouge" - }, - "Ruby": { - "color": "#701516", - "url": "https://github.com/trending?l=Ruby" - }, - "RUNOFF": { - "color": "#665a4e", - "url": "https://github.com/trending?l=RUNOFF" - }, - "Rust": { - "color": "#dea584", - "url": "https://github.com/trending?l=Rust" - }, - "Sage": { - "color": null, - "url": "https://github.com/trending?l=Sage" - }, - "SaltStack": { - "color": "#646464", - "url": "https://github.com/trending?l=SaltStack" - }, - "SAS": { - "color": "#B34936", - "url": "https://github.com/trending?l=SAS" - }, - "Scala": { - "color": "#c22d40", - "url": "https://github.com/trending?l=Scala" - }, - "Scheme": { - "color": "#1e4aec", - "url": "https://github.com/trending?l=Scheme" - }, - "Scilab": { - "color": null, - "url": "https://github.com/trending?l=Scilab" - }, - "Self": { - "color": "#0579aa", - "url": "https://github.com/trending?l=Self" - }, - "ShaderLab": { - "color": null, - "url": "https://github.com/trending?l=ShaderLab" - }, - "Shell": { - "color": "#89e051", - "url": "https://github.com/trending?l=Shell" - }, - "ShellSession": { - "color": null, - "url": "https://github.com/trending?l=ShellSession" - }, - "Shen": { - "color": "#120F14", - "url": "https://github.com/trending?l=Shen" - }, - "Slash": { - "color": "#007eff", - "url": "https://github.com/trending?l=Slash" - }, - "Smali": { - "color": null, - "url": "https://github.com/trending?l=Smali" - }, - "Smalltalk": { - "color": "#596706", - "url": "https://github.com/trending?l=Smalltalk" - }, - "Smarty": { - "color": null, - "url": "https://github.com/trending?l=Smarty" - }, - "SMT": { - "color": null, - "url": "https://github.com/trending?l=SMT" - }, - "SourcePawn": { - "color": "#5c7611", - "url": "https://github.com/trending?l=SourcePawn" - }, - "SQF": { - "color": "#3F3F3F", - "url": "https://github.com/trending?l=SQF" - }, - "SQLPL": { - "color": null, - "url": "https://github.com/trending?l=SQLPL" - }, - "Squirrel": { - "color": "#800000", - "url": "https://github.com/trending?l=Squirrel" - }, - "SRecode Template": { - "color": "#348a34", - "url": "https://github.com/trending?l=SRecode-Template" - }, - "Stan": { - "color": "#b2011d", - "url": "https://github.com/trending?l=Stan" - }, - "Standard ML": { - "color": "#dc566d", - "url": "https://github.com/trending?l=Standard-ML" - }, - "Stata": { - "color": null, - "url": "https://github.com/trending?l=Stata" - }, - "SuperCollider": { - "color": "#46390b", - "url": "https://github.com/trending?l=SuperCollider" - }, - "Swift": { - "color": "#ffac45", - "url": "https://github.com/trending?l=Swift" - }, - "SystemVerilog": { - "color": "#DAE1C2", - "url": "https://github.com/trending?l=SystemVerilog" - }, - "Tcl": { - "color": "#e4cc98", - "url": "https://github.com/trending?l=Tcl" - }, - "Tcsh": { - "color": null, - "url": "https://github.com/trending?l=Tcsh" - }, - "Terra": { - "color": "#00004c", - "url": "https://github.com/trending?l=Terra" - }, - "TeX": { - "color": "#3D6117", - "url": "https://github.com/trending?l=TeX" - }, - "Thrift": { - "color": null, - "url": "https://github.com/trending?l=Thrift" - }, - "TI Program": { - "color": "#A0AA87", - "url": "https://github.com/trending?l=TI-Program" - }, - "TLA": { - "color": null, - "url": "https://github.com/trending?l=TLA" - }, - "Turing": { - "color": "#cf142b", - "url": "https://github.com/trending?l=Turing" - }, - "TXL": { - "color": null, - "url": "https://github.com/trending?l=TXL" - }, - "TypeScript": { - "color": "#2b7489", - "url": "https://github.com/trending?l=TypeScript" - }, - "Unified Parallel C": { - "color": null, - "url": "https://github.com/trending?l=Unified-Parallel-C" - }, - "Unix Assembly": { - "color": null, - "url": "https://github.com/trending?l=Unix-Assembly" - }, - "Uno": { - "color": null, - "url": "https://github.com/trending?l=Uno" - }, - "UnrealScript": { - "color": "#a54c4d", - "url": "https://github.com/trending?l=UnrealScript" - }, - "UrWeb": { - "color": null, - "url": "https://github.com/trending?l=UrWeb" - }, - "Vala": { - "color": "#fbe5cd", - "url": "https://github.com/trending?l=Vala" - }, - "VCL": { - "color": null, - "url": "https://github.com/trending?l=VCL" - }, - "Verilog": { - "color": "#b2b7f8", - "url": "https://github.com/trending?l=Verilog" - }, - "VHDL": { - "color": "#adb2cb", - "url": "https://github.com/trending?l=VHDL" - }, - "Vim script": { - "color": "#199f4b", - "url": "https://github.com/trending?l=Vim-script" - }, - "Visual Basic": { - "color": "#945db7", - "url": "https://github.com/trending?l=Visual-Basic" - }, - "Volt": { - "color": "#1F1F1F", - "url": "https://github.com/trending?l=Volt" - }, - "Vue": { - "color": "#2c3e50", - "url": "https://github.com/trending?l=Vue" - }, - "Web Ontology Language": { - "color": "#9cc9dd", - "url": "https://github.com/trending?l=Web-Ontology-Language" - }, - "WebIDL": { - "color": null, - "url": "https://github.com/trending?l=WebIDL" - }, - "wisp": { - "color": "#7582D1", - "url": "https://github.com/trending?l=wisp" - }, - "X10": { - "color": "#4B6BEF", - "url": "https://github.com/trending?l=X10" - }, - "xBase": { - "color": "#403a40", - "url": "https://github.com/trending?l=xBase" - }, - "XC": { - "color": "#99DA07", - "url": "https://github.com/trending?l=XC" - }, - "Xojo": { - "color": null, - "url": "https://github.com/trending?l=Xojo" - }, - "XPages": { - "color": null, - "url": "https://github.com/trending?l=XPages" - }, - "XProc": { - "color": null, - "url": "https://github.com/trending?l=XProc" - }, - "XQuery": { - "color": "#5232e7", - "url": "https://github.com/trending?l=XQuery" - }, - "XS": { - "color": null, - "url": "https://github.com/trending?l=XS" - }, - "XSLT": { - "color": "#EB8CEB", - "url": "https://github.com/trending?l=XSLT" - }, - "Xtend": { - "color": null, - "url": "https://github.com/trending?l=Xtend" - }, - "Yacc": { - "color": "#4B6C4B", - "url": "https://github.com/trending?l=Yacc" - }, - "Zephir": { - "color": "#118f9e", - "url": "https://github.com/trending?l=Zephir" - }, - "Zimpl": { - "color": null, - "url": "https://github.com/trending?l=Zimpl" - } -} diff --git a/app/src/main/assets/fonts/app_font.ttf b/app/src/main/assets/fonts/app_font.ttf deleted file mode 100644 index 8c082c8de090865264d37594e396c4d6c0099fe4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 162876 zcma%k2S60Z_y5f7?j21yx)lyku!B@J_FiIdpixn=VDE~(i=txhJ;rW0PAp&nY$z&% zy^FoX#PnFWz5i!+xdZ&>`~UvVynDN|d$Vs|pEt9FP(p|czC@yL*{pesn>}tu5$5!s z5Z0_^#|~ZEjLknxm`e~Loh!EN(yhta1sj|Ri|I;;=bH{)0)w~jN#0Ee-HTqL2aM=9 zy3xkg6A39h4V_*bFmb%TVq?uqLINM+`nQ8d4<0f2&+iTpQllAub8>LMaifV1amDlU zaou6?@VG(cA8nEdsq-tLH^PU+jF=oz+u4&4_vIk){g8qEVm`Jw;E3N=$Nk|$&|sHl zHwWi2IIlQl#Q4c?=EcW@b{j%me8yYw zok%=LS0WW&$4D7rZbXA~L7Y#Q;|h^BN+B45w~B>4GKfFM@+d;`iJiG4@tKK6AKrJ% z4jo#OMueD68X^-iNV|~{J)zt9HL;da)*1AY_rY+CVZ?s*S$CkbP1ZnIttN`@|)H;W!^h zrbsDdAFDx*i9<=4B%-}N*{3PMHMC2!$VACO!6QKXUNN0?6fclkQV>}pd6M$lGNe9! zQ%B4pPGUCc&b-M=p%tkNY%4^PM#5$yvN&AtNk)j%$r3S$d?(H&eZ~5uH_IaR&=xHY zAxr3QWGQ`XP8S`4e4ovcig$@O{fVp+-;kc5Z;+-n=_RZptAtE4 zNE}IKYTBTEKbg!-WRBQ^^kW}L6F>tthfEdY$wuKVY05mvD#&y^+NTKL12V`U$g`U! zjC9o0A)`P`Gwl@f?_x6&#rY?uk=^1MlAy^X?L`BbA+8`T(N`~VGg%{TBo*jqvPm2V zd3GSatP1g!639+mU!mPWhG?6SezbsWmllFwspc2b3^Gt$iLopPFa99$OfaX25v0Fx zj_ebbk|n|cGFcc(W^;bBLnMw>CBec4GL;pOKCCC1K}f+KLQJE86M*{w2hb0u+N>1h zZ%@WBPw-|ONtSjIZ}4xh)PMwo-pSGtVgzn3ognR`MWm!6=@@xNmVI^Oto1-YT4`}$(lK&0pw?p?8#1zNP@LZNja{IXiJv%kw8gH+G(nj zF48@cBuyb}wF`+sn?Vd37oyYrM2wO|zDIwnv;pLpRGLIV_xpj5TZCTV`%O|)qbKg7 zjzo%E$!4)LU^}TUeIQ%JEjUJ-aF#01FRj(CUysi~YpkF*qhRwOeleM`Y)g4hzY zn#g#_cQ9ZKWIYJ5i;&Od0M+^PrE;+6MbM)GWT&tkV|hT5MTxACY{~cVCmS_ONHb|J zX`sDE_JYqVY-)j@f8zQtko^rZLR+1LO5Z_GMv=9!)w$AWvRD&H8j7dPkCi@pl8urP zeM0VBf5p9I2q0EGM(PT!$v5KPq=#lTi2{FOG~G$KRE^XUTa(VBmc(f@Ni)p^(ohSZ zrP)E2HZ=ut!X*WIKP-9VxNL3ACd2;70)BtzH(QjcYlitsZn#6;4A8OdVU*lMXK zSxx>X{@VSd85=}~1ESyqzJV_Y7owrV@H3ij#9OnR?6H|h_G$-^I*|7g@UyRUpLmPD zq^dZc=%rSqx6}c=dkz1QLx$MYB|9Ywd-EjgHU6Zl<_>srjSSEXg{~&Te=mbyP9n{r zvwOw!q#^F_&m7DKaSrT>`+8^6Knx`FMH^C$eM^oY){JBVeC;3bu_N)^1X53PQw8xC z;7z12=ZH-R>17j!`}B~2VIH3SdEl|?zaSQI|8NvR9_5U)nsft|=o( z8nTEMeNr31LKVBK< zLrHy2Cyf0d?yW#9!Tg^lqFGM_bCia?^=p&9Kz-|(x28B}hV&y~75rj8@N+UlxCK8x2Que8i9{^FhM1@F{a<-44ujs+ByBXiKtn2-BN4<* zjX8yh<`l%nP4tWTvx>r6F&sB;8&rynjlB4iE*Ai4DuvCW=_xlz&wvrWc%MRc*OH8@aq`H zu?6@j@Mhrmz}Lag()2g;7vTMf#m9vEWGTiP#`6p0cl&r=2HoC4e?xwN{1CVY$7~^D z8^>44W-bTLpRchv)O=FOgTSw^v51@!HoK${cPYdJlspr;-v7jk4j~^bj?WWYE_W`A z|10KsEYBsmj&Qjtx`KR`=af9JEsl9^$8$MlEIf~!Wj?I{_hH;8{x^URQG6u#lZ8Ov zm`}q`E(6X2q*(nUx9#G@itK24$D{~#?&s6&4b11|d{(PR3 zTIu8W;eODUT!Jp-)yn*e`vK6$X;b_Yw|Sn6aykm;3%eFOg zGCm(f-fZz>3QsW~;QY`cN9TF9A`d?QEanF-He~T@N`8oW44=zberN3)Jmb9Jyi+ir zQ*mEn$%ic%`906UIo}oE`!&YAK*`-PAK*DV=QWotpO5l6gvfLLujnj!Zq6=w{x5$0 z|NDEyp8w&;#Uqt6&Q+dScxRbM{xAHs zA6*W=ig~AH{`udqMc4iV?|@GSD0vz5Rf!dRjs@LU=2(R?kqTvH!Q9Tc&RcZDGSA>K zO_IzvIp7{a=w&W|jO@h#^9`%M@VJC$D0YWAoki9bUA5`~_XER;3!fJtUoTl}SqVR} zn=G`(Sxc-_4H32i6Oq` zZIZY7B&%r75YL;Rh=a{N!~*k2CizF@@*G*1mC%(m!(N67vJ(;Y!~;rt$vye1PZJJnrx|JVWBSFwePp zuFdoHLff<04yHF0S>_8{I}sB>#srO|)i6O2C7g(o^}`qrMH>x1lBCfvNh2vI%9#zm znaD&@Q0~V!Zf7?9M8H2$E8-HmMjsl9Y52LM#m$0%i+H9eYPDL?1{WpeNBl;nk!)?4 z2K4Z!p#zZ#OcVqV%n6l10Z8Fj@hkO%&eQ{qMk`5Lt;Wtyi$nB_Z>`40Rtu6jt#~@W z5nrNuBmYK&4W4eJ<^KU}w05?Vs60YB!;$iA!pX#gIHPPew)}ohh?djBFX1=%Ee>q8 zwm^8cDA`K30;ic#kgm~U%osHWFA1WC+Jf8Qw^nP1zVK)eE823pamxF%<*di80$2hP zHCke8%Q?(>!WpAn#-RrC68VGG4<8VoQTXAaQTT;c&L!Lm${<9}4~2MTMCe^%1)j|L z%BkVKiFhDK{0kQ#EPh6N2H99|4iUr^AEqDx2tEC7T&6Sl%H5mFcg)8)^FwK z>Sb%2(jEUD0}Y%ZToa&4>J5qna47J9){a3?(JktYU@Zo~M3GQ;0e9Ijgjs6#yJFsGfSjFDcZi2E*?K>o|A#eT8OK_R=e0q3gN6k$lVcEG$38!f2jB2~_DuZ0~d7B&1IbQub%a^c^;IdR25e5C(&pS4Y) zTcKTHr}|K6mm*D0Hm5^VWJ#P`9NgqM4f3R8bE_+7uuH&rZebFnn+jD9n?U7rDj%+MX)G#l4Y?= z>=FAzps*5K!AbBF77I&+mBJ3eAfyVHgdE|za9gY-28zwa4q|_Clo%&25Oc&k;#2W2 ziAp-j)r)#H^qTMWo7W#+pS;`Y?e)%jcfFV1S0A7c(ue5l>g(y7>BsA5>UZh)>ksOa z^=bN3K9Y~CkB5)1kH1e%pFY0KSL5sC>*8D1*UPt>Z!6zu-+`5~e_?;0{UXX{v&n46 zNY%0GG1eUz>yIRZWRYC*n*2)4R7YK?Kdnq_(XKR_4k;Y#cAA8-erBZ$$9e%{y^FCT zwJ03xJdAajuuAw|NEXtBY#|S0C8EC=B(@MciUY*a;uJAnye8fipNW4%cFtbJtAW=n zukBvHd;N*A61`6Es`u3E^_4KzV0|6ySijfr)*rxFQ}riHjI~$cSe=WFH3nm)7%RnC z3ouql-2Aus1^vN%hHfxtBJ?c*ECkF2%m$zuN+$v0%BPC zW4dj+XgX}#W7=)nVcKk3gdQ)Ov-uq+TO1!KFco}8Eg2Qof@HvMz;^ulFTn3OZcWI` zq?e;!>R)zvk@B+L%id3WJ?%lr)2>guJni(f_4A2O8$TcUwDwcmd`Kq$KHyeX7@z%Jv%^?6wT%& z6@AbXd4X~9wM?u%T7heNu@4&_yHuf!R$J(qk(lWBu6x7Q+Uj z20f3=XM@=g7R!dRVQe^AKo+t|Y%+^uQ`l5Cjl`2hY&x64X0lmqHd)MCiY-Y3YmIu4 zfh98|JIqp$K`v!S*)evUrLr`30(O3iEJH>0G)re0ER&sKXW2P|bpm#tU4Rd`2+PPO zE6FN$kKKnqc+8%#eAb4wWu4gw_K|&JpV=372iEg|J>=FWbRkJXSD~BGofweK_ZIpH zeTh+s7W$FHLVsZZNfBbm5n&)XDhv_^qXspE94DzltT0p zVsGJyaFlvbPgvAvKkWQaq>Veq;gX(TnOf!K>Sq>aQVv8RwJoDt5_#Ofiz9`fgzE`1a2{QM z3w)sv;P0Rr1d)xfF2K1ea62Y^CFnNVu|h=d0PX_j0PX=Ep`H7J$ABk*d4PPtOSBIL zepLtyfL{YXpnW9puZ6G>_&31cXos&Q{{XmOhzEQEn9x2Q7=A^8#lY}})CujNf$CIX zErFd?fTa@Z0;q(0Rss8~K(KyG15|(|t9}owU2G4IYpFnZ3y+d25<*Z7Jzk7tnv}Yc>^GufTL6(n}JWNAVB}v z1wa<=*#dk?1+oqJE&$^r+kyX3f$UaQTA*l$EcmoencD3GwpD@b2Zqc!5YR99slatz zfX=}`Df$i{MHB$9g@q~*@IZh*3D6w@ycZy21$qEOe(+HQI~xc*6cNBz_*w!#MTB*L z-hlNg5F;@7C~O2o12BFL+I9~wd7%=Ax2k3&Z7XaSC*As#Bh0_}gNCu>$Jq_3bqj7vf1#%V`G7?S! z#sZ+P9LPD~^gZtsye~SED@#wLkFvt(Ln`aHZXi42LW=y zYKsDhSOlw<3UHq#>Qq1!BUm+5fcr4f1>lO`&I5K+f%`SlT?MW~q6eTfo_i0tj0#+* z#Ih;~vw+K~Kpp~@2l%4Tcwj$3Mf?`JE>==ONCfr=1fu;3aF7a!nnbJx2u1r_;4l>s zLx~s;sEziYf$ONi^%X0&1l2RekBSX&4B+~UijM;1PvAy?#%Ny++(ZTP7jRP*5QmA_ zOa<mI-vi5fIF%nK+nZaDsY<+JF7ssY`dty?E{r31t^zuH$Wt4*a#d2 z=mr16W&WKC+*ZWiDhMgSeN^B!BlZRK!~GiI{)NEr9RL`GcCHtr0b|hr5#X_a325hX zn+TYM_G7@4Rp2%u#;L&VM4SRxfcwh=bD1r|aR4y<1XlmmXTn#YI;PUQ6c{q0Re-q+ zIKMf)oWE<(UK5z}l=H6#fb$6a;Pxl-@oxgO25bgw!TntReEfW@(SYrM9cT{*-U;{~ z&=#-@un+B_z_53$S}Qh;6)7Sf0<;7C2uMPEIXS90=V2DOOf*ze4=%Mj{-Pv zxIB*o($HQHnA6Ik7vLn|6xtgCp9b*0xePM^XYi~{;In{pxTi5N`~|Ag1Ql5#W&tju zy(#b|0Q?1ZT@djy;0l22%T)k;hBydt4R8m2qA%{5(BZd`i{z{Vc8d_n1>lN)ekQ~VzxBdz1jxgy0Ra3H4gt>s%*XL|U=F|G z_yh3ofIo1&8~9HE=;U_m-A)BAb3Fmr@)qEA+VE&xsiq@jHw@JRsI z!$kz8c@<~^FviY-E&=vXfi4BcSUJ#T!2T)_^ygDk1)ewgfR8?XaL;mrErcr2)xa7R z2x#$jQh}}k2ETnFW4ac&tO^wN?F$}rz=|O8t)>Fq2#m3DpqqfBRiK-JVFSJc(Y}R{ zO4%yVZG`+n0ic6!M=E?)1-=XG3);VkXa_H4vkDY^G#3D%xAcI4RBvmr?HHL%>9VNf z)I8rXuR^k|(6>(w1Ff#tH;-**pwTr9th#|#^{HVHs_R=Agi0+sNBTwS7wZ?dj#;d4 zp&!yO#voQwFfI&S92KZHkS>w2`0g6%V`vmr&U!d7DynV`gUGwVFL3wbD0DEiumfPF zDbQ5IAXRUxHwgY6BRfSJW;H8kXw)pKoR5#bxgn!tq#>hOIiIMg8U~G(M$kGvwzNvE zwz@%6wT8h)?V(Ggp;0*liCVmv_tz!T&&M!p@#1oeF#^kZM#=NzlziRLsCWZ7(EK=^ z)e&6*`T3ON4Sqg;KAFB_N0D$pJK8zqm_e zY9pjK1CHB}_^y$uq@wU6zg>8J4rK%em#UIy`o{`CwNV9UO*y8!7 z8QLAH8Avr^q>ii_H9ApzA9Jc3RH>Yf*kG$8ZS_q}A2%ExW09?DS5}UM&P_urdGI!| zPrG{6%J3s8yt;20Cw`1%JL)IuFb>!J^7K{#OSu+ z*j!cZnEl+C_Ue5O_l%1N)Z=ZX+?-3>@Msv`Hto(eJ<)r1(*p7bOONi^wBLRmd>lINVnO^zmR zY!lH7K3IROi+yEFiB2+LKU-bsB zw^5ho9PGT@`MFDDm%T2ZUB|noy8h-?-)*&9l6zVAf$oPrJUu3R9P#w_9OHT1^G)gS z($h@S%C(1{cPplAD;rj|n6|Q*A^V;Zj+q;Z+ ztoIAOsBfo_)34XxKt;2IPcNSdK8Zg2eC>Qk_#W`{_nYGPuHxQGo|T4Fy60cpf2}{1 zF`#Wge89cRp_PwS=~QJ-mDg3>bhTmC&Q<%pdbjFxtM93Pqh02@wm2k?fBX+>a?wMrmlP4gu1W3>HE#CdM)d1 zs&}V;&H4-K|Jfk6!H*3-Hf+=|x#8e&GB&nrJfd-Glkg^4O?{iLY-Zamu-W`( zADfS9zP|-+(W=Gr7Vle@ZP}t_UMp>@maXQsy4c#g_3YM{+thD!wyjs&HQ%~_yZGCG z+VyF-v0Xv?@7ka1(4xcBjx{-f4;_fD5P*X?}1ONTB`x=!g@&~1FT7fO>N%w6jGn7|4eWLIyGGw_>h0LOLGK~GPxW!>6WixB_7Vy+Dg8F+Az-=Ks+KMig+xXa+dgHwih z4%r&(7&|rg@z4fC4-Ru5wsp9E__X0UBlIK2jCeKD{lEUJFtXCfz>#%Eb{si=vk>F(1TPVYZ`007oQaW`y!7;gBNXI^vB}*i#IL)BOx+j zPC|OZhb1kSEMJnbXED0ug+N$x@OQCB{x^3&7*3Vu4aYLI8i#FtMjM#W! zQ^ifun+%&iZf>wSZgbk^Pg|O9*|cTPmOr-+*qXmBVq4rcd3)dO89OTMFzm?OS$^k` zokw?m{C>#ymv;s3+V(@OACBy9yZh9h3VTNFxwg0U-cEau?(^Iix9`{eZTFuzpgl0? zK+b`W2iqQ;bTI3X{UPr|A%~hDiaIpx(40eS5551<<;PV&{*}};scll1q+Usbl13&? zNqU5TFAZ%C$;rCp&dEoUuO`1p{$g}7Rx>s;b~Jux9A{i?++j>J<{94@&4)`L4m{lA zaPPz84<{Vnb@;^L>xbW_u#_?>K`AX$dZ&y_S(5TYN^;7nl$$9(9id0c9tk?q;z;i! z6OSx8^8JytBe_Rj9WfvEI9lUq)1%)V9d|V0=+2|Zk6t_a>R9VzPmcY4ywvfE$Lk*N zbbQG1na9^0KY0An@jp}TQhicur*=pkl$w*)IW0DAX4=}cgK1~e?x+2B!sdkAiE1aB zoalOD*oiqOHk>e=$U5=(#M={pp0q#ddD8D>-IJY8_C6VVa@NUpC%-?Lbn@KEPp70) z&ZjD$YIv&csUD|Bo|<=R^{E4=GEdz-_2IP5X`j=zPj@)o>-6B$GfuBQec<$&)Avq) zIQ=DEo9>$KogSY4ZF*#SO#0~bY3Zxdx1}FVzmonu{Zoc6BOs$uMpVYwjD(Cgne8(N zW=_jomANnTOy<4JU(aaIc%2D5)AmgNGjV5@pV@OJ`^@iWrL*PFhMaAEw(r@=XIGrv za(3U@jI(#n{(Me4SMFS`bFI$xJ2&}U;R;R2XS>v-3vUX;rX60r*$olP~%|*A1RWF8L zY1w^J zd#)y3y?8bE>fNg!ax^)PIUYG)IsQ5IbDHP0%juTWJ7-|dh@1&I({twMEX~=Kb1*06 zn)aI0HP357*IHidaIMF+(bpzlOT6~OwUgIwTzi*GbIaz2fFt_ zhjX)YZ|6SC{gkK63&?Ab*CMZd-r&4hc}w!v=k3Zf>*KFayFTywrt8M*m#^Qr{{Dt^!|O)GjSe>k-I#V`&5a*#WZlTW@#e;_H*IhF z-u&ifmzzUx&bqnbX7bJKo6m0++;Y2B>sI?)J#P)VHS*S!TMKTjytVb#ky}@8y}V_* z?Qy&2?UuLu-kyAW`RxO@&);_&ZDQ?7egL&b2!a?)-k&_OAYJ z_}vb72j87_cm3VuyO-`hyZiZ``@O(>E$;Qc7kh8Qz1jDc-rIHW#J!vM-rtw*SGXU3 zzy1Be_h;VUct7R-<@?X>e|n&M5b&VEgKiIoJ(%=h?t{b!n;sY+TzZiI;Gc(%4=X*a z_pr;up$}(0T=H=J!(9&z53?RVe)!iT`$w}Mt$nof(T|VP9$k2J{n6t`?;idAm_2rU zT=ud5T)$X}j+ApcnY+5Bty5At8<|M9f` z)1^;eKKtfb(`Ox?MLp~HEcV%$XK~MFKU?%{`?F)ua-O|>CO`Ll9`wBR^Zw7LK41O( z(DMt=pFIEg!udso7gb(_y=eTR-HWIf17D1JG5y8r7rS2=Uz~oC{o?kEXD@zv@%g3Z zWrdfaFB`r5_GRSDn3tnpPJ6lP<-V6kUS__$`tsh(moI;NX?kV*%Keqks~WHBylVcc z)2pag{a(es8uKdd)$CV`Uafew;nj{;`(7o#N_}%`aVUjO*|=2|^mgvs z#J89UVOkx7xnyPJcmmN7TdaLJkugRGowKt`9fO0;KyvxFM)|f?zDwm218E*<(KU!NqLheV8Zj&9NUI_n1tr@#{AqMhTS_U&z;wxu4u1yK^6_!@5u7R3 z?gbw#3Hb<>P4(EhaQPQGjXJzwf-F;JGD(KdyCkh?I-B&xnN2qJVSVCRAHv9X^IvqT zG6Dw@_%FoSgE)ImoJO*%7U^@h+@DcKs$n27s224TLWI!pU=KHquRrazr_`BC5yNZO z9v(qAiSC~d)u>;;=QrQr8S$bE^TSkB1dqxPgAizBb^_-S3p8kR4T8>KlZ)O2Ki3e6 ze^Ga@QFIA)B!Xp31~J!AL6H@{?Q;$GfkvC6i}pH$BieKZmt2F5&fuop>yc|9 zIzwrt#f#JL1KRzy2hoj-X#WJdU5@6EAa7kH4`P1Gataw~4icR;n=#88q>kPe!?Lvu z*cT_he2mQ3mb2GZXK={n-#Y$nbfwnOGM%wZ(V4H#;GJv0w?F?jRp-W=$5yA^NL{&L?piwOyBQ&k^LFgI?)KoJ=liQmcTXKTC~m-{twZ~alufktQ1Iy^yVEM0Ww zr!!Q5!~zX|I%CzM<_bDvE$f*v%umtCus~yk;K!L45g1gdlg`~v5V6hJ*=_spID!=Bl5_AicX)3QhR)!o@Qd#Gmb9=U+GwCdiY zb;~GO8_Tj{#r1RdABb-`Z_l0tZTo@!yR~jVXi(>Zyt(`KCbXQpZ%=}z!@vRE+H{B+ z(Djcd;@BqeGy~1=#XqETD9isaLl)zqv^s}!-R>;TkbxYG(U1p=MM7pIor&8KaFeB{8`)4bYJPIb0#hm zUPdqP64awX)2LAdZ_=jc?ABNcia5X*gx$$d6mBdw5^(C$c!{O8BLXC0o=?X+u)DWm03 z`FS^ahWuiG^q4k3DodioAALrA)hBhs=DvV%7uT>*#sVTdTwGYhgx}@`Y&^jtxAYH~ z_hAxi{zM)u?`}P2BK?g9>aSyY-K*o6*7ANi26UEZ{e*7te~v`2%3XwXMa3p^%NR&t zX@f1WZD46wZlwqb?zxhu0qA(5iGu~H00P2Ce%xwq!k!fa zQB0(GQ`4K3!uqrTxgb^;sg(lmZNq$6DY-O#!@Sqw-sOm66R`$oi`bxe3oSUKRh*&q znL)K8c(j6o`uZ=gGxnQr#@6W<)TmKV%?1t7gNu2t!0R;vaYYXpb+I@dRLj$kh9qxe z(Oai$YG9$4jDr>0!3s;^d3Dq$+Tn?I7XPF;D{g~!I-|3dZg?wWY3mtAp<{l&ObFAt zgao^|1}Ju+byoaLglPBp{o8!;@y|a!7EZ}(j|c|$wF6AvVn>}tXm8;3RZ%Q*no*f5qydjke_b$IjS~G<`n9qV{ZtFI7 z<(4IvKHf^cBj1suKwTg6d*KtP^S4BdQW$wD%gD>%qzqRGQcCe_B+z(`(B8&vgpM%= z@}s_ljy04jq3NY`uqecNqra7OqpLs9&kSXBhVr@iF6JE}&=3qm$HRc18av<&d88Ee z6$_&zoL_(+U63$$t$A`{s_AUbyQxDb&ovWykZev{J7dAJ&8rfGV76c^C5y%!dU^j$ zUt@KD!_0H99v>aIc*)$E@%S?qBn)!s2wk;5fADJD%rsE@N&Sdg8aW{PD?&YNb_^B(l=I{8Q1d4%v=K^>M| z8T{S|8>j&)DxjLFm6!~KW?nPvR=84GC6hFJb43C^+{eU2y{^g$7QkANQbQCDRXQSX9A#;jYx`^Kq#(7J&pZ8hmk7 ztlS5gW}$4|AzOC~XB1`Q`W0a7&IK0$TMB>$6%(mYHUL+QP63K!5kHEO2!p%M=v$mw zg+`)eSx7Z4nS{VIErnlH$vK0=!M69~`j4G&&b@A$J+|NI_n8?#uiNx_-Kx2BR?F{3 zES&#%{$eq7#QvaKCnufCe|mD_=~_YihabOtw_wMVjq5)yOBBm496xH&qQ_WdVL*;Im}YLW8$Iow zE8k6%Pswk?gd%rp!^Rfmz-`SlougA%(kWOFVPri`6z*e9TOe9e34f0x5Q&4rM62v!-Nk$Z zy5s2tK)7FUT4=&SsJX+Gv7N`B1=#cX5IYF0v?%jCPK%UlkT@+0C1FB2(=efX!G5-w z3a8}-E9Lnaprx((FJU5NT^hFDNgYdx*rkW8^<38Ftm%T0l;hFKh+Q{a`u`fgh#J2T zydom3@hcpXhR?@)IqpT%&(L0^2SMvyDscIB6ia7 zUOTfcCnxP6-f6vjws86k+K0;DXl_gE;Pso3A;b`@<|a0v*oIrUkZW`bw&5f?1sWwA zCw^q3GuC0&`H*|AAy{WDSJZ$>Y}H&t)j*?PQJa&_*vNXu^%ibcN#Fe=!d>`?JOvFr zZiEY#qeZ6GxQP7BQ%UfdtBVVQw&+4N9=tWem1p>xY=^r?PK1Rgv{|;&)hRALw$rSR zp{}dOEYY~isj~5sd@;q|VL1)R>v^PJr3P1HKg;V6J2*V1(>{EnF+YC!-LX?-y-^iu z&DxD7Y@mPtF2C8^t;?IMKTu(HwT7nKuk%yre7ZhMj{p0kyehN0-?)I_r*sc3M_uW$ z5BYLWdHJ&SgZkRie=7XKwXr-3HWlD6wTPN6R1GM~o-Mf^=O?!p4VbIp>R>DKaskg> ziB)Tjc1j~xR{?1uccp@G)wFfd1y+48t8w1cj(+$^r^)kBbm_>-vVE`s?06C5@pMO6 zk~it5KEFh~EXtmU5+OYUv4(09q0z=kNum&mbk;^5S&O`CP^}PWA9ebr%+38MPLYiG zRN@Gp#%CXW`16PHF%uWbZ{#dmf59gCnVdm=XRKS2D8G;l=Q0LuspgY9>s&tDXZkZ? z3e|3$F?{j}ZhMmu5$?iz%9G|Q=R_N+agcfq**KzW+;`U@RP z!qAodKpAriEK@0v?)d$GBadCDhT z2KM{!FcoZ(3|r;uh0hPf^KD6^|BtR4ZJClEmQZj0{G!Po*K(c|@@EQHOj|O91*W=q z@nEiLI)9cUo;3y9@etbKP5S?zwBx_chm2loboB~Maq{x^V!cxudUXIYRwy?9N>Cl& ziYx#Ll~1tf>BoF9fhyD-9y-K_ZRCFpM*00Z2GjI-K|Q=P!sW-ASu{U=_|7mniRsdZ z#_pk^muJ$}bm-gL)JOhJHc$FXeiBrNw%n}p4liqREh@Cr60$2X&9fM-;xsH$#e9L! z8o<KfXA9$y#h+Qgj=yoN@k)SD#WM^He6@7DX>ngSFO@3Eqlw zsnf_Ae{78mB~!4iVk4%lX~d?tu@0Yz;Z0h8-8Ed(LepI{NHbBhK(kh}TXR%n+Z(iM z73M*@)Q^=jf_V$yn9j1HuhJUNH*GUrveKq#t1bD~NbPuf z`Y%FJ2(bvIgwk4^w~yO}iqneYfSzz58gLoY?EM$$@=x`YnbRZ`|dd{vP&4eoCFNsZ5Ou z+(7J5*=c9Ab5o`)cDw+ga!O%=g*ldqlhIyK!f;8~jA&LA+n|bI5xfxQ_kM*@Ho%9* zX0S3JsFVE9Kk_~rwQ<+3M0qo-YeHQ5^U}?iTUIQZvsnODBg}Sq{qr0ml`p8W@v8{Q z@zsSgg;Y5s1#z}eWl8V`C9iYaeum4`MY1vyhZWx3{Hvv8@ zUEZHbpZ!g3SIwo}b4(*?K;pg~>*f2bo$0V-$iE$*9c)_bz}~H%ws1K%B2v;3ace9j z;18-vKxM1tlyLW!g(HK8mrU?&bhHv<^e?M~Z~qe0!LrJ7O4+aGxO@u8>snv0p>XZD zte}MYv+n;qrLGUx{xmyt?}laD*3n^C2gvVVua)79&VIjs=UTR?<+b$(pN_v0H*eka zQBhL|P2Dvr`PR6LGv{rXb{qTDD5(W$tb;VPmKacCI97*@ffP?Ul!`9bW<=0+a`kk% zhB!!a`TUFIvK4(U0jKt(PZv_pD7m^>IaMOOl&C;iVofn_adXiSt=5+WAoi(s5NB~e z-e7$g@lEwxLn_lLb#pKVtkcR&26QcQ98DpW3FX0wSIM5QN zspJDZs&XIi1fz9Qe7sfx7<%`T-GYhum zOHexJRm|c>RJ_!N0U&(xteM%Tr^^dzob=|?L)!zCvAE zsVt>9VeNL{6|WylsGC_`3!KOeGW!=-Apb5MlqP&|#{i&8}^Hefj~um@=Q1SMSW;;gJnX`Ojp zN7TQ_xH{T)f9hzu_-X3OMaMdJOPRl#Ie(OIteCDLrn3q1ZP_H9%Gobh-=70ne+OB; zhpZ}))<&I|Hz-ieR4Kh#2)5=n#Y_o#5Nd^3B*I<`6yA!H$5|WV2oibyK;^hnKhU6l z;K3RUSZ$LeO*}vHk^E)+z12s5vq`c^j9t2E)-MBe~evtIm7P+ z))^V;3o3sFhn=wA8DlJ6jxUfKN~;{!s2o<9Y9ZK?$SWMSQZES(3WpVhjX%ZrTa>5} z!@xt4+j@e(SRY5>L)}>r;p~r^S>N~Rr$?pkw;griHL4N=dV9U`l$~ zYh^LRE}9Es@>;CKWOP;UM21;B2a|lUqMT47B?gs1ROz)o*bl17~S)&4pg^Iu9!G7zSja z<-B)y=L=x34;)C_->9KoU|7%ouU`uX5=Z@b+Ig*QZ2z%|1>L~$Xt}%aJ2+m3R3vka zzLosBwqWy&eWCv;L7rlN7V?z&uS?-56gQ<`PYAs=`m{6`o+Cx(cnLh>uun=e1v7L*nA{U)% z8A_0~jL?$xDVE^~N9@Q)s808J%(5%yL1}o1p3ii7?N6gj>1p$+=V=f8Nrc!@J>&gT zQ-x#e zxLCoC?*K&k-96B#vo0*a#X9SJd;`K1Q8|MK%nOt~bZzCA^+WZc4H~;fgoR@#UAS2H zOKbU}%W9jZUBnaAyLv-~ELaNoAUc2}4rGE#h!W{6CQ`!cEoqQKZ&3}#Myav5*Ck(9 zVX}!G^1;H(|5<{$ps_0|!tit!Av$e*YU%*m>8ad{-o8iwij(JQNI~C8G)AsxS`2D8 zLu%bXZOLkug<6Z4RFP0f0=MEjbS&1H#jAF6qQNqGX3{~mLqKuZID&uy8GP*$- zm6LKfDaSRF+Hj*oa8zs$exg`$y)@5$JRurS1Q|tB3%6(ZIfwfBa)qUJrAgV(JBJ^d zNMkgqL#Gdpw@-V0v}vkXck+@S+ega_P1RWT_;FK*n1b2)_nQjd;jJLdrMN9&RL-P} z(Z0}@c&bujR3!#t3E~Rv#by}F+!NlwzPMF^;*w@XztK#)Sj?=%y78Nfn-z$HUG+ki z5ellDkjphSI+U-#^&GnETBzrWdRaJY34p~z9I~aNIzJC_JTw!&cMh(IST@foEbKM? zN#Y~w9QSnPL-|A6o+V3n?_08HFALZvFP3xUQd_?)p}_^VDfb^`86VvTZA;{6(MzGN zEE#EZRpYa3QT?Wb4Jxxx3!w_3FqgWdBtgY;p<+8DzlzjqE(BSJa7`$g40%1v zJU=FNpY51SXP>8Tj^Eq0%Ype@nDamK_35U6r2CVX$oJ*X;<1}+OkY;t;5_atM++Yc z$1&`yJmWt!phV?2UoqL%KXi=%Ip!J{h2tK)+(?`ySb9NB;HbWm#xDHN|6>u(UGq-s?J9-H4D>ASfn)~ zAg~qHz>T){>P909=dbvF#n9NgsJBK8GP5)ZyVgp1I@TcM(1m3RsDwCpZW98`&Lqa^y==13`J-u+b$ zz-yHLN;QZlD#*u#%ER*x9igcgZ?;G^44ZlBJj*aO|9h+8`sD(T2tM$gX`tp`Yd{tz zDJo|{)H%|>SGyniCJ$^)yGbm^=ee~b#({iU_U=*`-tfO z{CZd3N=MxO{P_+YA#c6Sl4yeIt?3b6BM)PK%oEgj$ZZ7!sBuD8giR1uy(qycB?Gh& zrHF+mN5qlae(}wKST8HZwG=ckzkq-+Prii!bo^3qL2ftjp?EmWbS=YoHxX>Ffh`u>80M|zt60_-2#l^saFv=C+)7xeUs!Nh7u`Va+VnqyN~c%F9l)*_t)-@0!#6ZdcGdwvb+_kY1ELN@K^oy^_s32O7PdL9a^@ zy^;%;D0aPuW2bTiXx3p~;ei$L5O-f5(zULawMUNR`6nCc&6`J(zBHzG4_|lf{Pr>} z+jLy;)70x9R{W8D@>wu{{#?3J{2=&ZZJ>$KSy>xU)mKSmJa|TyYj9E~`fkPdqN439 zUuMr$gs)Q8#N=P&u2s@z4^JpdnE2tuqE@r^wW->^>yG0I-!3sUs_<=J!FKDtu+^fzMG-$qEM?KZDLRb(Og)bdiY{?a_ZU)jamfR zG&e44#-*}v-}%z=5B+Y^3O>)Cc-~xVDTPpi?cXAwUHOn{#`0g&ZCQ)5gmj~~8#iQw zcc8JaH`cimy|Ixt-5Z)ztdLV;`=J4E``93CDPh@L*(~y}Bcz^gS|5}WuuU!^EC8WO zog!IcF}8xzOq&Mm5&iP9UFBeA^TT%Azb>ABoIZ0@>>OL#kd1t}vDcO@wsWIx9&Mpw z)-N}chfUi!T`t(dv#?n6OR1Om8}i($q@j^jtIo%O31UEDrfcyS{H+z4uBgJF*l6)e!PsM(I2ADl93P?1_>5cME$@G zKi-vx4YxjnhtAm0DmNqZXviB;CUfMkZxye&1o4J2|h@$%|L-)$98lX1_fF8YZU&4o&cUaS&o$NX&=4-r#K+$+YVHE$&sycm6{ zMM7H2=J?&q@{VToKH8)uwSWAEim7`OmhGs$kb3VMQ`hvgXWNc#!{^iT)!TPXph>5? z)rybVn^n8cn5%5gx(U%yu?>PoZ5ovpiRRrGpIx24XlNh0Ev*h&V+^SK4QFG3qI38TFSNLt5LQi#>W1SaoM((e zcujt{fXzUHw}2X@UCnUbU>BG|>~wZ$a8%wRG&&dQD4+OP&y3}iRX0O8R>!R`dKqfM zf~{wT0fh%;UW2iSsc@5aB{vuB+jqg{uZn(r%Oh6O_1K_LxMM-=duZ#HQ|X(wA6(hD zSD)d-`+V2igx7&wX(Q^geXIQQj_vaMZR1YRwsaP4b0S4Pa^bvuv@1Xo(_ikG0;C|}6=Lh-W{%qPaD@)#;eO}(1ca0*!fyJ=Hf|J6_ zN@Tdv5lJ&x;mG&KtI^c5J=-YyE882eI7M=eOynmEK z{OB%GEYsJ&`?SHMCWkHz4{;bgCvky%u3x9AmCG%o4MX~1Kk^{_f5Kw$_t^aDl+QBJ z(kZl=S%#0BNhb-X1wD4};5{S^h~m8kyqi^gA_@8wKO~$^Gffp5(n-{22j2PW3C(*6 zZaHF=C=@HZ`;6fY6q65E7V+_o5-`5~3c05w?iLNS)Qya;Rz2Z0*K*b~qh8734f;T% zuexK+7dq*y^My`^>3z9m@E&1$810=x!gOJ1^)6D%%HCo82EEP@m}>|Ocofyw_uiS=-Gq?dAb}J@5~Kx4LKNvJRf>XuBGNn3dl3Yr_W%hs^o}e; zO=t;4RD^(yDxjjMprE26WN*ITxwEq~gZ%&R`+m;@o83*>d(S=h)ZaO0`L@a9Sn#3% zIcT_RRnv~Gdd`-vJjHWoh$pwPayxghc;d-F`3Lf=QzwpZP-8`%_DMnIbA!7olck0= zn;~t^Fds5rZYbnADz&KC#LG@NAj{r3pA2KjuTd(>U??VRoT~Na!C=f1)jnYd&76>ycQ4I@} z;-ww#ZLIP;^=r3ivU&^iSuvoUi!G2=4rEciU#?!~l^2FBnKY>HfYyt!zPi!^X@xxx zah6$XoGH#?S)VASqV?HIi}<@O<-lOuBvfR}oz;3Mr#cV_`y_>4iIOTT*y&xcS|UIz zzd}uwaihXSO_f?!`+F#=iu3*gHbof?@18UUAR~){2i~eG6jk}QYu>b8;}=@2-Y{X- zs>ThMZl5`A^P1L;8aG?jQR!8uT9sO<&vhR^wr@tK($6jEKk?lGRchBx9V*eOj8`s8 zW%QghDh&fAk&}jDvX8a`LkR|=j2yKrN-N28uYHR@Tx#e1D*gTnMD~7#4;o@?qxwIM zkJ0UY;fU)mL|{aZ=;=&os)bPfoc`L021i7Af+LhHOojkJd;UHn&eYA@;@f$9=Bo%d zyJu`zl`Y3T`EdA*X1o&SOfp*|aC?2+$P%_ns^mwRNsZ4$@WR4pA`WgNs|WG-V4#r* zrxYJ7O>g%D|C^Qgf%!{5{HrgEAGe{MW=aFtSh*Rz?Fd!&pbe#zJwCXxm!q%0;V~3& zHsz8swGvC|3e{Mq)B|JKM(~!@?+tRffocz=+6iq{dIrDo&N%#y^PKHz~30+lR zm9-c(0&qc3X&ALcw8+4tU_HnyBuUIgdS7|P9H{tob-8ogkrgYC9Oj=M+t96D+b-SO zzS>n%daOBFu(^58i4&U~J%5o4SIDv>yJKr#XvRN z?2GKXY{~4);%ibizD{7JY(D5wep&horxTc697z{KyMYoh%Z$U6G_S>kst%M=oDvP+o!xKjU}cvyV#IEHG~LC2T)BzX+{ z^HMK)w3sf8u3ogiMi4@2Ty&q_ML{FY8`27|4E|?dL+Ixd}yb2 zpMJb|*Y2UM7PC6AdaG0x8N=T}>JGShfsh8HHA?D^jbLvJuj`RI705X3#f4am5hZs4 zqi2M30f!U`9{^IV*?Ns76#~6c*qvfEp$y&W(d-`Q&E7!$`JvGO+&3G|53%N>`F_41uiCKI zyYFf zQ@hPyc#JT~UoGh~FK3oiRJps9)_XIc$#VGf?rWXKdhyAxt-O=Z`nDy6^2ANWhxyeW z59i4<2LnXwe_(3Sg8Brbl>o#84i9|e58D8ouVtD+N?n2ozR{(X*G6SFk-CJ<6{I}_ zgw|AMjr4%Q9@r!qkI4kG|u-=H;>Q`D@prR*7HhcjDa> zcla4RZREa@HD-Jk182-Zrm(*w1U_9qHC{wdOyWXM>FTAE7LHd-go?;-fSnKo6m>Aw zi^gf+OVGZDuu%n*lO2zot8maT95^gS(o{c%B!y)_uC`_%1hbcN3-k7!p4{R{`?CjL z-Jevc`i%4eLz^G%FsE}R1x)db!;E1lIA(U0H}(Z#~{}W9`3W?%*sNBmDP2-<%WBsWl~wX z;c7{{0GE{n^rmECNmv#DcNpm@HMFEagG6aRTuXd$)xr^ zoww!4cVFKe)VJTJMHYFn-Xhp$qo6ZQHs7FaBw`>-a0NGsiA#Uh@}eP}`QB<+L4hVy9)2 z7JV1IRmD*mv4~2rkDZmP5T76jQNcrVVR-61=1pt_mZs=BRX+xcXC`pNLwq_sUhXDKX@K^48|@kZ7#rWdrErDo;?o3{@D|xzZv0q zf~!rDIB$CkTo>Udl}l2p6h+BDxYugNn8zgRc!<>!R$1M;MO?JNfO&>>bt)bQ6u=>Y zCQAYaOA#IbNnQw1JSKR~!GZ?xA`%RIq#B<1(;*u%*BfBm-XZG}f;q zcJ?eZrBL0vov!Ei{{IjJ!F16qaLQzXAjlnh;u!z}=UVqC)1F2Ul!Zk_RivTdA5Yv@ zP+wOI!n!AeK1?eEMn)wlOpu#wC!q%oD5VRLUxYyIBEjG^LC+3`2?cnRzAh;0E`1He-~9PSHY#RQFxI#nO3ll;=bwPyK*uyx zo!0`FnJe0!mYF&RD38*-_^lPtiuLfcBvn3>!){?cODfhIxThb}6(mV)1hgHf#d9DY zbKFr#E=3BStHtzSzytwK({enp@d^8yszIBM56H{w#OB@Pwb_q9v2#3Csl{uuPuzdF zf$3ndQZY3_Xzfng`b4x{KM!vXn3WW^8^TvO1t?{ck%v=&oo95&AX^Ga64dA+Pl6b% zh`T3-+eHbcGaYGi^aOJ9f2cqWbeCJSo7m1>xLR6NabiVjy=P5Q3Glcdpk0DyBGaUc zO|PNEG;8fYtqCGYECCAq*7Fw1 zZ-PJHR2`zuN?U-%cKNs2rr$3SWB~h;#4wB))jvSg;fDl}0wp7cJbwXnOi!m00n`a7 zzwKC6r)EH6otf@b6a=0Fa^Af)FJwi)g(gb>C(BT@mQ9WPnQamB)(@cFqktpv7hamS zLUFY%%&5N*#M4*k?WV;_X>ObuIF6GuVN0-3N(cehVJtV8q8I`?mf=6*?A}AtmX%m_ zLc>{uC+>a~9KYg&3ulWSZafsS+W&;~_ngV^7kvTVmu!8D?>ed0E)tmeMJg+wNWv9< zaFjnpDLFWe z`UFH$P)z(s+b@A>rjABV-y)YfY(1aL=J53sw#$vFVwtL!pUfTF`<;QiFkLKs84KLO z(s#1ptS}TYuXYzj2PpFczc1uxKEF%asax?q)J(R5S5O&I-DRpHT_gk?qH!G_t369Q zS%48b=vLecVY892be0e{S9S5lRXxRIGLv;?6#S`S+D}GlKdCtp6%EN*#jDUFgjt2u zz5qwVs-pDJzmaf>0x_MI)NSmw`LjN*)8N#Q!k^tWoExVf8Pj~$pEJ(Yt9xepb^a)K z?VMR_*Ug@>Ua8V!S%efYOG;kLXN~OHdpN&4V*BZV?@k-iv&T?Yjr$(FeChmwD_?!J zVRqC+H1}t=wJ@uu08vfZZrOxr5mG=G30@|#+&cnD3lqr+rVS5X%UtVUY!_J}^`P>> zwqxP*{l0$Em25U3(Cs0DH)Cy`R9hVRiCFU^CaCpX#ed$i z?M7fx;pbuSL0=x}WD+Y=D{6s%M?Qn^X?L0*Kd^?`ua&!s&RNB`c?;fE%!9lIh4f1_BXm_I@BM0M7!G2&q;xT>#U) zw0DN5N?p%xT~Vh-Kun_sO?K>%cCUM}T|`pt9m-jG#}mHgU`VEa-?tQH!I&*a!ZS;p z97pGZK7sbtjtt0*L}0fREn@^5uAJv+M9@)JR9>YJ=r0U6=zXA;5&SkzfP}Iccdj|i z-U?GnWu^w%(J9YdzZHSfXTr z&i3g!nSY%+ds_sIP?q`xIM!>qLHnyPg^?JPFK7#Jy6gmf>T)ePgtg&)h zw5WnH!2rYSO6m5%%(X7X00X}CQdwo;zD%X)uo)FNRZ3_&5I1)pQ2M=~DgE_2e<5o0 z)d{Y^#WaZ;e6r=fv0mG=UreLx)fABXcebnAjmiYibq50SCrlg)Lj`It)u(I>$v4=| z;huYB`6!(bs=tV+3t*T<*M?~CgA67VDvr~TdsvzWH=T_1MtVHCr05yRfQch9$BM7B zfC-n!UHC~l=Ug{4Z+tU!%I%&N?*3zz(wcwqPx+;f<}v=$h^-$DoH)HGed8=r1nAkI z+{UbC8=|mjTIC|lJ0v%pu}+x7m^+M3l|~n(Qb@9vMh34GZiY)j%1L~OI4l8! zI+ib6y8N#p%C9B1Z!gJ$NXN`ozLWm47vpcEE2W;N-51DW8U8i~r3r$;iliP*8L8oD zhnt?t@|UgUL!Yd+zrMW$|CNQ5KwR3BMMS)R2qMZQD3iEHlF{NApYfh@R=RAz1U;6d z`g-&j!jge9YfRMZ0$kW6|wQ*iNxGbIvNUVNf;uCd}Oe9YYlBxEzQ62n{V`)KE6t)_D!S4R_@#WjTO(+=Zsgb$aU>MLU+^^ zTY<>&0k`0G<5yOmEP#}@oDd>1T5pIf+C}Jnq9skyIwYya+ z^IWY7V>>52-!(P1(hK(M1E+`8^{-dmIbd#Bt&o?h;O@PxT#ze+v#5jEiyA-=KFKqZ za->)7=xRcEEe{i5nNIMsQ_t9;8ES&mxsd;{?VZzCm)VQ?MV7)Zl2&<_4?s3!zsN}A zcE~C9{cLiO94A+k>&y1e^hZ&zQGM%&QRh4eT+g9^za_249|JRpEX zP!(~ccY8K((!Fc5SGspdYh0~bLSl{I8+Ys4q;coBUrxZw@-@;hpmK|HnKu=g#~9*w zxQC^&L0rRU6~gkSD1^Nw3SpUhuyVOLNdHZ$3MO=f=hhJwEa^&KO;1;1T=X2}N^vWk zuG6-$2p8DK+;1ya_!7qmz>Rn zB-4LZjQleI%wxYX6`|3q8hw$JEEyV zGYdtiTNd7M32Y$4T*Ybxv`?w#Zdf2s5-lKHxFf(D+K1zBQKx$kYC|Z#r~jHMkfFlR z0k6>h7@CkVY5I1l(c_)WA-}@=P;0c+N(KDAKCtN?!+(%L!35iA)km}Hpkcw$c+~5< zEln4^dREfJ^v(!g z3=BoD1b&kOA@ss)PuWCA8qkxf2GIKm&En5XAv>keLS@zyG>f7Py-Yly#EX-1LZY?S zPF~RKUuR_;I|&SN1Jx8eC}?yOAR%wKFX*7`$tlYCI!4}B)S-j)yE~w*yrgL0>eX_+ z)p7v!3sJEzkz#_)J;j!|0cX@VLI**vz0*o_nvT%(X zh+CQZt=dQ6bHi-W;M0L>35`zy*M_HrN6JvsR)v+UlUn4%DaH^IDq8Y~kZe(Xd^KA* zg%l~4W&~5{Z-tnRd#znw4Taz?N&+C?=oS+M&k&esU^N^;5h(2u`bKWJmdOhi7u(jJ zSkL)_Ma3IVoUrdad4i2lcAh+`{5`j5OZXuq4q92E_%zsdB`s4+w&Yziqd>QK>$twOL zm2%(TaH+Jsk=8sE+;A4sqdeAJTGV1|ryw##`pUdi8h+MS>ln&VYK9qkWB0Q!f81wF(W4tkyg;X~4z&+uxo#J0RHo>Eao?UVDA( z^rfg<`fjd$R=G`^SoFg{=ELf&o9E8keKL<7JMtY_U2FMdr6o=dwlgxxHVubQaic)+ z4bI7;UiAH_6>NlMa#ct%CqEsD6=+)lB}w1FTrhc4v`NdhG)qP6kSWkqNI+rA1@01h zTwu#0A&w+Rjha&Dg1g;2j-UF^x&34E#uc(YGY1S@#wss-d-{sG?<{+L%)9ne*FNZ! zUA4-|Dd+BY;pz501CI>g<9pATKcMJjTD`UJjoKt&It7hj~3#o0GyZB(3yjI3-xAqx}6mKJ6$Alarnl^JI2Qehhkcg&s|IltJ{WqU~)p zOrs~tEA)7ekc@g1%Ucc&tK9@Ki4GG{?dTM>f*&%AV%!S_O;CYi4*iI^7@nR9VWLx} z7TTm*6r@l?wfrf71?3!HpWQuYx|B7ceJ^&n&_3$gq8t35BMVuN0d?2Snz?q{#F-nF zKWFA-tbMU*-GR&bAE%O+|M5Oc{@s5Q^GUEL&vo~3o&Ds)nb%66108$76Tb&+P@-+H zDvNlQcGpFGPN$>rgGk~UY){e|h9w@$;WnqJDdnKzj?;rFV;Pu0z+JU;xWMlsI%n-t zCpZHk7J?jVxPH3&I$%636$vs2i^&`{bY*Vwho3$=*RlJZPxAiBT`*wCjEARg{miPh z>^|t#mAQK|^BR^P*KEn=z4IIQ>ePJg5~{I$hrcJEgxrm_wNQOT{PbU!z^o$J1vMP8 zPb^jn7YvWZ8tFT=jEz9uV3}~Vo<_hRG7`)VSqn=Y$UZU6B_spMJNYDEKf8CM*ZzLB zi8QcL_mourY0W;J7EfYj-BazZG5qy)-@pH6x6(~Zb!_$W&YJDgU$62~t5Q{#zc+=| zU&b0`W8I5*H<3#TK`gGM3H2yAO+ODyctkL{o=XvtR5~dZB)AT&XaJkAeoyuU&=2i) z0{Hm6-=8unqLwt?!`yT+rSG|Z0%LKY6?!)=8Du-TnT1CB^yTEn8Z(VaVzRiDA|I)!$O5UH#g1 zldGmS?6-XIqO(;iW_QiWO~&4yD}JbK#5sq-^6?X~CzJiD-#%R$igVF{8l>t?raxHM zZsf4wY{L{nY(p;{_tcGR%t0nOW?U&lSJiBwF$o`>yG>~-uX7Kp-$1a6G^41Cyly!( z(js6jVqwcrPl*m{h}KgAovZZTDHhS7$FIanz0e+C5oa)^;H=u67$+n$QZ%f>%Am?+ zj|!(_k=hhK^h4XdSqDre50{$BTL-mF?Q5 z-j=$r*R0*RQl-!|#y+o@{bZI$_m2lJP!-oJrY=x=jM|d4@*0XrzM0qnmZB*njcrAf zmlPl20ZeHPpEBZw0Z2;+g_ZIA_DAEso_m%5HR{S-seVz;+Szk**3FrfBd=S+?+4Gl zJCmgp`)B_?lesS)ymaO4&hwvw#;-z;U%_gFsGE?fr-0y3oxr-FqAEnwDp8A2 zU{+daus6P$OqGf96+W+DrRo)5=|6EKbZ~Q0z4==cNNy@^hb>QXfuV4kG!EJA;fg08sfzv2xs8Slw3BOtYe9I{ssq71s zq&6Ayu-9<1ao#J9)MW~e=zAc&n_md$FR+iJSWVRF{lEiG z+%7He!Mb5HI7(yP3AQ)YXyMmuved#0mUZgWgv8!rpi5%Nk}>3{>T45;qJRr(bSM?P zfKwz7=v=JVU>fSSNA|N69F)OM&2|p!KXB+_HgrJ$Vb0knXA~ZJ@cMHbM;|Gi0pQX1 z_s@Q}Ycs3D&u`rR?WgzQS)q;EFTC*Akz*O!C$L!HBqZBdSU_X#AHtrjfPOh)T8Bh< z0!bdr$Ko4%AxdRS3y4x#GXh=p)80gE#+XGwu_BmK7?hYG9A*oO8fEFU7jziO@U(bM zPXhA^V>uXU2Vy|tH)U+?w$k?>o&7s+?t~FjuJAt&Ez42sHFYmpKii(UL>eCHyZQ59 z|GvbUNZhqx<>Ktku`KG!+QX++zRn)XUVHy&4D0(Lri`#+BvzF{_9L)LAhC6;1Po`1 zT37-V-khpUp&A=X0vl)}Ek%QS0dJRp4^9Rq6K!geX%mrB`EM!>=+HE+ynk}z^8C_q zemS{OvVZxsCLISZ9Q* z5#5aOoQb86oqi^Qxx6YI@k>Jxsy@NuxNtF0p^K)m0 z9hZWW+7yH7s_gN? zNN@?$_Gv!>rmYskH<>1CgjNh10kn2RVFX--!U%W?IT7#|is@MjJ#>knRtfZA*uUf< z815!HDY0~F&l-~9M7UC)lW|?2ld*vLxoA#Ce(5b)x#uNnHf|Y~G3R5Jz6HZFcCO*S z{k&Szr)5+}I`~C#PVu%8s;?Gn@-;e;3+bot+-o%uO$^sfOJ`H!%5q##Kn83IqTAFP z4Dn59IL*2Uj*p<`=}rK~WJz)$!<;El7XY8Bq&)qc&3gr2$%lx(3v*i~6np-1( zd-V8EinPkz6T4^bKj)7dF;@l$*G2sH3+yr6hT3?@SslM5f<5|no_UTG;4xpqF!FA& zC3EN&cP``t=%wE|e1O)xQNM7T-4E98e*C*!z-DdSwmF~oMJtgI-loFUuXz=AK6`pa zcU`TUxQj1Wim^^VTT^cxu7%euqWhV`(B!qbXc}dxfFxs}2JXJA0QBSa3wRBrM1HY{ zK5oO8Gn!ZcaI8XdiE?$FJpDxp;VgS(u;r$EV4hwTkg!r*|CLuFG+5F}_JJs3v<_e=HBO8`L~HB=wU z1y?mV0f7X>P6@NF0lJl~tMWJTo)6g1y!Ll&>ZbfPZ0ffFcmI4}%69jq{}|5Ta?iw& zZ2JFdQ8D&LlLGo9j!?liOqGQ_rESr|F(Ml83454=kI)p33uu{? z;xWu-Un9SZokC8EyXlKrpN8G8pQ7-~^%s_d^Cl^^2J7{GXDcg|?EvcmE#WJAuGjZ{ z-*>6+Cg1%4P+(JN_7)7*OAS`)<>$Lo3koQI=@~F0^l=JS@)!6i7}GHnQ=d$Wq_8AP zy;l~3*mMB6ot6%nBqPk)M)@n>{g+v{&`SQTO~^)QiR{c-v8LvhHHl^DbP>u?f8mW} zpzIYg)wB{d(CHZ-2mYjf)@UG9qaKD9Nvm1wn{Id7n`1k*j&OA9ms&cB2VIhS$St2V z8qqD)H(TkI_J&fEVx4V^Puagir6f(Ys|YDkQj7Y-VTz+dFcJF)Bmtwu!nO9o;Sd}b z(0x(VprHi<u;{mD$4YXJxVAEoJh)I&$sm@u<8q$1hzvX^&yq{Lf9B`R`fMsZ-gk zBx}V=W}oLP@0>gTz1*j0`Q1-G`k5%c8}>d;v+yJQkEdsYg##?QLbsL8>cL^C2jDD% z<9CyKSRS(L$t90^_zk^Ay3l6fIq~Sx`|VSymy=B3NHZX2_<0Fx*3^Yg)`5UV>p77J0KkDA^C;DQWGu zRi^1dSZ;)}``7Bc1dwbVJxx}bas5dx{%6HagA>FwA2LWmFwF=Jk~* z)HDKA-{7&8w3$i%+RP+>!sKXFx2#@Y@c;iBd;EKS|6Uv2j7(_ahtR~awgqZQlb2>e zUFdyaDWi|xu7)m9ead){7yIt}6#I~i<^ye<;=_>M@hPM?a`0R&_Ph&s&4=7IdN3|F z#m^0@;}u*%Trj%eC`Cw*PlGUrFH_S7b&bke4ONuP+LhU{cGt%eMwQhm%v-jlbU`F5 z^&^HZEtt>UTYu%>M6>hz7O{W_Ykpy2t3LRi$y@l@j~9K+Ki%}?4o>7CA_!NpbHekl zQ!#&n1Wr5|<=Tl@C}1(Sgoq@=gszKMLGMK3H^1p|}>_DCdwjV0`cA=h$of2NwJXD=hkDQznbz_g8I_ zGTa|a0|&F13wIv3k^h;tmPvJ&;9ODFq*QPO!+x${>#mm3qIKv??BiLr@J#i*z3#oK zwh-Z>K^jEb2nVbNhG>Q3!XYNm`g$Q^`|iKzcF!I#x`Fqr6K4sUjs-xN@QUqMndL9?v4a+7Ds|310!*7QzGlp`-3AVMM}d=VaoqFGSy&O zZPceo*lBKT^poTAp22sEnB{dIFTy6cYd#|?1IfBk{3R4guW~Yc*!IQ$Ln>|1@Kf!o)+*08Q zh6)c*np%HgV6c=sC)e$t%UBBgjqmjf&T2iEm13@<&b$(<%TKT`rAL_4dKCK(ht^ZD z)^OWGlY-D!Cd85c!V>EAQiNpF|KR-{C&#at9&|r&=>NYTDBqouJB45TnN8*EZ?VWp zx$m;lxA;0X^=I}KuSox;YElVapCOdM^4)*BFJhM+i+_=K0)dibLyXYW9ZOJN-=Bb^ zkYs_tFsYuz5~A5&V#>ah#CnO~*yD+X^d%>8cOqo&;KWIZ;9o}~$r=;dMhz-Q)t&&R z2qE+|FvaT|5*h{fm>wwn?(q!qZE_8znky5#kW@FUFd-7LIF6myr}?uumft{BGm5Xlvtg zAH8w8=Ll(qsnQcR^Eo#>YVP>k>3`Ycv%{M&LqYGF%Z+(5UCT%Z5Lmf%U4lSyXY->BOF)R){}R& z_d|tO6zs!lwn?h9dJSAW68eY*;IR_4#0gpT0!6ygWT6j$p3zh%#hyRDD zf$y_|1ue7%WQS~i4EdrFUq1kRx&*wRO*xKd|20;i)4;p!|L<6VW;Bu`pgY?!>@h2S z=&S2_ye2=6=b?Rv4eklCGDkYHZv814{SSD*0iE9*F42u8X*~(6Edkq@A_WdDQs5AE z%6QasQ(~d|sx79J?s$vS))gRTZRn8#Q_>!h0waM6{es2>WGdizDGKY|0Bf(WKUaA! zFYn1EZ41(Au>n#$fU`W*HzCm;WZ1(Z+R;*VYHS-Za6|81N=U!f7pFjn`} zx{Nh3TTdW+ZUMs;i%g%^k3hQ)mV2nDFiG(mf>tf-LqSy;%dt!yEE$tk%>M!!Yg19?3m*s6?QJc2TMP2>i%K#UA`+Y5{s1Lr%;Z3?P?Yny8!#y`3 z<0aIi+2k|eK|=g?Q^T~*dBD5qJZOB<9{ZP|5W@D3+g-gM&6BqZ?Gi(SD$foVb~^&MJq_k>Az$@V!xjSRA*M79*L20CpkT#p(n_U8I|t}& zlPJIenUH=6rD{k&sOq>-y(%6d00Vao7b2bNTYB(s#e}}?*>!3LCQNDCZwSrl+qf~8 z#VEO)V_IL)bx-NM95-ed4ee8Mvv=<%-H1E+x44t5EO*j^Y12((^M#bfg;b-ps}_w4 z*XY=2Y1qEw(S^~(rqR2jaW4y_Z{mwu98Cm?CT@+cN8cVCJqbUo9*>5l9~LA=r&@0- zpqd8q0(Cxs!#s1iDB&(5BBZ7mFY2<7IW_18caOZh1mi_rJ`4IzSy6&5;R8!7$B@yt zxAtHam@Ovf@98vTbkFMSwY$Kh$?%V-gGVE9U&pGx+I)&c-Y!<#3pg-IAexEVK-cvlnq8sNg~TzI9we3Qi-`26#O{5ifmGHlhR1~p%A z=^rT_VWGW74(kCu)>GcUB=d+Yuj6m>ySF8{9$P+_&{mW$=-2+$uA)Z=Y-h(7?39oe za)F66bJ0kQDt5KZdnY8o;J7Js>Y z7q1+JqJ{$?ZP&Iatz*l14`t7?tiw_XH{hYh)>yF{a)xefX`En554w?x+#p9S5>{7p z;yb#YQIC5eK!NnEbdYElP})2}8vXi(=ElBE@nxF;ULX%grRFSNyQZeOnfmP<%RjZu z&s?w|m!&Dk_&=5@n#!@P9XmA3c$M(%{m8R_mSt?Q*>p)M_T;sk41-bdmM|45hy?on zp38UTaxem!X-_`ns~GGc@ww1kBN3&IqwXT{RBdB2R`slwrH7RTH)gno=3qAZLXko? zaYGqlK#E|9KvxPYT8nLBnVu((k>8wrXGirkb?DJctYBF8VN=db=+_?;#h={x@Op}XH>+!Q^O;8e^d_8gItcglFNVE4aUtkxu6N5cCOr3%(w^-;_ozX2dN|rt7 zmtA#)i#?d`a+G%ugxu5o01=(lcaRZm-}T7{AHLD${FZ!{%R05~J~*$}TW|D2#KxWM z`f$mTlP>AHJE8Z;F@2;f?&LmWM)sDzwn@d;!O2CA2;|nIsMnD|O#%btl0DK$kpEvX z=imS#fDjxv8BCJ)CKb(7q#ae(E&z~`W;0^tWMUa7BX}5MCi3I(ajeB0lO)>= zHO3T|6I`qFR1#3SN%{-D`Iq451W!pQX0(dAms+z#yNErY3zg|ELV1|Z2d19UhKB&L zrN#c^>DaW4hfSNxB$;4)sUBFLNQ|&CXY85GvGWI3x)h=J_MtstjQiUU)eYOqRh zGXQ|qFJMV)ifumv!uRCctSCVEGSxdzkk_jj=I(&o#B9sa?`a)0YFuctutoS7O}MwkqNuml4O1EE9f1-7Q7P+{Or`Vtrz8wmBA6S$jFM3gmB z1Cbcoml9Zyet2-;Bz&7d20nq}??9HB@|Dn4h8IG)IYVNrk=h3%VI$CwARyswwb|a9 z`X#Wc(9Tk_M!mMjgNiSDl<>6d5^O(j0VS;K=!-lkAELd_P39w1@tUl)yEFyuxWTKD zG?FM9qud7l{NRJNH@OKqpLpXj|B6q0V+H(bBef3q(1Mu1I- zbs1us))n~dbtOBcUq=2r-xQe!GG(Q4={5EJF z3Ovmu)2?)yi(Tn2{;#{T1yPy~4weh`n+95tIshO+10y^PP@D^DWXLl&MjND!B|F(D z1i)lEp>g80#$H7D@?-6+3Z$`cH#{fCD)7rt12gn9LxW{UJ)ButV1-7hF&f$z(YgSS z%ohScKR}DR*F!YonDp$1%KXdFhR}K31k*-x30ncY7mqO_`5tFRveAXcPLh(669_e$ zOnGvA1+Wd9!%4;~4Wb|31A=tIiuc0{{AaG2qU6i>{;0^uD5^Urh();%%N4)4%%`w1 z3#Uj4?ks6k#Q1r90(jg+!55q~VU(4~kM~Mjuiz-pz(%+-LkU<&)3& zH}Y|Q>-=dcPZ~Zq-7nWsckW1ut@k;|=NvfqnS`oOwK=-^2hN~s~L{tC+Jd7xZ3yq3UUJk0j2#65RQECpt z7+5+)bJNX)d73$pe;3RlO_v&Tq@1LS|6-9A?+^B{$nITzd2P63<=Bm<_(YnVxmz#_ zXwrr^mbW{nV}?Qv*hLjn)9Aidq`bS$RXW90RdZb|Hj)r=L=2ccMsiB6fPtX+U2E5c zlA`MZAWfzQ3u<6hbdIV@*#=i7`0ABnD|A>2OI93WlDhUZFoQ*`S z4RvJCph;E&&Kf7{t>UDst7q`@tP%T&Bx8#v_5Tm4nMYhI;(di zYb_u4c(qb-(B$mPYM+f&p4&C$)c5i`{Tc>NOyAmL+*HPvjAcIdYhT|!&t#!jHKNJBjoM1fx6f%dx_rakOLl8S%h=itM3bsjZMt60mdoly zL)2RD*Axsb8H*`ViY8wn4p1I|$I_r48B0QI=%UA~Ez#=Ga17K4t=nh>klo}H7kXS| z*p>7Qr80mdMRcK3njBQo5N^Q)RRv7i9J+a`A1T^WuyU}wlO&l?SrH-1zj`-G{`{BUA2I(YLzwO1J^l!;ljuX523tE2c!x5$TZ)Eh z!R}EQhesXLBDSsbj&AL!Q6+_e69o%9sxXS!Bx-jQ8Pic@Oh=J19aWFsFO0fL@0%=U zOBo5#!|*?lr4k5nZ=^Nd4lgUNrWoRoltgVy^$;tXmda(^IsO}&w2oh&xIR#NJ7k0C zUaCh~Q=h!F@=%^Mc7JBp9{3g!utvYOpTvF}tCA_pEi|cq#v)LqzwmCBIYh%2s7M1k z1~Gt6GSK>wP8a~Nic_UV@d?Z)b$XwwtbYAiK4Cj|USOl9yeHSo8pC$fZuev?G#)ys zU>$zIUj)-SOqg&X!*n`ZVoKhcU1k?eu5oV-b49Ep6d6jbmx)*jyB1k`b<3Si62kq< z#?}tvm*(-QM_KKjJ*C*+OD*xKR;6ek)C{CYpW@-lV@DdS#bn!Ss=dNKe{vd|;%YrZJqy-AqN%M!Y>@@!P>s4=VN2f?O1dnu6wum3!4_7 zE!UfF>Z;S=O+&-A4x8a19M##zNDNbxQ%O-M z*A8E~a(IZEmgX9gds(@Bw8v12aTQD%-ebt%o_#B|nQ|zt)X>S3232T!yg#qsP+r~X zMf>gtU%5a0;=$`3JHGzoIjQ*brKTzRj8w#bGzr1`<5T)zm|AVP@)g zRu>lprUk`Ox&Vs%mK0!J;7pAu0p*$u0G}EgDx^z!L2K9?`1Onnu8b5{l?$#aDQabd zz*T}=sTW+SDe8;Hdl^BlMi*R-Qm`ghQ#0N5h@qA2AgZX7O{dJreQo|-s8vI=IgYWPL4dgYQUQ}MXc7oq5 zxVp4O^9zSrje=|0GbivH<7bWObNAOiBWF%z@e^jUGn3+8^BYVw4{1||Pj6MPub{aE zE=Noi>8d!yGp49c4MU17Y_f;e7SU`8r^dkzh|~FA4{1=8z*#~RI3jaogzg{%s9rAl zf-5-%GkM4!EJtH$v_4T4$l7)#5*@9~>*ZGOlf?9Rj0wO+e|G$}sG(e$@%>x>dmQ%1 z0RtvZB#9-WvCt1O@QB`59hygkI6;DE_m-5oB@inL_jMlB1F_`gq4d$=BQ7&ym!^mx zL^Z^>*e1&9T}dfwoIwCMVQ`HSyaf1;D$Ud}p!NHpLg?O!DS>XWTqf^5V0&VLdOrdj9 z<*?(I`J?&Fw)SrpClyHh*R4Hwdi4Z8jSVcr+800E!{T!Iqg!is@}e&ue!`z9SYb~- zMdaiE(+c$i_@7p2$z)-LTI&=7J|^HoYS`t-RB3(go-amUnzQ%8?ghQ3ty(ta9fS*p z#IU3*3CsVP{ms^1bFc1?-Fi(X+KqrcvCv)@x-Qg)o=?JV)lF4U!R}0y6G9U+?Bai_ zjMq{}7XK3e`oPw2_|2DC;yHe!F-thI=?+V5%5Sk_JI8NF#CraY@jKW%J0|X6EqLD@ zG zdtxR*D0Sw=3VqNp5`jiTh6Q*UchXFcK=0f5qaX`u1VF8vl<2EbSK^}vPntZeVwJ(O zM%5nJzo3aDeBhw+0YgGkYDw=#w+%-B+}`#G-pU4{4AHAwAaybWdlJVwBK-@rP>ge(u^;Dw2eM0-2IRNyJ=x1RnjgZGS| z!!H?sf!NaRGyK?yA*t1>rm`C&I(Hd4G`(u&)TSdlcNsAx{jF4f7VqI%)hem(*7^^+ zTaNJj3csQMU^<@A?^a1w{%F^?Z@a1)>DBn%c76N2UOf%Zd|&U=w_WwLjH>Q`=)3fc z-`0LEqpCg1`x~a8d%chLyEviByayYAo*@d5z5(F2Qiu}*tbw`huJ{xe+Loe>FggVS zPaKknrs#r2)GkHAw)Gw#019Y26N$ScC!=LD%dm$h;_jr|Sw>={ojL8viE^@xI{(N} zr_59Q#&vC6t0W$zvi__k-~42xKi|vVlvhct{!9E?(H|1ef0-p!3SQFSL%D14l7^>h z2cQXBH)VYQ>MYjs;F1%%H+hjB*atz&U;3zMe(>^_Kay@stnthI%cAcjez*y%1Wn<| zdkqzNuMyA4dkHf{-U-p@n`m&eG zE+{BkuP44F+g8XgsuK)Ath1e}Xk889f9j|LVXNy~(2+0bQz42K;dPsK;%n2J@EOJy zZV95ZB3R>$bV8kp+0sDp#Mj8c#NB=cQt5jvw9mWm%o(+nl}_BWh_7WGyT3eW5Otui zyM8~LH)M97Y9ubdc`zIH7Fkn?=|6bT zpf`q}9-6z&cj(9732m>{?mg(u8dC7DSrdDYe}1C-Z~N6Tb4_#Fl85){)17q7dYnyy z(}w$$?wyqENwZtrW?kP<6xo2CVvPxyqeRK{R3$-nH_Vql%C(nrJpR@0Vr}T}FM@m1 z&^`(p1)9MF?6t%jyy_HT0^^|ZhdqB*ZpeM}*rQwxnapbAZ|>nYl?mV{>NrqB)K7Vf zZY>UyH%w^l8zF~@qDv?Plo13_~m+6%8!Wk;c=rg|Zv*)Nvee5mx)p+tQ+i z?9=o6MgMW0!VCEW3|YLBdGhSpFWlX*JlZ|~UOom#JOV5A^UP5%p$R98g{KFz;gOk$ zfME@yngT0@9c0Q+Vx@*vq^%UgIH*;zXrGBtJ}p(Q%l!x5XQjGtA6aek7&Uu{sM_JT zdC{frA59Nm9KU?*qOH6v#R-_Gq@->aVYcpCU`zy@^-F1yINlQ@N$NGm17UO{K;|jI z>uidns7xF42Q>||oMub-N@#chwJ-8TKnYOS1LZS5gdP2juWz%YZ$UxdB`sMa#M4{3 zC29V{hi;@2+>@BC*e1P4t6c%EB}{6VZM-Rrr(0-(3G^4<1=4E00S?W&ME}ejYLQ9( zGwGS9dnQ2n^v2)-z_E;$ODgl#Vlx+D#5`*okdxTPoBRVd`Yyj)V@a>Pyk1KxGC%>` z-2D+dcjAOLmha0i*(cb;OUQK15mM1JBhhl-o^2G<9(1=~^>I+m3K?3c3`JOy9!xn@ zTvQ_=0(1bW0J^Wl8tDY6O+|-xd7-O-CrYc9v7-C#FQoSOr1_wAsciSV(iC?+H>@qu zuVo@=9blWR(b|%j66@4yZQ%@koi0hQju7<@qWl5RKx?f|f(jt0aAKH=^GV8>7ca`B z|GoI=nR&dI^!hk9;2YkST@-aMXzIvm@*x$zVD->F&S{{szwK>p^}6LIgtLXO#l9%| zW#MavEFmb&kT8JzVJr%{LlcjSO9=3t5QUTk?I+!k>$s=pyUQVYR9707{rE?kHi?x8 znP~3^iuxlTWSAp55yhJH7tdZ3yhd$V=$?TnJ}aaVHuV^2TF7oP#9{*()tj*0^t>29 zLvJ8DP0wg2`v$W~4ETrt%Z6I8-=r#ht|&y2da*B;7j@B!QHaVee$$C*hQNpSRf7dS zoF>$Wy;*9;EtyL_OMz;6fhPlG5DL(UzY>K_DQE=JjhH;>{S4tO1a$Ezvv?k>_2riv zJT0F?NJr7yA)_5s=~4=75ApN?^JqX3gV2vcPbrIC>8eF#k;1gX+Tns5!h+Ur!m^@! zm=T|#wL@G}Evs2v3z7ZT+DELM9CmSewF%>otlg*;?cCO#qJ!a_dACBnuI7R#5~k2EhxzFg(mj1dK#n zH7yAl3uTo$chrKp-%L8avRUVCv#M4u*tKA;I=OW>9+=ZxZZ@VdEBQjhr7UDit#d43 z&924I7d-G=&w}61zx&Vm?%%BrXWPCSF+6YNlr{6l(LG7y>l~T5GNHCkHdpX7JS>Ya z^;$I6D-CW#zz>#y3>Sm~p=JXtfD#JOP2_OUbWXAhs22*`0Yv@i0`?xCB%LqF4%zwS zD|@Ld#dk^>h)#&;*h2XT(Z{s|o3(c7*f9kK!zL|#bRYe> zc#Rd)SWW(!f4p>n8n=}5|MkZ!SJ@>x#i_8zub}!X0_$^lEK*vZ1#DokO}*?LsP%D& zm1k-qjHP;vx_Hl;0Gq)oVU}x4m9OMAZoABN7}a3Am$iEtYaOuktV%Q7uwQB|VcJowJs+$*;eI7IqmGjLm z$o<6A*5)vp=(snfU%sjJeampSAem6F_-Ff3NO28<*P%3KFv!wTQUY@G*eCp;G8b5{`IDy%QrK9U~nMTn7poO7c(q zTfTSs=Ik~d=DU~Cc+jFLH$L6FIi>z*?pxBay*t*Nh+wa>=Q@R+UjOFAuzf6cJ>S5O z4eWgV@3sr7q|0x{U-_Q95nH%{J`O$L)s_YZ1;qv$z6u#2z2CgWk@fB`#$TXGVvq}t zDU5-!VYnZ3lYwCI727m)g&L{-3e<_Y&d6TQrfoK|E@rG@%srC7Vy7bii*HFsuk(9j zMrZa4oA%L=&ws|C?!B`=7(8?)zcM5{M2hj58OGutm;GRRX0<6F4?7k9iU zf3hJnU>*(cwr${FDW8IiBG6wj+{59XpsB_7vzXi7oobE2sC6A=00k?(qWbAPHu#yS$?>dbLBabH`_}yk+4z5ckQOeK&Ya=*z-tSnq3)Rx{Ikb!6K`i1eEi90 zjMlpX4NR%4Zv^oA{+{)EY$r>O*m5bovJ9DgOhnEJg=JSv4|oR4IwJ1b=;9ZC zn7vri=Zw=n_F$?u2i?PMTfAQRza*a})FYx*dKs@*VL&aQZ($c2ktK#@#Y))GU}+NO zWO>GA?F*D*B_LJq<2z~&J+!8WV)~Wc^pHXi^&~coj53oVhUzsKmn15QbpqcfXMhV) zOGNfN8zz04zhhNxn$z8&sXGlV-`s$ zHt#et(z{g{^|?E;Yo`SU*A8pg6eT8FZMimD)M;mZ-;$E4;G86*d4lrWo(UkJuXl*D z*tIUD^+2R`!l*%fIvA5ogp@GSr8pQ8g4B?RWMh0fZWq!67*>F;Fxn91$@o8>& zuT4?5pYqO4erlfb;}7*Y$~3K9sf>e+w)Ii{L`>4;jOqLE7W;spMsy0IUA0T1;0LoD z{Y2a!FgnA;cLBg*WUBDWQ@nLm06OA_!2>2g{3D0u+m1FrnU|F|{%+Nk_h z<7aKyyatUo*G%Lw0e3z;`D4FhQ--ZrJZAO$EaJX?e56tVM-zo^;C`Nt(g=Ukl@oFf z4ETRtaw%gnCYCJfI$(}HW66YllS{g1%DosL_Qj9<;f-mR#^tSBxNqL(e;40k@9=eV*X7KXhf8%HxB30- z8O%PZC_TSy@{}Bgl>v0_z{o&&!Lc|Kr-nF#xvP&E7nefkEU(6KVhki~3=;X4J5d7o zU9FZ5qT665AT()x<$+#J4Mtz2jGD=*kr8kv6B22`Sg+LNd;T|L-?9D$9S0ASmHK%R zDYEkYNp!?sJAX~~`wu_<@D~{yxXYx)h{@m6ZsVSy;KVKD1G z7~{>3wHg&qzlXh2gVgl2c-%VD$j*pRvILDomJ$@1G&EnClgZB_k1^nW(J$BRZ5xc3 zjt%EUR+E*#&hVpwGe$~d*GS{1K3T&qe*9zimw8c})}5sDxrZ-zJUrRWFZr;R^~Wq^ z*kASH@01^L>yl9;7HHa^2o~r%%nMI5BLAv0fFcHJWCam8K<`eIiwp1HKvJoRVbt>r zRjUrqPH=u;S4R>iSSBPSiyZ@Qo9x+gq;yB>GGvsjG~8FE6jSaTnla0H`J9wLZqUS$ z{E35=I(7ZX0p-h%(#l!OH&37Z!np_Xkf}{pFJm2=zutM7yd`^e^E8m(_8Pw=|A}mF zJnXR1j>3^FJGiz9`WB;enw0oiKAV3>JUA%frL2GkI2|XyeA-KWA(7Fqp1CE0jk7ffo zQ50a=MZyVo?WaHaPb~TCf$fhSWh=V3?AOk}PpWj49md%f@D`eGqB!-wdpOmg7^C)u{UAfB}t*2xuQoTG#3;Cy$RrenJcT?Rb zJG+iJcO?Ha5)=3M)etFfADvA-p!RCv?!;qnI){<^wZx6|sT)Eud&9X15SjLdXtyCD z;7ysVR5c=ouw&3n*qgT$+SnS&ern5`lq^^0hfUScyWea*a6C!Dh-$Jl@Yt9S_Ohqz zq2s%bJ-9ckK7U z+~5M~7@%7_dkvP(yxRfhAnZ%Wo#SNXn~*BC}PQB zT5h6Vf?-%<#Mw@GU@7Wgj9K4z+*wHD>@jj3Hoo(wlWcq^+4#=g^t>29LvMfz^elyb zWw3LS6Wcbi3`T$&jt%10p6rgkWr1Nc>kUX-xe<4uVa4Ozw^|OI0M1ZJUHou(%U&N( zzcBQZbI11_Ded2}^J3dQV}ItqDF+XO2BTmpQ{8GgTN5?h(*uI|+#*JGdxny#CPxG| zjRF2vqdkcnJ32E1E=s^H0cs|wFaiPI1qVn{?neG-skDTZ*mQlyi__Qdywu$_blx&q zPR~mUWzzT?;VW6GT`Xufi&@=q_Dh_9#;1NcQd&NJMd98~oo0Ug4%XeP_%1qbv;yMp zB{kGk|7^i@>K49X>X=zVvF>H>EHn@Rd`$ zuJZ?@zM7NUwQ`TyQ&(=DBDHyA+^}Wsmv3V={*KA|XKurVwXW}t-Ej?TOenr%Z-N_F z3Z2>PrYR(rP=z=3@U#~~kyNCNjl6>zAbI90LXsnfDsDxH*JMgcW}GJ~lX;o9UYWkc zr(s@nC7Dd5?FW6}XRIk|+I5(8fejLuf$X7!C^lsOkGr=HkLp_chWFZg&rF24p>dKT zZ73mxB1MY?Ns7C>26riLA$UR|5L^qBjZUBx_ZANImKG|Ux7D}C&WT7uS^L- ziAaGl!~GzU^S*nm>rLmz8)tLW0`&<3&BCWFWR;nH&BNtq&#vBm?v3piE)*SQtEa5a zpD^$Akoy-)JJ;AX=)$LiiYE@qT|8;xOmVX~3)1-*Ia|DH`v9?T0pO_=@5CvKlluc{ zIj}mycxAg)4l!|MvBzPl5tP&$5s8bI##T+ZaJQTK`5q~&l_IZYO(N9utbLE^o$B>D zNjg|%7*+yM+}jQt?6Y2P6PL+3QoPWd<$Wx)dAkvfSt%~FUDe*3FAN^c-wRMjN?W0~ zB@0aj-%^R$g{Hm&y!DNIB{57)5K~1I+;_s@!8^eBm0x62>|xOI;?Q)OLLMw!2bzXr z^W`cM5As8MFbWu~%>sw_l1}uqhqau&X7Plp)AsiOOD8ik{j|IoU&jDf~+UE2c-nNfu7uKwt-LlcSev4=? zhsrOCC$SSrY@`ny*K8zf%Fm&`94RiuY)NcX8G3&dYlz(y0qMKqK;ch78Y0wC{J71W zvIcC>)lenqX^6>6i|X`TSvI#I+#aRvg|Up!u$bb0>botMY;f%u`EDcrJmO!R5KsBATet>Q5{)~NRXAqY%RGtVN76?)TP+b zE{Mmfh3^hCa=E?yOn zet{IYE+8VM$j_rnXaSy7@eIXLmyYS#W8CQ8y~ap#m+Vo!Dt8$@rYmq{ZRtZPMfex& zB%#pP9YQE`aU8+>@;m1H$=dt$cd09Ig$YSwv~W{Aj@*YJ0T!YnGHmM_3^MX=?%gX! zZ-4=VOYB`hOCvyEC3LNx*!j{e zXU$+|BYZqqY2o<`Hm@zl>@}1SAVD)`w$t(&5vd92T+8T^LHm_Ik zNn8FVrSG1X-!?OE-k#laH)OWSo4d~)uzTM8-8<*c-N%Lv6)z7x+%=UbYs`M zwxZu!c6rjIYetJMoikc?WrODJojP^TvKI69PMNZMnKXUgzI}^ZzP4}ovXY8TffnVyTOAx&`FLIHi)s(QJht<04k5jLK{CD zifcxiS{i&3(M-%yKW51}ViIt2ei&PT&vg^>#X#e86y1$5Z|u56)t#>rRP1LKlxKcc6+bKCH zC|q2Lo62c~DJBNs`Vjon#AV`NwqoF62gT2lr{|?*aLbZmVBub=a6L4KlNr1~Zod%> z>Sr1*u@oG4YzRbu93^G6KaS2oQ{sJ6&gkma#f@VwFtpR zpRp%@wSBIpDDB%NZ!54rymI>Uw`PwSHrLL2s(WSDfql^I^&SNUzVrI}yfSm~%;T4T zey?c6jMrx#pSc)vMGS~QZO~b&OOOC6Qw802JldUcBHZ3!yf9qYp5rEaN^lw8zXfG# z!jbrdH0$t~aIqIHEHMQ(QQkb1_$U(4tfuoAB&YEBfM8u;)M$h**dSom;*x`NwF(rg zTS`(CX~{~mFZJ=mmO!ZPN>CNHJ>pnH~gE+S6yuCwV%Rsi?2QDe`eXTMf0yq``!H-H!ib2eEm{! z%keiwH`))KIfj;akJZ&VdHE|uP=`IGKl%h?cajjRM0~4@+=)NGgcnu#t`WbfhN{46 zLS5mwwq<-{3^e2QAB-1X3X&OXNNnB6_B2ZAp)ssieO(@EW;dz`1IK zN|X)>6a`-bbHi2kMowgCAkg)BR86?0)C%UkQ)>lN;^a%wdYhy;q!Ix09Ef3&5+wek zU04Y1~7}eTS)OlS|@f?voQ|iHF?n&Rr0RiuZvASP@h_ z0eS8b7CWQYo#UK{NK=9@zb6S^R2+s2kI{&Ryuz>zAzfdAiP@HL{nX4Q$b$j3wo%MXIaoOo zKzB}PC&425ycu&fO>zqlATU0Wl0c*3gC)s?a+`kxxBbi{m-GSkq_|i%oF@OeN~bM-c~Q~3KhGLQO0b*59_9uj#tKSz>oWL zkp(l~u2^v|NNZ@q03T~lMXQ5|e^O6Gb4xz-q)losWs0@|SYhN)NQfh$P?$Wcc6>n}%X9!+Eba0)a7s6I+tZfG`k;o<#vW zG*s^=qc$xYIFCh3MliNRym9V!|IuUnu!03s^4{4$BKy;BLuw=qks`kTp`tTEOjItt zv8M7_HFre+*K@=HogPk4Zr=trBbhSH9G7fopgRVGPCW-dN{l8MgKGl2@d$AYkA{?- z4D?9$!WH9%S3YMvhMASYVhsnPgW^CavKS#`!4w6?OwEuY+rvGt;7 zDkUkFP=js`dXF3DPqr8h0VuGV>;q7hakEg4KGm@UCBBBZCl<3hCtaI17jN&=xnnQZ zr&Gs1>Zu#EJ0WA&yQO)@TbVc;(cC@mnS6cxdj*g5K9@i!2mF+l3SSk`h^4P%Dib}#qqtz6)?6Y7ljFz{ju_8^~C6DQq^hd4=j2t^plS02Y=YM zQAlR*mwqBH#PbZ{-=v|iJ5o5eunjDIXzySwSYuZ{G!FK8+;1I?f12CeMZ3q7H zvEU=-@)3x*=5y@hBf8;R+Gz7vCbx!BJ!lJSH*x1&XXgU>%P-4i~Yl~$6da+0aJfOTU^IItcXfN_2CP1G z{P@`d5?BR9L%`Qh&49uwR@i`Wmzu!^}@XALsJ!W;|mI0os}fb?7+AQ^EK zLAR-7Cl*&}#+9W?Zdh(;WE?KH>rS$CJL`Z?>>A6G8hYSu5S-(iuD zvUV*V=c?sjcHHW$g}ZG3*|lK&sWjini7T@f?-Ya9lnSd(6dgX6%Y?kLYnZV5_~9a# zdiIZiqC2OyCs!SCrr#Zx&%wKI?un_|?_%H2PoSfLQ*AA-K&^@hp@Aam*~5f^T$?p` zDi_MAgMq~v0M~#g!V`h}X5erd6+Y7Rx(GIC$L5#nhQ1KDv1n`kj%6#?J~m?8p72!x zMYeMLPDiZp{}eZT5GyPDOAi1+H6cf-s72U8S|YCvq@f@QG7Y#GmFf)u3$uVA>7pRX zM4tFwa5j=T)eriS=NHVjNZ-9XpeWL z1*vt#gmy7=PLGP|5F<9Le?PUJn9w$E&YPoR+9lvMQH6YAqx6aVKCH&+0>!jjlt~B( z5PqOQ;t`q$GEgkJG0fN>MD9e3N&sA8umD%fE-&#tv`(;6tUXx#jHW(}PYb3n%I_O+p>3a8MM8oi#?p3~x z(-<%@ShVq3P$KD${3<>hFN`-o`!8*H$x*HL^lJBbfb zLG5e*ZWSlqX%|RjR($vqmQKmMzA`(t94#KQbJUS&4fq}MAj=|S1d_e!Ikrnc;Y0U_#2X_Ks>4Q0VF6Gn@xIvPNigq zj>Fbm+rR(jo7wwgW{#aa?6c3rR>j5A{@k8NuQk|IbHs?=xh0*j?~K+deTVf#qVf#? ze(pgt7GUl_5iG-+W)`039a-kj)kU6Wmy{5%fu?DQM5Ape|6OB7n=9XZg8 zcu^G+d{yH`6}+fIdrr$tz>5Uq1y>H}1-yQ79v)Qr76}dBXF}~_{(c(Br!r`@el{dp z(D{6`e}D15Mh*Q^(z^F&E48Bxko~FP<5sh+i_;F;bMhsfXl;=2H}d;8URxVqj&b6=Pl2&E zuP|`a`T|QIETxsLeSb*Lx0*V*?aV7M8t!-}PeXXhRRLd4QgU*91XoqG>qZHO@_LV> z;^M^ygUcQVCLb>B^=bEOULJ~E7E{r|K6}y^%g%n|^h?zdV1PBkhHUSM9>;A2mlD~w z9q6mJ)D}3b7RFL}=9RJ3*7!?n<3%I9Xk@(bx}4SVm+Exdt-WZ7x4{`S1Wdn$R~f-Z zR=G>5TfGrUb9I9)HF}-ZgOyt5MF1nfPU%)>^63yQ0u~^TAzC!*kA+9dJlzXA6mn3= zNKI~@L<(G@tD!x?1dwXayfztbpSDdV%|CT&aR077V=6}%zt(@yxZy0~K!4?KEy;*XH$xWzT5SW^~sUO`E;k zd1{wchkEYp+iO&(7Ogwf?>HfA!HMY6?Pu(~e7>y!y4OP;=lI!n5dMhruok2X4G@9Q z3YEAz3*Aw}p+9)+aACAC301jf33G*o$QoV2PAkE=D`{_nIbXtK1w?KHlWdB|`uy=_ z{@9#9X7I->{@8^-_TZ2G_~QWnID|ir;*Z(nu1Bd;+(Z|Gk}FW((Dy5ZArvPe0wo)P^eiH^W?HS} zFjDIDAFkl(zlYIZk#xlj+bEu?DmC{J<5_y?wSj}@h_i+cnjO>-Q@8Z7l!ih#$lMvG@8jI0qfQ!f!lDPtHea}-(sLf_)0b;Q1L>!I6MbD z9omVaVr~@t^5h?-AGxgbR!QTMW^zz;Vn)y1>sA(u*TuTkUaHfpN6NKp*ILW6D9iTt zB`=n|DBb+6Zr!rUi!$cqEt{QMt5K~!^&3Mp+~;m1`)#J`jrAZm-G&rxM-_R_d%3i3 z*v?E37(5o9=ubtE$S(r?gFz37BHebME*2ZPD@%E{mXA-M3=T;<-NE^qL8lJJj@8!Y z_L5u-PmwhN24yomjuA-5TFGk)L9!FoO-|SB$sD)4&-rTQXRQ3J`>S)mdQEg4%2{!+ zC}-IrF?mzza`ncOz=D$Hiyyu2=luNMg+uo~2cIfErnY87pf8mn`-yH6;vkX2YVi(0 zLMQ`EFAk(K0v+`%*R(V?gzd|#S1T~O>5}}1dz_&K0q4HM4h~T_usC4@Fe8*(Ww;TQ z#41LHa+2@kii_0^@V1J=Jo#hsw*3}pbR1P+G9tSg1q3-_94U^5j!Z`%hrJh(C_mG5 zPX-9C*3vI9J%;FkA&vYgG9)FuVR&Y^t(P-|yE2gD0_R!<&xff9z2{YhV6FVLX1~|l zh==i4L@ts!B_R?a-rl-!(bn}DEn8&dpnl)v>hU!?^nInqYt<8K*berYG^tPRMvZDS zzl>q6QWo&ew7JSMniM)#u6?x`vpIW@8{aGK z!r@S~d&bxz6*>Jv03 z2=IfchTJNL6Ql@ZZ^+@{6z}a>w0KW`W~&yNeK+hFY;*P*H?B{5gNA9JTmo#v5%R(}uPK;n$@yb3p@%VbAF<<#_NppVpi-^Gi2+4J+x z_ibEz^mCPJx9!`g>WrkATJqPMH$S-la_<%|R0?a@zxneO^_Bf-zloJa2>tlVY|xGo zHDHUerP$y)mpQ#L7KGcOEnN|9Jdn)+8y)yJ$pctVU`$|2V8g)7z&?RkPXO%s4l4Dl zga=Z!B)XD-nx#T#wxWs-aPXJ**h^#Q%1{Q$X)I0o`#2Sp~iKN z1wq|U5#S)iw~F{aF{Lc_RC9XarCkHpmj^lX%{->jBYeV_z$yp02xDQY;CqL__|^F= z{^H(!m!$YBS95INs*kp8VMnM^#{UO*NTYH8?GAy?1p}hszu%$CsZrKDr0#k>8wt;r zO9X1YMP9+y+v~xqg7|XH4kHttHpAnqji@KNI@;@X7%*n>+_rBJRS1I(C0ovc^~6tT zZsBBJRZ$I1o0}T&Lh+S3Uq=AE$07%+PH*D-5a2}HiD#*~`>)Y&vb($3N2lDE*s9Ac zO8rjGc`}|IWNvU3s94f3`1U}^_|d{p?fW@nHoo7myC_itzv+lncngsVM`EHR;cFoN@mrIcNLES7*hQT{md+K_-T(3;K7ukkhHd9vf+jeM^6pYsdxQ z4s8_4k`>0oZj9v^j(w*;m+cXJV=>u+GkS8m37>fj zPyKEBH~BaI6XpudnYCdz+mg2^C!9?^`3{1ZrQSOpEq?dp+zHp;9RB9bG4pWZ*mF4s zd+rCHB6?9o@R$dY0$BcG`(e%chYWeXpYXYb3vm(zbuDIkDI2!!$#O}(sy^DhqxjOB z$K{*_e{N}8qJAJfDA|7NOrtYzW7h}+4gwl~p`-To9LJ39GJO)TQu(JScl}|zj-dw+ z+CeUT%DCmRjT0_v(fAaRFLiPMD2^z(BSpJ6is53Qij44_4Jzj1P;3MgzCz=Fx&xew zC^1x=&>H|RhYa^h@h@!cMvc-C_a4!Q{h0U(Re0=G^&9rD^&L8}swLeKSeAV1=*RC|?s)pcjGtE$^n^cM z`H6LS#))~Y!MMC!_%_Z`@fBzpGhnMMt8Aye^w=hmNcke$6rwuSeR!+!oWPj@XV&68RCN9PK2rB z7OUgKPGFnIO1a=3tHg+s?$S2*FX|Y;<-ti`>Ih5*Vt$SWG+z5{pa&mjUNX@}5`*I4 zPlP#)b{fGPa@P~??ZClaC!~=jYXQI-X%z8IqW0Z!hbcm~xgu%xt3k4jh!wAUV0;ZE zP)iy&D7+=$4yPL|a7s^?RfuwU897iw_Q!AU<6=hL|Bi);#}8~=f5@4)X|I@w#KC{D zn#}Ps3V_v8ZZaAC#zRE(c-#{BlH4hK@JBP$N41-Ot=^yg?fUOo#PI{0)*g@#=5N|3Chq#9 zdEuDL0qjNQ^YUIMEmhxEAK5S6zUk_8?jv(QD`P*AttIr+D~UM~he2Lif}P{N0lRU* z_+L!C57I;@_$xh|i)?uAQunH?iS=+!!tGuZ9m=H>n5e|=>US=-@BMFnV6m6nU;jCA z$--H`l5b7UDc<*WH#OQ%gehv^XxxjYpn0ERuPeh&%E90!XahjA9E(_yM+HG1hAs{Z zw1vGO^v08`?S%CwmTW-YK_f5}CmR-Gy)A*qo}5Tk>;SryFjf7e^Z7sCy70)AGj;63 z>8y^k^B?7q5%RW7>>EGB^^V)^x)Zr3QdNri$gum1m7Esp)U1>6ckz@1D|# zC*v_G=0{4E?Kk`y3W^;VM%|yD@iks66`MM%uNf0RDv4N2Q0Q zhS39HLX%e#{SWyE{k8K!K$%M?)DI4-C5)*L-cUb0&XTekNs~(!*2|IxJsB^pv)M{U zXz;?oBEN`V{RLg7@X`UiXsK}o9G&@2kwPLc&Q0vvlO&LlK=DP&GFM16ehJX9Y0t5k zJL*KX;g0&g`q3TaWRCw7^-2!APrHw@lj{3@&Tp;#crVqHmu*`Bktds{t$^!hD5gYG|)p=#!~mO9c6u#De^sWt-T>WjXm`!O{itviUN5 zW!u36g)6onJW${`bL8;3qu2owQGSskpxYx#ix7=tx&ea8jAR?v`_R@%GQS&&K9}ws zX_ZsiF9jd50ij~Im*z~wtT;SzKh_y3bX0sS_4jxrk1@F+16Y=WDV6XDZhn&jdAl^q z`t^JxJSY@S5{F%ej>rY+1Re|;9wf$z``vq4^-+!Lw{B6eoB6yxqN9`Lj%4Krzw%;( zHZP4^JA3rd5t*w1-OD(I*8yFUFjiZ$7g$D>5Jf0QfXpCU%dt7aN}-VK8-T}Q!UK*$ z2Tx(VNuD>ulepc3@&-L`R!WN1Zh_7}U|MaOt(|eSwk~@6ntP#)Gub(IX@&m9{?4Z;Wj>FACFg?h&9WnsAaWiP0u2KK}gn2Jk^ZGk66MY9E)3Ta_B( z5VJ;%C{UN!+0?D-{JSBn+T6W+2a9$!lEqcT4)?$g?*(^-)oIqw##T$kIiGN=kKeuWa^Anvjz=l-R$MI2=)<$&VYNr6b-2; zMrfx&&au>h+>jsW#F+_+CA=GMC8M1g;gPDHGL75}ylEA4Ihr zH)+w9`O9{H{`RcYwjmuFHfYyEik>Ha+IH3C39s+UOTG2AO&wi5Hojx0%o%Nnf>8m; zo&5ei{V-iy+XQ>n!Oh@Pys^mm@KoAqj zK%|t3N~8+}fuWN5H~1Np81ofTINq@q!T#7XUBZ#H%O4&Ik%oNec*Yhko4l-0{k1To z(d4|Dv+|a-d%0ojHnZ9+PjA>TyI~`->7?{}^M+5II=o503h9%EOq!(DtyQ;ft+cvz z*{^9eUZ_*2XFB0PtI|i}I;=Ys>(=Ep&ZCW0o19n-;`O{l7*tW5BSi#tfQQvWsVQLE zTnB}Wc<>slf`F_qCMqJ>=18kqJGrJ2#vUHY{(NQ7q@3-qE!iZgKC-T*yTPtiMDNupv}Oz!DUNuOly-zk9wo zgW_H#VYA#w9Bm(m--2*U$7!d_FDAuFa1(7KU(H)I#v!A_0tN0LYba)leQ2TF*VrgT zGy66~3_u@Y40_)CP%8$f1mmd$i!WVQkG~l#vz++~0KpyMFeo6l!s>WqMQ`32H+Nvm zW&`>)Z#l42YGOi-8VQwa+Q*&vuzA1Uty=W#{Ypa37Za0e)&l&|&}~BC1+0RIgl0mn zwvr_H`IC%@4;}(VbtaN@Pdwa<#x+%ZB9jOM(W@iSha2GnQ;w_*EDVG_Gu@2dP%5T# zrWEVL2P2=bhWR%-*m|BK#$FQI^Qo<#ycKcjL4UORJ`2%xFLSqJP1)@F#zj@0Fg> zZCsm-#-g~h!}MugL%U3w(w%O=K*YIs)%~hE{pK9R*iTLcjTa_~A@bl!;u1-hQT%vT_Cz3APR6<3c~xb8RgF=|2vQN>8L^e6Y1?yuQ{L+9C|#M9Tm!YYa&JAP$5#BJLB zl(M|a6r~8tx|YbrtG~ISX%*%TkJ40d%F8p4RPl}C>>Xm5r;;Mh+0ewPG9->%FEGfp z^5D2QHtwt#`0JCOKDUXDFV&Nl&sI0Hm$nt4^@U5E;9hP!bo<8r0k5c!H{~=aTl>JW zDY*qR<};%2Xop~{1n+qn!!FO+w*fXMOvVeZlQ3;qn(=A|xnPbAu#dOHT%T%hiYH|a z>b6>F1mf?B;}gn~)dhAJid+>Fiq4!_&)n35rqd6+2aS`rpn2IHO7N}5E{CK3O&LRH z;P4qCSscD+Vu}f$!-t~?xV~kNHM#03P}q$*#l^E&y-(GJ?BJ*Dq3UlJN>-pERhav* zwo~$B?3BM@?ejWdt}7TjWr($$r5S1#hyuwUicNd+6?8?v^y&87@P%^jEbSEB%@b z+V-*~6WJSTfE&eT$kq@heP$bv_)k4|*2~rq53)$9S&FDt)P$`8aR_*XM;6!86GRU( zZuNr1^E^I0A`CL#nqz--@C5(u9x{? z?t$QsKaDuI*kgj2yDRvMFT&2PB{Kw8Spx#fFR-Y@3Vk(t&xh9Y=(#qsB*iIxp{$#AQv*#1e(l9+glO z$yNsi@k-|VW%@F8bUKN54hwM%%4DUm7ri`C0Gi1j73<08Me_Ud`vjP z0uazf8PT3yfSiv|0W6)$c6i?A!TKcPL!^#?Tumas_8)q5CDNleK2guwSTpsMOFczT zOi(x7B7NPxe5!AgDW82drS(*C0@g-$?*&+!O{l3bJLyT<5;=h|mT1x}7~MSgA6UhW zZqfqxX_xqfY(HK z;l|<7S3e^!JCb=u9`6%6M{@=Xj_?+h*|gkL81AiZMVJBNB>aTYbL)~nq=2UG$>Nfx z^jkigp3hp5eUUt6%>b7}Xo!AyB$jBn;$^xt;P6^IsU;q`xUGYurQEF8ji~ct121_N znREr;QATL0*aHX|wD0gT?iuzR3(tkgn#9L{%6t>YsK>LK_}b6JL1SM9T5 zB|FZJt=ypYAxwpgV8^$IfR02P*$K}!;0FbBoh1m-u;`EOLtZ4RI|ph2@^6vRpvYK| z6(PHzklYU*DMy6MoT&3s=V_@d*oN{THq;D3g0d9+Zx*cn^py*BQdsaeF4c!Me0`@> zdslw`E;%yb@%6V$0!EJxcyixwECyI!*$j7jj2&y7r z$pPb=XIwlkpcyZ`NI&Ox#NfgtZcInk98?vg#aRl=`w&%641tJ)@&VxPR7xN<1j|Sj zzhx0F>GzL|KmOHL%)*P=$y7E1{+u`eP`@mz-eoc2tkUo3$$VX1@x1sRpq&V4XMqpJ z0a}M%$(kfc9%yd>Xo!;>w_?G8c|m3Du%|eS6QMGCkeXwBDft=au%ZCoL3g3LoDk?|S1_d#9-%dJw=Irsf z8+T(1@(Nhp=$~1Fdgoz9_4+2te@rU<(N-P%T}~LGL>k?{u>vp3z^R_$J2aCBAR>53 zHpFTmGi-H){1kNra%U+A1tj<2lSb~~;xvpl(0#cz52wMFs+*)G>e{?b?|pgyUe4^9 za|+hG;3(Lje)!_83#U)#jhZrVYE7+!pb_g4EzDFTOBLB?#(F40{ydb+E7(JcS6MzLD9Hkd13Z!fL^PA8U1WLFo5L2uid>m27uU1og z2l=v6iU?bg|YHzW2FYJacxzdhjoPt*)Uq1RJ=>xK&HljWPrw@bFAU;yj#; zNgS=bSmrbNxEKGlFl%ss61o5m-&J_@o2sw5)Y&evg-hMY2Ejk)FFn+7LH5D7mjMUp ztw?;2$U|cE5b?U(2DK-|_K+e)^5?W4@vC5Jmg5F)dybnQupWR0oMs%KQTIw(=RU|n z-ud^}7u9N#zj~fdRlO_yN4UTgL9)77K0`4pCcO$@_MqUijBDlJ+#0wqVT ztAupI7sMv&z%n8EFLri+#5R=ptKqC8+MNF&^;EB@BneTyn;$s#twLu{(jqh|#Y;ux zdWJz%ye=C@QiBT^wqL$R14)%&Zts~vp_57>)RH58gR_G{PCbVMKB0sKa{&+g#PtvE z(&0u2w|Q0K=DBJ;`eN!y7?Zf-mSPBtA0=2#1?<(Nq$Z;KXEXqf#-FYa*}pSOENnG7y^O5Q=bSvoG zw{O?8wtO2_OfqgioUAXR9tEDKtgV=fwZ>t3xl6qc)AVj@-c7`YksSgzgzya~lNuuJ zak<J)2Ba zp0wU)Tc_B;;V#!ew&1Rs#(wyP@BtbeVZufCLBa%ZP`Nh0pKTTSzeSsQS%WyR9LcR{ z;VqM}NccvMIykg;^a9JG4LO_=^bPl6{gon?w@b}f;m9zFGWrf>&zSt^O z9sGekDdC)k#Tt^Un=cUnR*A<$p$l<3dVNGrDe9 zPm#2!c08};H%SEKsNi!>h8@i!J81pKe6%<_tixYlhZie0)}i=lDIQQ+0J&97 zv?^%0@*HxUZ%rL+$O^I#NeM0z7t}0GP~aeg2xVMQ7Z`E^6Ivt2sRB4sv@p#}Q{ly; z4EoHAsFLm~RG=moR<7h5Rsrv5!McSA);-eKH`^EVu?BT(=f97&l%pYi*Fz_iApT*j zKvPFxEa9#dM*=1P3A%R*{U_w`oJBd?9BN~B+O|D^R!*oZ>_0cYW+ApIU#`1}TRe5% zn3JyjL+2;VJ^8MB_rb*Nj~2ailJ9%zukcZ6v4l$%S&JpK=qX;;*-L;k4uMM%2I<8` zCvklS66jz~3&;*Y>y<*3ThV^+WnHLuAR^AsD-e;}(~O>(wVx5sX^((C?KAa;%STftr=@n-h*mL^yr`Hui!a0{?$cjtl35-slxiVyof!3iJsvQW6ZYvfK{OiU zg(F@j9WPsoVFl-VXn1b;3sZ)P@}sVHGf+(vGAJdf^o`1_d0$JN5 zXHZlLqF;id_yI&wy$7t03qpDUHZK`f9>9_|?4G7xc!r#c2+{foi0Sw&Q58F}4E(np zb|P4qqd*=8%serT4#ew@cp1A4wDDeYfbTzE7>~_V5q!8&)@#Y$>*J0;u`wI7dCxF) ztS(-O?bT++QZxyR&XS}*!l!UyisH|4Upq@L=IKS^yujzm1*dl*MDKW@l~O3si3u#sGr zkp212J0vI43KGCcBJgVl7x_Ow3jBcWh89JQMF;mgn>e`_4s(#lI>_4 zed)n%Hf!ar%e8BM#cm!w@%FLaliaJnIM#poC0lsC`s@`}wLFv9bDPg!iTn1xkHTI_ z{(;GA>2Gz^Pe3f)>W!(dvFJJnwyWnMDH!piN$fU`+rd5;nyH^d-hq;&ceqKyEgTCB z2!{O=mk8?-c*9TJLNE8*f4_x>xdvpCSGxBv!`;Y|KUZ>Lfv}u+pg+ zF=4DFp|;sU66@8CFeI%Ln`^QpS&>S1z<7iEWJvc>upP;k8o*xI$Tjb$u~7-u_6z<@ ziwPW8A6`n{+{LShJ&fSE_f(o3!v26^>rP#jTtkMg8!`yuew_cM^L|&0(Gj*_`V{|P zfAWuq*bmr9M;4l&p1oMf9u3nuNeZPYZk9#{zDbgjSo*7N1SF-3sP8aLiKxsk4l);vtP8L6GA^nT7sycw1-;**THYR! zzzMf*9M9?nfwUwD!1iv9O)*=$NAlk8)W)8>~TeBZVfR#oRywkJ9BKz9i%5J@THmy;Lv3Dsz*JVM(e(G?_JQh?$}* z??lZ{014M&(1YXPBoSNuhgA{h|G4Ha^;fC=+2dV`()lSP5zfa0!~sl247sZ`}FfKbl==<;LzcHhVQg^umixMD+uE)`B8x=?(EU;ycnDz zl3P6m<#_Vr3{;;4dn-rmtz33FVsG>`)?$1nb zmaC5ROVk2P8isG#DQ(*j^^`!0&;HnmiUW%=qrwh8<7Tg7$JpWK)_YU+(U zG3zR-zfK(m!cWxSfs2n@q1C$H^M6z8+Ss4UaN1TjUU*qU;`M+kE)K>TzFlC0R!&8v zsM#Ze7%Y-8(+oO=4)qTOuajd*s!EC_%QCDvAPUbYcy0KDAw58f;03QoyWbU`cdtIh zYQ1?nZ^K*Ldw1#ByI+U){nVpI^5mNYY^y zFO@tP^pEP|&r<}gTe{(Nd5;|J7;r zGis9s@8i7r+3NR4jvUGFmM>=A*t7Gx-0in1{RblD1-(^ZiLHgW#b8jzfl9dMbA>!=-y8c+n7)`9Yh3KlT6$q*wg;6F*f`0w&4XQ%3;!%_|I{xCIQA!0S*gC(=Rn zv1`k<#$28Auk4^gSN6rLzqz(AKc3a;$kOd%=$4XY>t3@9?(@skchyqIkq`E%)%T-? z7uD|k5fO0hgi1myMX+SAbD6~e+Pv2m4IbPWQUjzaM2vZvPk?Hm&#Bb1*l3|@6gr?H zUt*&HYki!yDHlfHRi8}ybj`8fe4IYHLvuG4%$w4^_nraBQ;#ipwD6OI!xp{sR@^D- zuh0W~jKm^HTotj$8Ygv@*CKHB8q0iJ4R8&0itn+ZDk^rF7gzD;PqfD#219%7p(jQ) zCzKluNr3WUmUBv{a*OsJW8ax`dW>sp;FxPOu1{pHJxdR@?{FYzx0tl0BxkNz>#;Cp z`SK_E_M(rru-`U(K=7-bWdVC!0hvNGl$hk_aMn~0->@fgR%rmwRYv0l7Y-=moV0l( zU;>e)WSIbtTSPb|QhO7jA0F2cSt70cB8+sVsB{WgA@Ybu$`mG^h9!zx{d;|de_gsU zCa6GsaIf=~mgx<*WUgB}=Ipu0u3gIxb?ETMik)K8pRDHEIVFL=sP6QdORLs&?s@Jt zR_B4k`SDivL&1ks&9w_I$3ok299zU2{GOnn$j{4u;7$R>`bYrw+Z2iX69DU`ri(_3|f+k!$`?KGPy}5fjcG$mspBS>a zWZ6vje{7%3T%~^ZeX{e@b?zr?@6t+osC}hUtRx84jYcSCD^#SjKs>mF8&Ajd-%pcY zBV#3|JYnNaK@>mj$>Uh2!}D}-A*9p~4;swV2lk&E7sdqQ))!xX?Ao_{SLd$VR_qfi zKV-EQj(eOW%2Qa{pN@lf*N7pxcd>$AxbuHt1>v|){S_armOt*ZVW;PC8ryGb59Kts zNx76GZ3X=CNoV+4N^$slMNyzm^?b z@bHWFhZ?6(%U!o*%$d_a6t7!+sC}n>OV*2(AG4G-vrBB>mp)%*X{+6v>&{^{ANw4A zw~+n3@fN7`ELdqOp&Lsy{IX>%5lS41jA(R2;s)Cz??0HIH!^u5j!0Jt`%d>ax zswGEQi|ftaWf_On$6syVgNQaY9mTd+7VOobjz-6>c<4W6EM3K)3AGZeHOE0svVVYF zi7&(bL-8p`8pdbFLw5*@kHM3L=z;&((V56xmaH$!;n0^w1~OZ8Q}rw7N%ez0(nePC z=x;18{!Dc7rlUXlu_^B^7NI|Fjjl=S8KmRFfckKQr>z1o`es6w2{d0NU8m#$7 z;2`BxgxDxkAcC@R%@`Bo9&y8uaXQ95qR=6WT?{wJY6~F0kQ@qMiYUVoMkNmro|m9N zw`6sSHN3^K^;D{bRLQ)5Hd-Cil5mAx2Ar)gFYza-X_1UI=d1$}- z#V&CNi`)MOi`~xN8hv@@luP5-*sD{|{vw`xM|Gk-ea4maw^=6QzK`6nZ9}$MuDU6$ zP*qp6dZk2PXO+qvda4ADiV_;P1a(T#q37ma1A0?3k$iaSAX5H3jGPFO^{QeKdPND# zLQqNYZwuMG_VGOR#!L10tM_(D+gSX8gDh?vU(4mO##-J}4|G32^^Y>etofz7H(1u` zldAI_wwJxPR$k~N&? zMW?5eErh2RgLEU}greMIOBONrOh0Mn;A!hzQ*O^X`Nc(bp*Uq8yE?vOTE~$qCT71i z@bgiX8IP?-b+<0UB{34(Zd27mMAM z#1AgJ>x+IB*XOCnS*uZUT#2t(l14IEmY5?J*iN8Z?|Z<(d}QGAZ{*SyU7%nbHI1t+ z=A*0c8+un?a~y}6#__Jc7}o>y?dIb?=JN$>^BH8W#)}x!8DsX_j$y7(tl!CTk>;Wb z`t+T3@tr&QT%TI!;@&rm<8x(Vt}Pt?JA6zz?fXmu01XcaOM%TaV=Hl$xQ>th%=*oo zLeMvtqjA8>L299Flb1sp2lnW-RSgrp)yD2gBlk#QNF(Q>H)y5BdI~k&Odyv~6*u%L z{DG*maIh5ao>hCyx+}k__kO!~sP5c%H@vlT(eR1!Y=TsFzdE6jD5?*?_(lD4+_FJ8 zcjO+c%lklQsK+4X5bdZez_`SZ&xk&-&q-RI^_;L7`{{Jm3q`#Q?Oyn5P!+mRUVMzqSICfx34*ESEcEYB^4s@6qJ~niSvx5hrQq__B>@g;h%c|8gdLcR-pCE*t)Lr~>0Y91EKv^A5P`%d zkAADz!nv6bmRHHf{V^840s$q~ysZ#$AuDl_Tq^<`M%BTiw-jZTv%5uiA|@Zd zT{`jh{2!Q2T&@0bXv?IeY4?V0iQl?}BOsY(zX<$!g=i7JfH*WEwjz6^<@UDD< zUA#Kt{2=w`y~jR0I(g{P)ae8IcUr=dUsfNw?c&4RA9U)k9t+yO@W2gDwJIa!KR`St zB1e%PAGA>&RJ#3L-kha7iz?6)eXQ5PJdloGK zA|d7Cz{)`Z7pB}v@xe7ifw&@KUg9oq+r~DYW{F$a7WLx`E!2Ns{ro@dyASTM^5W}x z;_N-@wX40}QLpV1#n<6h4t>dm7~rdC|ymI!^`O8 zg>a@=nnHb8gXke5m@AkOUX8mMY90rZA%iSX7HSHzToxw-E|11-VL&-j%#iyC_7C$V z<>|~&znOlKb&*_b*qH8%lU)1uxmY>*wt7ELo#{>!Z%oYY+pfed-_FaU>>MyYIgewN zUcu0m0ZiG6u1Ap8i_fc?8HG*2w2n|6_+%_bRvtA$;s{3`?%7S1_I>l#2Op@<%Y)VG z-$>~tSEckk)@<`;^%QEFKPdfC%(gWGUXQoP4ThP)2;zWxL>Ww|cS}WGOd?BfbCC!& zN3fX|I3U1UHjY~{oXF%v8ZOWqt+Mbzo^Xan0$Rg(9^DxMdaZZQAo$s$YuCQ}u6EIoy0$rYfpFC`nxh-d9b~u89dC}_AzWm24M@zn17*u- z`xA5YaN!Z=j(Q625cvTYW=NvaU|(f^VjIh1jsNzEK>GuZte#J-)jolU%Db#Pi^oip z)n@WXwhMS4k<`!!rn1|m|H1ovftSr4jqrXIZ7+oA^hCDw8KVRB zz0^iGG3PE2);?o&u)detXoop^xNrfZ_1!Tc3H9tw={-RF8i)OP4ffLAp82`RM6la* zXq+I3uUbY=6w*ASIn$=mc5QU&cNpE=L9lCc7nC;gj5g=?(O@tA0Hgb$hP*L)cxko= zc5}2JU^k?1tk&k^Ak3-BVc&s$H!;UtZGetBlaSlz>maO5)mF;dvpU8p8ODU7IDMs0 zkDiEp4?MTk99<5uC+M&T;Vzxzup@c~bZH`6?3v%t(TeQszdMM0U1s`_fQdJXa3O~yJNWgHz=xm zjlF2XJY3ieDD?9*VXna*@LrWfk2u`+9_A;u2@fGTKmCd7*u~oVE^43XqkV!X7^e9N zGxb!PNk7W%@O}$?CsDA5oPu#%I^V}u`aWLt>cqhqb3`99Lz z*hl1k=qF^(9INk*HZ$#w2FGw=g=cTf(Uq|`FK8<*y@WZ3*ywgZ`o`?da!QTaIn5xr zZ8{`KsTR{MV<%QH#~SXABD*%Wlme8h+e-C$9YR5A682Ar+nm`)gS+$;M!&*213}?H zZ`{rpt)GxN+8=Nmv34PGq(Is+C%d@HJ? zukz{96B#!AZ=<8FqxtF3+&G<~&lu|k2f?h3-7(OF*@Pm-Yb>3l2J>+Afibb%9G!q2 zsjlPfV%+6Be3jkwRbKYM&E02omZ3V_Pmi9+I(tSNZn&Z_>uA18nj5R^Yp&9q+1PDu zW`bOUV>pT(nvk2L%L4K^9r8%EwdCZG_u`OGWEDKHaGGU>TpLaE(`dUeypuUQ538iH zQJ6hepPkDu_Mb6clhm?>%j{*t3T8-C&N6p2`;kWDPGB@qM7xkZ(#IHU&=zM^eXJ%K z1)4J#f;y)gqs^HEyk`DLpV=W4q6ZH%Mw@e2qtVcsDyo^hQd1;!jUk$J#v>iUOSp(> zBuVlYe2*x4%(P^{zol*CYuV1^j{QPp4{=}swgGznm=mh+Lbj&&TCG=C( zDJHkXksJ}Db8d>*_>tcka3VfB)pKXK7E1TP;33-FUCg-)gj>&=TbDZc-2ArF+_>!! zC3HAEGwXCpo4K4h^Hy{L`8(8xET%zy4x=@ww_0zyId`Jh+#aYm3;$+a4M@x#iTf{5 zZ|*>qYWS5fXO7or26D=mxMYp!B<$X1VGC<&j5ejD3i{0G7ip_z7lkCDC5>j=r1xxL z_+9xmhK*BVV#ww~5BP2Dk()7hV-Ur7m;Tg;9y0N+aua_)k{Qz{22RSpH1;07iwCsL z!Pyf$&Fzn|FI6}^*}`g;VbBIc5_cMuMC0;AqgwIv$?j>=D1*m4V|1#+XLgh~XD$@p z!b)`?fH`xJK3bcZXcWy%G-`>5MwxTRdCe`Gb8ltiJos(eR6qwveuiGuj~n?6Qo*Ud5m3R&F8-pF*V3oTTMJjh&}}jP z!JvV73!`+S6Y17o5msb%eu@SlSBhJsrF-rr;%BWq_kE+gm$b(Hyf|6h>MkiTulLen zHs@xwI#I%2>QEkSQ5m#QuYOt{B(6MeDPJCExyB;6)b z;@0hJ0&_MJmDBLCiHS3tg?*lzXW~qVe)BlaSY+SL6U;kpVvKR8r-6RnaS*jY@m=6< zfpFy+lqg=GnMaQBnOpNaQ~)VLrxvFCn5{T}8Fa`QuipwjvyJW$ z%}jS_j^_>;b32pu(c0WZKQ*YgvR%)B8rmtR6WZK#hqSr3G7Hr=<}NZcrD^U``3{$= zF*mfBZEU+*h%?aEzQ&k^xmY#9T#qq}DdphAU?rdv10wT%{mpaBxjaXF$*`bsx!lnh zquc1CE5TaiEATFW+L}v`<3dbxynr#9U1LXSeb(G-_i09lw&v0TjP7gu9-}cgzJEt) zJnqxeXXVh&s`MB}&*79*n>)MoWe+7atRPOC4#_5r9&9^i&YfMF2oHpQvWDJaj{Xs& zn{ryJ&0SbJ!b3~VxgGl4$Pp5&*giDpE-ZZ&r||UL`e>o7+LcYQIWZb@lNaRQzVMAa zQ8U?4eu8bacdybNLUIIK;2^rI!Le1Sqx`wFK8#oX0SA4zYPy=QMh)G$h#xH#Ic<`Hl*jJmVRW6 zHuVTt%rrjdF16YCDpTk?fst!DM&-`@(pSkXZ@57GIUeWH-WUNmMm zZJR#2Otc0&Udust$1HtxS+?F7&G8!5GYt(@*o*J1$YH_U9F~#%JG;0`Stkw)W})|S z3Uq6Ta#gey8L$BM_vLef?)^4wF?^MTRc~;4fy053ogpt|2}%r-`IIe`(HG;BLaBU* zd>}ET_%!rEIqSPVY}~OvK4W}l`$*%C-1NCi12Qo{xk;bM^yz~fK&3BD@hgU!a)V_J z!d7<5eG#w{1cmTZ@SVWfZe?}c$Fw!zE|b+-v-nM94?Wf)PEqOR8CGk4m${5dIyTvo zdSFMMzIoxgj)?uV`SAV3+lpMZrdVHzx(kw24e%x-c5 z!^+KJ;ip2d*oDp0O-^7?tfEMr2Am?>fSv9KjinRpYone7PeDSNt8+6YI(r zzGIDyn`u}CoraX7*#k)0>cGD_d$1{O8G5+0l1|Mv%Ve-Qb0LdlFa2$1gHvcT6Q`h= ziBqica0+v7Lz2_xPB-V?iDGhpw__&xJaESAny)rL*a7%wg>*(cGC-ign(3)q9PzR?D|9$MQMsyz=o&@f(5&R9kEx0r-+ChBp^yr5u}$$ z69inOCA$F@c0-8RviJX;bIWc3f6wsMcW_bsL3~mlr;ShYhmT8RSD)VmE~UaBq@wuaC!arjObT3m-W>^d zmvG*xZYf_#dYgUDJH{;~*1!3+l#PTKEiqYsz1 zi?yUJSgW+@Y0f8ZGrn`obv_lAPjWp5tPk z!3bnD_yDre%~gLRFbaA(e*7cB#__dJ)aE8fLwrAek*moZFPHM=IUccz*ZRIZU+dL# zYtHfFD-V>D@=)#jqzB4NxumWuL!6YAym3+<+Rv9ap7*Szz>VwRtUORo%Hy>dC3kHM zPbZZW)k;~(8H_s*Ijh}YCT4}3sKPT-8`X$M6KQHa6MU4A-o;JZ;{OnHp6SPRu z&+er^wH|(UHSJjOu7kg_HJm&?&^sl^H$2Lyu@h(B7H^P;l`Vc{Cyx)bt?-U3(|pR~ zw`Apy@}%k7^NEM7PqBZRAqAzYB`YY9V~6&;WOo78?_wf=S-y4O%_m{guF4k&6gKIQ1R< zXlmJ&MKV=O$=p1*edW>qzm~MgMa9N@;*Y8M-kdDA{fqxt((X%aWNr&TW#517wOmPA z#^0Qj2hwu=(Q@Bj%7>$6ULoZ~`&bW(20dGF8OEwh9~Zy3MJ^Fzo%y$Cha;d4IR9dwsq1Tr+t)^ zp+4T8H702b4OQA`+w*+s?_=%Oj=c}1bft`WKjxItSeopu_|n-MAHB?u1|OF8{j?kV zL0W=a^B&7jJ=dkkz4rUe!gv&{nF}rS+o_N6VvE;Laa9{vlV4*$=#B$D>&8}^)J@yB zhg?l=&!HyyrmoRa|5nA;f3e%y_tOWS*0dO-eM@nyn2ouc7Pl)_>kf*Qqfdp$ift8e zU9scY`Thw6)2j>IG5_;#f>yjTvmRfBM$MDTOuqp+s zp#IARTeTc*n#m3n(@LCeDB!}n;660ih*-0wq@5VoZBnbG%oLoO?Y4-6W2H8tDtdUjdmJI{pEcMu!u9=nEcHFy1U zp(ES?e|5q__Dd_gn@X93V-KSR`LU&4sMz2mHR;4wbW~|W$MgKSe#%IeWL%+*6L;X9 zK4tv4b)k%!B@(-nwl|55=sgwN>meK*dzk*nVPZFNsp7;|C3Vt%M|Eg#e3c7e>yZ5NCT1rWOa7(%}iH$d9dum-5 z_k&}r5p2Isy~QD(2gmthrqroQ8$P_%kL#!GS-q07VD8|dMx}jD^kX*wbFUAYLya~P z%-0C!!}JrAxQK36b>!)0M+U5ij!JH+(btxqHS0+Lf27ul`>PvQS+irXlv1U+N?GQC z;V-Pqc*0QT(5H;2iZ6>eVl(~Et> z+7s0`q+TDSXC`*?3Fzi}jk1>&pS2fiBBw;(-Ik=L^mA32o2Kw^d#PC!o0`4buUS8C z^ArwlAJ_^tos{3BmwRYzcv9q%gNJGzPV8}v6Zy1HrtRXPT6I&wLupd1g${mPp92~u zob6bCqxZs<8a2Y8as9|sc&8c-bI#2r7#PuGh(HP6-kPFz(!6<2x0nkLKV$3})C zK$%sJ<^4I_a)fq&%IMQ!dBq=nV!1zGHaLQ{4@aPjx2QvMApx6drH(uiH=rie{;%Ut z^40sZl2-V?YnGW!)G7!gH}ULfpM6H%roK-vHtU+Tc2)wnAUrIk18BHyx?xN{x8 zLEE_P%9l=_=g>NT0AsO4P1t+$u1t<1%{IS{O80T zYB$n+4)k=EKO(S<*v+N%PVDh^mt^U^*i+No(g*S8vl9k*6I=QCe^fQ2Y|;MG@>Ci@ z?Y+PJviK>WBc6upO%b`dumcEpX{qPw4kJR?TxFMHWhq z!_xdTe5=fzRjQ4u`AdCo9-N6Qb&&7X0pTw?;mXIVKgveHsoro}i*LK6q(I9XP;;tZ zi^@iIbp0^>rDR#8Z>40JXQP4#Uy)OI5L@sVZ{~VT(O{giEqxyF`34=em-`|G~E1J!)t!u zMoQ@LYirf#krGOuM;q6}Ps6WauXoZK$(@o0zQeOM18#F{B4wdDR?fu!zJ2CfM1^iE zbF3VtgPgcS2lx`e!`b)NIdK(_I2Mue;rrNmvHjV<4i>7%;>4bS2h;DdBxA!P-g-v$ zMm^yw=MCk<_bo0Tb4KHw+4tzKdlL7^7tm|_yFA?`d%}713=Z;l1ss1D`@Ll(eMN`( zyV$w-Apa1Xh@|+tGVdSKVUXwVy1Mjt%ll+{)q}I!x4x#Qou7o$w@_Eyj9p21!i7QsC6L;WXpMrked~8%K(y9>@ zX&gKU??ww+d{CQgslHttsqty>9F4g`OutUkCfoQ<2~QAvQ1Cp$+qmHu3g=to^K+TpACUwG3tmmY2zNB+M=`@w_vz+(|v@G#!$ajl`&vN5;mhgYu`x))L z2P_>O__=+o9c6uwnAN_oPR;kk=ZIs~oAoKBV^lz`YE^nrjjxWB`c&y`j%S?`=o zTiTF3HgZ-ojwa=UT{314tO1ClmQn;$5 zaehfFcdTG6^gYKqo%(q}=q;n0jC%#u=qB_Z%Z@yI<@vpGk0;ffE%#T;JzQiillyDc zy&VSQAu^ut*j)ohL_Ob;k1>AWlE!ZSg0;kVupW4yAK%BiA@PrL;|qR5Kk&mAn5>_l zq@QSJRn8_ZwH=x$`l-}a>?3WTf`0lQwV5>(Y!FmqRi#dBqnEwIqqiTsrJJ^DS)FBN z5Huj|!>?*$o}TAFlCRyi7oTm3yfI9FIq9<%+?8Kd=3St1WaLn0lH4#&lbt%8#xKg* z8)%W)Zfa~LsJ7?fn7Soo%Z6&lW4@@Ix+I*vy_&8nVFFunRvUAa)u!caQ^WQQ&Nnle zkZY;E8dz(6wD)CDKHlB?z&5>Z=*``a&HH%Fi|>xsZ!f(m5skc=`0Isv^WT4K!kfmk z7p{D3(zbh6Jn-b`M}}PW(13>~4w<^{?j^&Y9P{w{VTzv)k|+N|duAq$xk4mDTj9WI zN}j8GeTUprFM&W>TWS#rMZFBuAJW@xKYEdv`dw?>bWhs{p{qXpODN=bfC)3n~_RM{zkSsviV@yswkmL z?qB-3r^;HHRV=c&l{`OK_8uf_ofSSJ3oelOGH+1syU6|9lt!1a^O#G!3HBb(vm~XV zE&8Q7Sh76Nu4PRmwad}N&Te_E0z$`inU??m`fhpb_2W!JmwlLIzXRiJcFUU*xOd?l zn-hQDv+;Fy%bSw^(rqvNdn~)<_5HZN-iod8$Nf4|ZI`!v?onT>b@-Z$bBVm`D>R_( zr^-KP|F3{rM*)pQD!fSP-2RG36Ez>#TPvg?fz1nLCf;s&W0+Qorcd>_DT$Wuj?Kv2 z2B8}B62J$kEpyp|YQ7or_Z#}o|J9lw`#W|PxJtOO3GAc<*hJEP&aihMf=`}{ zkF#z>jebK9w9feM{^|>F+|Re_(ddj;s(Dh*Xk{m(O>(47bf0RO-U`6u;O4b5isy`0 zcG91Nk}h5R*(bR!9tWpA%=kK)wl7<~@vwu_9%eL5rtRw~uZ)tmj8{5%50v>`Zk_sg zH$>8VTFOaZae;&TKv|3CzTxAZst3hN5!#R&RPQ7!h~3h9l3{A5>+^7^o^YwIVn3h6 z-=q7~IxcN)v6^eFuSch6Nez#*3XG%Vp2=+R(0IGr9K~3EOTGiFY}SAQHt>>~g?LWN zEW~kk7ki^u1Ibwdu0CvU73mkMRQ175pqWHkufG&BjSTmwOz+85p^59UuwID z8+&rHM7~|*t-NTIxLstvW5cIuAL_#;&%ue?)yf#?g2bXEA8Ly|T>gu-(2kT=GiZKx z>Ovo!)YE=lc&j~~8ThI$oEG0nTbRV$Z}HwLMMq}tBDNzlJ88cpTe}}S%dI(VtUz;- z=rg4p*Ckp9&KK!}??6c-B=F{71^u34!SplhH0=*h+6W)GG{)+4#<2e6jjX^t-e};w zVg6{Z_1+MDr=*QP(}O&&NnDbCE^=AsyFt^w*2|Ljy@^XQ+KYXHWv{{mBP6_gqK7q5 zw8AD8u9xU<+cQb0Pok$e$-0!1?{&k^w`UQ4AMsPxuM@vq;$NHSk-93B@SYMbEk$TT zOX2;tSg2csCdfYS53(@uHfw1oi_YCBB_6N;mejfayu=2shA)H(P+b@Oso#VOedx6(omzjm!ns_k*e9s{X*Le;f5C)i0_ zNgyZf|G1vlnNc8geN5;ma|T4yFlPX|(w=EU|KF^6p$!EJf*avV58JhRJ&!BJ@>XR_ zT}^%?R^U#n8#0X+1$J^DSVVcbhn52wS=4K#p!k|TTgmZmPr~5~wX)ygi-CF#t=yH- z9$!ptj8t#wzTxnOnyc*a#z4J4Z8!A|m51tMd2c8ieqb8jSdF$ISj}J^LaH86&C$>CHtzQ`(>neWJ|p}LivneWM}k}Q{ppbZw= zMDS74hmpWx`#pP2{3N9A$91HjqK}jEK>d^?eY}*Xsy!_ly0|#0EBZLHZJ_p1l0Lp{ zV{VN9hFGxw)h+_g>|4dxPXF&eui(9fI`~7`H#*W1PVwzfy}sPb^E3nA`%jst%cn@a#-u)z9AlkgZUfIGPepJ z;DJ(n@UYJZJ|$U6bN}P^pF%EI4KX*wj}w$OL?l=Ex{X|c2ZY$8)>-HwNk%$vng&Q#Fuk!`*^i z{;hZ>eiIrE?C-aA@hPj8n7ZDY-dC`FS{iz?92M0{JKmb*=Cn4MleA%#Q&Z^G+Qsc1 zw8rqjRNkzi6s@%9tz+Fck>Vbg_^qF{?EaglB`yi%BC}g+XNpdpVtyn%eN5sKs}VY} zCHr?N9X!QwdW5R?5EskuB8k_I_b18wAt#=N{DoR=c>im8ztT;YJ{sYT5)*3KU6TTa zgbz+ksAYFevMzSwi$0tU9xbFqpIUo$e@&8am3x+y=&azA#CEj6r`BtXeYqOWo25DR z7}wrxBx%q0($;5a^YykKwUYh(?4&1<^sTwU7v1!O`ixtD_u~7hGpntngIh074&V7X ze8n1fUo!aE=aPf^`VI84mqFiM!Dsy(z8aKv*c?u%m4mVdg+BV1tgbu4d&4h7HaRqN z-%w?^D)^oBSN6Q-+}TMy(uN3(?)z;{!j3>4R2#@oVL9 zqE`mR6EaVfGQhpEuM%xic*CnbpIV+5UN{C$bS(9jY9ABzj^Z2d9Y43@Yt{G+zbs#9 zyY%Bd-25DJ(~@)99FBV2ElZmIh4zyDoA-vFzS^V2)4vYAl6lPh+dSM^VJ^LrdCdIV zJWls0rZ_iU^)H-SpQi0S9A8lm&r2)iNMoGMX&L%7#={Q7S(M{~T6q-uc}yjb3%ruo zqE+p3Z1MA$N*;OM8?|WVmqTjawRWj_*{Q*=d3V0Nmsg2z^(t8*y~+!OU&QM5>)w6K z%df<hjB?@Pkz2_vZ-YgO5U#3%Jntyy|ckFz`% zs=p@7SrMxw52;A(Cz6uK*SDTm*-5*tpY}xUW!;x*e%jt_O{agT)-G__D7r)BGIRp`oOO%iAi4&S_ykhv}4|;IKIqxogK&xyJ~P%Km1;qj23JT;#3N6nQPS3^o{WtCViH@%-={)n_0(pGK5yj|MH zQ-mkizpC&{CH!96bB6SNogV$90A2;!(lxZblcbGdb4we;VjOJ_l6;*WNw=!ZFek$VIh;Tb-5w z-+1r%xp`9cX6oY|S(Q9mxM`TaIk_s?ukqF?+%#MKg>SjBZ$3=gEnPp_!D)BWFFQ=y zt^OwMPTKmzq}`%c+R7qx@cuNA&5AC!P5OABl$y4*0tfF;t=A9J3Ocy0z`Gy)_x>Rx2 zxGDWhDiZstBvm}m#8hup4eQ&2jb$8lj9d3V(!+8oE+e8!OVSc$rW|Pp@??BvtQ(sV zdoQ*>n%~H+&4bhK#MeyywEeYnjs7O>PTG&jw55KOOgo}h+Dg_tcz+r&ld|5&+gl+k zcn60P+rj%&>s9-&L-6+I6*zb+o5V?bBIB4oy?wl!xSZn9M0p-n+HlHk@k3I^k0tb@ z=7Wuc_(xRADV##h2lA|!oiv0~u9TY3gHyg1PC3ivh_5BQC=oDAgj4#u=`^x$f`i1L zE1W`nsrwm8%tc?S+RSh%F1`h6KcphDFHUlb-}BFRad*-_5*(ehCyG7ga*FR+$abmX z_$`#YR%t_(=6?H;xT-Ges+95e(37?%F?>>=S+B$W{m#8AmsvV8YN5vF)q+7Wt+<(% zSC1*o?bM;JsV20S)NPl#n>)J}TS57lR$h*b-t(pMA{p3E*<704Yf|?}S0DCPs|gK0 zIH$g2q&~tTpInyhc;&-d)}(Jf%^0%in?2F*<_t;vuBXlV=C46-JzdhH*QAkeS!@1m zd(TMyq~CIX*V{d=2ie#7ua9T08pkKL)~GgqU7}RVDmyi4t=PN#J>x=Xf4=sv-CupF zw_Ou=$E9hBw*sA1-K(*9<@>jeqF2n$35hY*V^a5wDXMVudf|yr5@Q0N2(PqpZpSdr}MphgC}5^mT(Vp&fOlxPKv zn%v+_H}OW1go{ORD=s!N^AztI?WX1C$yWt)+fB>zw@Ff;>&%tS@%S7;a!Wk5%XRYO z1k5@)imj0>CYhx1H4@o-`$Uty($#lCS{dE<=mX1iEs@w#vv%dmxqJ5L*S+-am=~<> z`^>Th3wK#o_t8t2)@-cV{MLwvUNjDmySG;HVBGUv-0K)}#SVTc8@n@&hA&^_@>R(H zzi`+2;-$VSOd4$r9+x-)affcv6c2(!mlPb3d4GpP$~ugH znEm~U(Cl&JjLC@{{b+qlqPf0hw7y_WVjUwjj7$ekfb;5UkEY~~Kv8imHQ5@yP*1xjr5x;# zlPt%?93;j+&i>oX@u&wZHYoiG0rVW+}a$__y_?^cs<6>Me~~ zKCy!_BZ;?nUwdqO8PbwoMocKXUlEbW68~K3+68;Y1 zjwIjbgj;JQydCL(ERr+ihTkLMZAgEHq%WRr(tiRh`R)<*20rwrdr!;EQ`AnWK93E( zaRR9^j}4~<9o7oAn-)k)KyB5uOgCH!lO$j9eIfo&G(X%n_vhCWJwp0}`oo(NJ;oXt zH3y80(Pn;43*+a%P?NehvJFl*9g363Mc!<{SxC>av;ah#Uve9oQE z;3@u-!UKmTi!+48TR3cu5!8FO>BI@(PR zv1-vr29i9=dBhSd#qF$calgBb{7uS|X_oUb?lcj@8GNBh?iB&~sl&;_)ry7-ChDJ; zCB`P++M!Pw|4QQaZTfY3-|dOp-!#V6+-P*HSz?SEZ9G)7#%Npf6!_xHQFFBp!q+3D zKk%jG@895?D{b>2e4W4~zH;y2YqHU+;9Iw@!uQNC^z+vL@yAd4d7q9;tY5z;z9F&x zBYj(2qw1Qf(+>gbUJznk`$bEm? zHh*JgN07OA>iuVUuD&%G)aun!_so-JPrxg%Vvd6i)C|ixhuK}v+lAiQT~E!Axx|gl z+3RiiGkaROeWXv&1F3syb=*F@D27z?pjI3vZEwG2Y$Qf1nt@3R ziT#;1Sbd@1;azDUs;9v&68_h_PE+GKf!(}uf%`@QGxps#JRh~%$=#pLcOA6toYsan z;5IP&%<9Nm8TSnzf4;iFx5%B5$zzm%Rr2WKzF{Qu@co6%AM$3G*_p)KC3!eL!_SNz z$vlK}RXO-NLP>^`M?#5{RWhd!iYcs&rOcXkv644v1!_lf?+w?tr+Q8&x>&uWpX9ya zdmfa})bq-o2v?jW<-q47CC^Tl!}mY1AGp6(;RrPsgDNa;m#JfpTkHU zEqU~I-Z1+o^YA3$ROan@BXaIuII7N(R)W>7$vk8nSJ5hUZ236qBP4lT<-TDh^YDEU z?D$Q;%o+7NopP*^H5@D5wH;4LyHQ?bwf3SV9x$b|CRwv3T=`O(iFd5C8~&Lef04vz zZI;BJCE?fMV^O2FPX9}#^Q{w~9iUR;vs#evuhBl$UQ{XZ3BOIk!N=W8&e6G(0!=-9 zq!%E&OG>`)IqB10{`pMm7ob9Rnp#)WP3Sg^U58|kO1`z{?S!i^NZF~7l2k}eFF=u$ zoeBxR*};JD)SdXeQJ<&rVBa7V>F!X9?^Y?vMEWvgx}{q8q)HN4BjL{xe!qCId${3v z^qlyqyXz7EXbGo=Qg_z_pJ$x-lyR;vCHw|MKN8dZ-&jc-UeHAjpIZzEn7(JKR zuh|DY$>+~9^>)brn6jqqDW%1&g&Un=nxx1{Vu=Hq?> z@l*QFgge}rLHa5Cg%R#(0i>l>lcqdM@Hf~`)TZmcN6D9DeECGYM9tByv(;)a?P_A< zJ8A5%nDKolnXXrcSp-&%@Hr_9zm*B*&B0u)Es-=N+!>cRi`v^G@y~E;&*?QE2RE&i z_}94MNFHjnH|akp@y~YCcS_oa^uLh!{oL>yRs6*LcnG@%*3(K)q(P?XS0^$gow`t9 zXh5x{<$ds(Y=;t?=}o^&S$ENPSoMCUg!5Uqt%QF={MYG;vx3?Qw*wM?E);no(1h^s z-SCXW7UFMV6=HvhzXXx4(r+#C@uOLNBz%pV{&)$;_kcX%OXqr(8~?mSi1G@atYHl* zJh>kQelfXsJa6irb@x1XY>5lG-zxWOz4)>UIH*>B^Zsb??IF)u!{ekUE1rY;0`ER> zpFCeA_p(NpRjNU?qSuXoggkdR5@{x@M}um29iHbjb%9t)Bl6JDf<0 z|HWEFp@_tXB5><}*!e{$`jo6)+(mrV?oUdtMikwqR#kheyJdB*&;x7aPq~LirBR{NxiMsqkEiqIL_)M&m9S%;-_+& zim!GY3aTA6!0uqqtHo*b2rf)?H-EI=!B!jVSb^f;0z>JiG+-<723`kB_P0}AE1Xzn zvJVx^Y(QUeTB`<`oE|P|)vkD2yp{6Jv|QSxhxcn|nHfTXEGRHO3ksxsU@k*> zSokn{%HlM)L#*6W>SM$w);ZDoWA=MB6KBmbuAMa@F-E^d-khaKRpzAYsG=OvkG2#bj(NkyQ80Zp`QN0$BXMFuGc3t(VOhJVdC#2 z*M9x@J$gC3dk-x}Y@+;*q+s5SCV>lw;yW`C8u*LwUJ zx=y<$w%e|Up6ip$s6Yy*57P?gJmFHgTS~ho1xPfP5pnGkm zgj*@s0oEbk@5Tx8)x3%Bb((grHrKt*(6SM1PMTR-Jw4mK&PG!YxU0Vb*^@~ zK7rATA?#87fOeO58{dMt6@Ohb_DpV%<#+;D7xHun;e)iBx$C0cfsdmtSLYEjh;vW> zt-Iy!X1=_5Gilw+u|F|;^7f6uJwQ*wZef@0LHN|~VlP7#?{3~7LaHjyw&d#MtBz+# zn7TTtRw~CIlul|6%}7n*aRYDO5Tie-XXc)CAi#5sG{0XQn-l})m`m(+7NPh zny5Othc{1WC1*SBKKZpJon%^V!Qn1w+YZ{M;&C@2U8%M6;o{4f>2LwFYaBY`X;**t zKyWy280l4Wge(Hf0XA zvBR2<9rZTH_xYLHN7^KgCH!=47VFA&{5o?u&gG}G#{YYci}>lRR90W1U%?t=oiA#w z;<$#N&MJk?9Jlh*wK9G>bIB_>?qbD{uKmT2(GpN*!&BYhn8r*Ho!!41a6E!pr8)i{lk|b#(nI{VI+VXfdY#zW#}3 z@Fl*rglyNhb1c)rMBkdx^R>l%(X zTKzc=um*4(Xpy@$$QsOXh&6=ceHQg=J!3ti8P-UPdbFll%Q&vEs3U8Q#VCgLlSN+E z&sK=zFV;3{MDb82v#`f%R;SKgFV`C0^uS$%wAQ!Wb@T1oDT8jf=MH>Umf|ot&fsLF z-07^xOFlESV9K3|Y)-#v=-orL4u>9Zzxl2^w2p@!Nnhckj*8EN`Ubhz;dmV^1KQDi ze@EAT;l2fWrxo_oG1{?s`P$Ha+R~RGf6CFNd) z!>6*N&llQs?Mv+|R%6YC-&e!IYqcNQFLS;2lePg~-o&bs5FGuBwgryfrft`Dz|-aM zbVRGr+wk4j4)Eydd=dL>{Tw*7vp!sZif@v>0FPW`Tx@hTE;TMQx*6S#9!5{2mvOmq zh0)u%(&%GcWn67sV_a+WHToIX8P^*(7&jU>8U2l$jRD3J##6>K#$g!K=}J1^I`K5^HFoSIRZX^+wV6 z&$&pI%=u-E$|%X0ov|Qed&d6EU}mu@sq@PokTo>*mzl^$w5y-O!1;M`p-yM#mzNI( zQhwP*&QH<8|8)hMp~P|_GvWLcjfs5_M-RuE*`8hqg&KLZYc#?N;-5@v;=GDrAnPs zqBu;>U%{VY6|QKPHJ@4eMelbk-VTgi5zPhPf+V!k~%Fu4qv$2?O((7X>^w*EmkJoNN`nG2sTn9Ymx9eT>F4`b{ z5UaWevorRc+7R^rZ0#=nTXt~1TVJ3r)b7!j;Q6^%U&bD4_vxj0c^)uY8?Chmjbn}D zw1tXFf<1yn|Z4wgsIqgfN@(bEmNamNc8A#_> zw3$fgx3yVHDr@tR%b#eAkjThwI#^tDcVxx^fYZ5vU<9<9C`hfwgQtj^82)1NcsKRUgKBeS1pFL@1w=Va{1L9Y!23g z%6`$)uwU-h)6M(L`}7PY<@HRY{L^|iQhk(OgiL=$Z(zP=zOFYl-!#YQ&CPes@p=n$ zf;mBNWll6F>aEQW%}?}W%t_`{{dn^W^9u$OXP7hflh6X+>ZhOymguLN%gq(~dFBu1 zYW;k3gSk<^(A;cp*1MQn%yRu=bCr|)u=?m@l*OdKWA(NA>Eo>Ht?Tvi zR)4F%{+_a)^a;v((%-i}WtaYms(skaXdk`pus++Ki)}cYexIr3;0ZrZE5M$wOPp#O zt5KUzsG-fUzvn7n-P_oh+9K8_t7o}9TgqzeYEsG2=CG5`Ja(q|o-cYYU|qvPJHpc) z+H(5`Z3Q!#O6{MqXy!2=b3V5GLVFia7w|Mf=*7G<&)zG!EF{KKFjP6@@oXtEqdcp& zKhqi0();jS;fH;PFDna`aWSxvtEKciXWQTD-`IQgxx`$;ya!f*=_~AN+CZ+pQp;f< zwH$d{Sz6Whr@U1TZq@cuJ>4$Xo7y|bV}X9Ay-mN={!zb-H@n#p{YrZc`7Xr{E9Y2k zZz1*`V(%vQ7QT+WQ)2e9w@QpKF;?;92hyn^od{{{Aq~FkXs;qi_2sB?;zqT)lG9oC zR{dOZynu8rCB1I;FT~!WUj>~5+7TSf?Mj~P zbv3p9C+VC>dCme@9nBUuM?i;ffVtqmg!3}EpnzJ*fm4tTaL00LD{6mA%mP zEyeZj(6Eo)Rm%Y9ec-$gocDqAKE2eQtN#GMth5*FtLzQ>8v8psOe^80RZzh2%a+Df zj5p%E@wNNL4C1Wgjp;1tF6E7tP;)hDt$}-0$WB6b6Q`1patYZdaY&hvy(%A_G2OQZI@~%_GE1@J5&8do6u;9LE6g^w65dq&HC|h)Ct_53Y-OI z=R%*0?QiwViF+m3G}4Z;=WB|mud%miW1#d5N;=bCjdZC)-b>t;v=Dw-M*i>8f_jkB zL$vB;q_&w>xsSFtjMlUax^;tho~KOJlnJQV zIbX)PJGk{>Hky)kd%L5?siLBUVk0Cvf=*Jl2B8dhl2X9ua&jIe1vI$$P!zU7Ndiq8$}IRsGC$>!%!ksz$Cj z@;yRoTi}n?@JAH>7*9&8u@rmTgQ5NN+Tfb+w1*RqXpbenf%eBi`%A$0256tBeV?d+ z_D!`#iE?P)SzDgiqpe8PXr+mb(7q?M4}kl((7uZnO(dXwU2?t^+UG+1y3jri+UG+1 zI$(Jww4Vg+3!(j)&^{Lo2SWQUlsOwL&(Y6KR8r=-`o)PDv_ApbUkB|op?v_X+f)8^ zXq9X1d0@B@j99&7|3r?n$YB~etRaUbq^fFDQLl_tR*=dH-d@hzF>0-XS_}KKAszY` zBBcvyRb{+Y4jyGtYX{VFw9%1xt+$Kp$hB9B{c$n8+#Bxg!&%uPgW=SN?NYdRJQSP< z1?Pg_D(!2Y&p}Fk$J_I$;qQ?U3+)Oxc{aH3gbS1u+yoaaX1~a_aMfqvR||L(9z6I#P<&z&dnE2jFyjgYh%48Q5ZPFkiGcSeNp=5G_^@uT247 znOe60po!Qz(inL;x}UvXJ}+#3(=#gM}MXsy_tH(cJeI)!axPE3y1=7yTa^c z_cpHqZnt-vL+o89Wijt2{9dl_qBk(h@8Q4bL9Y8q{c|YfB&cAX#!1*`MzjOYB^Pimm;#|Wy!P&NZv%l{zmd@GWY;v|Z2RH{g zr?dZKCXfx}0{K7zP!A{q8Uam!X26la(LhU}HE=A@251Yk2RZ;J*}JS$fR4cFz?s0= zz`4M`>6TC9&SpDU8kLnwmSn$=`4FQt#=)*cb#60)at&)l^Mz(n9f!e-cI=6CjH>pb9m-~!-Md!0pm zJQE$!|EHtJ&O*Aa=6ao7Le6{0xrCfc$axhxmymM_IhT;@Dso*#uB*s(6}he=*AjAC zMNWIjX%#uGBBxd4w2GWc$Y~WlxwdG=)9k&*jlfMnf8b_d8n6x60h9v~U?;HK-fIrG z_gW_cC-d%w*dExCz=gvzyFq(7oY=Mq3*j zO^Tbm*<@~$U8JgJ^7X;mz7D_Cbk~>v9UiFp_@I{Jfl^~stC7aaqrV9czWDC(JJEk; zkGHsZo&L~l#-o};>$9l4D0LU5?xNIPl)8&jcTwstO5H`NyC`)RrS78CT@-m9rS78C zU6i_uQg>16E=oN`si!FQ6s4Y`)Kiptic(Ke>M2S+MX9GK^%SL^qSRBAdWup{QR*p5 zJw>UfDD@Pjo}$!KlzNI%Pf_Y7O5H@M8+Mrm=$}zHQR;?Wo|#9J4rBt^KrWCE6ae*r zBH&n{4bT?oKw0Xe?V@O?sBu5=0Kn{NG(;2)5k+c8k=jwDb`^n&dlKFDq_nvxZ7xcii_+$zw7Dp4 zE=rq=(&nPHxhQQeN}G$)=AyK@C~YoEn~T!s)ZWoSdj46!)z~O~0o6Zj01U!r9t;ct zh5~om`_OGw=(Z~KN)lM*xih zdSg~|;3%L4K)Eb%vcSnY9%u)g0DMZBRH?(1I!vj z64xJcJw_!MGHROToAlj7!0|6pTy3 zxD<>_!MGHROW6_iLOX;M4k3j@Na2vy1ODp?^rAm=Ip-?~y9)c@YI_^4ej5@xgoF-Z znQzu+bN+@fTCld5>m|T4!gq5Y18Du)KA;NN5B$pW1Dt;cXg^vFVADnoJEU8j>(dKv zfG4ss_ss#?JJLR+BMtN}0Qe#GLrDD)Qa^;$4yeDx zu&y^F=htIhZ$|Tk%vX8-8uzbreuMiri32X?81Bab?{fbU@Hy9C5KfN~DY^|U6+%me zkfz(vR3S7~2u&3-*YW%(U?XY%%>8E0+laFRC(M>y(LL+YJ?qhOA+%fwEf+!$tw+;^uzWXT`EJJY-E5r> zoC%x_;L}3FZ$rXwL&9&fE=J~c1$qNF0XGA;z!!I-Z#JQCHo>8BI5ZB2#^KO792tir zV{l{$jts$(aX2y#N54rhhntT>z%hpXanQygxJ!%cB? z*d}z?CUn>)bl4_z*d{nE4u{3zus9qRhr{A2o7K-46|hM^ilh9YClfx$Ep1|wa-^^fFj^npbgL#=m4B#$Ee*HwHu>$ zW7KYp+Ko}WF={tN?S`n`5F?a9{3cnzRrs;4#;?;C7|ZoHoR{HIYk)6j5I&v3zz|?4 zaHl;UN>@VZN+?|kr7NNILMXiuid90fN+?zd#VVm#B^0ZKVhf>GCDd97wJM=jB~)4n zg%(1gg-~cb6dDhO#zUQjP-P)hSO^ssLWPBtsFD&@Qld&qR7r^{DN!XQs-#2cjiojnH_$vY*Mc|_dd=!C?BJfcJK8nCc5%?$qA4TA!2z(TQk0S6<1U`zuD-n1j z0&hg%iwHarq5dP(e}uY^Q1=n)K0@6`sP72%9ihG>)OUpXj!@qb>N`SxN2u=z^&O$U zBh+_<`i`j9h<8bib{*W~>V+3Z^}4R+XY8v?qo)0y)16Ill`zzY95!M@7pr9tZx%UK(f;Lj5ovoVCM%kb zM(CI9qYfj~-Ci&YQ+KL;RZ>S0>LNltM5qJR-YTgB)#fUp{a)z47n<*d-WAYVwZlqi z9f8gfXdD6SFmzRIvl6;iK-UUrs@iEKbc|>tnQN3!U$cU~W(9rC3i_HAlyWPj+)4?z zXispDkBfe11@k!bwP~Ec;JljWYq(y^^*XLYoK=gd9bbQXRV;mT0x(+f<9}7(G@@3rNCuCH=sK}T%#vIY3R>Z z(4VcKKU+b6wu1g_1=QYRuwSRao?*r_z_Wxs2fP5h1iS;_qo#jbVZ0A8YD53Fg8pp< zwZ!ZnU<(iIo zq;Fh74Q??P61EuF!2Kp51gMr0A>JOs_X05h8k$u=HE;m<9rzQd0c>{0&;jUc1%M-{ zQ8cO56hNC=M*%GW>Xd$V1^w&_`q>p$JKzN1JbMe=u?6nf0(WeME4EoZIja_TIpB9o-g(g+_2x3qj74!Qd`SN)H=>eR))CVOy8`S85l~6MdHRDh)4&~zTypmgSc)kj%Rf@d&koy^gf5%zL93^kI@_ai`1}J&5$F8On zaY_-V6md#XDY8S!id%U`n(P|af^lP~wT79EoC`09;om%XH;)p8;oDrN)p8C2o6(M2 z8MCeA`ET%~$#`%!P%M&MS}{DD3qR(;k9o#rKsTT}&;#fR44`E{!TBlR8K8EHS5i9+ zALT)TFg%n86~gANS}s&TYNP#m*J=HPeMs08?q_iR4)~t1h1@R&R&l+R_}hUpAZ(Yz zLr4I^_W*l|69Xs!AE)UQ67Ah2Os4@Q6-&~WDYx0L(7FX z%Ha(qHOk=)BnM&O3xDK6!7v)fO2YgWuUzEcaJGDyeJrn4_ zsO#wfsY0nTsIvp!*a2_sfH%sZj`GzgKTR3DQ4Uqg;EkP7WCy%a4n@kKL>YWh4queR z7dzpLo$$p@_@W%XC^z?F^PGnt=6v7+fRSE!qa2x64sVoOxAB~GwdP>H9n2Nh+rhdF ztha-88CaLOSnmdF#ts=LJ{?e=rl0NYV7wiSw}YXF-FC23SShbj*+E#9fmIn;?FN(W zU{VGqWnfYUCcE(kcjR~$7Sd|Y>m)ZuDH*XFfK|i@7`g2xx82aE3i?z*pDO561#MKD z*$qvqph*>FuA})VrZwh7UPUA#G;8|(ZsN5 zVpudWESeY=O$>`BhD8&@qKRR}#IRsuSTHd>EHNyU7#2zl3ngYOKvxb1UIktUM$>Y~ za2^MI4onB;6Sf*y$MsLZPGC1J_hR&FSD-uBy*VQp(DX4heGE+>tL1U7M$=cL>8sK3 z)qmr0u14Ee8*#o~bT{xO@GkHXP}}2Nji#?g(^sSEtI_n;X!>e2eYMq@JS^J(9@^6$ zcz+LkzlU-5gFO(=h;`ieJSeY&=W+174QdqnZ@dkM^(-82#CQ}k^LgOE^(v%{{?dnu z(}&qDBe=?Y;EdMB>AS>DXy)-E}=hNLVvnMJdam!PWC8E=v$Z2w=QAsa~6H;5~Ru$?N`Pn4Zvi+ zj(85GS6M=@vV^{N34QGn`r0M*wM!V^%b{19L$5N2US$rw${YhN#F&1ZG5t7W`f?&a>$CIG^O5r-6~cDB?a3FcxaO47>`w4!j9a z4*KvV^x;eB!H$T-|LsXE!S7Il-=V~EJc%W#Jy_)C z6lM-OR%TpTnY7fnvYcqGaawC!Suf1AzmT5mML-we65tBpHQ+5^Hn1320#q`e=2y@sW`joDo(&-_SS&}%#B&&_ievrp9X-S#efESB6q z`1A7o&rz`-{XcXpJAk3_5BZZPwLMieTn@vGw0GIu}jy(P*PEY9aw8Uu^&>|*x%X95+$7POzgp% zrP)1frykjvwpV-XA;9s6Xe4bL|}QNNV8mwNuB!gMuYb9c({<`vwz7?dA2XJ(lAu9*yW}yMGSv zdUyZL*{Pp@{)X_xJ{3RNrjvLi(>XLOg|FoOWZZv#Wxw^$b-y~QKj+@L z_Kt_vi^Tj%p64A}7J2#xY59^jC5~5r8WQNRGC_FA=MGPPc(^#{!@nu{9yZP7+lMQk zo2F1A8MF44{RT705Bjr5IsuGt@uzS?gCTWl|1k&mzxYe#IOa_AmvCgn5__^8Q8nR} z;82}tZ}#Qa1OHc+sd*63U~iDrm6%E=7$Of$JVM8yrQ6`eb=G4Rh?Up?3$cs49<#Bg z)?+r2^_WM>dd#C(kJ*n^na+C561+#P>4AJhDs%ZA&$`P+ctO-k_I9jfU(edijr=;W zmVGm;;?)|=Q&@w!jg|2`_;qAPeL3qick?@))tGy#Xt2Yzq440nb6Lbm6+$s zO3Z)BO3d?RC1xjGt;D=gZ?Cu4E|!&;m&i)YuB^noOS@FRSHDlYTvl23mQ|Kl$|}pN zWR>MLMptarYh``q6RfX%MSE7(QI3^$loMqg z$+C{}b6H0@Mb=T4$U4fYvW{|&tfTx+)=|!tb(HgD9p(43j&i=Nqg){CC>P2)%0;q{ zaiRlRwJZ$xUkQq{e(?^G=N!$&AJ^Gmae~_NcX!+FrGG zl2w+hoz(tNYbUiD)=rMmO<6UWDXS*4Wz}SkteVV~Rg(p>YO+{XO*UZFB-^m^6AV(N6^>BjVYv#>4| zPcxT@A3MnL(^)Cp3eIlL&xFU1!LCvJGZ=6ty#P3~9UQNAl*yFc8Voq|L}H%AFAJXR zNb0BY%Z4Y_Zr^9{%ZDe$YYJE9v3B`vbn6BD>av2lGwTH|oTNu8Pd9%O6zJWtt(wx*AddX3Z->5qjlBLM@aB1ls48( z+E_DMSAF_?{O}4iU}U-hE$uksw9(tJ6Vvgux^!uE8Pe)9q}8R%`sc>_9r_(w6Ilh_ zSig&Q$UH9EVH0VGmb61t+My}!Fvz|Xy)?_X++f8EJ5yY%8SF}NgJ!ZL#m)2!2N(nJ z8sEZ-=(@%o^fv3sy67U>?R{E(<9_2|t(eyPxYodU(s+_MPa98j9BGW?_^k0PDUYH* zT2IzaTgLPBOY6xBYRh<${%Ji~M{OA|(@(7@tEo+-z-wUgIz84RcD{In>o@7S7O@A$ zXs+L)2V2B$7-P5|OHa0leKG#c_1pAli;x{3fd7Zahv4=R>#+@yBZkNkL*$4da>Nih zk}Yy1L*z)N$dOEuBbg#cGLa*5NZ~u`CSB8l>mMEKE-ICB9Su!9HwbawIBr`0j4j4G{>tn{v9R2$V?tM%S>i~~rnM(pr$ zxfW2nd}s#yd|auS?Df$HpZm4uwd}vq*X+yFer7+dj@tKwI5(I#Xc_GOaTC}5&Hlu{ z*}NG)%m8zM7GyV&TX^?Y87a8Uyp1>mS%;G+GO@nM#A1<&4MZjuBNHDa{fCf@X=?8f z;tw~6<2_&p5psE)k%j_x5m9^QJY_yboTrhV0kxk9F-IXoO=Rfv4Yjw?6kg!Ea*w?gT^L6uet-+hT79#`EFs6K z=2S3bmAhJP#CoF~b0&T*CAGf=!#Vg&Sb=1IM{0A;xrEO%=aItqGG;R0oDV(=%msuj zG8d8B5_1X1<>qqIT!F8p2#LRv<0=_fS#7Q+{swacblAvFLB&c3aNJ^Up`=^Qtx#_p zb2b{7+Zlf;Fn8cBYhac!4pU&3Gl!!AdP0rE>^66kPTY)>*FJL}$NeVXRyKb%f93d_ z`5VVS%s)8(W&Xu6VJ5V?ve{2v%diZt`QsS0f*jMVG%aAIRNTVu7|gX?`&9wTo>UrDzfTZ z_1VRUT>v;9VI85F?8n&%Z&PEdG1pD3CR{hQnsVLDYQ}YQt2x(4T1Rqylywx>M_Wg8 z-NI_YbxW%y*R8BpT(`DbbKTx*&yhU^@JO+z0LSxKFP3Nh3*TM?>wMOYtuD7ly9rh!jbnHjKQSIiGr}Qg&$G|VFY{oRvuW6!R>#Dva`b=rr zx>$}axKmm-z}`p4aa5YMk?7F?>+Mb^3pwKfgTDyTzh+i!{cTumdXjS=v5rzxY^x zCFKMBinZVPncDB{KT<4OxmdIL70W(lN;jLVPv=KSnhxKK6q zy&>U^^hO*T>y6ReP4p&QH`AMOY_2yaMD1LXsh_N$Oqw0_j)b3vcejxJq}a8PeW^PU zuJ$!4)-S=^Td4P7tXJ)Kb_Fqe^a0WILDBTNqUjr=>F?4CMaLJ5j!!opF-9riyBD(m)jQxk4!?CFJ7K-c^>|}E*Y6qcaXkS)b|JfCz0dVT{Mm(~ z;~R$(2P_=)Qc#s;o88XLLZWNhME?bnhi+C5XWd!}gjpt0RxbX;_N&?qw)B^ON} zG{Q!hYqf(*(5NsfxK{hP1PxX~a;f+#0;nezK(<%_ z^~3_m77L)BSOD3^AI2YOmtJNsbiA?v0%8H=(wkwI1kwHVMAHXEyXT5_FA%++Yu;|& zj;2vPo?>%|IRs6t`aS8U>h~Dtz2?1ysNPSydB1r-*GjuL61~p1OH8;$w0J=DcR=)a zrs(ei(ccY4e;1msny-?+(&Fi&#fwFY7m5})M2i=R7B3VnUTlsv$D+^1nd5j%X>>z0 zdWLB94AJNrqS13jqZ^{p(?p}Ei7qcTr!b$Pj%f6TqRR`->E?7&OKNn(oMq0U?6b|; zP)up}fN1wZ(eAmT-5tGNU@E;{WG-Y*L>Oji@8qy`kv!LecAmqSp&drPqth zb>=#9{K@=@qtfvK(edf*nzo7SpBZf_WM{w-*GlWBi@whneQ$`q&li1fh`!GkeQ%h| zcEj?Bm=P?7o#swbRu({kSO7(4l#!c4a}V<}baO8wIF=b>Zbluk3>uo1%+aVL_CZ6l z%B5)iH4SGnOrNYqM;RF&PN@wEgFhdQ7HCAp;!`yVnY;)^-w5wL!np< zg<>ldihU3e`ygHHgMiov>0%!Q#6CzD`ye3pLAuxn0kIF##Xbm#eUL8pK|t(-bn6%k z$!Q(S=vAS0oP~z9+AxY$XdQ1I&vjcyvkI+tRy(ehC6UhV;3sh1!RkP`vMPdnkCxu7 z*cL(S6zdeOJ6at%o^GAa@l5MXj%QnEb3E5Nm!q;ja>f2I#Qw+?`@<0XBUkJX!@AhI z7^|hL)s-VV9%-3ke-w!Q@&B}U=J8b(R~)}{=DZLQlDNef1f!w?B9O3&h%AaCyD?hS zx;4mBgTw?75fvUd>>VtU zLRMOWtHmsm7~?9=B+1FymJuUzNQe!StHy-_{it0vEH-whYT=ykz9I}ZEn6uxJ@ zfT*#TVnN-2&2(SXK%B~?ZVPOrHrRe$VMO}lO)kgs8b`F*8PS~RMl7o((K5b*P3q=y zCy4Y9%W^Ey*G|TcJDcd27e|*xSM#>RozeZ#a$;X5b@!ki+G0(XVnOyJQbPqcoW<6i zNyOOs*lG_%jYNA}Sy@(FsbjLl%1PCFPGwd&wrb*d9hW6uGmN>bxO6OM@E(o}Y%xZK=b~xEeQkNZ8+p&$=VeO>KYJDV2tnF5+ zt7@~wGF{EF*lMv%}uHm1DEODb_YV$_^PXY;`Hz)7+d290CA;M;qU!4E*{2BRo ze?J>q;KF7E4xqc7d((mb8`PM$q=lcS`m*3m76tLgV7yA8u zkw3r}`!@bS-`2PD2l*0zus_5f>f8In{Nerx-@$kEo&1r$vp>pr@m+m4U+T+zci+SJ z^u2sO=ZF;#xn<8jO$XW2}_;xUSSy`h-5IPwCV8jIP#a^*McBU(i438n;tl z)IaJ=x>jE%4)&|MPG8g4bv@Cr-_SR8qi)j8`nJ9+#kxiE^ex#(TI)N~O7`YHzR#V^ zHp=wX*e(xYi~K*%^#3l-bgDN_iB@FO7v+23jh^_ewVvkQ=5`8eO45qf(|&f_>(YB^ zMi1Pd-j{8U8}%Rcx&NleCHvb;p|`wl{e-8>#`HcFdQ|8)Qq z?AamMoX!(Q~EuRsk z#hAM<;OzKbpLi|X;p@H*Ox<^^Ct&{RorH?F6$OYF>|!nl|5&N(4x853^>YKEaST1xaPuVT?cn{ zBRtj3@KX!mrS5`{x*P6k2|UwMsgrtHCXMp2JSr<>r92@|!8tt(*R%#+X)WHLb$ER? zz#nabAKD^Yn*6+!TpH8lLsD|TFiqYqO};oyUX+q+F(bHRe#T0IVLlgP`scJ`9#_*e zzgQdXaCtDPL)}<+g_}>0{nTw|%qn9%oW`A4LTzqkJSt|a>E$Q*8e-AUh4onlyRw~m zdl~cHi*y#F!wb5VRr88t?PFbHN5=-ms$vUbt7Cu9*_T?%V{Td;l`u2vEW;^NTtze|3UZv`oFIn8wOhmbEG z63h2;umR7B<(tgo68_e~T3Q}JPyLz8x#c)nEg>jFlu=^Go=f&FojijZ4|qiFh}%t`(ROAai3_oUxz0p_omXsM=LD_ArX}k#%Df?@!wZwL zIaOx8FG#lRrX^v7T(AK)&q|WK8}wIFdD|dWd*1SmdrPTP>!ler zf=}72gySBayTWRf6VBFkG|e(FQ?n0}xb_C? zv>%wzzF@uf2QxK~K@x`xHO=F|1YD?T4giz)dY+~6+Y9@dX^)6g<{k7`AKq-xUkvdRVdB;k8Pm z*ZAL)I!?~pY$j==l;G*vv`cEMfGMlxyssbVhv9zAV>G&x_fL|u&s=1Ob6iXKw$MJD zwSu9}u3(JmJG-a0g%pb?b(FOM<4R4(ok8a$>^W*BU3Nr}t;&#DT|4TtSx>C|?oaNcGzrfV_h0`zgfXHO{>4tx z(fo^Ykd(;5a)@h`_Hr0ntzZ*7aNoL9yGbi>7!0J@e5o8*1&x*Aju0!G$4VR~hoq&B zi*lu(93@?(o0Li)IYy36OD&`&v}xi7ieOsXhFZ*Z%jHnLSZlOar|49jmU)CuOQpKy zI+fI1j!QBOmP;G*NtMsek(p+9DmSxC(r?!hv>rE+J>wmcj6^Qi_CWH%Dwjs=%*9&#Zyq{u{Qv*} diff --git a/app/src/main/assets/highlight/js/prettify.js b/app/src/main/assets/highlight/js/prettify.js deleted file mode 100644 index d9ae44f07..000000000 --- a/app/src/main/assets/highlight/js/prettify.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! highlight.js v9.10.0 | BSD3 License | git.io/hljslicense */ -!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/[&<>]/gm,function(e){return j[e]})}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){l+=""}function c(e){("start"===e.event?o:u)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=i();if(l+=n(a.substring(s,g[0].offset)),s=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===s);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return l+n(a.substr(s))}function s(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function l(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return s("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function s(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=s(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!L[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){y+=null!=E.sL?d():h(),k=""}function v(e){y+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(y+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');l(N);var R,E=i||N,x={},y="";for(R=E;R!==N;R=R.parent)R.cN&&(y=p(R.cN,"",!0)+y);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(y+=C);return{r:B,value:y,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(L);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"
    ":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?y[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,s,l=i(e);a(l)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,s=n.textContent,r=l?f(l,s,!0):g(s),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),s)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,l,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=L[n]=t(e);r.aliases&&r.aliases.forEach(function(e){y[e]=n})}function R(){return x(L)}function w(e){return e=(e||"").toLowerCase(),L[e]||L[y[e]]}var E=[],x=Object.keys,L={},y={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="
    ",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},j={"&":"&","<":"<",">":">"};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("avrasm",function(r){return{cI:!0,l:"\\.?"+r.IR,k:{keyword:"adc add adiw and andi asr bclr bld brbc brbs brcc brcs break breq brge brhc brhs brid brie brlo brlt brmi brne brpl brsh brtc brts brvc brvs bset bst call cbi cbr clc clh cli cln clr cls clt clv clz com cp cpc cpi cpse dec eicall eijmp elpm eor fmul fmuls fmulsu icall ijmp in inc jmp ld ldd ldi lds lpm lsl lsr mov movw mul muls mulsu neg nop or ori out pop push rcall ret reti rjmp rol ror sbc sbr sbrc sbrs sec seh sbi sbci sbic sbis sbiw sei sen ser ses set sev sez sleep spm st std sts sub subi swap tst wdr",built_in:"r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 x|0 xh xl y|0 yh yl z|0 zh zl ucsr1c udr1 ucsr1a ucsr1b ubrr1l ubrr1h ucsr0c ubrr0h tccr3c tccr3a tccr3b tcnt3h tcnt3l ocr3ah ocr3al ocr3bh ocr3bl ocr3ch ocr3cl icr3h icr3l etimsk etifr tccr1c ocr1ch ocr1cl twcr twdr twar twsr twbr osccal xmcra xmcrb eicra spmcsr spmcr portg ddrg ping portf ddrf sreg sph spl xdiv rampz eicrb eimsk gimsk gicr eifr gifr timsk tifr mcucr mcucsr tccr0 tcnt0 ocr0 assr tccr1a tccr1b tcnt1h tcnt1l ocr1ah ocr1al ocr1bh ocr1bl icr1h icr1l tccr2 tcnt2 ocr2 ocdr wdtcr sfior eearh eearl eedr eecr porta ddra pina portb ddrb pinb portc ddrc pinc portd ddrd pind spdr spsr spcr udr0 ucsr0a ucsr0b ubrr0l acsr admux adcsr adch adcl porte ddre pine pinf",meta:".byte .cseg .db .def .device .dseg .dw .endmacro .equ .eseg .exit .include .list .listmac .macro .nolist .org .set"},c:[r.CBCM,r.C(";","$",{r:0}),r.CNM,r.BNM,{cN:"number",b:"\\b(\\$[a-zA-Z0-9]+|0o[0-7]+)"},r.QSM,{cN:"string",b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"},{cN:"symbol",b:"^[A-Za-z0-9_.$]+:"},{cN:"meta",b:"#",e:"$"},{cN:"subst",b:"@[0-9]+"}]}});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[t],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[t],starts:{e:"",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("vbscript",function(e){return{aliases:["vbs"],cI:!0,k:{keyword:"call class const dim do loop erase execute executeglobal exit for each next function if then else on error option explicit new private property let get public randomize redim rem select case set stop sub while wend with end to elseif is or xor and not class_initialize class_terminate default preserve in me byval byref step resume goto",built_in:"lcase month vartype instrrev ubound setlocale getobject rgb getref string weekdayname rnd dateadd monthname now day minute isarray cbool round formatcurrency conversions csng timevalue second year space abs clng timeserial fixs len asc isempty maths dateserial atn timer isobject filter weekday datevalue ccur isdate instr datediff formatdatetime replace isnull right sgn array snumeric log cdbl hex chr lbound msgbox ucase getlocale cos cdate cbyte rtrim join hour oct typename trim strcomp int createobject loadpicture tan formatnumber mid scriptenginebuildversion scriptengine split scriptengineminorversion cint sin datepart ltrim sqr scriptenginemajorversion time derived eval date formatpercent exp inputbox left ascw chrw regexp server response request cstr err",literal:"true false null nothing empty"},i:"//",c:[e.inherit(e.QSM,{c:[{b:'""'}]}),e.C(/'/,/$/,{r:0}),e.CNM]}});hljs.registerLanguage("vbscript-html",function(r){return{sL:"xml",c:[{b:"<%",e:"%>",sL:"vbscript"}]}});hljs.registerLanguage("aspectj",function(e){var t="false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else extends implements break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws privileged aspectOf adviceexecution proceed cflowbelow cflow initialization preinitialization staticinitialization withincode target within execution getWithinTypeName handler thisJoinPoint thisJoinPointStaticPart thisEnclosingJoinPointStaticPart declare parents warning error soft precedence thisAspectInstance",i="get set args call";return{k:t,i:/<\/|#/,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{b:/\w+@/,r:0},{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"aspect",e:/[{;=]/,eE:!0,i:/[:;"\[\]]/,c:[{bK:"extends implements pertypewithin perthis pertarget percflowbelow percflow issingleton"},e.UTM,{b:/\([^\)]*/,e:/[)]+/,k:t+" "+i,eE:!1}]},{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,r:0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"pointcut after before around throwing returning",e:/[)]/,eE:!1,i:/["\[\]]/,c:[{b:e.UIR+"\\s*\\(",rB:!0,c:[e.UTM]}]},{b:/[:]/,rB:!0,e:/[{;]/,r:0,eE:!1,k:t,i:/["\[\]]/,c:[{b:e.UIR+"\\s*\\(",k:t+" "+i},e.QSM]},{bK:"new throw",r:0},{cN:"function",b:/\w+ +\w+(\.)?\w+\s*\([^\)]*\)\s*((throws)[\w\s,]+)?[\{;]/,rB:!0,e:/[{;=]/,k:t,eE:!0,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,r:0,k:t,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},e.CNM,{cN:"meta",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("r",function(e){var r="([a-zA-Z]|\\.[a-zA-Z.])[a-zA-Z0-9._]*";return{c:[e.HCM,{b:r,l:r,k:{keyword:"function if in break next repeat else for return switch while try tryCatch stop warning require library attach detach source setMethod setGeneric setGroupGeneric setClass ...",literal:"NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10"},r:0},{cN:"number",b:"0[xX][0-9a-fA-F]+[Li]?\\b",r:0},{cN:"number",b:"\\d+(?:[eE][+\\-]?\\d*)?L\\b",r:0},{cN:"number",b:"\\d+\\.(?!\\d)(?:i\\b)?",r:0},{cN:"number",b:"\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b",r:0},{cN:"number",b:"\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b",r:0},{b:"`",e:"`",r:0},{cN:"string",c:[e.BE],v:[{b:'"',e:'"'},{b:"'",e:"'"}]}]}});hljs.registerLanguage("ceylon",function(e){var a="assembly module package import alias class interface object given value assign void function new of extends satisfies abstracts in out return break continue throw assert dynamic if else switch case for while try catch finally then let this outer super is exists nonempty",t="shared abstract formal default actual variable late native deprecatedfinal sealed annotation suppressWarnings small",s="doc by license see throws tagged",n={cN:"subst",eB:!0,eE:!0,b:/``/,e:/``/,k:a,r:10},r=[{cN:"string",b:'"""',e:'"""',r:10},{cN:"string",b:'"',e:'"',c:[n]},{cN:"string",b:"'",e:"'"},{cN:"number",b:"#[0-9a-fA-F_]+|\\$[01_]+|[0-9_]+(?:\\.[0-9_](?:[eE][+-]?\\d+)?)?[kMGTPmunpf]?",r:0}];return n.c=r,{k:{keyword:a+" "+t,meta:s},i:"\\$[^01]|#[^0-9a-fA-F]",c:[e.CLCM,e.C("/\\*","\\*/",{c:["self"]}),{cN:"meta",b:'@[a-z]\\w*(?:\\:"[^"]*")?'}].concat(r)}});hljs.registerLanguage("scilab",function(e){var s=[e.CNM,{cN:"string",b:"'|\"",e:"'|\"",c:[e.BE,{b:"''"}]}];return{aliases:["sci"],l:/%?\w+/,k:{keyword:"abort break case clear catch continue do elseif else endfunction end for function global if pause return resume select try then while",literal:"%f %F %t %T %pi %eps %inf %nan %e %i %z %s",built_in:"abs and acos asin atan ceil cd chdir clearglobal cosh cos cumprod deff disp error exec execstr exists exp eye gettext floor fprintf fread fsolve imag isdef isempty isinfisnan isvector lasterror length load linspace list listfiles log10 log2 log max min msprintf mclose mopen ones or pathconvert poly printf prod pwd rand real round sinh sin size gsort sprintf sqrt strcat strcmps tring sum system tanh tan type typename warning zeros matrix"},i:'("|#|/\\*|\\s+/\\w+)',c:[{cN:"function",bK:"function",e:"$",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)"}]},{b:"[a-zA-Z_][a-zA-Z_0-9]*('+[\\.']*|[\\.']+)",e:"",r:0},{b:"\\[",e:"\\]'*[\\.']*",r:0,c:s},e.C("//","$")].concat(s)}});hljs.registerLanguage("fsharp",function(e){var t={b:"<",e:">",c:[e.inherit(e.TM,{b:/'[a-zA-Z0-9_]+/})]};return{aliases:["fs"],k:"abstract and as assert base begin class default delegate do done downcast downto elif else end exception extern false finally for fun function global if in inherit inline interface internal lazy let match member module mutable namespace new null of open or override private public rec return sig static struct then to true try type upcast use val void when while with yield",i:/\/\*/,c:[{cN:"keyword",b:/\b(yield|return|let|do)!/},{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},{cN:"string",b:'"""',e:'"""'},e.C("\\(\\*","\\*\\)"),{cN:"class",bK:"type",e:"\\(|=|$",eE:!0,c:[e.UTM,t]},{cN:"meta",b:"\\[<",e:">\\]",r:10},{cN:"symbol",b:"\\B('[A-Za-z])\\b",c:[e.BE]},e.CLCM,e.inherit(e.QSM,{i:null}),e.CNM]}});hljs.registerLanguage("csp",function(r){return{cI:!1,l:"[a-zA-Z][a-zA-Z0-9_-]*",k:{keyword:"base-uri child-src connect-src default-src font-src form-action frame-ancestors frame-src img-src media-src object-src plugin-types report-uri sandbox script-src style-src"},c:[{cN:"string",b:"'",e:"'"},{cN:"attribute",b:"^Content",e:":",eE:!0}]}});hljs.registerLanguage("matlab",function(e){var a=[e.CNM,{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]}],s={r:0,c:[{b:/'['\.]*/}]};return{k:{keyword:"break case catch classdef continue else elseif end enumerated events for function global if methods otherwise parfor persistent properties return spmd switch try while",built_in:"sin sind sinh asin asind asinh cos cosd cosh acos acosd acosh tan tand tanh atan atand atan2 atanh sec secd sech asec asecd asech csc cscd csch acsc acscd acsch cot cotd coth acot acotd acoth hypot exp expm1 log log1p log10 log2 pow2 realpow reallog realsqrt sqrt nthroot nextpow2 abs angle complex conj imag real unwrap isreal cplxpair fix floor ceil round mod rem sign airy besselj bessely besselh besseli besselk beta betainc betaln ellipj ellipke erf erfc erfcx erfinv expint gamma gammainc gammaln psi legendre cross dot factor isprime primes gcd lcm rat rats perms nchoosek factorial cart2sph cart2pol pol2cart sph2cart hsv2rgb rgb2hsv zeros ones eye repmat rand randn linspace logspace freqspace meshgrid accumarray size length ndims numel disp isempty isequal isequalwithequalnans cat reshape diag blkdiag tril triu fliplr flipud flipdim rot90 find sub2ind ind2sub bsxfun ndgrid permute ipermute shiftdim circshift squeeze isscalar isvector ans eps realmax realmin pi i inf nan isnan isinf isfinite j why compan gallery hadamard hankel hilb invhilb magic pascal rosser toeplitz vander wilkinson"},i:'(//|"|#|/\\*|\\s+/\\w+)',c:[{cN:"function",bK:"function",e:"$",c:[e.UTM,{cN:"params",v:[{b:"\\(",e:"\\)"},{b:"\\[",e:"\\]"}]}]},{b:/[a-zA-Z_][a-zA-Z_0-9]*'['\.]*/,rB:!0,r:0,c:[{b:/[a-zA-Z_][a-zA-Z_0-9]*/,r:0},s.c[0]]},{b:"\\[",e:"\\]",c:a,r:0,starts:s},{b:"\\{",e:/}/,c:a,r:0,starts:s},{b:/\)/,r:0,starts:s},e.C("^\\s*\\%\\{\\s*$","^\\s*\\%\\}\\s*$"),e.C("\\%","$")].concat(a)}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/-?[a-z\._]+/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,a,t]}});hljs.registerLanguage("dns",function(d){return{aliases:["bind","zone"],k:{keyword:"IN A AAAA AFSDB APL CAA CDNSKEY CDS CERT CNAME DHCID DLV DNAME DNSKEY DS HIP IPSECKEY KEY KX LOC MX NAPTR NS NSEC NSEC3 NSEC3PARAM PTR RRSIG RP SIG SOA SRV SSHFP TA TKEY TLSA TSIG TXT"},c:[d.C(";","$",{r:0}),{cN:"meta",b:/^\$(TTL|GENERATE|INCLUDE|ORIGIN)\b/},{cN:"number",b:"((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))\\b"},{cN:"number",b:"((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\b"},d.inherit(d.NM,{b:/\b\d+[dhwm]?/})]}});hljs.registerLanguage("clojure",function(e){var t={"builtin-name":"def defonce cond apply if-not if-let if not not= = < > <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize"},r="a-zA-Z_\\-!.?+*=<>&#'",n="["+r+"]["+r+"0-9/;:]*",a="[-+]?\\d+(\\.\\d+)?",o={b:n,r:0},s={cN:"number",b:a,r:0},i=e.inherit(e.QSM,{i:null}),c=e.C(";","$",{r:0}),d={cN:"literal",b:/\b(true|false|nil)\b/},l={b:"[\\[\\{]",e:"[\\]\\}]"},m={cN:"comment",b:"\\^"+n},p=e.C("\\^\\{","\\}"),u={cN:"symbol",b:"[:]{1,2}"+n},f={b:"\\(",e:"\\)"},h={eW:!0,r:0},y={k:t,l:n,cN:"name",b:n,starts:h},b=[f,i,m,p,c,u,l,s,d,o];return f.c=[e.C("comment",""),y,h],h.c=b,l.c=b,{aliases:["clj"],i:/\S/,c:[f,i,m,p,c,u,l,s,d]}});hljs.registerLanguage("clojure-repl",function(e){return{c:[{cN:"meta",b:/^([\w.-]+|\s*#_)=>/,starts:{e:/$/,sL:"clojure"}}]}});hljs.registerLanguage("rsl",function(e){return{k:{keyword:"float color point normal vector matrix while for if do return else break extern continue",built_in:"abs acos ambient area asin atan atmosphere attribute calculatenormal ceil cellnoise clamp comp concat cos degrees depth Deriv diffuse distance Du Dv environment exp faceforward filterstep floor format fresnel incident length lightsource log match max min mod noise normalize ntransform opposite option phong pnoise pow printf ptlined radians random reflect refract renderinfo round setcomp setxcomp setycomp setzcomp shadow sign sin smoothstep specular specularbrdf spline sqrt step tan texture textureinfo trace transform vtransform xcomp ycomp zcomp"},i:"",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b://,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("gams",function(e){var a={keyword:"abort acronym acronyms alias all and assign binary card diag display else eq file files for free ge gt if integer le loop lt maximizing minimizing model models ne negative no not option options or ord positive prod put putpage puttl repeat sameas semicont semiint smax smin solve sos1 sos2 sum system table then until using while xor yes",literal:"eps inf na","built-in":"abs arccos arcsin arctan arctan2 Beta betaReg binomial ceil centropy cos cosh cvPower div div0 eDist entropy errorf execSeed exp fact floor frac gamma gammaReg log logBeta logGamma log10 log2 mapVal max min mod ncpCM ncpF ncpVUpow ncpVUsin normal pi poly power randBinomial randLinear randTriangle round rPower sigmoid sign signPower sin sinh slexp sllog10 slrec sqexp sqlog10 sqr sqrec sqrt tan tanh trunc uniform uniformInt vcPower bool_and bool_eqv bool_imp bool_not bool_or bool_xor ifThen rel_eq rel_ge rel_gt rel_le rel_lt rel_ne gday gdow ghour gleap gmillisec gminute gmonth gsecond gyear jdate jnow jstart jtime errorLevel execError gamsRelease gamsVersion handleCollect handleDelete handleStatus handleSubmit heapFree heapLimit heapSize jobHandle jobKill jobStatus jobTerminate licenseLevel licenseStatus maxExecError sleep timeClose timeComp timeElapsed timeExec timeStart"},o={cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0},r={cN:"symbol",v:[{b:/\=[lgenxc]=/},{b:/\$/}]},t={cN:"comment",v:[{b:"'",e:"'"},{b:'"',e:'"'}],i:"\\n",c:[e.BE]},i={b:"/",e:"/",k:a,c:[t,e.CLCM,e.CBCM,e.QSM,e.ASM,e.CNM]},l={b:/[a-z][a-z0-9_]*(\([a-z0-9_, ]*\))?[ \t]+/,eB:!0,e:"$",eW:!0,c:[t,i,{cN:"comment",b:/([ ]*[a-z0-9&#*=?@>\\<:\-,()$\[\]_.{}!+%^]+)+/,r:0}]};return{aliases:["gms"],cI:!0,k:a,c:[e.C(/^\$ontext/,/^\$offtext/),{cN:"meta",b:"^\\$[a-z0-9]+",e:"$",rB:!0,c:[{cN:"meta-keyword",b:"^\\$[a-z0-9]+"}]},e.C("^\\*","$"),e.CLCM,e.CBCM,e.QSM,e.ASM,{bK:"set sets parameter parameters variable variables scalar scalars equation equations",e:";",c:[e.C("^\\*","$"),e.CLCM,e.CBCM,e.QSM,e.ASM,i,l]},{bK:"table",e:";",rB:!0,c:[{bK:"table",e:"$",c:[l]},e.C("^\\*","$"),e.CLCM,e.CBCM,e.QSM,e.ASM,e.CNM]},{cN:"function",b:/^[a-z][a-z0-9_,\-+' ()$]+\.{2}/,rB:!0,c:[{cN:"title",b:/^[a-z][a-z0-9_]+/},o,r]},e.CNM,r]}});hljs.registerLanguage("scala",function(e){var t={cN:"meta",b:"@[A-Za-z]+"},a={cN:"subst",v:[{b:"\\$[A-Za-z0-9_]+"},{b:"\\${",e:"}"}]},r={cN:"string",v:[{b:'"',e:'"',i:"\\n",c:[e.BE]},{b:'"""',e:'"""',r:10},{b:'[a-z]+"',e:'"',i:"\\n",c:[e.BE,a]},{cN:"string",b:'[a-z]+"""',e:'"""',c:[a],r:10}]},c={cN:"symbol",b:"'\\w[\\w\\d_]*(?!')"},i={cN:"type",b:"\\b[A-Z][A-Za-z0-9_]*",r:0},s={cN:"title",b:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/,r:0},n={cN:"class",bK:"class object trait type",e:/[:={\[\n;]/,eE:!0,c:[{bK:"extends with",r:10},{b:/\[/,e:/\]/,eB:!0,eE:!0,r:0,c:[i]},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,r:0,c:[i]},s]},l={cN:"function",bK:"def",e:/[:={\[(\n;]/,eE:!0,c:[s]};return{k:{literal:"true false null",keyword:"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit"},c:[e.CLCM,e.CBCM,r,c,i,l,n,e.CNM,t]}});hljs.registerLanguage("maxima",function(e){var t="if then else elseif for thru do while unless step in and or not",a="true false unknown inf minf ind und %e %i %pi %phi %gamma",r=" abasep abs absint absolute_real_time acos acosh acot acoth acsc acsch activate addcol add_edge add_edges addmatrices addrow add_vertex add_vertices adjacency_matrix adjoin adjoint af agd airy airy_ai airy_bi airy_dai airy_dbi algsys alg_type alias allroots alphacharp alphanumericp amortization %and annuity_fv annuity_pv antid antidiff AntiDifference append appendfile apply apply1 apply2 applyb1 apropos args arit_amortization arithmetic arithsum array arrayapply arrayinfo arraymake arraysetapply ascii asec asech asin asinh askinteger asksign assoc assoc_legendre_p assoc_legendre_q assume assume_external_byte_order asympa at atan atan2 atanh atensimp atom atvalue augcoefmatrix augmented_lagrangian_method av average_degree backtrace bars barsplot barsplot_description base64 base64_decode bashindices batch batchload bc2 bdvac belln benefit_cost bern bernpoly bernstein_approx bernstein_expand bernstein_poly bessel bessel_i bessel_j bessel_k bessel_simplify bessel_y beta beta_incomplete beta_incomplete_generalized beta_incomplete_regularized bezout bfallroots bffac bf_find_root bf_fmin_cobyla bfhzeta bfloat bfloatp bfpsi bfpsi0 bfzeta biconnected_components bimetric binomial bipartition block blockmatrixp bode_gain bode_phase bothcoef box boxplot boxplot_description break bug_report build_info|10 buildq build_sample burn cabs canform canten cardinality carg cartan cartesian_product catch cauchy_matrix cbffac cdf_bernoulli cdf_beta cdf_binomial cdf_cauchy cdf_chi2 cdf_continuous_uniform cdf_discrete_uniform cdf_exp cdf_f cdf_gamma cdf_general_finite_discrete cdf_geometric cdf_gumbel cdf_hypergeometric cdf_laplace cdf_logistic cdf_lognormal cdf_negative_binomial cdf_noncentral_chi2 cdf_noncentral_student_t cdf_normal cdf_pareto cdf_poisson cdf_rank_sum cdf_rayleigh cdf_signed_rank cdf_student_t cdf_weibull cdisplay ceiling central_moment cequal cequalignore cf cfdisrep cfexpand cgeodesic cgreaterp cgreaterpignore changename changevar chaosgame charat charfun charfun2 charlist charp charpoly chdir chebyshev_t chebyshev_u checkdiv check_overlaps chinese cholesky christof chromatic_index chromatic_number cint circulant_graph clear_edge_weight clear_rules clear_vertex_label clebsch_gordan clebsch_graph clessp clesspignore close closefile cmetric coeff coefmatrix cograd col collapse collectterms columnop columnspace columnswap columnvector combination combine comp2pui compare compfile compile compile_file complement_graph complete_bipartite_graph complete_graph complex_number_p components compose_functions concan concat conjugate conmetderiv connected_components connect_vertices cons constant constantp constituent constvalue cont2part content continuous_freq contortion contour_plot contract contract_edge contragrad contrib_ode convert coord copy copy_file copy_graph copylist copymatrix cor cos cosh cot coth cov cov1 covdiff covect covers crc24sum create_graph create_list csc csch csetup cspline ctaylor ct_coordsys ctransform ctranspose cube_graph cuboctahedron_graph cunlisp cv cycle_digraph cycle_graph cylindrical days360 dblint deactivate declare declare_constvalue declare_dimensions declare_fundamental_dimensions declare_fundamental_units declare_qty declare_translated declare_unit_conversion declare_units declare_weights decsym defcon define define_alt_display define_variable defint defmatch defrule defstruct deftaylor degree_sequence del delete deleten delta demo demoivre denom depends derivdegree derivlist describe desolve determinant dfloat dgauss_a dgauss_b dgeev dgemm dgeqrf dgesv dgesvd diag diagmatrix diag_matrix diagmatrixp diameter diff digitcharp dimacs_export dimacs_import dimension dimensionless dimensions dimensions_as_list direct directory discrete_freq disjoin disjointp disolate disp dispcon dispform dispfun dispJordan display disprule dispterms distrib divide divisors divsum dkummer_m dkummer_u dlange dodecahedron_graph dotproduct dotsimp dpart draw draw2d draw3d drawdf draw_file draw_graph dscalar echelon edge_coloring edge_connectivity edges eigens_by_jacobi eigenvalues eigenvectors eighth einstein eivals eivects elapsed_real_time elapsed_run_time ele2comp ele2polynome ele2pui elem elementp elevation_grid elim elim_allbut eliminate eliminate_using ellipse elliptic_e elliptic_ec elliptic_eu elliptic_f elliptic_kc elliptic_pi ematrix empty_graph emptyp endcons entermatrix entertensor entier equal equalp equiv_classes erf erfc erf_generalized erfi errcatch error errormsg errors euler ev eval_string evenp every evolution evolution2d evundiff example exp expand expandwrt expandwrt_factored expint expintegral_chi expintegral_ci expintegral_e expintegral_e1 expintegral_ei expintegral_e_simplify expintegral_li expintegral_shi expintegral_si explicit explose exponentialize express expt exsec extdiff extract_linear_equations extremal_subset ezgcd %f f90 facsum factcomb factor factorfacsum factorial factorout factorsum facts fast_central_elements fast_linsolve fasttimes featurep fernfale fft fib fibtophi fifth filename_merge file_search file_type fillarray findde find_root find_root_abs find_root_error find_root_rel first fix flatten flength float floatnump floor flower_snark flush flush1deriv flushd flushnd flush_output fmin_cobyla forget fortran fourcos fourexpand fourier fourier_elim fourint fourintcos fourintsin foursimp foursin fourth fposition frame_bracket freeof freshline fresnel_c fresnel_s from_adjacency_matrix frucht_graph full_listify fullmap fullmapl fullratsimp fullratsubst fullsetify funcsolve fundamental_dimensions fundamental_units fundef funmake funp fv g0 g1 gamma gamma_greek gamma_incomplete gamma_incomplete_generalized gamma_incomplete_regularized gauss gauss_a gauss_b gaussprob gcd gcdex gcdivide gcfac gcfactor gd generalized_lambert_w genfact gen_laguerre genmatrix gensym geo_amortization geo_annuity_fv geo_annuity_pv geomap geometric geometric_mean geosum get getcurrentdirectory get_edge_weight getenv get_lu_factors get_output_stream_string get_pixel get_plot_option get_tex_environment get_tex_environment_default get_vertex_label gfactor gfactorsum ggf girth global_variances gn gnuplot_close gnuplot_replot gnuplot_reset gnuplot_restart gnuplot_start go Gosper GosperSum gr2d gr3d gradef gramschmidt graph6_decode graph6_encode graph6_export graph6_import graph_center graph_charpoly graph_eigenvalues graph_flow graph_order graph_periphery graph_product graph_size graph_union great_rhombicosidodecahedron_graph great_rhombicuboctahedron_graph grid_graph grind grobner_basis grotzch_graph hamilton_cycle hamilton_path hankel hankel_1 hankel_2 harmonic harmonic_mean hav heawood_graph hermite hessian hgfred hilbertmap hilbert_matrix hipow histogram histogram_description hodge horner hypergeometric i0 i1 %ibes ic1 ic2 ic_convert ichr1 ichr2 icosahedron_graph icosidodecahedron_graph icurvature ident identfor identity idiff idim idummy ieqn %if ifactors iframes ifs igcdex igeodesic_coords ilt image imagpart imetric implicit implicit_derivative implicit_plot indexed_tensor indices induced_subgraph inferencep inference_result infix info_display init_atensor init_ctensor in_neighbors innerproduct inpart inprod inrt integerp integer_partitions integrate intersect intersection intervalp intopois intosum invariant1 invariant2 inverse_fft inverse_jacobi_cd inverse_jacobi_cn inverse_jacobi_cs inverse_jacobi_dc inverse_jacobi_dn inverse_jacobi_ds inverse_jacobi_nc inverse_jacobi_nd inverse_jacobi_ns inverse_jacobi_sc inverse_jacobi_sd inverse_jacobi_sn invert invert_by_adjoint invert_by_lu inv_mod irr is is_biconnected is_bipartite is_connected is_digraph is_edge_in_graph is_graph is_graph_or_digraph ishow is_isomorphic isolate isomorphism is_planar isqrt isreal_p is_sconnected is_tree is_vertex_in_graph items_inference %j j0 j1 jacobi jacobian jacobi_cd jacobi_cn jacobi_cs jacobi_dc jacobi_dn jacobi_ds jacobi_nc jacobi_nd jacobi_ns jacobi_p jacobi_sc jacobi_sd jacobi_sn JF jn join jordan julia julia_set julia_sin %k kdels kdelta kill killcontext kostka kron_delta kronecker_product kummer_m kummer_u kurtosis kurtosis_bernoulli kurtosis_beta kurtosis_binomial kurtosis_chi2 kurtosis_continuous_uniform kurtosis_discrete_uniform kurtosis_exp kurtosis_f kurtosis_gamma kurtosis_general_finite_discrete kurtosis_geometric kurtosis_gumbel kurtosis_hypergeometric kurtosis_laplace kurtosis_logistic kurtosis_lognormal kurtosis_negative_binomial kurtosis_noncentral_chi2 kurtosis_noncentral_student_t kurtosis_normal kurtosis_pareto kurtosis_poisson kurtosis_rayleigh kurtosis_student_t kurtosis_weibull label labels lagrange laguerre lambda lambert_w laplace laplacian_matrix last lbfgs lc2kdt lcharp lc_l lcm lc_u ldefint ldisp ldisplay legendre_p legendre_q leinstein length let letrules letsimp levi_civita lfreeof lgtreillis lhs li liediff limit Lindstedt linear linearinterpol linear_program linear_regression line_graph linsolve listarray list_correlations listify list_matrix_entries list_nc_monomials listoftens listofvars listp lmax lmin load loadfile local locate_matrix_entry log logcontract log_gamma lopow lorentz_gauge lowercasep lpart lratsubst lreduce lriemann lsquares_estimates lsquares_estimates_approximate lsquares_estimates_exact lsquares_mse lsquares_residual_mse lsquares_residuals lsum ltreillis lu_backsub lucas lu_factor %m macroexpand macroexpand1 make_array makebox makefact makegamma make_graph make_level_picture makelist makeOrders make_poly_continent make_poly_country make_polygon make_random_state make_rgb_picture makeset make_string_input_stream make_string_output_stream make_transform mandelbrot mandelbrot_set map mapatom maplist matchdeclare matchfix mat_cond mat_fullunblocker mat_function mathml_display mat_norm matrix matrixmap matrixp matrix_size mattrace mat_trace mat_unblocker max max_clique max_degree max_flow maximize_lp max_independent_set max_matching maybe md5sum mean mean_bernoulli mean_beta mean_binomial mean_chi2 mean_continuous_uniform mean_deviation mean_discrete_uniform mean_exp mean_f mean_gamma mean_general_finite_discrete mean_geometric mean_gumbel mean_hypergeometric mean_laplace mean_logistic mean_lognormal mean_negative_binomial mean_noncentral_chi2 mean_noncentral_student_t mean_normal mean_pareto mean_poisson mean_rayleigh mean_student_t mean_weibull median median_deviation member mesh metricexpandall mgf1_sha1 min min_degree min_edge_cut minfactorial minimalPoly minimize_lp minimum_spanning_tree minor minpack_lsquares minpack_solve min_vertex_cover min_vertex_cut mkdir mnewton mod mode_declare mode_identity ModeMatrix moebius mon2schur mono monomial_dimensions multibernstein_poly multi_display_for_texinfo multi_elem multinomial multinomial_coeff multi_orbit multiplot_mode multi_pui multsym multthru mycielski_graph nary natural_unit nc_degree ncexpt ncharpoly negative_picture neighbors new newcontext newdet new_graph newline newton new_variable next_prime nicedummies niceindices ninth nofix nonarray noncentral_moment nonmetricity nonnegintegerp nonscalarp nonzeroandfreeof notequal nounify nptetrad npv nroots nterms ntermst nthroot nullity nullspace num numbered_boundaries numberp number_to_octets num_distinct_partitions numerval numfactor num_partitions nusum nzeta nzetai nzetar octets_to_number octets_to_oid odd_girth oddp ode2 ode_check odelin oid_to_octets op opena opena_binary openr openr_binary openw openw_binary operatorp opsubst optimize %or orbit orbits ordergreat ordergreatp orderless orderlessp orthogonal_complement orthopoly_recur orthopoly_weight outermap out_neighbors outofpois pade parabolic_cylinder_d parametric parametric_surface parg parGosper parse_string parse_timedate part part2cont partfrac partition partition_set partpol path_digraph path_graph pathname_directory pathname_name pathname_type pdf_bernoulli pdf_beta pdf_binomial pdf_cauchy pdf_chi2 pdf_continuous_uniform pdf_discrete_uniform pdf_exp pdf_f pdf_gamma pdf_general_finite_discrete pdf_geometric pdf_gumbel pdf_hypergeometric pdf_laplace pdf_logistic pdf_lognormal pdf_negative_binomial pdf_noncentral_chi2 pdf_noncentral_student_t pdf_normal pdf_pareto pdf_poisson pdf_rank_sum pdf_rayleigh pdf_signed_rank pdf_student_t pdf_weibull pearson_skewness permanent permut permutation permutations petersen_graph petrov pickapart picture_equalp picturep piechart piechart_description planar_embedding playback plog plot2d plot3d plotdf ploteq plsquares pochhammer points poisdiff poisexpt poisint poismap poisplus poissimp poissubst poistimes poistrim polar polarform polartorect polar_to_xy poly_add poly_buchberger poly_buchberger_criterion poly_colon_ideal poly_content polydecomp poly_depends_p poly_elimination_ideal poly_exact_divide poly_expand poly_expt poly_gcd polygon poly_grobner poly_grobner_equal poly_grobner_member poly_grobner_subsetp poly_ideal_intersection poly_ideal_polysaturation poly_ideal_polysaturation1 poly_ideal_saturation poly_ideal_saturation1 poly_lcm poly_minimization polymod poly_multiply polynome2ele polynomialp poly_normal_form poly_normalize poly_normalize_list poly_polysaturation_extension poly_primitive_part poly_pseudo_divide poly_reduced_grobner poly_reduction poly_saturation_extension poly_s_polynomial poly_subtract polytocompanion pop postfix potential power_mod powerseries powerset prefix prev_prime primep primes principal_components print printf printfile print_graph printpois printprops prodrac product properties propvars psi psubst ptriangularize pui pui2comp pui2ele pui2polynome pui_direct puireduc push put pv qput qrange qty quad_control quad_qag quad_qagi quad_qagp quad_qags quad_qawc quad_qawf quad_qawo quad_qaws quadrilateral quantile quantile_bernoulli quantile_beta quantile_binomial quantile_cauchy quantile_chi2 quantile_continuous_uniform quantile_discrete_uniform quantile_exp quantile_f quantile_gamma quantile_general_finite_discrete quantile_geometric quantile_gumbel quantile_hypergeometric quantile_laplace quantile_logistic quantile_lognormal quantile_negative_binomial quantile_noncentral_chi2 quantile_noncentral_student_t quantile_normal quantile_pareto quantile_poisson quantile_rayleigh quantile_student_t quantile_weibull quartile_skewness quit qunit quotient racah_v racah_w radcan radius random random_bernoulli random_beta random_binomial random_bipartite_graph random_cauchy random_chi2 random_continuous_uniform random_digraph random_discrete_uniform random_exp random_f random_gamma random_general_finite_discrete random_geometric random_graph random_graph1 random_gumbel random_hypergeometric random_laplace random_logistic random_lognormal random_negative_binomial random_network random_noncentral_chi2 random_noncentral_student_t random_normal random_pareto random_permutation random_poisson random_rayleigh random_regular_graph random_student_t random_tournament random_tree random_weibull range rank rat ratcoef ratdenom ratdiff ratdisrep ratexpand ratinterpol rational rationalize ratnumer ratnump ratp ratsimp ratsubst ratvars ratweight read read_array read_binary_array read_binary_list read_binary_matrix readbyte readchar read_hashed_array readline read_list read_matrix read_nested_list readonly read_xpm real_imagpart_to_conjugate realpart realroots rearray rectangle rectform rectform_log_if_constant recttopolar rediff reduce_consts reduce_order region region_boundaries region_boundaries_plus rem remainder remarray rembox remcomps remcon remcoord remfun remfunction remlet remove remove_constvalue remove_dimensions remove_edge remove_fundamental_dimensions remove_fundamental_units remove_plot_option remove_vertex rempart remrule remsym remvalue rename rename_file reset reset_displays residue resolvante resolvante_alternee1 resolvante_bipartite resolvante_diedrale resolvante_klein resolvante_klein3 resolvante_produit_sym resolvante_unitaire resolvante_vierer rest resultant return reveal reverse revert revert2 rgb2level rhs ricci riemann rinvariant risch rk rmdir rncombine romberg room rootscontract round row rowop rowswap rreduce run_testsuite %s save saving scalarp scaled_bessel_i scaled_bessel_i0 scaled_bessel_i1 scalefactors scanmap scatterplot scatterplot_description scene schur2comp sconcat scopy scsimp scurvature sdowncase sec sech second sequal sequalignore set_alt_display setdifference set_draw_defaults set_edge_weight setelmx setequalp setify setp set_partitions set_plot_option set_prompt set_random_state set_tex_environment set_tex_environment_default setunits setup_autoload set_up_dot_simplifications set_vertex_label seventh sexplode sf sha1sum sha256sum shortest_path shortest_weighted_path show showcomps showratvars sierpinskiale sierpinskimap sign signum similaritytransform simp_inequality simplify_sum simplode simpmetderiv simtran sin sinh sinsert sinvertcase sixth skewness skewness_bernoulli skewness_beta skewness_binomial skewness_chi2 skewness_continuous_uniform skewness_discrete_uniform skewness_exp skewness_f skewness_gamma skewness_general_finite_discrete skewness_geometric skewness_gumbel skewness_hypergeometric skewness_laplace skewness_logistic skewness_lognormal skewness_negative_binomial skewness_noncentral_chi2 skewness_noncentral_student_t skewness_normal skewness_pareto skewness_poisson skewness_rayleigh skewness_student_t skewness_weibull slength smake small_rhombicosidodecahedron_graph small_rhombicuboctahedron_graph smax smin smismatch snowmap snub_cube_graph snub_dodecahedron_graph solve solve_rec solve_rec_rat some somrac sort sparse6_decode sparse6_encode sparse6_export sparse6_import specint spherical spherical_bessel_j spherical_bessel_y spherical_hankel1 spherical_hankel2 spherical_harmonic spherical_to_xyz splice split sposition sprint sqfr sqrt sqrtdenest sremove sremovefirst sreverse ssearch ssort sstatus ssubst ssubstfirst staircase standardize standardize_inverse_trig starplot starplot_description status std std1 std_bernoulli std_beta std_binomial std_chi2 std_continuous_uniform std_discrete_uniform std_exp std_f std_gamma std_general_finite_discrete std_geometric std_gumbel std_hypergeometric std_laplace std_logistic std_lognormal std_negative_binomial std_noncentral_chi2 std_noncentral_student_t std_normal std_pareto std_poisson std_rayleigh std_student_t std_weibull stemplot stirling stirling1 stirling2 strim striml strimr string stringout stringp strong_components struve_h struve_l sublis sublist sublist_indices submatrix subsample subset subsetp subst substinpart subst_parallel substpart substring subvar subvarp sum sumcontract summand_to_rec supcase supcontext symbolp symmdifference symmetricp system take_channel take_inference tan tanh taylor taylorinfo taylorp taylor_simplifier taytorat tcl_output tcontract tellrat tellsimp tellsimpafter tentex tenth test_mean test_means_difference test_normality test_proportion test_proportions_difference test_rank_sum test_sign test_signed_rank test_variance test_variance_ratio tex tex1 tex_display texput %th third throw time timedate timer timer_info tldefint tlimit todd_coxeter toeplitz tokens to_lisp topological_sort to_poly to_poly_solve totaldisrep totalfourier totient tpartpol trace tracematrix trace_options transform_sample translate translate_file transpose treefale tree_reduce treillis treinat triangle triangularize trigexpand trigrat trigreduce trigsimp trunc truncate truncated_cube_graph truncated_dodecahedron_graph truncated_icosahedron_graph truncated_tetrahedron_graph tr_warnings_get tube tutte_graph ueivects uforget ultraspherical underlying_graph undiff union unique uniteigenvectors unitp units unit_step unitvector unorder unsum untellrat untimer untrace uppercasep uricci uriemann uvect vandermonde_matrix var var1 var_bernoulli var_beta var_binomial var_chi2 var_continuous_uniform var_discrete_uniform var_exp var_f var_gamma var_general_finite_discrete var_geometric var_gumbel var_hypergeometric var_laplace var_logistic var_lognormal var_negative_binomial var_noncentral_chi2 var_noncentral_student_t var_normal var_pareto var_poisson var_rayleigh var_student_t var_weibull vector vectorpotential vectorsimp verbify vers vertex_coloring vertex_connectivity vertex_degree vertex_distance vertex_eccentricity vertex_in_degree vertex_out_degree vertices vertices_to_cycle vertices_to_path %w weyl wheel_graph wiener_index wigner_3j wigner_6j wigner_9j with_stdout write_binary_data writebyte write_data writefile wronskian xreduce xthru %y Zeilberger zeroequiv zerofor zeromatrix zeromatrixp zeta zgeev zheev zlange zn_add_table zn_carmichael_lambda zn_characteristic_factors zn_determinant zn_factor_generators zn_invert_by_lu zn_log zn_mult_table absboxchar activecontexts adapt_depth additive adim aform algebraic algepsilon algexact aliases allbut all_dotsimp_denoms allocation allsym alphabetic animation antisymmetric arrays askexp assume_pos assume_pos_pred assumescalar asymbol atomgrad atrig1 axes axis_3d axis_bottom axis_left axis_right axis_top azimuth background background_color backsubst berlefact bernstein_explicit besselexpand beta_args_sum_to_integer beta_expand bftorat bftrunc bindtest border boundaries_array box boxchar breakup %c capping cauchysum cbrange cbtics center cflength cframe_flag cnonmet_flag color color_bar color_bar_tics colorbox columns commutative complex cone context contexts contour contour_levels cosnpiflag ctaypov ctaypt ctayswitch ctayvar ct_coords ctorsion_flag ctrgsimp cube current_let_rule_package cylinder data_file_name debugmode decreasing default_let_rule_package delay dependencies derivabbrev derivsubst detout diagmetric diff dim dimensions dispflag display2d|10 display_format_internal distribute_over doallmxops domain domxexpt domxmxops domxnctimes dontfactor doscmxops doscmxplus dot0nscsimp dot0simp dot1simp dotassoc dotconstrules dotdistrib dotexptsimp dotident dotscrules draw_graph_program draw_realpart edge_color edge_coloring edge_partition edge_type edge_width %edispflag elevation %emode endphi endtheta engineering_format_floats enhanced3d %enumer epsilon_lp erfflag erf_representation errormsg error_size error_syms error_type %e_to_numlog eval even evenfun evflag evfun ev_point expandwrt_denom expintexpand expintrep expon expop exptdispflag exptisolate exptsubst facexpand facsum_combine factlim factorflag factorial_expand factors_only fb feature features file_name file_output_append file_search_demo file_search_lisp file_search_maxima|10 file_search_tests file_search_usage file_type_lisp file_type_maxima|10 fill_color fill_density filled_func fixed_vertices flipflag float2bf font font_size fortindent fortspaces fpprec fpprintprec functions gamma_expand gammalim gdet genindex gensumnum GGFCFMAX GGFINFINITY globalsolve gnuplot_command gnuplot_curve_styles gnuplot_curve_titles gnuplot_default_term_command gnuplot_dumb_term_command gnuplot_file_args gnuplot_file_name gnuplot_out_file gnuplot_pdf_term_command gnuplot_pm3d gnuplot_png_term_command gnuplot_postamble gnuplot_preamble gnuplot_ps_term_command gnuplot_svg_term_command gnuplot_term gnuplot_view_args Gosper_in_Zeilberger gradefs grid grid2d grind halfangles head_angle head_both head_length head_type height hypergeometric_representation %iargs ibase icc1 icc2 icounter idummyx ieqnprint ifb ifc1 ifc2 ifg ifgi ifr iframe_bracket_form ifri igeowedge_flag ikt1 ikt2 imaginary inchar increasing infeval infinity inflag infolists inm inmc1 inmc2 intanalysis integer integervalued integrate_use_rootsof integration_constant integration_constant_counter interpolate_color intfaclim ip_grid ip_grid_in irrational isolate_wrt_times iterations itr julia_parameter %k1 %k2 keepfloat key key_pos kinvariant kt label label_alignment label_orientation labels lassociative lbfgs_ncorrections lbfgs_nfeval_max leftjust legend letrat let_rule_packages lfg lg lhospitallim limsubst linear linear_solver linechar linel|10 linenum line_type linewidth line_width linsolve_params linsolvewarn lispdisp listarith listconstvars listdummyvars lmxchar load_pathname loadprint logabs logarc logcb logconcoeffp logexpand lognegint logsimp logx logx_secondary logy logy_secondary logz lriem m1pbranch macroexpansion macros mainvar manual_demo maperror mapprint matrix_element_add matrix_element_mult matrix_element_transpose maxapplydepth maxapplyheight maxima_tempdir|10 maxima_userdir|10 maxnegex MAX_ORD maxposex maxpsifracdenom maxpsifracnum maxpsinegint maxpsiposint maxtayorder mesh_lines_color method mod_big_prime mode_check_errorp mode_checkp mode_check_warnp mod_test mod_threshold modular_linear_solver modulus multiplicative multiplicities myoptions nary negdistrib negsumdispflag newline newtonepsilon newtonmaxiter nextlayerfactor niceindicespref nm nmc noeval nolabels nonegative_lp noninteger nonscalar noun noundisp nouns np npi nticks ntrig numer numer_pbranch obase odd oddfun opacity opproperties opsubst optimprefix optionset orientation origin orthopoly_returns_intervals outative outchar packagefile palette partswitch pdf_file pfeformat phiresolution %piargs piece pivot_count_sx pivot_max_sx plot_format plot_options plot_realpart png_file pochhammer_max_index points pointsize point_size points_joined point_type poislim poisson poly_coefficient_ring poly_elimination_order polyfactor poly_grobner_algorithm poly_grobner_debug poly_monomial_order poly_primary_elimination_order poly_return_term_list poly_secondary_elimination_order poly_top_reduction_only posfun position powerdisp pred prederror primep_number_of_tests product_use_gamma program programmode promote_float_to_bigfloat prompt proportional_axes props psexpand ps_file radexpand radius radsubstflag rassociative ratalgdenom ratchristof ratdenomdivide rateinstein ratepsilon ratfac rational ratmx ratprint ratriemann ratsimpexpons ratvarswitch ratweights ratweyl ratwtlvl real realonly redraw refcheck resolution restart resultant ric riem rmxchar %rnum_list rombergabs rombergit rombergmin rombergtol rootsconmode rootsepsilon run_viewer same_xy same_xyz savedef savefactors scalar scalarmatrixp scale scale_lp setcheck setcheckbreak setval show_edge_color show_edges show_edge_type show_edge_width show_id show_label showtime show_vertex_color show_vertex_size show_vertex_type show_vertices show_weight simp simplified_output simplify_products simpproduct simpsum sinnpiflag solvedecomposes solveexplicit solvefactors solvenullwarn solveradcan solvetrigwarn space sparse sphere spring_embedding_depth sqrtdispflag stardisp startphi starttheta stats_numer stringdisp structures style sublis_apply_lambda subnumsimp sumexpand sumsplitfact surface surface_hide svg_file symmetric tab taylordepth taylor_logexpand taylor_order_coefficients taylor_truncate_polynomials tensorkill terminal testsuite_files thetaresolution timer_devalue title tlimswitch tr track transcompile transform transform_xy translate_fast_arrays transparent transrun tr_array_as_ref tr_bound_function_applyp tr_file_tty_messagesp tr_float_can_branch_complex tr_function_call_default trigexpandplus trigexpandtimes triginverses trigsign trivial_solutions tr_numer tr_optimize_max_loop tr_semicompile tr_state_vars tr_warn_bad_function_calls tr_warn_fexpr tr_warn_meval tr_warn_mode tr_warn_undeclared tr_warn_undefined_variable tstep ttyoff tube_extremes ufg ug %unitexpand unit_vectors uric uriem use_fast_arrays user_preamble usersetunits values vect_cross verbose vertex_color vertex_coloring vertex_partition vertex_size vertex_type view warnings weyl width windowname windowtitle wired_surface wireframe xaxis xaxis_color xaxis_secondary xaxis_type xaxis_width xlabel xlabel_secondary xlength xrange xrange_secondary xtics xtics_axis xtics_rotate xtics_rotate_secondary xtics_secondary xtics_secondary_axis xu_grid x_voxel xy_file xyplane xy_scale yaxis yaxis_color yaxis_secondary yaxis_type yaxis_width ylabel ylabel_secondary ylength yrange yrange_secondary ytics ytics_axis ytics_rotate ytics_rotate_secondary ytics_secondary ytics_secondary_axis yv_grid y_voxel yx_ratio zaxis zaxis_color zaxis_type zaxis_width zeroa zerob zerobern zeta%pi zlabel zlabel_rotate zlength zmin zn_primroot_limit zn_primroot_pretest",i="_ __ %|0 %%|0";return{l:"[A-Za-z_%][0-9A-Za-z_%]*",k:{keyword:t,literal:a,built_in:r,symbol:i},c:[{cN:"comment",b:"/\\*",e:"\\*/",c:["self"]},e.QSM,{cN:"number",r:0,v:[{b:"\\b(\\d+|\\d+\\.|\\.\\d+|\\d+\\.\\d+)[Ee][-+]?\\d+\\b"},{b:"\\b(\\d+|\\d+\\.|\\.\\d+|\\d+\\.\\d+)[Bb][-+]?\\d+\\b",r:10},{b:"\\b(\\.\\d+|\\d+\\.\\d+)\\b"},{b:"\\b(\\d+|0[0-9A-Za-z]+)\\.?\\b"}]}],i:/@/}});hljs.registerLanguage("python",function(e){var r={keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},b={cN:"meta",b:/^(>>>|\.\.\.) /},c={cN:"subst",b:/\{/,e:/\}/,k:r,i:/#/},a={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[b],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[b],r:10},{b:/(fr|rf|f)'''/,e:/'''/,c:[b,c]},{b:/(fr|rf|f)"""/,e:/"""/,c:[b,c]},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},{b:/(fr|rf|f)'/,e:/'/,c:[c]},{b:/(fr|rf|f)"/,e:/"/,c:[c]},e.ASM,e.QSM]},s={cN:"number",r:0,v:[{b:e.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:e.CNR+"[lLjJ]?"}]},i={cN:"params",b:/\(/,e:/\)/,c:["self",b,s,a]};return c.c=[a,s,b],{aliases:["py","gyp"],k:r,i:/(<\/|->|\?)|=>/,c:[b,s,a,e.HCM,{v:[{cN:"function",bK:"def"},{cN:"class",bK:"class"}],e:/:/,i:/[${=;\n,]/,c:[e.UTM,i,{b:/->/,eW:!0,k:"None"}]},{cN:"meta",b:/^[\t ]*@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("erlang",function(e){var r="[a-z'][a-zA-Z0-9_']*",c="("+r+":"+r+"|"+r+")",b={keyword:"after and andalso|10 band begin bnot bor bsl bzr bxor case catch cond div end fun if let not of orelse|10 query receive rem try when xor",literal:"false true"},i=e.C("%","$"),n={cN:"number",b:"\\b(\\d+#[a-fA-F0-9]+|\\d+(\\.\\d+)?([eE][-+]?\\d+)?)",r:0},a={b:"fun\\s+"+r+"/\\d+"},d={b:c+"\\(",e:"\\)",rB:!0,r:0,c:[{b:c,r:0},{b:"\\(",e:"\\)",eW:!0,rE:!0,r:0}]},o={b:"{",e:"}",r:0},t={b:"\\b_([A-Z][A-Za-z0-9_]*)?",r:0},f={b:"[A-Z][a-zA-Z0-9_]*",r:0},l={b:"#"+e.UIR,r:0,rB:!0,c:[{b:"#"+e.UIR,r:0},{b:"{",e:"}",r:0}]},s={bK:"fun receive if try case",e:"end",k:b};s.c=[i,a,e.inherit(e.ASM,{cN:""}),s,d,e.QSM,n,o,t,f,l];var u=[i,a,s,d,e.QSM,n,o,t,f,l];d.c[1].c=u,o.c=u,l.c[1].c=u;var h={cN:"params",b:"\\(",e:"\\)",c:u};return{aliases:["erl"],k:b,i:"(",rB:!0,i:"\\(|#|//|/\\*|\\\\|:|;",c:[h,e.inherit(e.TM,{b:r})],starts:{e:";|\\.",k:b,c:u}},i,{b:"^-",e:"\\.",r:0,eE:!0,rB:!0,l:"-"+e.IR,k:"-module -record -undef -export -ifdef -ifndef -author -copyright -doc -vsn -import -include -include_lib -compile -define -else -endif -file -behaviour -behavior -spec",c:[h]},n,e.QSM,l,t,f,o,{b:/\.$/}]}});hljs.registerLanguage("dsconfig",function(e){var i={cN:"string",b:/"/,e:/"/},r={cN:"string",b:/'/,e:/'/},s={cN:"string",b:"[\\w-?]+:\\w+",e:"\\W",r:0},t={cN:"string",b:"\\w+-?\\w+",e:"\\W",r:0};return{k:"dsconfig",c:[{cN:"keyword",b:"^dsconfig",e:"\\s",eE:!0,r:10},{cN:"built_in",b:"(list|create|get|set|delete)-(\\w+)",e:"\\s",eE:!0,i:"!@#$%^&*()",r:10},{cN:"built_in",b:"--(\\w+)",e:"\\s",eE:!0},i,r,s,t,e.HCM]}});hljs.registerLanguage("hy",function(e){var t={"builtin-name":"!= % %= & &= * ** **= *= *map + += , --build-class-- --import-- -= . / // //= /= < << <<= <= = > >= >> >>= @ @= ^ ^= abs accumulate all and any ap-compose ap-dotimes ap-each ap-each-while ap-filter ap-first ap-if ap-last ap-map ap-map-when ap-pipe ap-reduce ap-reject apply as-> ascii assert assoc bin break butlast callable calling-module-name car case cdr chain chr coll? combinations compile compress cond cons cons? continue count curry cut cycle dec def default-method defclass defmacro defmacro-alias defmacro/g! defmain defmethod defmulti defn defn-alias defnc defnr defreader defseq del delattr delete-route dict-comp dir disassemble dispatch-reader-macro distinct divmod do doto drop drop-last drop-while empty? end-sequence eval eval-and-compile eval-when-compile even? every? except exec filter first flatten float? fn fnc fnr for for* format fraction genexpr gensym get getattr global globals group-by hasattr hash hex id identity if if* if-not if-python2 import in inc input instance? integer integer-char? integer? interleave interpose is is-coll is-cons is-empty is-even is-every is-float is-instance is-integer is-integer-char is-iterable is-iterator is-keyword is-neg is-none is-not is-numeric is-odd is-pos is-string is-symbol is-zero isinstance islice issubclass iter iterable? iterate iterator? keyword keyword? lambda last len let lif lif-not list* list-comp locals loop macro-error macroexpand macroexpand-1 macroexpand-all map max merge-with method-decorator min multi-decorator multicombinations name neg? next none? nonlocal not not-in not? nth numeric? oct odd? open or ord partition permutations pos? post-route postwalk pow prewalk print product profile/calls profile/cpu put-route quasiquote quote raise range read read-str recursive-replace reduce remove repeat repeatedly repr require rest round route route-with-methods rwm second seq set-comp setattr setv some sorted string string? sum switch symbol? take take-nth take-while tee try unless unquote unquote-splicing vars walk when while with with* with-decorator with-gensyms xi xor yield yield-from zero? zip zip-longest | |= ~"},i="a-zA-Z_\\-!.?+*=<>&#'",a="["+i+"]["+i+"0-9/;:]*",r="[-+]?\\d+(\\.\\d+)?",o={cN:"meta",b:"^#!",e:"$"},s={b:a,r:0},n={cN:"number",b:r,r:0},l=e.inherit(e.QSM,{i:null}),c=e.C(";","$",{r:0}),d={cN:"literal",b:/\b([Tt]rue|[Ff]alse|nil|None)\b/},p={b:"[\\[\\{]",e:"[\\]\\}]"},m={cN:"comment",b:"\\^"+a},u=e.C("\\^\\{","\\}"),f={cN:"symbol",b:"[:]{1,2}"+a},h={b:"\\(",e:"\\)"},b={eW:!0,r:0},g={k:t,l:a,cN:"name",b:a,starts:b},y=[h,l,m,u,c,f,p,n,d,s];return h.c=[e.C("comment",""),g,b],b.c=y,p.c=y,{aliases:["hylang"],i:/\S/,c:[o,h,l,m,u,c,f,p,n,d]}});hljs.registerLanguage("nix",function(e){var r={keyword:"rec with let in inherit assert if else then",literal:"true false or and null",built_in:"import abort baseNameOf dirOf isNull builtins map removeAttrs throw toString derivation"},t={cN:"subst",b:/\$\{/,e:/}/,k:r},i={b:/[a-zA-Z0-9-_]+(\s*=)/,rB:!0,r:0,c:[{cN:"attr",b:/\S+/}]},s={cN:"string",c:[t],v:[{b:"''",e:"''"},{b:'"',e:'"'}]},a=[e.NM,e.HCM,e.CBCM,s,i];return t.c=a,{aliases:["nixos"],k:r,c:a}});hljs.registerLanguage("d",function(e){var t={keyword:"abstract alias align asm assert auto body break byte case cast catch class const continue debug default delete deprecated do else enum export extern final finally for foreach foreach_reverse|10 goto if immutable import in inout int interface invariant is lazy macro mixin module new nothrow out override package pragma private protected public pure ref return scope shared static struct super switch synchronized template this throw try typedef typeid typeof union unittest version void volatile while with __FILE__ __LINE__ __gshared|10 __thread __traits __DATE__ __EOF__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__",built_in:"bool cdouble cent cfloat char creal dchar delegate double dstring float function idouble ifloat ireal long real short string ubyte ucent uint ulong ushort wchar wstring",literal:"false null true"},r="(0|[1-9][\\d_]*)",a="(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)",i="0[bB][01_]+",n="([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*)",_="0[xX]"+n,c="([eE][+-]?"+a+")",d="("+a+"(\\.\\d*|"+c+")|\\d+\\."+a+a+"|\\."+r+c+"?)",o="(0[xX]("+n+"\\."+n+"|\\.?"+n+")[pP][+-]?"+a+")",s="("+r+"|"+i+"|"+_+")",l="("+o+"|"+d+")",u="\\\\(['\"\\?\\\\abfnrtv]|u[\\dA-Fa-f]{4}|[0-7]{1,3}|x[\\dA-Fa-f]{2}|U[\\dA-Fa-f]{8})|&[a-zA-Z\\d]{2,};",b={cN:"number",b:"\\b"+s+"(L|u|U|Lu|LU|uL|UL)?",r:0},f={cN:"number",b:"\\b("+l+"([fF]|L|i|[fF]i|Li)?|"+s+"(i|[fF]i|Li))",r:0},g={cN:"string",b:"'("+u+"|.)",e:"'",i:"."},h={b:u,r:0},p={cN:"string",b:'"',c:[h],e:'"[cwd]?'},m={cN:"string",b:'[rq]"',e:'"[cwd]?',r:5},w={cN:"string",b:"`",e:"`[cwd]?"},N={cN:"string",b:'x"[\\da-fA-F\\s\\n\\r]*"[cwd]?',r:10},A={cN:"string",b:'q"\\{',e:'\\}"'},F={cN:"meta",b:"^#!",e:"$",r:5},y={cN:"meta",b:"#(line)",e:"$",r:5},L={cN:"keyword",b:"@[a-zA-Z_][a-zA-Z_\\d]*"},v=e.C("\\/\\+","\\+\\/",{c:["self"],r:10});return{l:e.UIR,k:t,c:[e.CLCM,e.CBCM,v,N,p,m,w,A,f,b,g,F,y,L]}});hljs.registerLanguage("ldif",function(e){return{c:[{cN:"attribute",b:"^dn",e:": ",eE:!0,starts:{e:"$",r:0},r:10},{cN:"attribute",b:"^\\w",e:": ",eE:!0,starts:{e:"$",r:0}},{cN:"literal",b:"^-",e:"$"},e.HCM]}});hljs.registerLanguage("parser3",function(r){var e=r.C("{","}",{c:["self"]});return{sL:"xml",r:0,c:[r.C("^#","$"),r.C("\\^rem{","}",{r:10,c:[e]}),{cN:"meta",b:"^@(?:BASE|USE|CLASS|OPTIONS)$",r:10},{cN:"title",b:"@[\\w\\-]+\\[[\\w^;\\-]*\\](?:\\[[\\w^;\\-]*\\])?(?:.*)$"},{cN:"variable",b:"\\$\\{?[\\w\\-\\.\\:]+\\}?"},{cN:"keyword",b:"\\^[\\w\\-\\.\\:]+"},{cN:"number",b:"\\^#[0-9a-fA-F]+"},r.CNM]}});hljs.registerLanguage("stata",function(e){return{aliases:["do","ado"],cI:!0,k:"if else in foreach for forv forva forval forvalu forvalue forvalues by bys bysort xi quietly qui capture about ac ac_7 acprplot acprplot_7 adjust ado adopath adoupdate alpha ameans an ano anov anova anova_estat anova_terms anovadef aorder ap app appe appen append arch arch_dr arch_estat arch_p archlm areg areg_p args arima arima_dr arima_estat arima_p as asmprobit asmprobit_estat asmprobit_lf asmprobit_mfx__dlg asmprobit_p ass asse asser assert avplot avplot_7 avplots avplots_7 bcskew0 bgodfrey binreg bip0_lf biplot bipp_lf bipr_lf bipr_p biprobit bitest bitesti bitowt blogit bmemsize boot bootsamp bootstrap bootstrap_8 boxco_l boxco_p boxcox boxcox_6 boxcox_p bprobit br break brier bro brow brows browse brr brrstat bs bs_7 bsampl_w bsample bsample_7 bsqreg bstat bstat_7 bstat_8 bstrap bstrap_7 ca ca_estat ca_p cabiplot camat canon canon_8 canon_8_p canon_estat canon_p cap caprojection capt captu captur capture cat cc cchart cchart_7 cci cd censobs_table centile cf char chdir checkdlgfiles checkestimationsample checkhlpfiles checksum chelp ci cii cl class classutil clear cli clis clist clo clog clog_lf clog_p clogi clogi_sw clogit clogit_lf clogit_p clogitp clogl_sw cloglog clonevar clslistarray cluster cluster_measures cluster_stop cluster_tree cluster_tree_8 clustermat cmdlog cnr cnre cnreg cnreg_p cnreg_sw cnsreg codebook collaps4 collapse colormult_nb colormult_nw compare compress conf confi confir confirm conren cons const constr constra constrai constrain constraint continue contract copy copyright copysource cor corc corr corr2data corr_anti corr_kmo corr_smc corre correl correla correlat correlate corrgram cou coun count cox cox_p cox_sw coxbase coxhaz coxvar cprplot cprplot_7 crc cret cretu cretur creturn cross cs cscript cscript_log csi ct ct_is ctset ctst_5 ctst_st cttost cumsp cumsp_7 cumul cusum cusum_7 cutil d|0 datasig datasign datasigna datasignat datasignatu datasignatur datasignature datetof db dbeta de dec deco decod decode deff des desc descr descri describ describe destring dfbeta dfgls dfuller di di_g dir dirstats dis discard disp disp_res disp_s displ displa display distinct do doe doed doedi doedit dotplot dotplot_7 dprobit drawnorm drop ds ds_util dstdize duplicates durbina dwstat dydx e|0 ed edi edit egen eivreg emdef en enc enco encod encode eq erase ereg ereg_lf ereg_p ereg_sw ereghet ereghet_glf ereghet_glf_sh ereghet_gp ereghet_ilf ereghet_ilf_sh ereghet_ip eret eretu eretur ereturn err erro error est est_cfexist est_cfname est_clickable est_expand est_hold est_table est_unhold est_unholdok estat estat_default estat_summ estat_vce_only esti estimates etodow etof etomdy ex exi exit expand expandcl fac fact facto factor factor_estat factor_p factor_pca_rotated factor_rotate factormat fcast fcast_compute fcast_graph fdades fdadesc fdadescr fdadescri fdadescrib fdadescribe fdasav fdasave fdause fh_st file open file read file close file filefilter fillin find_hlp_file findfile findit findit_7 fit fl fli flis flist for5_0 form forma format fpredict frac_154 frac_adj frac_chk frac_cox frac_ddp frac_dis frac_dv frac_in frac_mun frac_pp frac_pq frac_pv frac_wgt frac_xo fracgen fracplot fracplot_7 fracpoly fracpred fron_ex fron_hn fron_p fron_tn fron_tn2 frontier ftodate ftoe ftomdy ftowdate g|0 gamhet_glf gamhet_gp gamhet_ilf gamhet_ip gamma gamma_d2 gamma_p gamma_sw gammahet gdi_hexagon gdi_spokes ge gen gene gener genera generat generate genrank genstd genvmean gettoken gl gladder gladder_7 glim_l01 glim_l02 glim_l03 glim_l04 glim_l05 glim_l06 glim_l07 glim_l08 glim_l09 glim_l10 glim_l11 glim_l12 glim_lf glim_mu glim_nw1 glim_nw2 glim_nw3 glim_p glim_v1 glim_v2 glim_v3 glim_v4 glim_v5 glim_v6 glim_v7 glm glm_6 glm_p glm_sw glmpred glo glob globa global glogit glogit_8 glogit_p gmeans gnbre_lf gnbreg gnbreg_5 gnbreg_p gomp_lf gompe_sw gomper_p gompertz gompertzhet gomphet_glf gomphet_glf_sh gomphet_gp gomphet_ilf gomphet_ilf_sh gomphet_ip gphdot gphpen gphprint gprefs gprobi_p gprobit gprobit_8 gr gr7 gr_copy gr_current gr_db gr_describe gr_dir gr_draw gr_draw_replay gr_drop gr_edit gr_editviewopts gr_example gr_example2 gr_export gr_print gr_qscheme gr_query gr_read gr_rename gr_replay gr_save gr_set gr_setscheme gr_table gr_undo gr_use graph graph7 grebar greigen greigen_7 greigen_8 grmeanby grmeanby_7 gs_fileinfo gs_filetype gs_graphinfo gs_stat gsort gwood h|0 hadimvo hareg hausman haver he heck_d2 heckma_p heckman heckp_lf heckpr_p heckprob hel help hereg hetpr_lf hetpr_p hetprob hettest hexdump hilite hist hist_7 histogram hlogit hlu hmeans hotel hotelling hprobit hreg hsearch icd9 icd9_ff icd9p iis impute imtest inbase include inf infi infil infile infix inp inpu input ins insheet insp inspe inspec inspect integ inten intreg intreg_7 intreg_p intrg2_ll intrg_ll intrg_ll2 ipolate iqreg ir irf irf_create irfm iri is_svy is_svysum isid istdize ivprob_1_lf ivprob_lf ivprobit ivprobit_p ivreg ivreg_footnote ivtob_1_lf ivtob_lf ivtobit ivtobit_p jackknife jacknife jknife jknife_6 jknife_8 jkstat joinby kalarma1 kap kap_3 kapmeier kappa kapwgt kdensity kdensity_7 keep ksm ksmirnov ktau kwallis l|0 la lab labe label labelbook ladder levels levelsof leverage lfit lfit_p li lincom line linktest lis list lloghet_glf lloghet_glf_sh lloghet_gp lloghet_ilf lloghet_ilf_sh lloghet_ip llogi_sw llogis_p llogist llogistic llogistichet lnorm_lf lnorm_sw lnorma_p lnormal lnormalhet lnormhet_glf lnormhet_glf_sh lnormhet_gp lnormhet_ilf lnormhet_ilf_sh lnormhet_ip lnskew0 loadingplot loc loca local log logi logis_lf logistic logistic_p logit logit_estat logit_p loglogs logrank loneway lookfor lookup lowess lowess_7 lpredict lrecomp lroc lroc_7 lrtest ls lsens lsens_7 lsens_x lstat ltable ltable_7 ltriang lv lvr2plot lvr2plot_7 m|0 ma mac macr macro makecns man manova manova_estat manova_p manovatest mantel mark markin markout marksample mat mat_capp mat_order mat_put_rr mat_rapp mata mata_clear mata_describe mata_drop mata_matdescribe mata_matsave mata_matuse mata_memory mata_mlib mata_mosave mata_rename mata_which matalabel matcproc matlist matname matr matri matrix matrix_input__dlg matstrik mcc mcci md0_ md1_ md1debug_ md2_ md2debug_ mds mds_estat mds_p mdsconfig mdslong mdsmat mdsshepard mdytoe mdytof me_derd mean means median memory memsize meqparse mer merg merge mfp mfx mhelp mhodds minbound mixed_ll mixed_ll_reparm mkassert mkdir mkmat mkspline ml ml_5 ml_adjs ml_bhhhs ml_c_d ml_check ml_clear ml_cnt ml_debug ml_defd ml_e0 ml_e0_bfgs ml_e0_cycle ml_e0_dfp ml_e0i ml_e1 ml_e1_bfgs ml_e1_bhhh ml_e1_cycle ml_e1_dfp ml_e2 ml_e2_cycle ml_ebfg0 ml_ebfr0 ml_ebfr1 ml_ebh0q ml_ebhh0 ml_ebhr0 ml_ebr0i ml_ecr0i ml_edfp0 ml_edfr0 ml_edfr1 ml_edr0i ml_eds ml_eer0i ml_egr0i ml_elf ml_elf_bfgs ml_elf_bhhh ml_elf_cycle ml_elf_dfp ml_elfi ml_elfs ml_enr0i ml_enrr0 ml_erdu0 ml_erdu0_bfgs ml_erdu0_bhhh ml_erdu0_bhhhq ml_erdu0_cycle ml_erdu0_dfp ml_erdu0_nrbfgs ml_exde ml_footnote ml_geqnr ml_grad0 ml_graph ml_hbhhh ml_hd0 ml_hold ml_init ml_inv ml_log ml_max ml_mlout ml_mlout_8 ml_model ml_nb0 ml_opt ml_p ml_plot ml_query ml_rdgrd ml_repor ml_s_e ml_score ml_searc ml_technique ml_unhold mleval mlf_ mlmatbysum mlmatsum mlog mlogi mlogit mlogit_footnote mlogit_p mlopts mlsum mlvecsum mnl0_ mor more mov move mprobit mprobit_lf mprobit_p mrdu0_ mrdu1_ mvdecode mvencode mvreg mvreg_estat n|0 nbreg nbreg_al nbreg_lf nbreg_p nbreg_sw nestreg net newey newey_7 newey_p news nl nl_7 nl_9 nl_9_p nl_p nl_p_7 nlcom nlcom_p nlexp2 nlexp2_7 nlexp2a nlexp2a_7 nlexp3 nlexp3_7 nlgom3 nlgom3_7 nlgom4 nlgom4_7 nlinit nllog3 nllog3_7 nllog4 nllog4_7 nlog_rd nlogit nlogit_p nlogitgen nlogittree nlpred no nobreak noi nois noisi noisil noisily note notes notes_dlg nptrend numlabel numlist odbc old_ver olo olog ologi ologi_sw ologit ologit_p ologitp on one onew onewa oneway op_colnm op_comp op_diff op_inv op_str opr opro oprob oprob_sw oprobi oprobi_p oprobit oprobitp opts_exclusive order orthog orthpoly ou out outf outfi outfil outfile outs outsh outshe outshee outsheet ovtest pac pac_7 palette parse parse_dissim pause pca pca_8 pca_display pca_estat pca_p pca_rotate pcamat pchart pchart_7 pchi pchi_7 pcorr pctile pentium pergram pergram_7 permute permute_8 personal peto_st pkcollapse pkcross pkequiv pkexamine pkexamine_7 pkshape pksumm pksumm_7 pl plo plot plugin pnorm pnorm_7 poisgof poiss_lf poiss_sw poisso_p poisson poisson_estat post postclose postfile postutil pperron pr prais prais_e prais_e2 prais_p predict predictnl preserve print pro prob probi probit probit_estat probit_p proc_time procoverlay procrustes procrustes_estat procrustes_p profiler prog progr progra program prop proportion prtest prtesti pwcorr pwd q\\s qby qbys qchi qchi_7 qladder qladder_7 qnorm qnorm_7 qqplot qqplot_7 qreg qreg_c qreg_p qreg_sw qu quadchk quantile quantile_7 que quer query range ranksum ratio rchart rchart_7 rcof recast reclink recode reg reg3 reg3_p regdw regr regre regre_p2 regres regres_p regress regress_estat regriv_p remap ren rena renam rename renpfix repeat replace report reshape restore ret retu retur return rm rmdir robvar roccomp roccomp_7 roccomp_8 rocf_lf rocfit rocfit_8 rocgold rocplot rocplot_7 roctab roctab_7 rolling rologit rologit_p rot rota rotat rotate rotatemat rreg rreg_p ru run runtest rvfplot rvfplot_7 rvpplot rvpplot_7 sa safesum sample sampsi sav save savedresults saveold sc sca scal scala scalar scatter scm_mine sco scob_lf scob_p scobi_sw scobit scor score scoreplot scoreplot_help scree screeplot screeplot_help sdtest sdtesti se search separate seperate serrbar serrbar_7 serset set set_defaults sfrancia sh she shel shell shewhart shewhart_7 signestimationsample signrank signtest simul simul_7 simulate simulate_8 sktest sleep slogit slogit_d2 slogit_p smooth snapspan so sor sort spearman spikeplot spikeplot_7 spikeplt spline_x split sqreg sqreg_p sret sretu sretur sreturn ssc st st_ct st_hc st_hcd st_hcd_sh st_is st_issys st_note st_promo st_set st_show st_smpl st_subid stack statsby statsby_8 stbase stci stci_7 stcox stcox_estat stcox_fr stcox_fr_ll stcox_p stcox_sw stcoxkm stcoxkm_7 stcstat stcurv stcurve stcurve_7 stdes stem stepwise stereg stfill stgen stir stjoin stmc stmh stphplot stphplot_7 stphtest stphtest_7 stptime strate strate_7 streg streg_sw streset sts sts_7 stset stsplit stsum sttocc sttoct stvary stweib su suest suest_8 sum summ summa summar summari summariz summarize sunflower sureg survcurv survsum svar svar_p svmat svy svy_disp svy_dreg svy_est svy_est_7 svy_estat svy_get svy_gnbreg_p svy_head svy_header svy_heckman_p svy_heckprob_p svy_intreg_p svy_ivreg_p svy_logistic_p svy_logit_p svy_mlogit_p svy_nbreg_p svy_ologit_p svy_oprobit_p svy_poisson_p svy_probit_p svy_regress_p svy_sub svy_sub_7 svy_x svy_x_7 svy_x_p svydes svydes_8 svygen svygnbreg svyheckman svyheckprob svyintreg svyintreg_7 svyintrg svyivreg svylc svylog_p svylogit svymarkout svymarkout_8 svymean svymlog svymlogit svynbreg svyolog svyologit svyoprob svyoprobit svyopts svypois svypois_7 svypoisson svyprobit svyprobt svyprop svyprop_7 svyratio svyreg svyreg_p svyregress svyset svyset_7 svyset_8 svytab svytab_7 svytest svytotal sw sw_8 swcnreg swcox swereg swilk swlogis swlogit swologit swoprbt swpois swprobit swqreg swtobit swweib symmetry symmi symplot symplot_7 syntax sysdescribe sysdir sysuse szroeter ta tab tab1 tab2 tab_or tabd tabdi tabdis tabdisp tabi table tabodds tabodds_7 tabstat tabu tabul tabula tabulat tabulate te tempfile tempname tempvar tes test testnl testparm teststd tetrachoric time_it timer tis tob tobi tobit tobit_p tobit_sw token tokeni tokeniz tokenize tostring total translate translator transmap treat_ll treatr_p treatreg trim trnb_cons trnb_mean trpoiss_d2 trunc_ll truncr_p truncreg tsappend tset tsfill tsline tsline_ex tsreport tsrevar tsrline tsset tssmooth tsunab ttest ttesti tut_chk tut_wait tutorial tw tware_st two twoway twoway__fpfit_serset twoway__function_gen twoway__histogram_gen twoway__ipoint_serset twoway__ipoints_serset twoway__kdensity_gen twoway__lfit_serset twoway__normgen_gen twoway__pci_serset twoway__qfit_serset twoway__scatteri_serset twoway__sunflower_gen twoway_ksm_serset ty typ type typeof u|0 unab unabbrev unabcmd update us use uselabel var var_mkcompanion var_p varbasic varfcast vargranger varirf varirf_add varirf_cgraph varirf_create varirf_ctable varirf_describe varirf_dir varirf_drop varirf_erase varirf_graph varirf_ograph varirf_rename varirf_set varirf_table varlist varlmar varnorm varsoc varstable varstable_w varstable_w2 varwle vce vec vec_fevd vec_mkphi vec_p vec_p_w vecirf_create veclmar veclmar_w vecnorm vecnorm_w vecrank vecstable verinst vers versi versio version view viewsource vif vwls wdatetof webdescribe webseek webuse weib1_lf weib2_lf weib_lf weib_lf0 weibhet_glf weibhet_glf_sh weibhet_glfa weibhet_glfa_sh weibhet_gp weibhet_ilf weibhet_ilf_sh weibhet_ilfa weibhet_ilfa_sh weibhet_ip weibu_sw weibul_p weibull weibull_c weibull_s weibullhet wh whelp whi which whil while wilc_st wilcoxon win wind windo window winexec wntestb wntestb_7 wntestq xchart xchart_7 xcorr xcorr_7 xi xi_6 xmlsav xmlsave xmluse xpose xsh xshe xshel xshell xt_iis xt_tis xtab_p xtabond xtbin_p xtclog xtcloglog xtcloglog_8 xtcloglog_d2 xtcloglog_pa_p xtcloglog_re_p xtcnt_p xtcorr xtdata xtdes xtfront_p xtfrontier xtgee xtgee_elink xtgee_estat xtgee_makeivar xtgee_p xtgee_plink xtgls xtgls_p xthaus xthausman xtht_p xthtaylor xtile xtint_p xtintreg xtintreg_8 xtintreg_d2 xtintreg_p xtivp_1 xtivp_2 xtivreg xtline xtline_ex xtlogit xtlogit_8 xtlogit_d2 xtlogit_fe_p xtlogit_pa_p xtlogit_re_p xtmixed xtmixed_estat xtmixed_p xtnb_fe xtnb_lf xtnbreg xtnbreg_pa_p xtnbreg_refe_p xtpcse xtpcse_p xtpois xtpoisson xtpoisson_d2 xtpoisson_pa_p xtpoisson_refe_p xtpred xtprobit xtprobit_8 xtprobit_d2 xtprobit_re_p xtps_fe xtps_lf xtps_ren xtps_ren_8 xtrar_p xtrc xtrc_p xtrchh xtrefe_p xtreg xtreg_be xtreg_fe xtreg_ml xtreg_pa_p xtreg_re xtregar xtrere_p xtset xtsf_ll xtsf_llti xtsum xttab xttest0 xttobit xttobit_8 xttobit_p xttrans yx yxview__barlike_draw yxview_area_draw yxview_bar_draw yxview_dot_draw yxview_dropline_draw yxview_function_draw yxview_iarrow_draw yxview_ilabels_draw yxview_normal_draw yxview_pcarrow_draw yxview_pcbarrow_draw yxview_pccapsym_draw yxview_pcscatter_draw yxview_pcspike_draw yxview_rarea_draw yxview_rbar_draw yxview_rbarm_draw yxview_rcap_draw yxview_rcapsym_draw yxview_rconnected_draw yxview_rline_draw yxview_rscatter_draw yxview_rspike_draw yxview_spike_draw yxview_sunflower_draw zap_s zinb zinb_llf zinb_plf zip zip_llf zip_p zip_plf zt_ct_5 zt_hc_5 zt_hcd_5 zt_is_5 zt_iss_5 zt_sho_5 zt_smp_5 ztbase_5 ztcox_5 ztdes_5 ztereg_5 ztfill_5 ztgen_5 ztir_5 ztjoin_5 ztnb ztnb_p ztp ztp_p zts_5 ztset_5 ztspli_5 ztsum_5 zttoct_5 ztvary_5 ztweib_5",c:[{cN:"symbol",b:/`[a-zA-Z0-9_]+'/},{cN:"variable",b:/\$\{?[a-zA-Z0-9_]+\}?/},{cN:"string",v:[{b:'`"[^\r\n]*?"\''},{b:'"[^\r\n"]*"'}]},{cN:"built_in",v:[{b:"\\b(abs|acos|asin|atan|atan2|atanh|ceil|cloglog|comb|cos|digamma|exp|floor|invcloglog|invlogit|ln|lnfact|lnfactorial|lngamma|log|log10|max|min|mod|reldif|round|sign|sin|sqrt|sum|tan|tanh|trigamma|trunc|betaden|Binomial|binorm|binormal|chi2|chi2tail|dgammapda|dgammapdada|dgammapdadx|dgammapdx|dgammapdxdx|F|Fden|Ftail|gammaden|gammap|ibeta|invbinomial|invchi2|invchi2tail|invF|invFtail|invgammap|invibeta|invnchi2|invnFtail|invnibeta|invnorm|invnormal|invttail|nbetaden|nchi2|nFden|nFtail|nibeta|norm|normal|normalden|normd|npnchi2|tden|ttail|uniform|abbrev|char|index|indexnot|length|lower|ltrim|match|plural|proper|real|regexm|regexr|regexs|reverse|rtrim|string|strlen|strlower|strltrim|strmatch|strofreal|strpos|strproper|strreverse|strrtrim|strtrim|strupper|subinstr|subinword|substr|trim|upper|word|wordcount|_caller|autocode|byteorder|chop|clip|cond|e|epsdouble|epsfloat|group|inlist|inrange|irecode|matrix|maxbyte|maxdouble|maxfloat|maxint|maxlong|mi|minbyte|mindouble|minfloat|minint|minlong|missing|r|recode|replay|return|s|scalar|d|date|day|dow|doy|halfyear|mdy|month|quarter|week|year|d|daily|dofd|dofh|dofm|dofq|dofw|dofy|h|halfyearly|hofd|m|mofd|monthly|q|qofd|quarterly|tin|twithin|w|weekly|wofd|y|yearly|yh|ym|yofd|yq|yw|cholesky|colnumb|colsof|corr|det|diag|diag0cnt|el|get|hadamard|I|inv|invsym|issym|issymmetric|J|matmissing|matuniform|mreldif|nullmat|rownumb|rowsof|sweep|syminv|trace|vec|vecdiag)(?=\\(|$)"}]},e.C("^[ ]*\\*.*$",!1),e.CLCM,e.CBCM]}});hljs.registerLanguage("qml",function(r){var e={keyword:"in of on if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await import",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Behavior bool color coordinate date double enumeration font geocircle georectangle geoshape int list matrix4x4 parent point quaternion real rect size string url var variant vector2d vector3d vector4dPromise"},t="[a-zA-Z_][a-zA-Z0-9\\._]*",a={cN:"keyword",b:"\\bproperty\\b",starts:{cN:"string",e:"(:|=|;|,|//|/\\*|$)",rE:!0}},n={cN:"keyword",b:"\\bsignal\\b",starts:{cN:"string",e:"(\\(|:|=|;|,|//|/\\*|$)",rE:!0}},o={cN:"attribute",b:"\\bid\\s*:",starts:{cN:"string",e:t,rE:!1}},i={b:t+"\\s*:",rB:!0,c:[{cN:"attribute",b:t,e:"\\s*:",eE:!0,r:0}],r:0},c={b:t+"\\s*{",e:"{",rB:!0,r:0,c:[r.inherit(r.TM,{b:t})]};return{aliases:["qt"],cI:!1,k:e,c:[{cN:"meta",b:/^\s*['"]use (strict|asm)['"]/},r.ASM,r.QSM,{cN:"string",b:"`",e:"`",c:[r.BE,{cN:"subst",b:"\\$\\{",e:"\\}"}]},r.CLCM,r.CBCM,{cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:r.CNR}],r:0},{b:"("+r.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[r.CLCM,r.CBCM,r.RM,{b:/\s*[);\]]/,r:0,sL:"xml"}],r:0},n,a,{cN:"function",bK:"function",e:/\{/,eE:!0,c:[r.inherit(r.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:[r.CLCM,r.CBCM]}],i:/\[|%/},{b:"\\."+r.IR,r:0},o,i,c],i:/#/}});hljs.registerLanguage("irpf90",function(e){var t={cN:"params",b:"\\(",e:"\\)"},n={literal:".False. .True.",keyword:"kind do while private call intrinsic where elsewhere type endtype endmodule endselect endinterface end enddo endif if forall endforall only contains default return stop then public subroutine|10 function program .and. .or. .not. .le. .eq. .ge. .gt. .lt. goto save else use module select case access blank direct exist file fmt form formatted iostat name named nextrec number opened rec recl sequential status unformatted unit continue format pause cycle exit c_null_char c_alert c_backspace c_form_feed flush wait decimal round iomsg synchronous nopass non_overridable pass protected volatile abstract extends import non_intrinsic value deferred generic final enumerator class associate bind enum c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr c_new_line c_carriage_return c_horizontal_tab c_vertical_tab iso_c_binding c_loc c_funloc c_associated c_f_pointer c_ptr c_funptr iso_fortran_env character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor numeric_storage_size output_unit c_f_procpointer ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode newunit contiguous recursive pad position action delim readwrite eor advance nml interface procedure namelist include sequence elemental pure integer real character complex logical dimension allocatable|10 parameter external implicit|10 none double precision assign intent optional pointer target in out common equivalence data begin_provider &begin_provider end_provider begin_shell end_shell begin_template end_template subst assert touch soft_touch provide no_dep free irp_if irp_else irp_endif irp_write irp_read",built_in:"alog alog10 amax0 amax1 amin0 amin1 amod cabs ccos cexp clog csin csqrt dabs dacos dasin datan datan2 dcos dcosh ddim dexp dint dlog dlog10 dmax1 dmin1 dmod dnint dsign dsin dsinh dsqrt dtan dtanh float iabs idim idint idnint ifix isign max0 max1 min0 min1 sngl algama cdabs cdcos cdexp cdlog cdsin cdsqrt cqabs cqcos cqexp cqlog cqsin cqsqrt dcmplx dconjg derf derfc dfloat dgamma dimag dlgama iqint qabs qacos qasin qatan qatan2 qcmplx qconjg qcos qcosh qdim qerf qerfc qexp qgamma qimag qlgama qlog qlog10 qmax1 qmin1 qmod qnint qsign qsin qsinh qsqrt qtan qtanh abs acos aimag aint anint asin atan atan2 char cmplx conjg cos cosh exp ichar index int log log10 max min nint sign sin sinh sqrt tan tanh print write dim lge lgt lle llt mod nullify allocate deallocate adjustl adjustr all allocated any associated bit_size btest ceiling count cshift date_and_time digits dot_product eoshift epsilon exponent floor fraction huge iand ibclr ibits ibset ieor ior ishft ishftc lbound len_trim matmul maxexponent maxloc maxval merge minexponent minloc minval modulo mvbits nearest pack present product radix random_number random_seed range repeat reshape rrspacing scale scan selected_int_kind selected_real_kind set_exponent shape size spacing spread sum system_clock tiny transpose trim ubound unpack verify achar iachar transfer dble entry dprod cpu_time command_argument_count get_command get_command_argument get_environment_variable is_iostat_end ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode is_iostat_eor move_alloc new_line selected_char_kind same_type_as extends_type_ofacosh asinh atanh bessel_j0 bessel_j1 bessel_jn bessel_y0 bessel_y1 bessel_yn erf erfc erfc_scaled gamma log_gamma hypot norm2 atomic_define atomic_ref execute_command_line leadz trailz storage_size merge_bits bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr num_images parity popcnt poppar shifta shiftl shiftr this_image IRP_ALIGN irp_here"};return{cI:!0,k:n,i:/\/\*/,c:[e.inherit(e.ASM,{cN:"string",r:0}),e.inherit(e.QSM,{cN:"string",r:0}),{cN:"function",bK:"subroutine function program",i:"[${=\\n]",c:[e.UTM,t]},e.C("!","$",{r:0}),e.C("begin_doc","end_doc",{r:10}),{cN:"number",b:"(?=\\b|\\+|\\-|\\.)(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*)(?:[de][+-]?\\d+)?\\b\\.?",r:0}]}});hljs.registerLanguage("ruleslanguage",function(T){return{k:{keyword:"BILL_PERIOD BILL_START BILL_STOP RS_EFFECTIVE_START RS_EFFECTIVE_STOP RS_JURIS_CODE RS_OPCO_CODE INTDADDATTRIBUTE|5 INTDADDVMSG|5 INTDBLOCKOP|5 INTDBLOCKOPNA|5 INTDCLOSE|5 INTDCOUNT|5 INTDCOUNTSTATUSCODE|5 INTDCREATEMASK|5 INTDCREATEDAYMASK|5 INTDCREATEFACTORMASK|5 INTDCREATEHANDLE|5 INTDCREATEOVERRIDEDAYMASK|5 INTDCREATEOVERRIDEMASK|5 INTDCREATESTATUSCODEMASK|5 INTDCREATETOUPERIOD|5 INTDDELETE|5 INTDDIPTEST|5 INTDEXPORT|5 INTDGETERRORCODE|5 INTDGETERRORMESSAGE|5 INTDISEQUAL|5 INTDJOIN|5 INTDLOAD|5 INTDLOADACTUALCUT|5 INTDLOADDATES|5 INTDLOADHIST|5 INTDLOADLIST|5 INTDLOADLISTDATES|5 INTDLOADLISTENERGY|5 INTDLOADLISTHIST|5 INTDLOADRELATEDCHANNEL|5 INTDLOADSP|5 INTDLOADSTAGING|5 INTDLOADUOM|5 INTDLOADUOMDATES|5 INTDLOADUOMHIST|5 INTDLOADVERSION|5 INTDOPEN|5 INTDREADFIRST|5 INTDREADNEXT|5 INTDRECCOUNT|5 INTDRELEASE|5 INTDREPLACE|5 INTDROLLAVG|5 INTDROLLPEAK|5 INTDSCALAROP|5 INTDSCALE|5 INTDSETATTRIBUTE|5 INTDSETDSTPARTICIPANT|5 INTDSETSTRING|5 INTDSETVALUE|5 INTDSETVALUESTATUS|5 INTDSHIFTSTARTTIME|5 INTDSMOOTH|5 INTDSORT|5 INTDSPIKETEST|5 INTDSUBSET|5 INTDTOU|5 INTDTOURELEASE|5 INTDTOUVALUE|5 INTDUPDATESTATS|5 INTDVALUE|5 STDEV INTDDELETEEX|5 INTDLOADEXACTUAL|5 INTDLOADEXCUT|5 INTDLOADEXDATES|5 INTDLOADEX|5 INTDLOADEXRELATEDCHANNEL|5 INTDSAVEEX|5 MVLOAD|5 MVLOADACCT|5 MVLOADACCTDATES|5 MVLOADACCTHIST|5 MVLOADDATES|5 MVLOADHIST|5 MVLOADLIST|5 MVLOADLISTDATES|5 MVLOADLISTHIST|5 IF FOR NEXT DONE SELECT END CALL ABORT CLEAR CHANNEL FACTOR LIST NUMBER OVERRIDE SET WEEK DISTRIBUTIONNODE ELSE WHEN THEN OTHERWISE IENUM CSV INCLUDE LEAVE RIDER SAVE DELETE NOVALUE SECTION WARN SAVE_UPDATE DETERMINANT LABEL REPORT REVENUE EACH IN FROM TOTAL CHARGE BLOCK AND OR CSV_FILE RATE_CODE AUXILIARY_DEMAND UIDACCOUNT RS BILL_PERIOD_SELECT HOURS_PER_MONTH INTD_ERROR_STOP SEASON_SCHEDULE_NAME ACCOUNTFACTOR ARRAYUPPERBOUND CALLSTOREDPROC GETADOCONNECTION GETCONNECT GETDATASOURCE GETQUALIFIER GETUSERID HASVALUE LISTCOUNT LISTOP LISTUPDATE LISTVALUE PRORATEFACTOR RSPRORATE SETBINPATH SETDBMONITOR WQ_OPEN BILLINGHOURS DATE DATEFROMFLOAT DATETIMEFROMSTRING DATETIMETOSTRING DATETOFLOAT DAY DAYDIFF DAYNAME DBDATETIME HOUR MINUTE MONTH MONTHDIFF MONTHHOURS MONTHNAME ROUNDDATE SAMEWEEKDAYLASTYEAR SECOND WEEKDAY WEEKDIFF YEAR YEARDAY YEARSTR COMPSUM HISTCOUNT HISTMAX HISTMIN HISTMINNZ HISTVALUE MAXNRANGE MAXRANGE MINRANGE COMPIKVA COMPKVA COMPKVARFROMKQKW COMPLF IDATTR FLAG LF2KW LF2KWH MAXKW POWERFACTOR READING2USAGE AVGSEASON MAXSEASON MONTHLYMERGE SEASONVALUE SUMSEASON ACCTREADDATES ACCTTABLELOAD CONFIGADD CONFIGGET CREATEOBJECT CREATEREPORT EMAILCLIENT EXPBLKMDMUSAGE EXPMDMUSAGE EXPORT_USAGE FACTORINEFFECT GETUSERSPECIFIEDSTOP INEFFECT ISHOLIDAY RUNRATE SAVE_PROFILE SETREPORTTITLE USEREXIT WATFORRUNRATE TO TABLE ACOS ASIN ATAN ATAN2 BITAND CEIL COS COSECANT COSH COTANGENT DIVQUOT DIVREM EXP FABS FLOOR FMOD FREPM FREXPN LOG LOG10 MAX MAXN MIN MINNZ MODF POW ROUND ROUND2VALUE ROUNDINT SECANT SIN SINH SQROOT TAN TANH FLOAT2STRING FLOAT2STRINGNC INSTR LEFT LEN LTRIM MID RIGHT RTRIM STRING STRINGNC TOLOWER TOUPPER TRIM NUMDAYS READ_DATE STAGING",built_in:"IDENTIFIER OPTIONS XML_ELEMENT XML_OP XML_ELEMENT_OF DOMDOCCREATE DOMDOCLOADFILE DOMDOCLOADXML DOMDOCSAVEFILE DOMDOCGETROOT DOMDOCADDPI DOMNODEGETNAME DOMNODEGETTYPE DOMNODEGETVALUE DOMNODEGETCHILDCT DOMNODEGETFIRSTCHILD DOMNODEGETSIBLING DOMNODECREATECHILDELEMENT DOMNODESETATTRIBUTE DOMNODEGETCHILDELEMENTCT DOMNODEGETFIRSTCHILDELEMENT DOMNODEGETSIBLINGELEMENT DOMNODEGETATTRIBUTECT DOMNODEGETATTRIBUTEI DOMNODEGETATTRIBUTEBYNAME DOMNODEGETBYNAME"},c:[T.CLCM,T.CBCM,T.ASM,T.QSM,T.CNM,{cN:"literal",v:[{b:"#\\s+[a-zA-Z\\ \\.]*",r:0},{b:"#[a-zA-Z\\ \\.]+"}]}]}});hljs.registerLanguage("inform7",function(e){var r="\\[",o="\\]";return{aliases:["i7"],cI:!0,k:{keyword:"thing room person man woman animal container supporter backdrop door scenery open closed locked inside gender is are say understand kind of rule"},c:[{cN:"string",b:'"',e:'"',r:0,c:[{cN:"subst",b:r,e:o}]},{cN:"section",b:/^(Volume|Book|Part|Chapter|Section|Table)\b/,e:"$"},{b:/^(Check|Carry out|Report|Instead of|To|Rule|When|Before|After)\b/,e:":",c:[{b:"\\(This",e:"\\)"}]},{cN:"comment",b:r,e:o,c:["self"]}]}});hljs.registerLanguage("elixir",function(e){var r="[a-zA-Z_][a-zA-Z0-9_]*(\\!|\\?)?",n="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",b="and false then defined module in return redo retry end for true self when next until do begin unless nil break not case cond alias while ensure or include use alias fn quote",c={cN:"subst",b:"#\\{",e:"}",l:r,k:b},a={cN:"string",c:[e.BE,c],v:[{b:/'/,e:/'/},{b:/"/,e:/"/}]},i={cN:"function",bK:"def defp defmacro",e:/\B\b/,c:[e.inherit(e.TM,{b:r,endsParent:!0})]},l=e.inherit(i,{cN:"class",bK:"defimpl defmodule defprotocol defrecord",e:/\bdo\b|$|;/}),s=[a,e.HCM,l,i,{cN:"symbol",b:":(?!\\s)",c:[a,{b:n}],r:0},{cN:"symbol",b:r+":",r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{b:"->"},{b:"("+e.RSR+")\\s*",c:[e.HCM,{cN:"regexp",i:"\\n",c:[e.BE,c],v:[{b:"/",e:"/[a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}],r:0}];return c.c=s,{l:r,k:b,c:s}});hljs.registerLanguage("ebnf",function(a){var e=a.C(/\(\*/,/\*\)/),t={cN:"attribute",b:/^[ ]*[a-zA-Z][a-zA-Z-]*([\s-]+[a-zA-Z][a-zA-Z]*)*/},r={cN:"meta",b:/\?.*\?/},b={b:/=/,e:/;/,c:[e,r,a.ASM,a.QSM]};return{i:/\S/,c:[e,t,b]}});hljs.registerLanguage("objectivec",function(e){var t={cN:"built_in",b:"\\b(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)\\w+"},_={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},i=/[a-zA-Z@][a-zA-Z0-9_]*/,n="@interface @class @protocol @implementation";return{aliases:["mm","objc","obj-c"],k:_,l:i,i:""}]}]},{cN:"class",b:"("+n.split(" ").join("|")+")\\b",e:"({|$)",eE:!0,k:n,l:i,c:[e.UTM]},{b:"\\."+e.UIR,r:0}]}});hljs.registerLanguage("thrift",function(e){var t="bool byte i16 i32 i64 double string binary";return{k:{keyword:"namespace const typedef struct enum service exception void oneway set list map required optional",built_in:t,literal:"true false"},c:[e.QSM,e.NM,e.CLCM,e.CBCM,{cN:"class",bK:"struct enum service exception",e:/\{/,i:/\n/,c:[e.inherit(e.TM,{starts:{eW:!0,eE:!0}})]},{b:"\\b(set|list|map)\\s*<",e:">",k:t,c:["self"]}]}});hljs.registerLanguage("haskell",function(e){var i={v:[e.C("--","$"),e.C("{-","-}",{c:["self"]})]},a={cN:"meta",b:"{-#",e:"#-}"},l={cN:"meta",b:"^#",e:"$"},c={cN:"type",b:"\\b[A-Z][\\w']*",r:0},n={b:"\\(",e:"\\)",i:'"',c:[a,l,{cN:"type",b:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},e.inherit(e.TM,{b:"[_a-z][\\w']*"}),i]},s={b:"{",e:"}",c:n.c};return{aliases:["hs"],k:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",c:[{bK:"module",e:"where",k:"module where",c:[n,i],i:"\\W\\.|;"},{b:"\\bimport\\b",e:"$",k:"import qualified as hiding",c:[n,i],i:"\\W\\.|;"},{cN:"class",b:"^(\\s*)?(class|instance)\\b",e:"where",k:"class family instance where",c:[c,n,i]},{cN:"class",b:"\\b(data|(new)?type)\\b",e:"$",k:"data family type newtype deriving",c:[a,c,n,s,i]},{bK:"default",e:"$",c:[c,n,i]},{bK:"infix infixl infixr",e:"$",c:[e.CNM,i]},{b:"\\bforeign\\b",e:"$",k:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",c:[c,e.QSM,i]},{cN:"meta",b:"#!\\/usr\\/bin\\/env runhaskell",e:"$"},a,l,e.QSM,e.CNM,c,e.inherit(e.TM,{b:"^[_a-z][\\w']*"}),i,{b:"->|<-"}]}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("basic",function(E){return{cI:!0,i:"^.",l:"[a-zA-Z][a-zA-Z0-9_$%!#]*",k:{keyword:"ABS ASC AND ATN AUTO|0 BEEP BLOAD|10 BSAVE|10 CALL CALLS CDBL CHAIN CHDIR CHR$|10 CINT CIRCLE CLEAR CLOSE CLS COLOR COM COMMON CONT COS CSNG CSRLIN CVD CVI CVS DATA DATE$ DEFDBL DEFINT DEFSNG DEFSTR DEF|0 SEG USR DELETE DIM DRAW EDIT END ENVIRON ENVIRON$ EOF EQV ERASE ERDEV ERDEV$ ERL ERR ERROR EXP FIELD FILES FIX FOR|0 FRE GET GOSUB|10 GOTO HEX$ IF|0 THEN ELSE|0 INKEY$ INP INPUT INPUT# INPUT$ INSTR IMP INT IOCTL IOCTL$ KEY ON OFF LIST KILL LEFT$ LEN LET LINE LLIST LOAD LOC LOCATE LOF LOG LPRINT USING LSET MERGE MID$ MKDIR MKD$ MKI$ MKS$ MOD NAME NEW NEXT NOISE NOT OCT$ ON OR PEN PLAY STRIG OPEN OPTION BASE OUT PAINT PALETTE PCOPY PEEK PMAP POINT POKE POS PRINT PRINT] PSET PRESET PUT RANDOMIZE READ REM RENUM RESET|0 RESTORE RESUME RETURN|0 RIGHT$ RMDIR RND RSET RUN SAVE SCREEN SGN SHELL SIN SOUND SPACE$ SPC SQR STEP STICK STOP STR$ STRING$ SWAP SYSTEM TAB TAN TIME$ TIMER TROFF TRON TO USR VAL VARPTR VARPTR$ VIEW WAIT WHILE WEND WIDTH WINDOW WRITE XOR"},c:[E.QSM,E.C("REM","$",{r:10}),E.C("'","$",{r:0}),{cN:"symbol",b:"^[0-9]+ ",r:10},{cN:"number",b:"\\b([0-9]+[0-9edED.]*[#!]?)",r:0},{cN:"number",b:"(&[hH][0-9a-fA-F]{1,4})"},{cN:"number",b:"(&[oO][0-7]{1,6})"}]}});hljs.registerLanguage("makefile",function(e){var a={cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]};return{aliases:["mk","mak"],c:[e.HCM,{b:/^\w+\s*\W*=/,rB:!0,r:0,starts:{e:/\s*\W*=/,eE:!0,starts:{e:/$/,r:0,c:[a]}}},{cN:"section",b:/^[\w]+:\s*$/},{cN:"meta",b:/^\.PHONY:/,e:/$/,k:{"meta-keyword":".PHONY"},l:/[\.\w]+/},{b:/^\t+/,e:/$/,r:0,c:[e.QSM,a]}]}});hljs.registerLanguage("glsl",function(e){return{k:{keyword:"break continue discard do else for if return while switch case default attribute binding buffer ccw centroid centroid varying coherent column_major const cw depth_any depth_greater depth_less depth_unchanged early_fragment_tests equal_spacing flat fractional_even_spacing fractional_odd_spacing highp in index inout invariant invocations isolines layout line_strip lines lines_adjacency local_size_x local_size_y local_size_z location lowp max_vertices mediump noperspective offset origin_upper_left out packed patch pixel_center_integer point_mode points precise precision quads r11f_g11f_b10f r16 r16_snorm r16f r16i r16ui r32f r32i r32ui r8 r8_snorm r8i r8ui readonly restrict rg16 rg16_snorm rg16f rg16i rg16ui rg32f rg32i rg32ui rg8 rg8_snorm rg8i rg8ui rgb10_a2 rgb10_a2ui rgba16 rgba16_snorm rgba16f rgba16i rgba16ui rgba32f rgba32i rgba32ui rgba8 rgba8_snorm rgba8i rgba8ui row_major sample shared smooth std140 std430 stream triangle_strip triangles triangles_adjacency uniform varying vertices volatile writeonly",type:"atomic_uint bool bvec2 bvec3 bvec4 dmat2 dmat2x2 dmat2x3 dmat2x4 dmat3 dmat3x2 dmat3x3 dmat3x4 dmat4 dmat4x2 dmat4x3 dmat4x4 double dvec2 dvec3 dvec4 float iimage1D iimage1DArray iimage2D iimage2DArray iimage2DMS iimage2DMSArray iimage2DRect iimage3D iimageBufferiimageCube iimageCubeArray image1D image1DArray image2D image2DArray image2DMS image2DMSArray image2DRect image3D imageBuffer imageCube imageCubeArray int isampler1D isampler1DArray isampler2D isampler2DArray isampler2DMS isampler2DMSArray isampler2DRect isampler3D isamplerBuffer isamplerCube isamplerCubeArray ivec2 ivec3 ivec4 mat2 mat2x2 mat2x3 mat2x4 mat3 mat3x2 mat3x3 mat3x4 mat4 mat4x2 mat4x3 mat4x4 sampler1D sampler1DArray sampler1DArrayShadow sampler1DShadow sampler2D sampler2DArray sampler2DArrayShadow sampler2DMS sampler2DMSArray sampler2DRect sampler2DRectShadow sampler2DShadow sampler3D samplerBuffer samplerCube samplerCubeArray samplerCubeArrayShadow samplerCubeShadow image1D uimage1DArray uimage2D uimage2DArray uimage2DMS uimage2DMSArray uimage2DRect uimage3D uimageBuffer uimageCube uimageCubeArray uint usampler1D usampler1DArray usampler2D usampler2DArray usampler2DMS usampler2DMSArray usampler2DRect usampler3D samplerBuffer usamplerCube usamplerCubeArray uvec2 uvec3 uvec4 vec2 vec3 vec4 void",built_in:"gl_MaxAtomicCounterBindings gl_MaxAtomicCounterBufferSize gl_MaxClipDistances gl_MaxClipPlanes gl_MaxCombinedAtomicCounterBuffers gl_MaxCombinedAtomicCounters gl_MaxCombinedImageUniforms gl_MaxCombinedImageUnitsAndFragmentOutputs gl_MaxCombinedTextureImageUnits gl_MaxComputeAtomicCounterBuffers gl_MaxComputeAtomicCounters gl_MaxComputeImageUniforms gl_MaxComputeTextureImageUnits gl_MaxComputeUniformComponents gl_MaxComputeWorkGroupCount gl_MaxComputeWorkGroupSize gl_MaxDrawBuffers gl_MaxFragmentAtomicCounterBuffers gl_MaxFragmentAtomicCounters gl_MaxFragmentImageUniforms gl_MaxFragmentInputComponents gl_MaxFragmentInputVectors gl_MaxFragmentUniformComponents gl_MaxFragmentUniformVectors gl_MaxGeometryAtomicCounterBuffers gl_MaxGeometryAtomicCounters gl_MaxGeometryImageUniforms gl_MaxGeometryInputComponents gl_MaxGeometryOutputComponents gl_MaxGeometryOutputVertices gl_MaxGeometryTextureImageUnits gl_MaxGeometryTotalOutputComponents gl_MaxGeometryUniformComponents gl_MaxGeometryVaryingComponents gl_MaxImageSamples gl_MaxImageUnits gl_MaxLights gl_MaxPatchVertices gl_MaxProgramTexelOffset gl_MaxTessControlAtomicCounterBuffers gl_MaxTessControlAtomicCounters gl_MaxTessControlImageUniforms gl_MaxTessControlInputComponents gl_MaxTessControlOutputComponents gl_MaxTessControlTextureImageUnits gl_MaxTessControlTotalOutputComponents gl_MaxTessControlUniformComponents gl_MaxTessEvaluationAtomicCounterBuffers gl_MaxTessEvaluationAtomicCounters gl_MaxTessEvaluationImageUniforms gl_MaxTessEvaluationInputComponents gl_MaxTessEvaluationOutputComponents gl_MaxTessEvaluationTextureImageUnits gl_MaxTessEvaluationUniformComponents gl_MaxTessGenLevel gl_MaxTessPatchComponents gl_MaxTextureCoords gl_MaxTextureImageUnits gl_MaxTextureUnits gl_MaxVaryingComponents gl_MaxVaryingFloats gl_MaxVaryingVectors gl_MaxVertexAtomicCounterBuffers gl_MaxVertexAtomicCounters gl_MaxVertexAttribs gl_MaxVertexImageUniforms gl_MaxVertexOutputComponents gl_MaxVertexOutputVectors gl_MaxVertexTextureImageUnits gl_MaxVertexUniformComponents gl_MaxVertexUniformVectors gl_MaxViewports gl_MinProgramTexelOffset gl_BackColor gl_BackLightModelProduct gl_BackLightProduct gl_BackMaterial gl_BackSecondaryColor gl_ClipDistance gl_ClipPlane gl_ClipVertex gl_Color gl_DepthRange gl_EyePlaneQ gl_EyePlaneR gl_EyePlaneS gl_EyePlaneT gl_Fog gl_FogCoord gl_FogFragCoord gl_FragColor gl_FragCoord gl_FragData gl_FragDepth gl_FrontColor gl_FrontFacing gl_FrontLightModelProduct gl_FrontLightProduct gl_FrontMaterial gl_FrontSecondaryColor gl_GlobalInvocationID gl_InstanceID gl_InvocationID gl_Layer gl_LightModel gl_LightSource gl_LocalInvocationID gl_LocalInvocationIndex gl_ModelViewMatrix gl_ModelViewMatrixInverse gl_ModelViewMatrixInverseTranspose gl_ModelViewMatrixTranspose gl_ModelViewProjectionMatrix gl_ModelViewProjectionMatrixInverse gl_ModelViewProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixTranspose gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_Normal gl_NormalMatrix gl_NormalScale gl_NumSamples gl_NumWorkGroups gl_ObjectPlaneQ gl_ObjectPlaneR gl_ObjectPlaneS gl_ObjectPlaneT gl_PatchVerticesIn gl_Point gl_PointCoord gl_PointSize gl_Position gl_PrimitiveID gl_PrimitiveIDIn gl_ProjectionMatrix gl_ProjectionMatrixInverse gl_ProjectionMatrixInverseTranspose gl_ProjectionMatrixTranspose gl_SampleID gl_SampleMask gl_SampleMaskIn gl_SamplePosition gl_SecondaryColor gl_TessCoord gl_TessLevelInner gl_TessLevelOuter gl_TexCoord gl_TextureEnvColor gl_TextureMatrix gl_TextureMatrixInverse gl_TextureMatrixInverseTranspose gl_TextureMatrixTranspose gl_Vertex gl_VertexID gl_ViewportIndex gl_WorkGroupID gl_WorkGroupSize gl_in gl_out EmitStreamVertex EmitVertex EndPrimitive EndStreamPrimitive abs acos acosh all any asin asinh atan atanh atomicAdd atomicAnd atomicCompSwap atomicCounter atomicCounterDecrement atomicCounterIncrement atomicExchange atomicMax atomicMin atomicOr atomicXor barrier bitCount bitfieldExtract bitfieldInsert bitfieldReverse ceil clamp cos cosh cross dFdx dFdy degrees determinant distance dot equal exp exp2 faceforward findLSB findMSB floatBitsToInt floatBitsToUint floor fma fract frexp ftransform fwidth greaterThan greaterThanEqual groupMemoryBarrier imageAtomicAdd imageAtomicAnd imageAtomicCompSwap imageAtomicExchange imageAtomicMax imageAtomicMin imageAtomicOr imageAtomicXor imageLoad imageSize imageStore imulExtended intBitsToFloat interpolateAtCentroid interpolateAtOffset interpolateAtSample inverse inversesqrt isinf isnan ldexp length lessThan lessThanEqual log log2 matrixCompMult max memoryBarrier memoryBarrierAtomicCounter memoryBarrierBuffer memoryBarrierImage memoryBarrierShared min mix mod modf noise1 noise2 noise3 noise4 normalize not notEqual outerProduct packDouble2x32 packHalf2x16 packSnorm2x16 packSnorm4x8 packUnorm2x16 packUnorm4x8 pow radians reflect refract round roundEven shadow1D shadow1DLod shadow1DProj shadow1DProjLod shadow2D shadow2DLod shadow2DProj shadow2DProjLod sign sin sinh smoothstep sqrt step tan tanh texelFetch texelFetchOffset texture texture1D texture1DLod texture1DProj texture1DProjLod texture2D texture2DLod texture2DProj texture2DProjLod texture3D texture3DLod texture3DProj texture3DProjLod textureCube textureCubeLod textureGather textureGatherOffset textureGatherOffsets textureGrad textureGradOffset textureLod textureLodOffset textureOffset textureProj textureProjGrad textureProjGradOffset textureProjLod textureProjLodOffset textureProjOffset textureQueryLevels textureQueryLod textureSize transpose trunc uaddCarry uintBitsToFloat umulExtended unpackDouble2x32 unpackHalf2x16 unpackSnorm2x16 unpackSnorm4x8 unpackUnorm2x16 unpackUnorm4x8 usubBorrow",literal:"true false"},i:'"',c:[e.CLCM,e.CBCM,e.CNM,{cN:"meta",b:"#",e:"$"}]}});hljs.registerLanguage("nginx",function(e){var r={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},b={eW:!0,l:"[a-z/_]+",k:{literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,r],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[r]},{cN:"regexp",c:[e.BE,r],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},r]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s+{",rB:!0,e:"{",c:[{cN:"section",b:e.UIR}],r:0},{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"attribute",b:e.UIR,starts:b}],r:0}],i:"[^\\s\\}]"}});hljs.registerLanguage("accesslog",function(T){return{c:[{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+\\b",r:0},{cN:"string",b:'"(GET|POST|HEAD|PUT|DELETE|CONNECT|OPTIONS|PATCH|TRACE)',e:'"',k:"GET POST HEAD PUT DELETE CONNECT OPTIONS PATCH TRACE",i:"\\n",r:10},{cN:"string",b:/\[/,e:/\]/,i:"\\n"},{cN:"string",b:'"',e:'"',i:"\\n"}]}});hljs.registerLanguage("moonscript",function(e){var t={keyword:"if then not for in while do return else elseif break continue switch and or unless when class extends super local import export from using",literal:"true false nil",built_in:"_G _VERSION assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall coroutine debug io math os package string table"},r="[A-Za-z$_][0-9A-Za-z$_]*",s={cN:"subst",b:/#\{/,e:/}/,k:t},a=[e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'/,e:/'/,c:[e.BE]},{b:/"/,e:/"/,c:[e.BE,s]}]},{cN:"built_in",b:"@__"+e.IR},{b:"@"+e.IR},{b:e.IR+"\\\\"+e.IR}];s.c=a;var c=e.inherit(e.TM,{b:r}),n="(\\(.*\\))?\\s*\\B[-=]>",i={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:t,c:["self"].concat(a)}]};return{aliases:["moon"],k:t,i:/\/\*/,c:a.concat([e.C("--","$"),{cN:"function",b:"^\\s*"+r+"\\s*=\\s*"+n,e:"[-=]>",rB:!0,c:[c,i]},{b:/[\(,:=]\s*/,r:0,c:[{cN:"function",b:n,e:"[-=]>",rB:!0,c:[i]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[c]},c]},{cN:"name",b:r+":",e:":",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage("cos",function(e){var t={cN:"string",v:[{b:'"',e:'"',c:[{b:'""',r:0}]}]},r={cN:"number",b:"\\b(\\d+(\\.\\d*)?|\\.\\d+)",r:0},s="property parameter class classmethod clientmethod extends as break catch close continue do d|0 else elseif for goto halt hang h|0 if job j|0 kill k|0 lock l|0 merge new open quit q|0 read r|0 return set s|0 tcommit throw trollback try tstart use view while write w|0 xecute x|0 zkill znspace zn ztrap zwrite zw zzdump zzwrite print zbreak zinsert zload zprint zremove zsave zzprint mv mvcall mvcrt mvdim mvprint zquit zsync ascii";return{cI:!0,aliases:["cos","cls"],k:s,c:[r,t,e.CLCM,e.CBCM,{cN:"comment",b:/;/,e:"$",r:0},{cN:"built_in",b:/(?:\$\$?|\.\.)\^?[a-zA-Z]+/},{cN:"built_in",b:/\$\$\$[a-zA-Z]+/},{cN:"built_in",b:/%[a-z]+(?:\.[a-z]+)*/},{cN:"symbol",b:/\^%?[a-zA-Z][\w]*/},{cN:"keyword",b:/##class|##super|#define|#dim/},{b:/&sql\(/,e:/\)/,eB:!0,eE:!0,sL:"sql"},{b:/&(js|jscript|javascript)/,eB:!0,eE:!0,sL:"javascript"},{b:/&html<\s*\s*>/,sL:"xml"}]}});hljs.registerLanguage("sml",function(e){return{aliases:["ml"],k:{keyword:"abstype and andalso as case datatype do else end eqtype exception fn fun functor handle if in include infix infixr let local nonfix of op open orelse raise rec sharing sig signature struct structure then type val with withtype where while",built_in:"array bool char exn int list option order real ref string substring vector unit word",literal:"true false NONE SOME LESS EQUAL GREATER nil"},i:/\/\/|>>/,l:"[a-z_]\\w*!?",c:[{cN:"literal",b:/\[(\|\|)?\]|\(\)/,r:0},e.C("\\(\\*","\\*\\)",{c:["self"]}),{cN:"symbol",b:"'[A-Za-z_](?!')[\\w']*"},{cN:"type",b:"`[A-Z][\\w']*"},{cN:"type",b:"\\b[A-Z][\\w']*",r:0},{b:"[a-z_]\\w*'[\\w']*"},e.inherit(e.ASM,{cN:"string",r:0}),e.inherit(e.QSM,{i:null}),{cN:"number",b:"\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)",r:0},{b:/[-=]>/}]}});hljs.registerLanguage("protobuf",function(e){return{k:{keyword:"package import option optional required repeated group",built_in:"double float int32 int64 uint32 uint64 sint32 sint64 fixed32 fixed64 sfixed32 sfixed64 bool string bytes",literal:"true false"},c:[e.QSM,e.NM,e.CLCM,{cN:"class",bK:"message enum service",e:/\{/,i:/\n/,c:[e.inherit(e.TM,{starts:{eW:!0,eE:!0}})]},{cN:"function",bK:"rpc",e:/;/,eE:!0,k:"rpc returns"},{b:/^\s*[A-Z_]+/,e:/\s*=/,eE:!0}]}});hljs.registerLanguage("php",function(e){var c={b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},i={cN:"meta",b:/<\?(php)?|\?>/},t={cN:"string",c:[e.BE,i],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},a={v:[e.BNM,e.CNM]};return{aliases:["php3","php4","php5","php6"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[e.HCM,e.C("//","$",{c:[i]}),e.C("/\\*","\\*/",{c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.C("__halt_compiler.+?;",!1,{eW:!0,k:"__halt_compiler",l:e.UIR}),{cN:"string",b:/<<<['"]?\w+['"]?$/,e:/^\w+;?$/,c:[e.BE,{cN:"subst",v:[{b:/\$\w+/},{b:/\{\$/,e:/\}/}]}]},i,{cN:"keyword",b:/\$this\b/},c,{b:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",c,e.CBCM,t,a]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},t,a]}});hljs.registerLanguage("gcode",function(N){var e="[A-Z_][A-Z0-9_.]*",c="\\%",E="IF DO WHILE ENDWHILE CALL ENDIF SUB ENDSUB GOTO REPEAT ENDREPEAT EQ LT GT NE GE LE OR XOR",i={cN:"meta",b:"([O])([0-9]+)"},n=[N.CLCM,N.CBCM,N.C(/\(/,/\)/),N.inherit(N.CNM,{b:"([-+]?([0-9]*\\.?[0-9]+\\.?))|"+N.CNR}),N.inherit(N.ASM,{i:null}),N.inherit(N.QSM,{i:null}),{cN:"name",b:"([G])([0-9]+\\.?[0-9]?)"},{cN:"name",b:"([M])([0-9]+\\.?[0-9]?)"},{cN:"attr",b:"(VC|VS|#)",e:"(\\d+)"},{cN:"attr",b:"(VZOFX|VZOFY|VZOFZ)"},{cN:"built_in",b:"(ATAN|ABS|ACOS|ASIN|SIN|COS|EXP|FIX|FUP|ROUND|LN|TAN)(\\[)",e:"([-+]?([0-9]*\\.?[0-9]+\\.?))(\\])"},{cN:"symbol",v:[{b:"N",e:"\\d+",i:"\\W"}]}];return{aliases:["nc"],cI:!0,l:e,k:E,c:[{cN:"meta",b:c},i].concat(n)}});hljs.registerLanguage("fortran",function(e){var t={cN:"params",b:"\\(",e:"\\)"},n={literal:".False. .True.",keyword:"kind do while private call intrinsic where elsewhere type endtype endmodule endselect endinterface end enddo endif if forall endforall only contains default return stop then public subroutine|10 function program .and. .or. .not. .le. .eq. .ge. .gt. .lt. goto save else use module select case access blank direct exist file fmt form formatted iostat name named nextrec number opened rec recl sequential status unformatted unit continue format pause cycle exit c_null_char c_alert c_backspace c_form_feed flush wait decimal round iomsg synchronous nopass non_overridable pass protected volatile abstract extends import non_intrinsic value deferred generic final enumerator class associate bind enum c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr c_new_line c_carriage_return c_horizontal_tab c_vertical_tab iso_c_binding c_loc c_funloc c_associated c_f_pointer c_ptr c_funptr iso_fortran_env character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor numeric_storage_size output_unit c_f_procpointer ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode newunit contiguous recursive pad position action delim readwrite eor advance nml interface procedure namelist include sequence elemental pure integer real character complex logical dimension allocatable|10 parameter external implicit|10 none double precision assign intent optional pointer target in out common equivalence data",built_in:"alog alog10 amax0 amax1 amin0 amin1 amod cabs ccos cexp clog csin csqrt dabs dacos dasin datan datan2 dcos dcosh ddim dexp dint dlog dlog10 dmax1 dmin1 dmod dnint dsign dsin dsinh dsqrt dtan dtanh float iabs idim idint idnint ifix isign max0 max1 min0 min1 sngl algama cdabs cdcos cdexp cdlog cdsin cdsqrt cqabs cqcos cqexp cqlog cqsin cqsqrt dcmplx dconjg derf derfc dfloat dgamma dimag dlgama iqint qabs qacos qasin qatan qatan2 qcmplx qconjg qcos qcosh qdim qerf qerfc qexp qgamma qimag qlgama qlog qlog10 qmax1 qmin1 qmod qnint qsign qsin qsinh qsqrt qtan qtanh abs acos aimag aint anint asin atan atan2 char cmplx conjg cos cosh exp ichar index int log log10 max min nint sign sin sinh sqrt tan tanh print write dim lge lgt lle llt mod nullify allocate deallocate adjustl adjustr all allocated any associated bit_size btest ceiling count cshift date_and_time digits dot_product eoshift epsilon exponent floor fraction huge iand ibclr ibits ibset ieor ior ishft ishftc lbound len_trim matmul maxexponent maxloc maxval merge minexponent minloc minval modulo mvbits nearest pack present product radix random_number random_seed range repeat reshape rrspacing scale scan selected_int_kind selected_real_kind set_exponent shape size spacing spread sum system_clock tiny transpose trim ubound unpack verify achar iachar transfer dble entry dprod cpu_time command_argument_count get_command get_command_argument get_environment_variable is_iostat_end ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode is_iostat_eor move_alloc new_line selected_char_kind same_type_as extends_type_ofacosh asinh atanh bessel_j0 bessel_j1 bessel_jn bessel_y0 bessel_y1 bessel_yn erf erfc erfc_scaled gamma log_gamma hypot norm2 atomic_define atomic_ref execute_command_line leadz trailz storage_size merge_bits bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr num_images parity popcnt poppar shifta shiftl shiftr this_image"};return{cI:!0,aliases:["f90","f95"],k:n,i:/\/\*/,c:[e.inherit(e.ASM,{cN:"string",r:0}),e.inherit(e.QSM,{cN:"string",r:0}),{cN:"function",bK:"subroutine function program",i:"[${=\\n]",c:[e.UTM,t]},e.C("!","$",{r:0}),{cN:"number",b:"(?=\\b|\\+|\\-|\\.)(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*)(?:[de][+-]?\\d+)?\\b\\.?",r:0}]}});hljs.registerLanguage("q",function(e){var s={keyword:"do while select delete by update from",literal:"0b 1b",built_in:"neg not null string reciprocal floor ceiling signum mod xbar xlog and or each scan over prior mmu lsq inv md5 ltime gtime count first var dev med cov cor all any rand sums prds mins maxs fills deltas ratios avgs differ prev next rank reverse iasc idesc asc desc msum mcount mavg mdev xrank mmin mmax xprev rotate distinct group where flip type key til get value attr cut set upsert raze union inter except cross sv vs sublist enlist read0 read1 hopen hclose hdel hsym hcount peach system ltrim rtrim trim lower upper ssr view tables views cols xcols keys xkey xcol xasc xdesc fkeys meta lj aj aj0 ij pj asof uj ww wj wj1 fby xgroup ungroup ej save load rsave rload show csv parse eval min max avg wavg wsum sin cos tan sum",type:"`float `double int `timestamp `timespan `datetime `time `boolean `symbol `char `byte `short `long `real `month `date `minute `second `guid"};return{aliases:["k","kdb"],k:s,l:/(`?)[A-Za-z0-9_]+\b/,c:[e.CLCM,e.QSM,e.CNM]}});hljs.registerLanguage("ada",function(e){var r="\\d(_|\\d)*",t="[eE][-+]?"+r,s=r+"(\\."+r+")?("+t+")?",n="\\w+",a=r+"#"+n+"(\\."+n+")?#("+t+")?",i="\\b("+a+"|"+s+")",c="[A-Za-z](_?[A-Za-z0-9.])*",o="[]{}%#'\"",b=e.C("--","$"),d={b:"\\s+:\\s+",e:"\\s*(:=|;|\\)|=>|$)",i:o,c:[{bK:"loop for declare others",endsParent:!0},{cN:"keyword",bK:"not null constant access function procedure in out aliased exception"},{cN:"type",b:c,endsParent:!0,r:0}]};return{cI:!0,k:{keyword:"abort else new return abs elsif not reverse abstract end accept entry select access exception of separate aliased exit or some all others subtype and for out synchronized array function overriding at tagged generic package task begin goto pragma terminate body private then if procedure type case in protected constant interface is raise use declare range delay limited record when delta loop rem while digits renames with do mod requeue xor",literal:"True False"},c:[b,{cN:"string",b:/"/,e:/"/,c:[{b:/""/,r:0}]},{cN:"string",b:/'.'/},{cN:"number",b:i,r:0},{cN:"symbol",b:"'"+c},{cN:"title",b:"(\\bwith\\s+)?(\\bprivate\\s+)?\\bpackage\\s+(\\bbody\\s+)?",e:"(is|$)",k:"package body",eB:!0,eE:!0,i:o},{b:"(\\b(with|overriding)\\s+)?\\b(function|procedure)\\s+",e:"(\\bis|\\bwith|\\brenames|\\)\\s*;)",k:"overriding function procedure with is renames return",rB:!0,c:[b,{cN:"title",b:"(\\bwith\\s+)?\\b(function|procedure)\\s+",e:"(\\(|\\s+|$)",eB:!0,eE:!0,i:o},d,{cN:"type",b:"\\breturn\\s+",e:"(\\s+|;|$)",k:"return",eB:!0,eE:!0,endsParent:!0,i:o}]},{cN:"type",b:"\\b(sub)?type\\s+",e:"\\s+",k:"type",eB:!0,i:o},d]}});hljs.registerLanguage("verilog",function(e){var n={keyword:"accept_on alias always always_comb always_ff always_latch and assert assign assume automatic before begin bind bins binsof bit break buf|0 bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable dist do edge else end endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup endinterface endmodule endpackage endprimitive endprogram endproperty endspecify endsequence endtable endtask enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin function generate|5 genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import incdir include initial inout input inside instance int integer interconnect interface intersect join join_any join_none large let liblist library local localparam logic longint macromodule matches medium modport module nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 or output package packed parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 s_always s_eventually s_nexttime s_until s_until_with scalared sequence shortint shortreal showcancelled signed small soft solve specify specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior trireg type typedef union unique unique0 unsigned until until_with untyped use uwire var vectored virtual void wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor",literal:"null",built_in:"$finish $stop $exit $fatal $error $warning $info $realtime $time $printtimescale $bitstoreal $bitstoshortreal $itor $signed $cast $bits $stime $timeformat $realtobits $shortrealtobits $rtoi $unsigned $asserton $assertkill $assertpasson $assertfailon $assertnonvacuouson $assertoff $assertcontrol $assertpassoff $assertfailoff $assertvacuousoff $isunbounded $sampled $fell $changed $past_gclk $fell_gclk $changed_gclk $rising_gclk $steady_gclk $coverage_control $coverage_get $coverage_save $set_coverage_db_name $rose $stable $past $rose_gclk $stable_gclk $future_gclk $falling_gclk $changing_gclk $display $coverage_get_max $coverage_merge $get_coverage $load_coverage_db $typename $unpacked_dimensions $left $low $increment $clog2 $ln $log10 $exp $sqrt $pow $floor $ceil $sin $cos $tan $countbits $onehot $isunknown $fatal $warning $dimensions $right $high $size $asin $acos $atan $atan2 $hypot $sinh $cosh $tanh $asinh $acosh $atanh $countones $onehot0 $error $info $random $dist_chi_square $dist_erlang $dist_exponential $dist_normal $dist_poisson $dist_t $dist_uniform $q_initialize $q_remove $q_exam $async$and$array $async$nand$array $async$or$array $async$nor$array $sync$and$array $sync$nand$array $sync$or$array $sync$nor$array $q_add $q_full $psprintf $async$and$plane $async$nand$plane $async$or$plane $async$nor$plane $sync$and$plane $sync$nand$plane $sync$or$plane $sync$nor$plane $system $display $displayb $displayh $displayo $strobe $strobeb $strobeh $strobeo $write $readmemb $readmemh $writememh $value$plusargs $dumpvars $dumpon $dumplimit $dumpports $dumpportson $dumpportslimit $writeb $writeh $writeo $monitor $monitorb $monitorh $monitoro $writememb $dumpfile $dumpoff $dumpall $dumpflush $dumpportsoff $dumpportsall $dumpportsflush $fclose $fdisplay $fdisplayb $fdisplayh $fdisplayo $fstrobe $fstrobeb $fstrobeh $fstrobeo $swrite $swriteb $swriteh $swriteo $fscanf $fread $fseek $fflush $feof $fopen $fwrite $fwriteb $fwriteh $fwriteo $fmonitor $fmonitorb $fmonitorh $fmonitoro $sformat $sformatf $fgetc $ungetc $fgets $sscanf $rewind $ftell $ferror"};return{aliases:["v","sv","svh"],cI:!1,k:n,l:/[\w\$]+/,c:[e.CBCM,e.CLCM,e.QSM,{cN:"number",c:[e.BE],v:[{b:"\\b((\\d+'(b|h|o|d|B|H|O|D))[0-9xzXZa-fA-F_]+)"},{b:"\\B(('(b|h|o|d|B|H|O|D))[0-9xzXZa-fA-F_]+)"},{b:"\\b([0-9_])+",r:0}]},{cN:"variable",v:[{b:"#\\((?!parameter).+\\)"},{b:"\\.\\w+",r:0}]},{cN:"meta",b:"`",e:"$",k:{"meta-keyword":"define __FILE__ __LINE__ begin_keywords celldefine default_nettype define else elsif end_keywords endcelldefine endif ifdef ifndef include line nounconnected_drive pragma resetall timescale unconnected_drive undef undefineall"},r:0}]}});hljs.registerLanguage("elm",function(e){var i={v:[e.C("--","$"),e.C("{-","-}",{c:["self"]})]},t={cN:"type",b:"\\b[A-Z][\\w']*",r:0},c={b:"\\(",e:"\\)",i:'"',c:[{cN:"type",b:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},i]},n={b:"{",e:"}",c:c.c};return{k:"let in if then else case of where module import exposing type alias as infix infixl infixr port effect command subscription",c:[{bK:"port effect module",e:"exposing",k:"port effect module where command subscription exposing",c:[c,i],i:"\\W\\.|;"},{b:"import",e:"$",k:"import as exposing",c:[c,i],i:"\\W\\.|;"},{b:"type",e:"$",k:"type alias",c:[t,c,n,i]},{bK:"infix infixl infixr",e:"$",c:[e.CNM,i]},{b:"port",e:"$",k:"port",c:[i]},e.QSM,e.CNM,t,e.inherit(e.TM,{b:"^[_a-z][\\w']*"}),i,{b:"->|<-"}]}});hljs.registerLanguage("xl",function(e){var t="ObjectLoader Animate MovieCredits Slides Filters Shading Materials LensFlare Mapping VLCAudioVideo StereoDecoder PointCloud NetworkAccess RemoteControl RegExp ChromaKey Snowfall NodeJS Speech Charts",o={keyword:"if then else do while until for loop import with is as where when by data constant integer real text name boolean symbol infix prefix postfix block tree",literal:"true false nil",built_in:"in mod rem and or xor not abs sign floor ceil sqrt sin cos tan asin acos atan exp expm1 log log2 log10 log1p pi at text_length text_range text_find text_replace contains page slide basic_slide title_slide title subtitle fade_in fade_out fade_at clear_color color line_color line_width texture_wrap texture_transform texture scale_?x scale_?y scale_?z? translate_?x translate_?y translate_?z? rotate_?x rotate_?y rotate_?z? rectangle circle ellipse sphere path line_to move_to quad_to curve_to theme background contents locally time mouse_?x mouse_?y mouse_buttons "+t},a={cN:"string",b:'"',e:'"',i:"\\n"},r={cN:"string",b:"'",e:"'",i:"\\n"},i={cN:"string",b:"<<",e:">>"},l={cN:"number",b:"[0-9]+#[0-9A-Z_]+(\\.[0-9-A-Z_]+)?#?([Ee][+-]?[0-9]+)?"},n={bK:"import",e:"$",k:o,c:[a]},s={cN:"function",b:/[a-z][^\n]*->/,rB:!0,e:/->/,c:[e.inherit(e.TM,{starts:{eW:!0,k:o}})]};return{aliases:["tao"],l:/[a-zA-Z][a-zA-Z0-9_?]*/,k:o,c:[e.CLCM,e.CBCM,a,r,i,s,n,l,e.NM]}});hljs.registerLanguage("nsis",function(e){var t={cN:"variable",b:/\$(ADMINTOOLS|APPDATA|CDBURN_AREA|CMDLINE|COMMONFILES32|COMMONFILES64|COMMONFILES|COOKIES|DESKTOP|DOCUMENTS|EXEDIR|EXEFILE|EXEPATH|FAVORITES|FONTS|HISTORY|HWNDPARENT|INSTDIR|INTERNET_CACHE|LANGUAGE|LOCALAPPDATA|MUSIC|NETHOOD|OUTDIR|PICTURES|PLUGINSDIR|PRINTHOOD|PROFILE|PROGRAMFILES32|PROGRAMFILES64|PROGRAMFILES|QUICKLAUNCH|RECENT|RESOURCES_LOCALIZED|RESOURCES|SENDTO|SMPROGRAMS|SMSTARTUP|STARTMENU|SYSDIR|TEMP|TEMPLATES|VIDEOS|WINDIR)/},i={cN:"variable",b:/\$+{[\w\.:-]+}/},n={cN:"variable",b:/\$+\w+/,i:/\(\){}/},r={cN:"variable",b:/\$+\([\w\^\.:-]+\)/},o={cN:"params",b:"(ARCHIVE|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_OFFLINE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY|HKCR|HKCU|HKDD|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_DYN_DATA|HKEY_LOCAL_MACHINE|HKEY_PERFORMANCE_DATA|HKEY_USERS|HKLM|HKPD|HKU|IDABORT|IDCANCEL|IDIGNORE|IDNO|IDOK|IDRETRY|IDYES|MB_ABORTRETRYIGNORE|MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3|MB_DEFBUTTON4|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_RIGHT|MB_RTLREADING|MB_SETFOREGROUND|MB_TOPMOST|MB_USERICON|MB_YESNO|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SYSTEM|TEMPORARY)"},l={cN:"keyword",b:/\!(addincludedir|addplugindir|appendfile|cd|define|delfile|echo|else|endif|error|execute|finalize|getdllversionsystem|ifdef|ifmacrodef|ifmacrondef|ifndef|if|include|insertmacro|macroend|macro|makensis|packhdr|searchparse|searchreplace|tempfile|undef|verbose|warning)/},s={cN:"subst",b:/\$(\\[nrt]|\$)/},a={cN:"class",b:/\w+\:\:\w+/},S={cN:"string",v:[{b:'"',e:'"'},{b:"'",e:"'"},{b:"`",e:"`"}],i:/\n/,c:[s,t,i,n,r]};return{cI:!1,k:{keyword:"Abort AddBrandingImage AddSize AllowRootDirInstall AllowSkipFiles AutoCloseWindow BGFont BGGradient BrandingText BringToFront Call CallInstDLL Caption ChangeUI CheckBitmap ClearErrors CompletedText ComponentText CopyFiles CRCCheck CreateDirectory CreateFont CreateShortCut Delete DeleteINISec DeleteINIStr DeleteRegKey DeleteRegValue DetailPrint DetailsButtonText DirText DirVar DirVerify EnableWindow EnumRegKey EnumRegValue Exch Exec ExecShell ExecWait ExpandEnvStrings File FileBufSize FileClose FileErrorText FileOpen FileRead FileReadByte FileReadUTF16LE FileReadWord FileSeek FileWrite FileWriteByte FileWriteUTF16LE FileWriteWord FindClose FindFirst FindNext FindWindow FlushINI FunctionEnd GetCurInstType GetCurrentAddress GetDlgItem GetDLLVersion GetDLLVersionLocal GetErrorLevel GetFileTime GetFileTimeLocal GetFullPathName GetFunctionAddress GetInstDirError GetLabelAddress GetTempFileName Goto HideWindow Icon IfAbort IfErrors IfFileExists IfRebootFlag IfSilent InitPluginsDir InstallButtonText InstallColors InstallDir InstallDirRegKey InstProgressFlags InstType InstTypeGetText InstTypeSetText IntCmp IntCmpU IntFmt IntOp IsWindow LangString LicenseBkColor LicenseData LicenseForceSelection LicenseLangString LicenseText LoadLanguageFile LockWindow LogSet LogText ManifestDPIAware ManifestSupportedOS MessageBox MiscButtonText Name Nop OutFile Page PageCallbacks PageExEnd Pop Push Quit ReadEnvStr ReadINIStr ReadRegDWORD ReadRegStr Reboot RegDLL Rename RequestExecutionLevel ReserveFile Return RMDir SearchPath SectionEnd SectionGetFlags SectionGetInstTypes SectionGetSize SectionGetText SectionGroupEnd SectionIn SectionSetFlags SectionSetInstTypes SectionSetSize SectionSetText SendMessage SetAutoClose SetBrandingImage SetCompress SetCompressor SetCompressorDictSize SetCtlColors SetCurInstType SetDatablockOptimize SetDateSave SetDetailsPrint SetDetailsView SetErrorLevel SetErrors SetFileAttributes SetFont SetOutPath SetOverwrite SetRebootFlag SetRegView SetShellVarContext SetSilent ShowInstDetails ShowUninstDetails ShowWindow SilentInstall SilentUnInstall Sleep SpaceTexts StrCmp StrCmpS StrCpy StrLen SubCaption Unicode UninstallButtonText UninstallCaption UninstallIcon UninstallSubCaption UninstallText UninstPage UnRegDLL Var VIAddVersionKey VIFileVersion VIProductVersion WindowIcon WriteINIStr WriteRegBin WriteRegDWORD WriteRegExpandStr WriteRegStr WriteUninstaller XPStyle",literal:"admin all auto both bottom bzip2 colored components current custom directory false force hide highest ifdiff ifnewer instfiles lastused leave left license listonly lzma nevershow none normal notset off on open print right show silent silentlog smooth textonly top true try un.components un.custom un.directory un.instfiles un.license uninstConfirm user Win10 Win7 Win8 WinVista zlib"},c:[e.HCM,e.CBCM,e.C(";","$",{r:0}),{cN:"function",bK:"Function PageEx Section SectionGroup",e:"$"},S,l,i,n,r,o,a,e.NM]}});hljs.registerLanguage("x86asm",function(s){return{cI:!0,l:"[.%]?"+s.IR,k:{keyword:"lock rep repe repz repne repnz xaquire xrelease bnd nobnd aaa aad aam aas adc add and arpl bb0_reset bb1_reset bound bsf bsr bswap bt btc btr bts call cbw cdq cdqe clc cld cli clts cmc cmp cmpsb cmpsd cmpsq cmpsw cmpxchg cmpxchg486 cmpxchg8b cmpxchg16b cpuid cpu_read cpu_write cqo cwd cwde daa das dec div dmint emms enter equ f2xm1 fabs fadd faddp fbld fbstp fchs fclex fcmovb fcmovbe fcmove fcmovnb fcmovnbe fcmovne fcmovnu fcmovu fcom fcomi fcomip fcomp fcompp fcos fdecstp fdisi fdiv fdivp fdivr fdivrp femms feni ffree ffreep fiadd ficom ficomp fidiv fidivr fild fimul fincstp finit fist fistp fisttp fisub fisubr fld fld1 fldcw fldenv fldl2e fldl2t fldlg2 fldln2 fldpi fldz fmul fmulp fnclex fndisi fneni fninit fnop fnsave fnstcw fnstenv fnstsw fpatan fprem fprem1 fptan frndint frstor fsave fscale fsetpm fsin fsincos fsqrt fst fstcw fstenv fstp fstsw fsub fsubp fsubr fsubrp ftst fucom fucomi fucomip fucomp fucompp fxam fxch fxtract fyl2x fyl2xp1 hlt ibts icebp idiv imul in inc incbin insb insd insw int int01 int1 int03 int3 into invd invpcid invlpg invlpga iret iretd iretq iretw jcxz jecxz jrcxz jmp jmpe lahf lar lds lea leave les lfence lfs lgdt lgs lidt lldt lmsw loadall loadall286 lodsb lodsd lodsq lodsw loop loope loopne loopnz loopz lsl lss ltr mfence monitor mov movd movq movsb movsd movsq movsw movsx movsxd movzx mul mwait neg nop not or out outsb outsd outsw packssdw packsswb packuswb paddb paddd paddsb paddsiw paddsw paddusb paddusw paddw pand pandn pause paveb pavgusb pcmpeqb pcmpeqd pcmpeqw pcmpgtb pcmpgtd pcmpgtw pdistib pf2id pfacc pfadd pfcmpeq pfcmpge pfcmpgt pfmax pfmin pfmul pfrcp pfrcpit1 pfrcpit2 pfrsqit1 pfrsqrt pfsub pfsubr pi2fd pmachriw pmaddwd pmagw pmulhriw pmulhrwa pmulhrwc pmulhw pmullw pmvgezb pmvlzb pmvnzb pmvzb pop popa popad popaw popf popfd popfq popfw por prefetch prefetchw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb psubd psubsb psubsiw psubsw psubusb psubusw psubw punpckhbw punpckhdq punpckhwd punpcklbw punpckldq punpcklwd push pusha pushad pushaw pushf pushfd pushfq pushfw pxor rcl rcr rdshr rdmsr rdpmc rdtsc rdtscp ret retf retn rol ror rdm rsdc rsldt rsm rsts sahf sal salc sar sbb scasb scasd scasq scasw sfence sgdt shl shld shr shrd sidt sldt skinit smi smint smintold smsw stc std sti stosb stosd stosq stosw str sub svdc svldt svts swapgs syscall sysenter sysexit sysret test ud0 ud1 ud2b ud2 ud2a umov verr verw fwait wbinvd wrshr wrmsr xadd xbts xchg xlatb xlat xor cmove cmovz cmovne cmovnz cmova cmovnbe cmovae cmovnb cmovb cmovnae cmovbe cmovna cmovg cmovnle cmovge cmovnl cmovl cmovnge cmovle cmovng cmovc cmovnc cmovo cmovno cmovs cmovns cmovp cmovpe cmovnp cmovpo je jz jne jnz ja jnbe jae jnb jb jnae jbe jna jg jnle jge jnl jl jnge jle jng jc jnc jo jno js jns jpo jnp jpe jp sete setz setne setnz seta setnbe setae setnb setnc setb setnae setcset setbe setna setg setnle setge setnl setl setnge setle setng sets setns seto setno setpe setp setpo setnp addps addss andnps andps cmpeqps cmpeqss cmpleps cmpless cmpltps cmpltss cmpneqps cmpneqss cmpnleps cmpnless cmpnltps cmpnltss cmpordps cmpordss cmpunordps cmpunordss cmpps cmpss comiss cvtpi2ps cvtps2pi cvtsi2ss cvtss2si cvttps2pi cvttss2si divps divss ldmxcsr maxps maxss minps minss movaps movhps movlhps movlps movhlps movmskps movntps movss movups mulps mulss orps rcpps rcpss rsqrtps rsqrtss shufps sqrtps sqrtss stmxcsr subps subss ucomiss unpckhps unpcklps xorps fxrstor fxrstor64 fxsave fxsave64 xgetbv xsetbv xsave xsave64 xsaveopt xsaveopt64 xrstor xrstor64 prefetchnta prefetcht0 prefetcht1 prefetcht2 maskmovq movntq pavgb pavgw pextrw pinsrw pmaxsw pmaxub pminsw pminub pmovmskb pmulhuw psadbw pshufw pf2iw pfnacc pfpnacc pi2fw pswapd maskmovdqu clflush movntdq movnti movntpd movdqa movdqu movdq2q movq2dq paddq pmuludq pshufd pshufhw pshuflw pslldq psrldq psubq punpckhqdq punpcklqdq addpd addsd andnpd andpd cmpeqpd cmpeqsd cmplepd cmplesd cmpltpd cmpltsd cmpneqpd cmpneqsd cmpnlepd cmpnlesd cmpnltpd cmpnltsd cmpordpd cmpordsd cmpunordpd cmpunordsd cmppd comisd cvtdq2pd cvtdq2ps cvtpd2dq cvtpd2pi cvtpd2ps cvtpi2pd cvtps2dq cvtps2pd cvtsd2si cvtsd2ss cvtsi2sd cvtss2sd cvttpd2pi cvttpd2dq cvttps2dq cvttsd2si divpd divsd maxpd maxsd minpd minsd movapd movhpd movlpd movmskpd movupd mulpd mulsd orpd shufpd sqrtpd sqrtsd subpd subsd ucomisd unpckhpd unpcklpd xorpd addsubpd addsubps haddpd haddps hsubpd hsubps lddqu movddup movshdup movsldup clgi stgi vmcall vmclear vmfunc vmlaunch vmload vmmcall vmptrld vmptrst vmread vmresume vmrun vmsave vmwrite vmxoff vmxon invept invvpid pabsb pabsw pabsd palignr phaddw phaddd phaddsw phsubw phsubd phsubsw pmaddubsw pmulhrsw pshufb psignb psignw psignd extrq insertq movntsd movntss lzcnt blendpd blendps blendvpd blendvps dppd dpps extractps insertps movntdqa mpsadbw packusdw pblendvb pblendw pcmpeqq pextrb pextrd pextrq phminposuw pinsrb pinsrd pinsrq pmaxsb pmaxsd pmaxud pmaxuw pminsb pminsd pminud pminuw pmovsxbw pmovsxbd pmovsxbq pmovsxwd pmovsxwq pmovsxdq pmovzxbw pmovzxbd pmovzxbq pmovzxwd pmovzxwq pmovzxdq pmuldq pmulld ptest roundpd roundps roundsd roundss crc32 pcmpestri pcmpestrm pcmpistri pcmpistrm pcmpgtq popcnt getsec pfrcpv pfrsqrtv movbe aesenc aesenclast aesdec aesdeclast aesimc aeskeygenassist vaesenc vaesenclast vaesdec vaesdeclast vaesimc vaeskeygenassist vaddpd vaddps vaddsd vaddss vaddsubpd vaddsubps vandpd vandps vandnpd vandnps vblendpd vblendps vblendvpd vblendvps vbroadcastss vbroadcastsd vbroadcastf128 vcmpeq_ospd vcmpeqpd vcmplt_ospd vcmpltpd vcmple_ospd vcmplepd vcmpunord_qpd vcmpunordpd vcmpneq_uqpd vcmpneqpd vcmpnlt_uspd vcmpnltpd vcmpnle_uspd vcmpnlepd vcmpord_qpd vcmpordpd vcmpeq_uqpd vcmpnge_uspd vcmpngepd vcmpngt_uspd vcmpngtpd vcmpfalse_oqpd vcmpfalsepd vcmpneq_oqpd vcmpge_ospd vcmpgepd vcmpgt_ospd vcmpgtpd vcmptrue_uqpd vcmptruepd vcmplt_oqpd vcmple_oqpd vcmpunord_spd vcmpneq_uspd vcmpnlt_uqpd vcmpnle_uqpd vcmpord_spd vcmpeq_uspd vcmpnge_uqpd vcmpngt_uqpd vcmpfalse_ospd vcmpneq_ospd vcmpge_oqpd vcmpgt_oqpd vcmptrue_uspd vcmppd vcmpeq_osps vcmpeqps vcmplt_osps vcmpltps vcmple_osps vcmpleps vcmpunord_qps vcmpunordps vcmpneq_uqps vcmpneqps vcmpnlt_usps vcmpnltps vcmpnle_usps vcmpnleps vcmpord_qps vcmpordps vcmpeq_uqps vcmpnge_usps vcmpngeps vcmpngt_usps vcmpngtps vcmpfalse_oqps vcmpfalseps vcmpneq_oqps vcmpge_osps vcmpgeps vcmpgt_osps vcmpgtps vcmptrue_uqps vcmptrueps vcmplt_oqps vcmple_oqps vcmpunord_sps vcmpneq_usps vcmpnlt_uqps vcmpnle_uqps vcmpord_sps vcmpeq_usps vcmpnge_uqps vcmpngt_uqps vcmpfalse_osps vcmpneq_osps vcmpge_oqps vcmpgt_oqps vcmptrue_usps vcmpps vcmpeq_ossd vcmpeqsd vcmplt_ossd vcmpltsd vcmple_ossd vcmplesd vcmpunord_qsd vcmpunordsd vcmpneq_uqsd vcmpneqsd vcmpnlt_ussd vcmpnltsd vcmpnle_ussd vcmpnlesd vcmpord_qsd vcmpordsd vcmpeq_uqsd vcmpnge_ussd vcmpngesd vcmpngt_ussd vcmpngtsd vcmpfalse_oqsd vcmpfalsesd vcmpneq_oqsd vcmpge_ossd vcmpgesd vcmpgt_ossd vcmpgtsd vcmptrue_uqsd vcmptruesd vcmplt_oqsd vcmple_oqsd vcmpunord_ssd vcmpneq_ussd vcmpnlt_uqsd vcmpnle_uqsd vcmpord_ssd vcmpeq_ussd vcmpnge_uqsd vcmpngt_uqsd vcmpfalse_ossd vcmpneq_ossd vcmpge_oqsd vcmpgt_oqsd vcmptrue_ussd vcmpsd vcmpeq_osss vcmpeqss vcmplt_osss vcmpltss vcmple_osss vcmpless vcmpunord_qss vcmpunordss vcmpneq_uqss vcmpneqss vcmpnlt_usss vcmpnltss vcmpnle_usss vcmpnless vcmpord_qss vcmpordss vcmpeq_uqss vcmpnge_usss vcmpngess vcmpngt_usss vcmpngtss vcmpfalse_oqss vcmpfalsess vcmpneq_oqss vcmpge_osss vcmpgess vcmpgt_osss vcmpgtss vcmptrue_uqss vcmptruess vcmplt_oqss vcmple_oqss vcmpunord_sss vcmpneq_usss vcmpnlt_uqss vcmpnle_uqss vcmpord_sss vcmpeq_usss vcmpnge_uqss vcmpngt_uqss vcmpfalse_osss vcmpneq_osss vcmpge_oqss vcmpgt_oqss vcmptrue_usss vcmpss vcomisd vcomiss vcvtdq2pd vcvtdq2ps vcvtpd2dq vcvtpd2ps vcvtps2dq vcvtps2pd vcvtsd2si vcvtsd2ss vcvtsi2sd vcvtsi2ss vcvtss2sd vcvtss2si vcvttpd2dq vcvttps2dq vcvttsd2si vcvttss2si vdivpd vdivps vdivsd vdivss vdppd vdpps vextractf128 vextractps vhaddpd vhaddps vhsubpd vhsubps vinsertf128 vinsertps vlddqu vldqqu vldmxcsr vmaskmovdqu vmaskmovps vmaskmovpd vmaxpd vmaxps vmaxsd vmaxss vminpd vminps vminsd vminss vmovapd vmovaps vmovd vmovq vmovddup vmovdqa vmovqqa vmovdqu vmovqqu vmovhlps vmovhpd vmovhps vmovlhps vmovlpd vmovlps vmovmskpd vmovmskps vmovntdq vmovntqq vmovntdqa vmovntpd vmovntps vmovsd vmovshdup vmovsldup vmovss vmovupd vmovups vmpsadbw vmulpd vmulps vmulsd vmulss vorpd vorps vpabsb vpabsw vpabsd vpacksswb vpackssdw vpackuswb vpackusdw vpaddb vpaddw vpaddd vpaddq vpaddsb vpaddsw vpaddusb vpaddusw vpalignr vpand vpandn vpavgb vpavgw vpblendvb vpblendw vpcmpestri vpcmpestrm vpcmpistri vpcmpistrm vpcmpeqb vpcmpeqw vpcmpeqd vpcmpeqq vpcmpgtb vpcmpgtw vpcmpgtd vpcmpgtq vpermilpd vpermilps vperm2f128 vpextrb vpextrw vpextrd vpextrq vphaddw vphaddd vphaddsw vphminposuw vphsubw vphsubd vphsubsw vpinsrb vpinsrw vpinsrd vpinsrq vpmaddwd vpmaddubsw vpmaxsb vpmaxsw vpmaxsd vpmaxub vpmaxuw vpmaxud vpminsb vpminsw vpminsd vpminub vpminuw vpminud vpmovmskb vpmovsxbw vpmovsxbd vpmovsxbq vpmovsxwd vpmovsxwq vpmovsxdq vpmovzxbw vpmovzxbd vpmovzxbq vpmovzxwd vpmovzxwq vpmovzxdq vpmulhuw vpmulhrsw vpmulhw vpmullw vpmulld vpmuludq vpmuldq vpor vpsadbw vpshufb vpshufd vpshufhw vpshuflw vpsignb vpsignw vpsignd vpslldq vpsrldq vpsllw vpslld vpsllq vpsraw vpsrad vpsrlw vpsrld vpsrlq vptest vpsubb vpsubw vpsubd vpsubq vpsubsb vpsubsw vpsubusb vpsubusw vpunpckhbw vpunpckhwd vpunpckhdq vpunpckhqdq vpunpcklbw vpunpcklwd vpunpckldq vpunpcklqdq vpxor vrcpps vrcpss vrsqrtps vrsqrtss vroundpd vroundps vroundsd vroundss vshufpd vshufps vsqrtpd vsqrtps vsqrtsd vsqrtss vstmxcsr vsubpd vsubps vsubsd vsubss vtestps vtestpd vucomisd vucomiss vunpckhpd vunpckhps vunpcklpd vunpcklps vxorpd vxorps vzeroall vzeroupper pclmullqlqdq pclmulhqlqdq pclmullqhqdq pclmulhqhqdq pclmulqdq vpclmullqlqdq vpclmulhqlqdq vpclmullqhqdq vpclmulhqhqdq vpclmulqdq vfmadd132ps vfmadd132pd vfmadd312ps vfmadd312pd vfmadd213ps vfmadd213pd vfmadd123ps vfmadd123pd vfmadd231ps vfmadd231pd vfmadd321ps vfmadd321pd vfmaddsub132ps vfmaddsub132pd vfmaddsub312ps vfmaddsub312pd vfmaddsub213ps vfmaddsub213pd vfmaddsub123ps vfmaddsub123pd vfmaddsub231ps vfmaddsub231pd vfmaddsub321ps vfmaddsub321pd vfmsub132ps vfmsub132pd vfmsub312ps vfmsub312pd vfmsub213ps vfmsub213pd vfmsub123ps vfmsub123pd vfmsub231ps vfmsub231pd vfmsub321ps vfmsub321pd vfmsubadd132ps vfmsubadd132pd vfmsubadd312ps vfmsubadd312pd vfmsubadd213ps vfmsubadd213pd vfmsubadd123ps vfmsubadd123pd vfmsubadd231ps vfmsubadd231pd vfmsubadd321ps vfmsubadd321pd vfnmadd132ps vfnmadd132pd vfnmadd312ps vfnmadd312pd vfnmadd213ps vfnmadd213pd vfnmadd123ps vfnmadd123pd vfnmadd231ps vfnmadd231pd vfnmadd321ps vfnmadd321pd vfnmsub132ps vfnmsub132pd vfnmsub312ps vfnmsub312pd vfnmsub213ps vfnmsub213pd vfnmsub123ps vfnmsub123pd vfnmsub231ps vfnmsub231pd vfnmsub321ps vfnmsub321pd vfmadd132ss vfmadd132sd vfmadd312ss vfmadd312sd vfmadd213ss vfmadd213sd vfmadd123ss vfmadd123sd vfmadd231ss vfmadd231sd vfmadd321ss vfmadd321sd vfmsub132ss vfmsub132sd vfmsub312ss vfmsub312sd vfmsub213ss vfmsub213sd vfmsub123ss vfmsub123sd vfmsub231ss vfmsub231sd vfmsub321ss vfmsub321sd vfnmadd132ss vfnmadd132sd vfnmadd312ss vfnmadd312sd vfnmadd213ss vfnmadd213sd vfnmadd123ss vfnmadd123sd vfnmadd231ss vfnmadd231sd vfnmadd321ss vfnmadd321sd vfnmsub132ss vfnmsub132sd vfnmsub312ss vfnmsub312sd vfnmsub213ss vfnmsub213sd vfnmsub123ss vfnmsub123sd vfnmsub231ss vfnmsub231sd vfnmsub321ss vfnmsub321sd rdfsbase rdgsbase rdrand wrfsbase wrgsbase vcvtph2ps vcvtps2ph adcx adox rdseed clac stac xstore xcryptecb xcryptcbc xcryptctr xcryptcfb xcryptofb montmul xsha1 xsha256 llwpcb slwpcb lwpval lwpins vfmaddpd vfmaddps vfmaddsd vfmaddss vfmaddsubpd vfmaddsubps vfmsubaddpd vfmsubaddps vfmsubpd vfmsubps vfmsubsd vfmsubss vfnmaddpd vfnmaddps vfnmaddsd vfnmaddss vfnmsubpd vfnmsubps vfnmsubsd vfnmsubss vfrczpd vfrczps vfrczsd vfrczss vpcmov vpcomb vpcomd vpcomq vpcomub vpcomud vpcomuq vpcomuw vpcomw vphaddbd vphaddbq vphaddbw vphadddq vphaddubd vphaddubq vphaddubw vphaddudq vphadduwd vphadduwq vphaddwd vphaddwq vphsubbw vphsubdq vphsubwd vpmacsdd vpmacsdqh vpmacsdql vpmacssdd vpmacssdqh vpmacssdql vpmacsswd vpmacssww vpmacswd vpmacsww vpmadcsswd vpmadcswd vpperm vprotb vprotd vprotq vprotw vpshab vpshad vpshaq vpshaw vpshlb vpshld vpshlq vpshlw vbroadcasti128 vpblendd vpbroadcastb vpbroadcastw vpbroadcastd vpbroadcastq vpermd vpermpd vpermps vpermq vperm2i128 vextracti128 vinserti128 vpmaskmovd vpmaskmovq vpsllvd vpsllvq vpsravd vpsrlvd vpsrlvq vgatherdpd vgatherqpd vgatherdps vgatherqps vpgatherdd vpgatherqd vpgatherdq vpgatherqq xabort xbegin xend xtest andn bextr blci blcic blsi blsic blcfill blsfill blcmsk blsmsk blsr blcs bzhi mulx pdep pext rorx sarx shlx shrx tzcnt tzmsk t1mskc valignd valignq vblendmpd vblendmps vbroadcastf32x4 vbroadcastf64x4 vbroadcasti32x4 vbroadcasti64x4 vcompresspd vcompressps vcvtpd2udq vcvtps2udq vcvtsd2usi vcvtss2usi vcvttpd2udq vcvttps2udq vcvttsd2usi vcvttss2usi vcvtudq2pd vcvtudq2ps vcvtusi2sd vcvtusi2ss vexpandpd vexpandps vextractf32x4 vextractf64x4 vextracti32x4 vextracti64x4 vfixupimmpd vfixupimmps vfixupimmsd vfixupimmss vgetexppd vgetexpps vgetexpsd vgetexpss vgetmantpd vgetmantps vgetmantsd vgetmantss vinsertf32x4 vinsertf64x4 vinserti32x4 vinserti64x4 vmovdqa32 vmovdqa64 vmovdqu32 vmovdqu64 vpabsq vpandd vpandnd vpandnq vpandq vpblendmd vpblendmq vpcmpltd vpcmpled vpcmpneqd vpcmpnltd vpcmpnled vpcmpd vpcmpltq vpcmpleq vpcmpneqq vpcmpnltq vpcmpnleq vpcmpq vpcmpequd vpcmpltud vpcmpleud vpcmpnequd vpcmpnltud vpcmpnleud vpcmpud vpcmpequq vpcmpltuq vpcmpleuq vpcmpnequq vpcmpnltuq vpcmpnleuq vpcmpuq vpcompressd vpcompressq vpermi2d vpermi2pd vpermi2ps vpermi2q vpermt2d vpermt2pd vpermt2ps vpermt2q vpexpandd vpexpandq vpmaxsq vpmaxuq vpminsq vpminuq vpmovdb vpmovdw vpmovqb vpmovqd vpmovqw vpmovsdb vpmovsdw vpmovsqb vpmovsqd vpmovsqw vpmovusdb vpmovusdw vpmovusqb vpmovusqd vpmovusqw vpord vporq vprold vprolq vprolvd vprolvq vprord vprorq vprorvd vprorvq vpscatterdd vpscatterdq vpscatterqd vpscatterqq vpsraq vpsravq vpternlogd vpternlogq vptestmd vptestmq vptestnmd vptestnmq vpxord vpxorq vrcp14pd vrcp14ps vrcp14sd vrcp14ss vrndscalepd vrndscaleps vrndscalesd vrndscaless vrsqrt14pd vrsqrt14ps vrsqrt14sd vrsqrt14ss vscalefpd vscalefps vscalefsd vscalefss vscatterdpd vscatterdps vscatterqpd vscatterqps vshuff32x4 vshuff64x2 vshufi32x4 vshufi64x2 kandnw kandw kmovw knotw kortestw korw kshiftlw kshiftrw kunpckbw kxnorw kxorw vpbroadcastmb2q vpbroadcastmw2d vpconflictd vpconflictq vplzcntd vplzcntq vexp2pd vexp2ps vrcp28pd vrcp28ps vrcp28sd vrcp28ss vrsqrt28pd vrsqrt28ps vrsqrt28sd vrsqrt28ss vgatherpf0dpd vgatherpf0dps vgatherpf0qpd vgatherpf0qps vgatherpf1dpd vgatherpf1dps vgatherpf1qpd vgatherpf1qps vscatterpf0dpd vscatterpf0dps vscatterpf0qpd vscatterpf0qps vscatterpf1dpd vscatterpf1dps vscatterpf1qpd vscatterpf1qps prefetchwt1 bndmk bndcl bndcu bndcn bndmov bndldx bndstx sha1rnds4 sha1nexte sha1msg1 sha1msg2 sha256rnds2 sha256msg1 sha256msg2 hint_nop0 hint_nop1 hint_nop2 hint_nop3 hint_nop4 hint_nop5 hint_nop6 hint_nop7 hint_nop8 hint_nop9 hint_nop10 hint_nop11 hint_nop12 hint_nop13 hint_nop14 hint_nop15 hint_nop16 hint_nop17 hint_nop18 hint_nop19 hint_nop20 hint_nop21 hint_nop22 hint_nop23 hint_nop24 hint_nop25 hint_nop26 hint_nop27 hint_nop28 hint_nop29 hint_nop30 hint_nop31 hint_nop32 hint_nop33 hint_nop34 hint_nop35 hint_nop36 hint_nop37 hint_nop38 hint_nop39 hint_nop40 hint_nop41 hint_nop42 hint_nop43 hint_nop44 hint_nop45 hint_nop46 hint_nop47 hint_nop48 hint_nop49 hint_nop50 hint_nop51 hint_nop52 hint_nop53 hint_nop54 hint_nop55 hint_nop56 hint_nop57 hint_nop58 hint_nop59 hint_nop60 hint_nop61 hint_nop62 hint_nop63",built_in:"ip eip rip al ah bl bh cl ch dl dh sil dil bpl spl r8b r9b r10b r11b r12b r13b r14b r15b ax bx cx dx si di bp sp r8w r9w r10w r11w r12w r13w r14w r15w eax ebx ecx edx esi edi ebp esp eip r8d r9d r10d r11d r12d r13d r14d r15d rax rbx rcx rdx rsi rdi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15 cs ds es fs gs ss st st0 st1 st2 st3 st4 st5 st6 st7 mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7 xmm8 xmm9 xmm10 xmm11 xmm12 xmm13 xmm14 xmm15 xmm16 xmm17 xmm18 xmm19 xmm20 xmm21 xmm22 xmm23 xmm24 xmm25 xmm26 xmm27 xmm28 xmm29 xmm30 xmm31 ymm0 ymm1 ymm2 ymm3 ymm4 ymm5 ymm6 ymm7 ymm8 ymm9 ymm10 ymm11 ymm12 ymm13 ymm14 ymm15 ymm16 ymm17 ymm18 ymm19 ymm20 ymm21 ymm22 ymm23 ymm24 ymm25 ymm26 ymm27 ymm28 ymm29 ymm30 ymm31 zmm0 zmm1 zmm2 zmm3 zmm4 zmm5 zmm6 zmm7 zmm8 zmm9 zmm10 zmm11 zmm12 zmm13 zmm14 zmm15 zmm16 zmm17 zmm18 zmm19 zmm20 zmm21 zmm22 zmm23 zmm24 zmm25 zmm26 zmm27 zmm28 zmm29 zmm30 zmm31 k0 k1 k2 k3 k4 k5 k6 k7 bnd0 bnd1 bnd2 bnd3 cr0 cr1 cr2 cr3 cr4 cr8 dr0 dr1 dr2 dr3 dr8 tr3 tr4 tr5 tr6 tr7 r0 r1 r2 r3 r4 r5 r6 r7 r0b r1b r2b r3b r4b r5b r6b r7b r0w r1w r2w r3w r4w r5w r6w r7w r0d r1d r2d r3d r4d r5d r6d r7d r0h r1h r2h r3h r0l r1l r2l r3l r4l r5l r6l r7l r8l r9l r10l r11l r12l r13l r14l r15l db dw dd dq dt ddq do dy dz resb resw resd resq rest resdq reso resy resz incbin equ times byte word dword qword nosplit rel abs seg wrt strict near far a32 ptr",meta:"%define %xdefine %+ %undef %defstr %deftok %assign %strcat %strlen %substr %rotate %elif %else %endif %if %ifmacro %ifctx %ifidn %ifidni %ifid %ifnum %ifstr %iftoken %ifempty %ifenv %error %warning %fatal %rep %endrep %include %push %pop %repl %pathsearch %depend %use %arg %stacksize %local %line %comment %endcomment .nolist __FILE__ __LINE__ __SECT__ __BITS__ __OUTPUT_FORMAT__ __DATE__ __TIME__ __DATE_NUM__ __TIME_NUM__ __UTC_DATE__ __UTC_TIME__ __UTC_DATE_NUM__ __UTC_TIME_NUM__ __PASS__ struc endstruc istruc at iend align alignb sectalign daz nodaz up down zero default option assume public bits use16 use32 use64 default section segment absolute extern global common cpu float __utf16__ __utf16le__ __utf16be__ __utf32__ __utf32le__ __utf32be__ __float8__ __float16__ __float32__ __float64__ __float80m__ __float80e__ __float128l__ __float128h__ __Infinity__ __QNaN__ __SNaN__ Inf NaN QNaN SNaN float8 float16 float32 float64 float80m float80e float128l float128h __FLOAT_DAZ__ __FLOAT_ROUND__ __FLOAT__"},c:[s.C(";","$",{r:0}),{cN:"number",v:[{b:"\\b(?:([0-9][0-9_]*)?\\.[0-9_]*(?:[eE][+-]?[0-9_]+)?|(0[Xx])?[0-9][0-9_]*\\.?[0-9_]*(?:[pP](?:[+-]?[0-9_]+)?)?)\\b",r:0},{b:"\\$[0-9][0-9A-Fa-f]*",r:0},{b:"\\b(?:[0-9A-Fa-f][0-9A-Fa-f_]*[Hh]|[0-9][0-9_]*[DdTt]?|[0-7][0-7_]*[QqOo]|[0-1][0-1_]*[BbYy])\\b"},{b:"\\b(?:0[Xx][0-9A-Fa-f_]+|0[DdTt][0-9_]+|0[QqOo][0-7_]+|0[BbYy][0-1_]+)\\b"}]},s.QSM,{cN:"string",v:[{b:"'",e:"[^\\\\]'"},{b:"`",e:"[^\\\\]`"}],r:0},{cN:"symbol",v:[{b:"^\\s*[A-Za-z._?][A-Za-z0-9_$#@~.?]*(:|\\s+label)"},{b:"^\\s*%%[A-Za-z0-9_$#@~.?]*:"}],r:0},{cN:"subst",b:"%[0-9]+",r:0},{cN:"subst",b:"%!S+",r:0},{cN:"meta",b:/^\s*\.[\w_-]+/}]}});hljs.registerLanguage("hsp",function(e){return{cI:!0,l:/[\w\._]+/,k:"goto gosub return break repeat loop continue wait await dim sdim foreach dimtype dup dupptr end stop newmod delmod mref run exgoto on mcall assert logmes newlab resume yield onexit onerror onkey onclick oncmd exist delete mkdir chdir dirlist bload bsave bcopy memfile if else poke wpoke lpoke getstr chdpm memexpand memcpy memset notesel noteadd notedel noteload notesave randomize noteunsel noteget split strrep setease button chgdisp exec dialog mmload mmplay mmstop mci pset pget syscolor mes print title pos circle cls font sysfont objsize picload color palcolor palette redraw width gsel gcopy gzoom gmode bmpsave hsvcolor getkey listbox chkbox combox input mesbox buffer screen bgscr mouse objsel groll line clrobj boxf objprm objmode stick grect grotate gsquare gradf objimage objskip objenable celload celdiv celput newcom querycom delcom cnvstow comres axobj winobj sendmsg comevent comevarg sarrayconv callfunc cnvwtos comevdisp libptr system hspstat hspver stat cnt err strsize looplev sublev iparam wparam lparam refstr refdval int rnd strlen length length2 length3 length4 vartype gettime peek wpeek lpeek varptr varuse noteinfo instr abs limit getease str strmid strf getpath strtrim sin cos tan atan sqrt double absf expf logf limitf powf geteasef mousex mousey mousew hwnd hinstance hdc ginfo objinfo dirinfo sysinfo thismod __hspver__ __hsp30__ __date__ __time__ __line__ __file__ _debug __hspdef__ and or xor not screen_normal screen_palette screen_hide screen_fixedsize screen_tool screen_frame gmode_gdi gmode_mem gmode_rgb0 gmode_alpha gmode_rgb0alpha gmode_add gmode_sub gmode_pixela ginfo_mx ginfo_my ginfo_act ginfo_sel ginfo_wx1 ginfo_wy1 ginfo_wx2 ginfo_wy2 ginfo_vx ginfo_vy ginfo_sizex ginfo_sizey ginfo_winx ginfo_winy ginfo_mesx ginfo_mesy ginfo_r ginfo_g ginfo_b ginfo_paluse ginfo_dispx ginfo_dispy ginfo_cx ginfo_cy ginfo_intid ginfo_newid ginfo_sx ginfo_sy objinfo_mode objinfo_bmscr objinfo_hwnd notemax notesize dir_cur dir_exe dir_win dir_sys dir_cmdline dir_desktop dir_mydoc dir_tv font_normal font_bold font_italic font_underline font_strikeout font_antialias objmode_normal objmode_guifont objmode_usefont gsquare_grad msgothic msmincho do until while wend for next _break _continue switch case default swbreak swend ddim ldim alloc m_pi rad2deg deg2rad ease_linear ease_quad_in ease_quad_out ease_quad_inout ease_cubic_in ease_cubic_out ease_cubic_inout ease_quartic_in ease_quartic_out ease_quartic_inout ease_bounce_in ease_bounce_out ease_bounce_inout ease_shake_in ease_shake_out ease_shake_inout ease_loop",c:[e.CLCM,e.CBCM,e.QSM,e.ASM,{cN:"string",b:'{"',e:'"}',c:[e.BE]},e.C(";","$",{r:0}),{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"addion cfunc cmd cmpopt comfunc const defcfunc deffunc define else endif enum epack func global if ifdef ifndef include modcfunc modfunc modinit modterm module pack packopt regcmd runtime undef usecom uselib"},c:[e.inherit(e.QSM,{cN:"meta-string"}),e.NM,e.CNM,e.CLCM,e.CBCM]},{cN:"symbol",b:"^\\*(\\w+|@)"},e.NM,e.CNM]}});hljs.registerLanguage("lasso",function(e){var r="[a-zA-Z_][\\w.]*",a="<\\?(lasso(script)?|=)",t="\\]|\\?>",n={literal:"true false none minimal full all void and or not bw nbw ew new cn ncn lt lte gt gte eq neq rx nrx ft",built_in:"array date decimal duration integer map pair string tag xml null boolean bytes keyword list locale queue set stack staticarray local var variable global data self inherited currentcapture givenblock",keyword:"cache database_names database_schemanames database_tablenames define_tag define_type email_batch encode_set html_comment handle handle_error header if inline iterate ljax_target link link_currentaction link_currentgroup link_currentrecord link_detail link_firstgroup link_firstrecord link_lastgroup link_lastrecord link_nextgroup link_nextrecord link_prevgroup link_prevrecord log loop namespace_using output_none portal private protect records referer referrer repeating resultset rows search_args search_arguments select sort_args sort_arguments thread_atomic value_list while abort case else fail_if fail_ifnot fail if_empty if_false if_null if_true loop_abort loop_continue loop_count params params_up return return_value run_children soap_definetag soap_lastrequest soap_lastresponse tag_name ascending average by define descending do equals frozen group handle_failure import in into join let match max min on order parent protected provide public require returnhome skip split_thread sum take thread to trait type where with yield yieldhome"},i=e.C("",{r:0}),s={cN:"meta",b:"\\[noprocess\\]",starts:{e:"\\[/noprocess\\]",rE:!0,c:[i]}},l={cN:"meta",b:"\\[/noprocess|"+a},o={cN:"symbol",b:"'"+r+"'"},c=[e.CLCM,e.CBCM,e.inherit(e.CNM,{b:e.CNR+"|(-?infinity|NaN)\\b"}),e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null}),{cN:"string",b:"`",e:"`"},{v:[{b:"[#$]"+r},{b:"#",e:"\\d+",i:"\\W"}]},{cN:"type",b:"::\\s*",e:r,i:"\\W"},{cN:"params",v:[{b:"-(?!infinity)"+r,r:0},{b:"(\\.\\.\\.)"}]},{b:/(->|\.)\s*/,r:0,c:[o]},{cN:"class",bK:"define",rE:!0,e:"\\(|=>",c:[e.inherit(e.TM,{b:r+"(=(?!>))?|[-+*/%](?!>)"})]}];return{aliases:["ls","lassoscript"],cI:!0,l:r+"|&[lg]t;",k:n,c:[{cN:"meta",b:t,r:0,starts:{e:"\\[|"+a,rE:!0,r:0,c:[i]}},s,l,{cN:"meta",b:"\\[no_square_brackets",starts:{e:"\\[/no_square_brackets\\]",l:r+"|&[lg]t;",k:n,c:[{cN:"meta",b:t,r:0,starts:{e:"\\[noprocess\\]|"+a,rE:!0,c:[i]}},s,l].concat(c)}},{cN:"meta",b:"\\[",r:0},{cN:"meta",b:"^#!",e:"lasso9$",r:10}].concat(c)}});hljs.registerLanguage("profile",function(e){return{c:[e.CNM,{b:"[a-zA-Z_][\\da-zA-Z_]+\\.[\\da-zA-Z_]{1,3}",e:":",eE:!0},{b:"(ncalls|tottime|cumtime)",e:"$",k:"ncalls tottime|10 cumtime|10 filename",r:10},{b:"function calls",e:"$",c:[e.CNM],r:10},e.ASM,e.QSM,{cN:"string",b:"\\(",e:"\\)$",eB:!0,eE:!0,r:0}]}});hljs.registerLanguage("tcl",function(e){return{aliases:["tk"],k:"after append apply array auto_execok auto_import auto_load auto_mkindex auto_mkindex_old auto_qualify auto_reset bgerror binary break catch cd chan clock close concat continue dde dict encoding eof error eval exec exit expr fblocked fconfigure fcopy file fileevent filename flush for foreach format gets glob global history http if incr info interp join lappend|10 lassign|10 lindex|10 linsert|10 list llength|10 load lrange|10 lrepeat|10 lreplace|10 lreverse|10 lsearch|10 lset|10 lsort|10 mathfunc mathop memory msgcat namespace open package parray pid pkg::create pkg_mkIndex platform platform::shell proc puts pwd read refchan regexp registry regsub|10 rename return safe scan seek set socket source split string subst switch tcl_endOfWord tcl_findLibrary tcl_startOfNextWord tcl_startOfPreviousWord tcl_wordBreakAfter tcl_wordBreakBefore tcltest tclvars tell time tm trace unknown unload unset update uplevel upvar variable vwait while",c:[e.C(";[ \\t]*#","$"),e.C("^[ \\t]*#","$"),{bK:"proc",e:"[\\{]",eE:!0,c:[{cN:"title",b:"[ \\t\\n\\r]+(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*",e:"[ \\t\\n\\r]",eW:!0,eE:!0}]},{eE:!0,v:[{b:"\\$(\\{)?(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*\\(([a-zA-Z0-9_])*\\)",e:"[^a-zA-Z0-9_\\}\\$]"},{b:"\\$(\\{)?(::)?[a-zA-Z_]((::)?[a-zA-Z0-9_])*",e:"(\\))?[^a-zA-Z0-9_\\}\\$]"}]},{cN:"string",c:[e.BE],v:[e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},{cN:"number",v:[e.BNM,e.CNM]}]}});hljs.registerLanguage("ocaml",function(e){return{aliases:["ml"],k:{keyword:"and as assert asr begin class constraint do done downto else end exception external for fun function functor if in include inherit! inherit initializer land lazy let lor lsl lsr lxor match method!|10 method mod module mutable new object of open! open or private rec sig struct then to try type val! val virtual when while with parser value",built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 string unit in_channel out_channel ref",literal:"true false"},i:/\/\/|>>/,l:"[a-z_]\\w*!?",c:[{cN:"literal",b:"\\[(\\|\\|)?\\]|\\(\\)",r:0},e.C("\\(\\*","\\*\\)",{c:["self"]}),{cN:"symbol",b:"'[A-Za-z_](?!')[\\w']*"},{cN:"type",b:"`[A-Z][\\w']*"},{cN:"type",b:"\\b[A-Z][\\w']*",r:0},{b:"[a-z_]\\w*'[\\w']*",r:0},e.inherit(e.ASM,{cN:"string",r:0}),e.inherit(e.QSM,{i:null}),{cN:"number",b:"\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)",r:0},{b:/[-=]>/}]}});hljs.registerLanguage("leaf",function(e){return{c:[{cN:"function",b:"#+[A-Za-z_0-9]*\\(",e:" {",rB:!0,eE:!0,c:[{cN:"keyword",b:"#+"},{cN:"title",b:"[A-Za-z_][A-Za-z_0-9]*"},{cN:"params",b:"\\(",e:"\\)",endsParent:!0,c:[{cN:"string",b:'"',e:'"'},{cN:"variable",b:"[A-Za-z_][A-Za-z_0-9]*"}]}]}]}});hljs.registerLanguage("monkey",function(e){var n={cN:"number",r:0,v:[{b:"[$][a-fA-F0-9]+"},e.NM]};return{cI:!0,k:{keyword:"public private property continue exit extern new try catch eachin not abstract final select case default const local global field end if then else elseif endif while wend repeat until forever for to step next return module inline throw import",built_in:"DebugLog DebugStop Error Print ACos ACosr ASin ASinr ATan ATan2 ATan2r ATanr Abs Abs Ceil Clamp Clamp Cos Cosr Exp Floor Log Max Max Min Min Pow Sgn Sgn Sin Sinr Sqrt Tan Tanr Seed PI HALFPI TWOPI",literal:"true false null and or shl shr mod"},i:/\/\*/,c:[e.C("#rem","#end"),e.C("'","$",{r:0}),{cN:"function",bK:"function method",e:"[(=:]|$",i:/\n/,c:[e.UTM]},{cN:"class",bK:"class interface",e:"$",c:[{bK:"extends implements"},e.UTM]},{cN:"built_in",b:"\\b(self|super)\\b"},{cN:"meta",b:"\\s*#",e:"$",k:{"meta-keyword":"if else elseif endif end then"}},{cN:"meta",b:"^\\s*strict\\b"},{bK:"alias",e:"=",c:[e.UTM]},e.QSM,n]}});hljs.registerLanguage("groovy",function(e){return{k:{literal:"true false null",keyword:"byte short char int long boolean float double void def as in assert trait super this abstract static volatile transient public private protected synchronized final class interface enum if else for while switch case break default continue throw throws try catch finally implements extends new import package return instanceof"},c:[e.C("/\\*\\*","\\*/",{r:0,c:[{b:/\w+@/,r:0},{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,{cN:"string",b:'"""',e:'"""'},{cN:"string",b:"'''",e:"'''"},{cN:"string",b:"\\$/",e:"/\\$",r:10},e.ASM,{cN:"regexp",b:/~?\/[^\/\n]+\//,c:[e.BE]},e.QSM,{cN:"meta",b:"^#!/usr/bin/env",e:"$",i:"\n"},e.BNM,{cN:"class",bK:"class interface trait enum",e:"{",i:":",c:[{bK:"extends implements"},e.UTM]},e.CNM,{cN:"meta",b:"@[A-Za-z]+"},{cN:"string",b:/[^\?]{0}[A-Za-z0-9_$]+ *:/},{b:/\?/,e:/\:/},{cN:"symbol",b:"^\\s*[A-Za-z0-9_$]+:",r:0}],i:/#|<\//}});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[{b:'(u8?|U)?L?"',e:'"',i:"\\n",c:[t.BE]},{b:'(u8?|U)?R"',e:'"',c:[t.BE]},{b:"'\\\\?.",e:"'",i:"."}]},s={cN:"number",v:[{b:"\\b(0b[01']+)"},{b:"\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{b:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],r:0},i={cN:"meta",b:/#\s*[a-z]+\b/,e:/$/,k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},c:[{b:/\\\n/,r:0},t.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:/<[^\n>]*>/,e:/$/,i:"\\n"},t.CLCM,t.CBCM]},a=t.IR+"\\s*\\(",c={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return",built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",literal:"true false nullptr NULL"},n=[e,t.CLCM,t.CBCM,s,r];return{aliases:["c","cc","h","c++","h++","hpp"],k:c,i:"",k:c,c:["self",e]},{b:t.IR+"::",k:c},{v:[{b:/=/,e:/;/},{b:/\(/,e:/\)/},{bK:"new throw return else",e:/;/}],k:c,c:n.concat([{b:/\(/,e:/\)/,k:c,c:n.concat(["self"]),r:0}]),r:0},{cN:"function",b:"("+t.IR+"[\\*&\\s]+)+"+a,rB:!0,e:/[{;=]/,eE:!0,k:c,i:/[^\w\s\*&]/,c:[{b:a,rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:c,r:0,c:[t.CLCM,t.CBCM,r,s,e]},t.CLCM,t.CBCM,i]}]),exports:{preprocessor:i,strings:r,k:c}}});hljs.registerLanguage("sqf",function(e){var t=e.getLanguage("cpp").exports,a={cN:"variable",b:/\b_+[a-zA-Z_]\w*/},o={cN:"title",b:/[a-zA-Z][a-zA-Z0-9]+_fnc_\w*/},r={cN:"string",v:[{b:'"',e:'"',c:[{b:'""',r:0}]},{b:"'",e:"'",c:[{b:"''",r:0}]}]};return{aliases:["sqf"],cI:!0,k:{keyword:"case catch default do else exit exitWith for forEach from if switch then throw to try waitUntil while with",built_in:"abs accTime acos action actionIDs actionKeys actionKeysImages actionKeysNames actionKeysNamesArray actionName actionParams activateAddons activatedAddons activateKey add3DENConnection add3DENEventHandler add3DENLayer addAction addBackpack addBackpackCargo addBackpackCargoGlobal addBackpackGlobal addCamShake addCuratorAddons addCuratorCameraArea addCuratorEditableObjects addCuratorEditingArea addCuratorPoints addEditorObject addEventHandler addGoggles addGroupIcon addHandgunItem addHeadgear addItem addItemCargo addItemCargoGlobal addItemPool addItemToBackpack addItemToUniform addItemToVest addLiveStats addMagazine addMagazineAmmoCargo addMagazineCargo addMagazineCargoGlobal addMagazineGlobal addMagazinePool addMagazines addMagazineTurret addMenu addMenuItem addMissionEventHandler addMPEventHandler addMusicEventHandler addOwnedMine addPlayerScores addPrimaryWeaponItem addPublicVariableEventHandler addRating addResources addScore addScoreSide addSecondaryWeaponItem addSwitchableUnit addTeamMember addToRemainsCollector addUniform addVehicle addVest addWaypoint addWeapon addWeaponCargo addWeaponCargoGlobal addWeaponGlobal addWeaponItem addWeaponPool addWeaponTurret agent agents AGLToASL aimedAtTarget aimPos airDensityRTD airportSide AISFinishHeal alive all3DENEntities allControls allCurators allCutLayers allDead allDeadMen allDisplays allGroups allMapMarkers allMines allMissionObjects allow3DMode allowCrewInImmobile allowCuratorLogicIgnoreAreas allowDamage allowDammage allowFileOperations allowFleeing allowGetIn allowSprint allPlayers allSites allTurrets allUnits allUnitsUAV allVariables ammo and animate animateDoor animateSource animationNames animationPhase animationSourcePhase animationState append apply armoryPoints arrayIntersect asin ASLToAGL ASLToATL assert assignAsCargo assignAsCargoIndex assignAsCommander assignAsDriver assignAsGunner assignAsTurret assignCurator assignedCargo assignedCommander assignedDriver assignedGunner assignedItems assignedTarget assignedTeam assignedVehicle assignedVehicleRole assignItem assignTeam assignToAirport atan atan2 atg ATLToASL attachedObject attachedObjects attachedTo attachObject attachTo attackEnabled backpack backpackCargo backpackContainer backpackItems backpackMagazines backpackSpaceFor behaviour benchmark binocular blufor boundingBox boundingBoxReal boundingCenter breakOut breakTo briefingName buildingExit buildingPos buttonAction buttonSetAction cadetMode call callExtension camCommand camCommit camCommitPrepared camCommitted camConstuctionSetParams camCreate camDestroy cameraEffect cameraEffectEnableHUD cameraInterest cameraOn cameraView campaignConfigFile camPreload camPreloaded camPrepareBank camPrepareDir camPrepareDive camPrepareFocus camPrepareFov camPrepareFovRange camPreparePos camPrepareRelPos camPrepareTarget camSetBank camSetDir camSetDive camSetFocus camSetFov camSetFovRange camSetPos camSetRelPos camSetTarget camTarget camUseNVG canAdd canAddItemToBackpack canAddItemToUniform canAddItemToVest cancelSimpleTaskDestination canFire canMove canSlingLoad canStand canSuspend canUnloadInCombat canVehicleCargo captive captiveNum cbChecked cbSetChecked ceil channelEnabled cheatsEnabled checkAIFeature checkVisibility civilian className clearAllItemsFromBackpack clearBackpackCargo clearBackpackCargoGlobal clearGroupIcons clearItemCargo clearItemCargoGlobal clearItemPool clearMagazineCargo clearMagazineCargoGlobal clearMagazinePool clearOverlay clearRadio clearWeaponCargo clearWeaponCargoGlobal clearWeaponPool clientOwner closeDialog closeDisplay closeOverlay collapseObjectTree collect3DENHistory combatMode commandArtilleryFire commandChat commander commandFire commandFollow commandFSM commandGetOut commandingMenu commandMove commandRadio commandStop commandSuppressiveFire commandTarget commandWatch comment commitOverlay compile compileFinal completedFSM composeText configClasses configFile configHierarchy configName configNull configProperties configSourceAddonList configSourceMod configSourceModList connectTerminalToUAV controlNull controlsGroupCtrl copyFromClipboard copyToClipboard copyWaypoints cos count countEnemy countFriendly countSide countType countUnknown create3DENComposition create3DENEntity createAgent createCenter createDialog createDiaryLink createDiaryRecord createDiarySubject createDisplay createGearDialog createGroup createGuardedPoint createLocation createMarker createMarkerLocal createMenu createMine createMissionDisplay createMPCampaignDisplay createSimpleObject createSimpleTask createSite createSoundSource createTask createTeam createTrigger createUnit createVehicle createVehicleCrew createVehicleLocal crew ctrlActivate ctrlAddEventHandler ctrlAngle ctrlAutoScrollDelay ctrlAutoScrollRewind ctrlAutoScrollSpeed ctrlChecked ctrlClassName ctrlCommit ctrlCommitted ctrlCreate ctrlDelete ctrlEnable ctrlEnabled ctrlFade ctrlHTMLLoaded ctrlIDC ctrlIDD ctrlMapAnimAdd ctrlMapAnimClear ctrlMapAnimCommit ctrlMapAnimDone ctrlMapCursor ctrlMapMouseOver ctrlMapScale ctrlMapScreenToWorld ctrlMapWorldToScreen ctrlModel ctrlModelDirAndUp ctrlModelScale ctrlParent ctrlParentControlsGroup ctrlPosition ctrlRemoveAllEventHandlers ctrlRemoveEventHandler ctrlScale ctrlSetActiveColor ctrlSetAngle ctrlSetAutoScrollDelay ctrlSetAutoScrollRewind ctrlSetAutoScrollSpeed ctrlSetBackgroundColor ctrlSetChecked ctrlSetEventHandler ctrlSetFade ctrlSetFocus ctrlSetFont ctrlSetFontH1 ctrlSetFontH1B ctrlSetFontH2 ctrlSetFontH2B ctrlSetFontH3 ctrlSetFontH3B ctrlSetFontH4 ctrlSetFontH4B ctrlSetFontH5 ctrlSetFontH5B ctrlSetFontH6 ctrlSetFontH6B ctrlSetFontHeight ctrlSetFontHeightH1 ctrlSetFontHeightH2 ctrlSetFontHeightH3 ctrlSetFontHeightH4 ctrlSetFontHeightH5 ctrlSetFontHeightH6 ctrlSetFontHeightSecondary ctrlSetFontP ctrlSetFontPB ctrlSetFontSecondary ctrlSetForegroundColor ctrlSetModel ctrlSetModelDirAndUp ctrlSetModelScale ctrlSetPosition ctrlSetScale ctrlSetStructuredText ctrlSetText ctrlSetTextColor ctrlSetTooltip ctrlSetTooltipColorBox ctrlSetTooltipColorShade ctrlSetTooltipColorText ctrlShow ctrlShown ctrlText ctrlTextHeight ctrlType ctrlVisible curatorAddons curatorCamera curatorCameraArea curatorCameraAreaCeiling curatorCoef curatorEditableObjects curatorEditingArea curatorEditingAreaType curatorMouseOver curatorPoints curatorRegisteredObjects curatorSelected curatorWaypointCost current3DENOperation currentChannel currentCommand currentMagazine currentMagazineDetail currentMagazineDetailTurret currentMagazineTurret currentMuzzle currentNamespace currentTask currentTasks currentThrowable currentVisionMode currentWaypoint currentWeapon currentWeaponMode currentWeaponTurret currentZeroing cursorObject cursorTarget customChat customRadio cutFadeOut cutObj cutRsc cutText damage date dateToNumber daytime deActivateKey debriefingText debugFSM debugLog deg delete3DENEntities deleteAt deleteCenter deleteCollection deleteEditorObject deleteGroup deleteIdentity deleteLocation deleteMarker deleteMarkerLocal deleteRange deleteResources deleteSite deleteStatus deleteTeam deleteVehicle deleteVehicleCrew deleteWaypoint detach detectedMines diag_activeMissionFSMs diag_activeScripts diag_activeSQFScripts diag_activeSQSScripts diag_captureFrame diag_captureSlowFrame diag_codePerformance diag_drawMode diag_enable diag_enabled diag_fps diag_fpsMin diag_frameNo diag_list diag_log diag_logSlowFrame diag_mergeConfigFile diag_recordTurretLimits diag_tickTime diag_toggle dialog diarySubjectExists didJIP didJIPOwner difficulty difficultyEnabled difficultyEnabledRTD difficultyOption direction directSay disableAI disableCollisionWith disableConversation disableDebriefingStats disableNVGEquipment disableRemoteSensors disableSerialization disableTIEquipment disableUAVConnectability disableUserInput displayAddEventHandler displayCtrl displayNull displayParent displayRemoveAllEventHandlers displayRemoveEventHandler displaySetEventHandler dissolveTeam distance distance2D distanceSqr distributionRegion do3DENAction doArtilleryFire doFire doFollow doFSM doGetOut doMove doorPhase doStop doSuppressiveFire doTarget doWatch drawArrow drawEllipse drawIcon drawIcon3D drawLine drawLine3D drawLink drawLocation drawPolygon drawRectangle driver drop east echo edit3DENMissionAttributes editObject editorSetEventHandler effectiveCommander emptyPositions enableAI enableAIFeature enableAimPrecision enableAttack enableAudioFeature enableCamShake enableCaustics enableChannel enableCollisionWith enableCopilot enableDebriefingStats enableDiagLegend enableEndDialog enableEngineArtillery enableEnvironment enableFatigue enableGunLights enableIRLasers enableMimics enablePersonTurret enableRadio enableReload enableRopeAttach enableSatNormalOnDetail enableSaving enableSentences enableSimulation enableSimulationGlobal enableStamina enableTeamSwitch enableUAVConnectability enableUAVWaypoints enableVehicleCargo endLoadingScreen endMission engineOn enginesIsOnRTD enginesRpmRTD enginesTorqueRTD entities estimatedEndServerTime estimatedTimeLeft evalObjectArgument everyBackpack everyContainer exec execEditorScript execFSM execVM exp expectedDestination exportJIPMessages eyeDirection eyePos face faction fadeMusic fadeRadio fadeSound fadeSpeech failMission fillWeaponsFromPool find findCover findDisplay findEditorObject findEmptyPosition findEmptyPositionReady findNearestEnemy finishMissionInit finite fire fireAtTarget firstBackpack flag flagOwner flagSide flagTexture fleeing floor flyInHeight flyInHeightASL fog fogForecast fogParams forceAddUniform forcedMap forceEnd forceMap forceRespawn forceSpeed forceWalk forceWeaponFire forceWeatherChange forEachMember forEachMemberAgent forEachMemberTeam format formation formationDirection formationLeader formationMembers formationPosition formationTask formatText formLeader freeLook fromEditor fuel fullCrew gearIDCAmmoCount gearSlotAmmoCount gearSlotData get3DENActionState get3DENAttribute get3DENCamera get3DENConnections get3DENEntity get3DENEntityID get3DENGrid get3DENIconsVisible get3DENLayerEntities get3DENLinesVisible get3DENMissionAttribute get3DENMouseOver get3DENSelected getAimingCoef getAllHitPointsDamage getAllOwnedMines getAmmoCargo getAnimAimPrecision getAnimSpeedCoef getArray getArtilleryAmmo getArtilleryComputerSettings getArtilleryETA getAssignedCuratorLogic getAssignedCuratorUnit getBackpackCargo getBleedingRemaining getBurningValue getCameraViewDirection getCargoIndex getCenterOfMass getClientState getClientStateNumber getConnectedUAV getCustomAimingCoef getDammage getDescription getDir getDirVisual getDLCs getEditorCamera getEditorMode getEditorObjectScope getElevationOffset getFatigue getFriend getFSMVariable getFuelCargo getGroupIcon getGroupIconParams getGroupIcons getHideFrom getHit getHitIndex getHitPointDamage getItemCargo getMagazineCargo getMarkerColor getMarkerPos getMarkerSize getMarkerType getMass getMissionConfig getMissionConfigValue getMissionDLCs getMissionLayerEntities getModelInfo getMousePosition getNumber getObjectArgument getObjectChildren getObjectDLC getObjectMaterials getObjectProxy getObjectTextures getObjectType getObjectViewDistance getOxygenRemaining getPersonUsedDLCs getPilotCameraDirection getPilotCameraPosition getPilotCameraRotation getPilotCameraTarget getPlayerChannel getPlayerScores getPlayerUID getPos getPosASL getPosASLVisual getPosASLW getPosATL getPosATLVisual getPosVisual getPosWorld getRelDir getRelPos getRemoteSensorsDisabled getRepairCargo getResolution getShadowDistance getShotParents getSlingLoad getSpeed getStamina getStatValue getSuppression getTerrainHeightASL getText getUnitLoadout getUnitTrait getVariable getVehicleCargo getWeaponCargo getWeaponSway getWPPos glanceAt globalChat globalRadio goggles goto group groupChat groupFromNetId groupIconSelectable groupIconsVisible groupId groupOwner groupRadio groupSelectedUnits groupSelectUnit grpNull gunner gusts halt handgunItems handgunMagazine handgunWeapon handsHit hasInterface hasPilotCamera hasWeapon hcAllGroups hcGroupParams hcLeader hcRemoveAllGroups hcRemoveGroup hcSelected hcSelectGroup hcSetGroup hcShowBar hcShownBar headgear hideBody hideObject hideObjectGlobal hideSelection hint hintC hintCadet hintSilent hmd hostMission htmlLoad HUDMovementLevels humidity image importAllGroups importance in inArea inAreaArray incapacitatedState independent inflame inflamed inGameUISetEventHandler inheritsFrom initAmbientLife inPolygon inputAction inRangeOfArtillery insertEditorObject intersect is3DEN is3DENMultiplayer isAbleToBreathe isAgent isArray isAutoHoverOn isAutonomous isAutotest isBleeding isBurning isClass isCollisionLightOn isCopilotEnabled isDedicated isDLCAvailable isEngineOn isEqualTo isEqualType isEqualTypeAll isEqualTypeAny isEqualTypeArray isEqualTypeParams isFilePatchingEnabled isFlashlightOn isFlatEmpty isForcedWalk isFormationLeader isHidden isInRemainsCollector isInstructorFigureEnabled isIRLaserOn isKeyActive isKindOf isLightOn isLocalized isManualFire isMarkedForCollection isMultiplayer isMultiplayerSolo isNil isNull isNumber isObjectHidden isObjectRTD isOnRoad isPipEnabled isPlayer isRealTime isRemoteExecuted isRemoteExecutedJIP isServer isShowing3DIcons isSprintAllowed isStaminaEnabled isSteamMission isStreamFriendlyUIEnabled isText isTouchingGround isTurnedOut isTutHintsEnabled isUAVConnectable isUAVConnected isUniformAllowed isVehicleCargo isWalking isWeaponDeployed isWeaponRested itemCargo items itemsWithMagazines join joinAs joinAsSilent joinSilent joinString kbAddDatabase kbAddDatabaseTargets kbAddTopic kbHasTopic kbReact kbRemoveTopic kbTell kbWasSaid keyImage keyName knowsAbout land landAt landResult language laserTarget lbAdd lbClear lbColor lbCurSel lbData lbDelete lbIsSelected lbPicture lbSelection lbSetColor lbSetCurSel lbSetData lbSetPicture lbSetPictureColor lbSetPictureColorDisabled lbSetPictureColorSelected lbSetSelectColor lbSetSelectColorRight lbSetSelected lbSetTooltip lbSetValue lbSize lbSort lbSortByValue lbText lbValue leader leaderboardDeInit leaderboardGetRows leaderboardInit leaveVehicle libraryCredits libraryDisclaimers lifeState lightAttachObject lightDetachObject lightIsOn lightnings limitSpeed linearConversion lineBreak lineIntersects lineIntersectsObjs lineIntersectsSurfaces lineIntersectsWith linkItem list listObjects ln lnbAddArray lnbAddColumn lnbAddRow lnbClear lnbColor lnbCurSelRow lnbData lnbDeleteColumn lnbDeleteRow lnbGetColumnsPosition lnbPicture lnbSetColor lnbSetColumnsPos lnbSetCurSelRow lnbSetData lnbSetPicture lnbSetText lnbSetValue lnbSize lnbText lnbValue load loadAbs loadBackpack loadFile loadGame loadIdentity loadMagazine loadOverlay loadStatus loadUniform loadVest local localize locationNull locationPosition lock lockCameraTo lockCargo lockDriver locked lockedCargo lockedDriver lockedTurret lockIdentity lockTurret lockWP log logEntities logNetwork logNetworkTerminate lookAt lookAtPos magazineCargo magazines magazinesAllTurrets magazinesAmmo magazinesAmmoCargo magazinesAmmoFull magazinesDetail magazinesDetailBackpack magazinesDetailUniform magazinesDetailVest magazinesTurret magazineTurretAmmo mapAnimAdd mapAnimClear mapAnimCommit mapAnimDone mapCenterOnCamera mapGridPosition markAsFinishedOnSteam markerAlpha markerBrush markerColor markerDir markerPos markerShape markerSize markerText markerType max members menuAction menuAdd menuChecked menuClear menuCollapse menuData menuDelete menuEnable menuEnabled menuExpand menuHover menuPicture menuSetAction menuSetCheck menuSetData menuSetPicture menuSetValue menuShortcut menuShortcutText menuSize menuSort menuText menuURL menuValue min mineActive mineDetectedBy missionConfigFile missionDifficulty missionName missionNamespace missionStart missionVersion mod modelToWorld modelToWorldVisual modParams moonIntensity moonPhase morale move move3DENCamera moveInAny moveInCargo moveInCommander moveInDriver moveInGunner moveInTurret moveObjectToEnd moveOut moveTime moveTo moveToCompleted moveToFailed musicVolume name nameSound nearEntities nearestBuilding nearestLocation nearestLocations nearestLocationWithDubbing nearestObject nearestObjects nearestTerrainObjects nearObjects nearObjectsReady nearRoads nearSupplies nearTargets needReload netId netObjNull newOverlay nextMenuItemIndex nextWeatherChange nMenuItems not numberToDate objectCurators objectFromNetId objectParent objNull objStatus onBriefingGroup onBriefingNotes onBriefingPlan onBriefingTeamSwitch onCommandModeChanged onDoubleClick onEachFrame onGroupIconClick onGroupIconOverEnter onGroupIconOverLeave onHCGroupSelectionChanged onMapSingleClick onPlayerConnected onPlayerDisconnected onPreloadFinished onPreloadStarted onShowNewObject onTeamSwitch openCuratorInterface openDLCPage openMap openYoutubeVideo opfor or orderGetIn overcast overcastForecast owner param params parseNumber parseText parsingNamespace particlesQuality pi pickWeaponPool pitch pixelGrid pixelGridBase pixelGridNoUIScale pixelH pixelW playableSlotsNumber playableUnits playAction playActionNow player playerRespawnTime playerSide playersNumber playGesture playMission playMove playMoveNow playMusic playScriptedMission playSound playSound3D position positionCameraToWorld posScreenToWorld posWorldToScreen ppEffectAdjust ppEffectCommit ppEffectCommitted ppEffectCreate ppEffectDestroy ppEffectEnable ppEffectEnabled ppEffectForceInNVG precision preloadCamera preloadObject preloadSound preloadTitleObj preloadTitleRsc preprocessFile preprocessFileLineNumbers primaryWeapon primaryWeaponItems primaryWeaponMagazine priority private processDiaryLink productVersion profileName profileNamespace profileNameSteam progressLoadingScreen progressPosition progressSetPosition publicVariable publicVariableClient publicVariableServer pushBack pushBackUnique putWeaponPool queryItemsPool queryMagazinePool queryWeaponPool rad radioChannelAdd radioChannelCreate radioChannelRemove radioChannelSetCallSign radioChannelSetLabel radioVolume rain rainbow random rank rankId rating rectangular registeredTasks registerTask reload reloadEnabled remoteControl remoteExec remoteExecCall remove3DENConnection remove3DENEventHandler remove3DENLayer removeAction removeAll3DENEventHandlers removeAllActions removeAllAssignedItems removeAllContainers removeAllCuratorAddons removeAllCuratorCameraAreas removeAllCuratorEditingAreas removeAllEventHandlers removeAllHandgunItems removeAllItems removeAllItemsWithMagazines removeAllMissionEventHandlers removeAllMPEventHandlers removeAllMusicEventHandlers removeAllOwnedMines removeAllPrimaryWeaponItems removeAllWeapons removeBackpack removeBackpackGlobal removeCuratorAddons removeCuratorCameraArea removeCuratorEditableObjects removeCuratorEditingArea removeDrawIcon removeDrawLinks removeEventHandler removeFromRemainsCollector removeGoggles removeGroupIcon removeHandgunItem removeHeadgear removeItem removeItemFromBackpack removeItemFromUniform removeItemFromVest removeItems removeMagazine removeMagazineGlobal removeMagazines removeMagazinesTurret removeMagazineTurret removeMenuItem removeMissionEventHandler removeMPEventHandler removeMusicEventHandler removeOwnedMine removePrimaryWeaponItem removeSecondaryWeaponItem removeSimpleTask removeSwitchableUnit removeTeamMember removeUniform removeVest removeWeapon removeWeaponGlobal removeWeaponTurret requiredVersion resetCamShake resetSubgroupDirection resistance resize resources respawnVehicle restartEditorCamera reveal revealMine reverse reversedMouseY roadAt roadsConnectedTo roleDescription ropeAttachedObjects ropeAttachedTo ropeAttachEnabled ropeAttachTo ropeCreate ropeCut ropeDestroy ropeDetach ropeEndPosition ropeLength ropes ropeUnwind ropeUnwound rotorsForcesRTD rotorsRpmRTD round runInitScript safeZoneH safeZoneW safeZoneWAbs safeZoneX safeZoneXAbs safeZoneY save3DENInventory saveGame saveIdentity saveJoysticks saveOverlay saveProfileNamespace saveStatus saveVar savingEnabled say say2D say3D scopeName score scoreSide screenshot screenToWorld scriptDone scriptName scriptNull scudState secondaryWeapon secondaryWeaponItems secondaryWeaponMagazine select selectBestPlaces selectDiarySubject selectedEditorObjects selectEditorObject selectionNames selectionPosition selectLeader selectMax selectMin selectNoPlayer selectPlayer selectRandom selectWeapon selectWeaponTurret sendAUMessage sendSimpleCommand sendTask sendTaskResult sendUDPMessage serverCommand serverCommandAvailable serverCommandExecutable serverName serverTime set set3DENAttribute set3DENAttributes set3DENGrid set3DENIconsVisible set3DENLayer set3DENLinesVisible set3DENMissionAttributes set3DENModelsVisible set3DENObjectType set3DENSelected setAccTime setAirportSide setAmmo setAmmoCargo setAnimSpeedCoef setAperture setApertureNew setArmoryPoints setAttributes setAutonomous setBehaviour setBleedingRemaining setCameraInterest setCamShakeDefParams setCamShakeParams setCamUseTi setCaptive setCenterOfMass setCollisionLight setCombatMode setCompassOscillation setCuratorCameraAreaCeiling setCuratorCoef setCuratorEditingAreaType setCuratorWaypointCost setCurrentChannel setCurrentTask setCurrentWaypoint setCustomAimCoef setDamage setDammage setDate setDebriefingText setDefaultCamera setDestination setDetailMapBlendPars setDir setDirection setDrawIcon setDropInterval setEditorMode setEditorObjectScope setEffectCondition setFace setFaceAnimation setFatigue setFlagOwner setFlagSide setFlagTexture setFog setFormation setFormationTask setFormDir setFriend setFromEditor setFSMVariable setFuel setFuelCargo setGroupIcon setGroupIconParams setGroupIconsSelectable setGroupIconsVisible setGroupId setGroupIdGlobal setGroupOwner setGusts setHideBehind setHit setHitIndex setHitPointDamage setHorizonParallaxCoef setHUDMovementLevels setIdentity setImportance setLeader setLightAmbient setLightAttenuation setLightBrightness setLightColor setLightDayLight setLightFlareMaxDistance setLightFlareSize setLightIntensity setLightnings setLightUseFlare setLocalWindParams setMagazineTurretAmmo setMarkerAlpha setMarkerAlphaLocal setMarkerBrush setMarkerBrushLocal setMarkerColor setMarkerColorLocal setMarkerDir setMarkerDirLocal setMarkerPos setMarkerPosLocal setMarkerShape setMarkerShapeLocal setMarkerSize setMarkerSizeLocal setMarkerText setMarkerTextLocal setMarkerType setMarkerTypeLocal setMass setMimic setMousePosition setMusicEffect setMusicEventHandler setName setNameSound setObjectArguments setObjectMaterial setObjectMaterialGlobal setObjectProxy setObjectTexture setObjectTextureGlobal setObjectViewDistance setOvercast setOwner setOxygenRemaining setParticleCircle setParticleClass setParticleFire setParticleParams setParticleRandom setPilotCameraDirection setPilotCameraRotation setPilotCameraTarget setPilotLight setPiPEffect setPitch setPlayable setPlayerRespawnTime setPos setPosASL setPosASL2 setPosASLW setPosATL setPosition setPosWorld setRadioMsg setRain setRainbow setRandomLip setRank setRectangular setRepairCargo setShadowDistance setShotParents setSide setSimpleTaskAlwaysVisible setSimpleTaskCustomData setSimpleTaskDescription setSimpleTaskDestination setSimpleTaskTarget setSimpleTaskType setSimulWeatherLayers setSize setSkill setSlingLoad setSoundEffect setSpeaker setSpeech setSpeedMode setStamina setStaminaScheme setStatValue setSuppression setSystemOfUnits setTargetAge setTaskResult setTaskState setTerrainGrid setText setTimeMultiplier setTitleEffect setTriggerActivation setTriggerArea setTriggerStatements setTriggerText setTriggerTimeout setTriggerType setType setUnconscious setUnitAbility setUnitLoadout setUnitPos setUnitPosWeak setUnitRank setUnitRecoilCoefficient setUnitTrait setUnloadInCombat setUserActionText setVariable setVectorDir setVectorDirAndUp setVectorUp setVehicleAmmo setVehicleAmmoDef setVehicleArmor setVehicleCargo setVehicleId setVehicleLock setVehiclePosition setVehicleTiPars setVehicleVarName setVelocity setVelocityTransformation setViewDistance setVisibleIfTreeCollapsed setWaves setWaypointBehaviour setWaypointCombatMode setWaypointCompletionRadius setWaypointDescription setWaypointForceBehaviour setWaypointFormation setWaypointHousePosition setWaypointLoiterRadius setWaypointLoiterType setWaypointName setWaypointPosition setWaypointScript setWaypointSpeed setWaypointStatements setWaypointTimeout setWaypointType setWaypointVisible setWeaponReloadingTime setWind setWindDir setWindForce setWindStr setWPPos show3DIcons showChat showCinemaBorder showCommandingMenu showCompass showCuratorCompass showGPS showHUD showLegend showMap shownArtilleryComputer shownChat shownCompass shownCuratorCompass showNewEditorObject shownGPS shownHUD shownMap shownPad shownRadio shownScoretable shownUAVFeed shownWarrant shownWatch showPad showRadio showScoretable showSubtitles showUAVFeed showWarrant showWatch showWaypoint showWaypoints side sideAmbientLife sideChat sideEmpty sideEnemy sideFriendly sideLogic sideRadio sideUnknown simpleTasks simulationEnabled simulCloudDensity simulCloudOcclusion simulInClouds simulWeatherSync sin size sizeOf skill skillFinal skipTime sleep sliderPosition sliderRange sliderSetPosition sliderSetRange sliderSetSpeed sliderSpeed slingLoadAssistantShown soldierMagazines someAmmo sort soundVolume spawn speaker speed speedMode splitString sqrt squadParams stance startLoadingScreen step stop stopEngineRTD stopped str sunOrMoon supportInfo suppressFor surfaceIsWater surfaceNormal surfaceType swimInDepth switchableUnits switchAction switchCamera switchGesture switchLight switchMove synchronizedObjects synchronizedTriggers synchronizedWaypoints synchronizeObjectsAdd synchronizeObjectsRemove synchronizeTrigger synchronizeWaypoint systemChat systemOfUnits tan targetKnowledge targetsAggregate targetsQuery taskAlwaysVisible taskChildren taskCompleted taskCustomData taskDescription taskDestination taskHint taskMarkerOffset taskNull taskParent taskResult taskState taskType teamMember teamMemberNull teamName teams teamSwitch teamSwitchEnabled teamType terminate terrainIntersect terrainIntersectASL text textLog textLogFormat tg time timeMultiplier titleCut titleFadeOut titleObj titleRsc titleText toArray toFixed toLower toString toUpper triggerActivated triggerActivation triggerArea triggerAttachedVehicle triggerAttachObject triggerAttachVehicle triggerStatements triggerText triggerTimeout triggerTimeoutCurrent triggerType turretLocal turretOwner turretUnit tvAdd tvClear tvCollapse tvCount tvCurSel tvData tvDelete tvExpand tvPicture tvSetCurSel tvSetData tvSetPicture tvSetPictureColor tvSetPictureColorDisabled tvSetPictureColorSelected tvSetPictureRight tvSetPictureRightColor tvSetPictureRightColorDisabled tvSetPictureRightColorSelected tvSetText tvSetTooltip tvSetValue tvSort tvSortByValue tvText tvTooltip tvValue type typeName typeOf UAVControl uiNamespace uiSleep unassignCurator unassignItem unassignTeam unassignVehicle underwater uniform uniformContainer uniformItems uniformMagazines unitAddons unitAimPosition unitAimPositionVisual unitBackpack unitIsUAV unitPos unitReady unitRecoilCoefficient units unitsBelowHeight unlinkItem unlockAchievement unregisterTask updateDrawIcon updateMenuItem updateObjectTree useAISteeringComponent useAudioTimeForMoves vectorAdd vectorCos vectorCrossProduct vectorDiff vectorDir vectorDirVisual vectorDistance vectorDistanceSqr vectorDotProduct vectorFromTo vectorMagnitude vectorMagnitudeSqr vectorMultiply vectorNormalized vectorUp vectorUpVisual vehicle vehicleCargoEnabled vehicleChat vehicleRadio vehicles vehicleVarName velocity velocityModelSpace verifySignature vest vestContainer vestItems vestMagazines viewDistance visibleCompass visibleGPS visibleMap visiblePosition visiblePositionASL visibleScoretable visibleWatch waves waypointAttachedObject waypointAttachedVehicle waypointAttachObject waypointAttachVehicle waypointBehaviour waypointCombatMode waypointCompletionRadius waypointDescription waypointForceBehaviour waypointFormation waypointHousePosition waypointLoiterRadius waypointLoiterType waypointName waypointPosition waypoints waypointScript waypointsEnabledUAV waypointShow waypointSpeed waypointStatements waypointTimeout waypointTimeoutCurrent waypointType waypointVisible weaponAccessories weaponAccessoriesCargo weaponCargo weaponDirection weaponInertia weaponLowered weapons weaponsItems weaponsItemsCargo weaponState weaponsTurret weightRTD west WFSideText wind",literal:"true false nil"},c:[e.CLCM,e.CBCM,e.NM,a,o,r,t.preprocessor],i:/#/}});hljs.registerLanguage("java",function(e){var a="[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*",t=a+"(<"+a+"(\\s*,\\s*"+a+")*>)?",r="false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",s="\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",c={cN:"number",b:s,r:0};return{aliases:["jsp"],k:r,i:/<\/|#/,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{b:/\w+@/,r:0},{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"new throw return else",r:0},{cN:"function",b:"("+t+"\\s+)+"+e.UIR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,k:r,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},c,{cN:"meta",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("mel",function(e){return{k:"int float string vector matrix if else switch case default while do for in break continue global proc return about abs addAttr addAttributeEditorNodeHelp addDynamic addNewShelfTab addPP addPanelCategory addPrefixToName advanceToNextDrivenKey affectedNet affects aimConstraint air alias aliasAttr align alignCtx alignCurve alignSurface allViewFit ambientLight angle angleBetween animCone animCurveEditor animDisplay animView annotate appendStringArray applicationName applyAttrPreset applyTake arcLenDimContext arcLengthDimension arclen arrayMapper art3dPaintCtx artAttrCtx artAttrPaintVertexCtx artAttrSkinPaintCtx artAttrTool artBuildPaintMenu artFluidAttrCtx artPuttyCtx artSelectCtx artSetPaintCtx artUserPaintCtx assignCommand assignInputDevice assignViewportFactories attachCurve attachDeviceAttr attachSurface attrColorSliderGrp attrCompatibility attrControlGrp attrEnumOptionMenu attrEnumOptionMenuGrp attrFieldGrp attrFieldSliderGrp attrNavigationControlGrp attrPresetEditWin attributeExists attributeInfo attributeMenu attributeQuery autoKeyframe autoPlace bakeClip bakeFluidShading bakePartialHistory bakeResults bakeSimulation basename basenameEx batchRender bessel bevel bevelPlus binMembership bindSkin blend2 blendShape blendShapeEditor blendShapePanel blendTwoAttr blindDataType boneLattice boundary boxDollyCtx boxZoomCtx bufferCurve buildBookmarkMenu buildKeyframeMenu button buttonManip CBG cacheFile cacheFileCombine cacheFileMerge cacheFileTrack camera cameraView canCreateManip canvas capitalizeString catch catchQuiet ceil changeSubdivComponentDisplayLevel changeSubdivRegion channelBox character characterMap characterOutlineEditor characterize chdir checkBox checkBoxGrp checkDefaultRenderGlobals choice circle circularFillet clamp clear clearCache clip clipEditor clipEditorCurrentTimeCtx clipSchedule clipSchedulerOutliner clipTrimBefore closeCurve closeSurface cluster cmdFileOutput cmdScrollFieldExecuter cmdScrollFieldReporter cmdShell coarsenSubdivSelectionList collision color colorAtPoint colorEditor colorIndex colorIndexSliderGrp colorSliderButtonGrp colorSliderGrp columnLayout commandEcho commandLine commandPort compactHairSystem componentEditor compositingInterop computePolysetVolume condition cone confirmDialog connectAttr connectControl connectDynamic connectJoint connectionInfo constrain constrainValue constructionHistory container containsMultibyte contextInfo control convertFromOldLayers convertIffToPsd convertLightmap convertSolidTx convertTessellation convertUnit copyArray copyFlexor copyKey copySkinWeights cos cpButton cpCache cpClothSet cpCollision cpConstraint cpConvClothToMesh cpForces cpGetSolverAttr cpPanel cpProperty cpRigidCollisionFilter cpSeam cpSetEdit cpSetSolverAttr cpSolver cpSolverTypes cpTool cpUpdateClothUVs createDisplayLayer createDrawCtx createEditor createLayeredPsdFile createMotionField createNewShelf createNode createRenderLayer createSubdivRegion cross crossProduct ctxAbort ctxCompletion ctxEditMode ctxTraverse currentCtx currentTime currentTimeCtx currentUnit curve curveAddPtCtx curveCVCtx curveEPCtx curveEditorCtx curveIntersect curveMoveEPCtx curveOnSurface curveSketchCtx cutKey cycleCheck cylinder dagPose date defaultLightListCheckBox defaultNavigation defineDataServer defineVirtualDevice deformer deg_to_rad delete deleteAttr deleteShadingGroupsAndMaterials deleteShelfTab deleteUI deleteUnusedBrushes delrandstr detachCurve detachDeviceAttr detachSurface deviceEditor devicePanel dgInfo dgdirty dgeval dgtimer dimWhen directKeyCtx directionalLight dirmap dirname disable disconnectAttr disconnectJoint diskCache displacementToPoly displayAffected displayColor displayCull displayLevelOfDetail displayPref displayRGBColor displaySmoothness displayStats displayString displaySurface distanceDimContext distanceDimension doBlur dolly dollyCtx dopeSheetEditor dot dotProduct doubleProfileBirailSurface drag dragAttrContext draggerContext dropoffLocator duplicate duplicateCurve duplicateSurface dynCache dynControl dynExport dynExpression dynGlobals dynPaintEditor dynParticleCtx dynPref dynRelEdPanel dynRelEditor dynamicLoad editAttrLimits editDisplayLayerGlobals editDisplayLayerMembers editRenderLayerAdjustment editRenderLayerGlobals editRenderLayerMembers editor editorTemplate effector emit emitter enableDevice encodeString endString endsWith env equivalent equivalentTol erf error eval evalDeferred evalEcho event exactWorldBoundingBox exclusiveLightCheckBox exec executeForEachObject exists exp expression expressionEditorListen extendCurve extendSurface extrude fcheck fclose feof fflush fgetline fgetword file fileBrowserDialog fileDialog fileExtension fileInfo filetest filletCurve filter filterCurve filterExpand filterStudioImport findAllIntersections findAnimCurves findKeyframe findMenuItem findRelatedSkinCluster finder firstParentOf fitBspline flexor floatEq floatField floatFieldGrp floatScrollBar floatSlider floatSlider2 floatSliderButtonGrp floatSliderGrp floor flow fluidCacheInfo fluidEmitter fluidVoxelInfo flushUndo fmod fontDialog fopen formLayout format fprint frameLayout fread freeFormFillet frewind fromNativePath fwrite gamma gauss geometryConstraint getApplicationVersionAsFloat getAttr getClassification getDefaultBrush getFileList getFluidAttr getInputDeviceRange getMayaPanelTypes getModifiers getPanel getParticleAttr getPluginResource getenv getpid glRender glRenderEditor globalStitch gmatch goal gotoBindPose grabColor gradientControl gradientControlNoAttr graphDollyCtx graphSelectContext graphTrackCtx gravity grid gridLayout group groupObjectsByName HfAddAttractorToAS HfAssignAS HfBuildEqualMap HfBuildFurFiles HfBuildFurImages HfCancelAFR HfConnectASToHF HfCreateAttractor HfDeleteAS HfEditAS HfPerformCreateAS HfRemoveAttractorFromAS HfSelectAttached HfSelectAttractors HfUnAssignAS hardenPointCurve hardware hardwareRenderPanel headsUpDisplay headsUpMessage help helpLine hermite hide hilite hitTest hotBox hotkey hotkeyCheck hsv_to_rgb hudButton hudSlider hudSliderButton hwReflectionMap hwRender hwRenderLoad hyperGraph hyperPanel hyperShade hypot iconTextButton iconTextCheckBox iconTextRadioButton iconTextRadioCollection iconTextScrollList iconTextStaticLabel ikHandle ikHandleCtx ikHandleDisplayScale ikSolver ikSplineHandleCtx ikSystem ikSystemInfo ikfkDisplayMethod illustratorCurves image imfPlugins inheritTransform insertJoint insertJointCtx insertKeyCtx insertKnotCurve insertKnotSurface instance instanceable instancer intField intFieldGrp intScrollBar intSlider intSliderGrp interToUI internalVar intersect iprEngine isAnimCurve isConnected isDirty isParentOf isSameObject isTrue isValidObjectName isValidString isValidUiName isolateSelect itemFilter itemFilterAttr itemFilterRender itemFilterType joint jointCluster jointCtx jointDisplayScale jointLattice keyTangent keyframe keyframeOutliner keyframeRegionCurrentTimeCtx keyframeRegionDirectKeyCtx keyframeRegionDollyCtx keyframeRegionInsertKeyCtx keyframeRegionMoveKeyCtx keyframeRegionScaleKeyCtx keyframeRegionSelectKeyCtx keyframeRegionSetKeyCtx keyframeRegionTrackCtx keyframeStats lassoContext lattice latticeDeformKeyCtx launch launchImageEditor layerButton layeredShaderPort layeredTexturePort layout layoutDialog lightList lightListEditor lightListPanel lightlink lineIntersection linearPrecision linstep listAnimatable listAttr listCameras listConnections listDeviceAttachments listHistory listInputDeviceAxes listInputDeviceButtons listInputDevices listMenuAnnotation listNodeTypes listPanelCategories listRelatives listSets listTransforms listUnselected listerEditor loadFluid loadNewShelf loadPlugin loadPluginLanguageResources loadPrefObjects localizedPanelLabel lockNode loft log longNameOf lookThru ls lsThroughFilter lsType lsUI Mayatomr mag makeIdentity makeLive makePaintable makeRoll makeSingleSurface makeTubeOn makebot manipMoveContext manipMoveLimitsCtx manipOptions manipRotateContext manipRotateLimitsCtx manipScaleContext manipScaleLimitsCtx marker match max memory menu menuBarLayout menuEditor menuItem menuItemToShelf menuSet menuSetPref messageLine min minimizeApp mirrorJoint modelCurrentTimeCtx modelEditor modelPanel mouse movIn movOut move moveIKtoFK moveKeyCtx moveVertexAlongDirection multiProfileBirailSurface mute nParticle nameCommand nameField namespace namespaceInfo newPanelItems newton nodeCast nodeIconButton nodeOutliner nodePreset nodeType noise nonLinear normalConstraint normalize nurbsBoolean nurbsCopyUVSet nurbsCube nurbsEditUV nurbsPlane nurbsSelect nurbsSquare nurbsToPoly nurbsToPolygonsPref nurbsToSubdiv nurbsToSubdivPref nurbsUVSet nurbsViewDirectionVector objExists objectCenter objectLayer objectType objectTypeUI obsoleteProc oceanNurbsPreviewPlane offsetCurve offsetCurveOnSurface offsetSurface openGLExtension openMayaPref optionMenu optionMenuGrp optionVar orbit orbitCtx orientConstraint outlinerEditor outlinerPanel overrideModifier paintEffectsDisplay pairBlend palettePort paneLayout panel panelConfiguration panelHistory paramDimContext paramDimension paramLocator parent parentConstraint particle particleExists particleInstancer particleRenderInfo partition pasteKey pathAnimation pause pclose percent performanceOptions pfxstrokes pickWalk picture pixelMove planarSrf plane play playbackOptions playblast plugAttr plugNode pluginInfo pluginResourceUtil pointConstraint pointCurveConstraint pointLight pointMatrixMult pointOnCurve pointOnSurface pointPosition poleVectorConstraint polyAppend polyAppendFacetCtx polyAppendVertex polyAutoProjection polyAverageNormal polyAverageVertex polyBevel polyBlendColor polyBlindData polyBoolOp polyBridgeEdge polyCacheMonitor polyCheck polyChipOff polyClipboard polyCloseBorder polyCollapseEdge polyCollapseFacet polyColorBlindData polyColorDel polyColorPerVertex polyColorSet polyCompare polyCone polyCopyUV polyCrease polyCreaseCtx polyCreateFacet polyCreateFacetCtx polyCube polyCut polyCutCtx polyCylinder polyCylindricalProjection polyDelEdge polyDelFacet polyDelVertex polyDuplicateAndConnect polyDuplicateEdge polyEditUV polyEditUVShell polyEvaluate polyExtrudeEdge polyExtrudeFacet polyExtrudeVertex polyFlipEdge polyFlipUV polyForceUV polyGeoSampler polyHelix polyInfo polyInstallAction polyLayoutUV polyListComponentConversion polyMapCut polyMapDel polyMapSew polyMapSewMove polyMergeEdge polyMergeEdgeCtx polyMergeFacet polyMergeFacetCtx polyMergeUV polyMergeVertex polyMirrorFace polyMoveEdge polyMoveFacet polyMoveFacetUV polyMoveUV polyMoveVertex polyNormal polyNormalPerVertex polyNormalizeUV polyOptUvs polyOptions polyOutput polyPipe polyPlanarProjection polyPlane polyPlatonicSolid polyPoke polyPrimitive polyPrism polyProjection polyPyramid polyQuad polyQueryBlindData polyReduce polySelect polySelectConstraint polySelectConstraintMonitor polySelectCtx polySelectEditCtx polySeparate polySetToFaceNormal polySewEdge polyShortestPathCtx polySmooth polySoftEdge polySphere polySphericalProjection polySplit polySplitCtx polySplitEdge polySplitRing polySplitVertex polyStraightenUVBorder polySubdivideEdge polySubdivideFacet polyToSubdiv polyTorus polyTransfer polyTriangulate polyUVSet polyUnite polyWedgeFace popen popupMenu pose pow preloadRefEd print progressBar progressWindow projFileViewer projectCurve projectTangent projectionContext projectionManip promptDialog propModCtx propMove psdChannelOutliner psdEditTextureFile psdExport psdTextureFile putenv pwd python querySubdiv quit rad_to_deg radial radioButton radioButtonGrp radioCollection radioMenuItemCollection rampColorPort rand randomizeFollicles randstate rangeControl readTake rebuildCurve rebuildSurface recordAttr recordDevice redo reference referenceEdit referenceQuery refineSubdivSelectionList refresh refreshAE registerPluginResource rehash reloadImage removeJoint removeMultiInstance removePanelCategory rename renameAttr renameSelectionList renameUI render renderGlobalsNode renderInfo renderLayerButton renderLayerParent renderLayerPostProcess renderLayerUnparent renderManip renderPartition renderQualityNode renderSettings renderThumbnailUpdate renderWindowEditor renderWindowSelectContext renderer reorder reorderDeformers requires reroot resampleFluid resetAE resetPfxToPolyCamera resetTool resolutionNode retarget reverseCurve reverseSurface revolve rgb_to_hsv rigidBody rigidSolver roll rollCtx rootOf rot rotate rotationInterpolation roundConstantRadius rowColumnLayout rowLayout runTimeCommand runup sampleImage saveAllShelves saveAttrPreset saveFluid saveImage saveInitialState saveMenu savePrefObjects savePrefs saveShelf saveToolSettings scale scaleBrushBrightness scaleComponents scaleConstraint scaleKey scaleKeyCtx sceneEditor sceneUIReplacement scmh scriptCtx scriptEditorInfo scriptJob scriptNode scriptTable scriptToShelf scriptedPanel scriptedPanelType scrollField scrollLayout sculpt searchPathArray seed selLoadSettings select selectContext selectCurveCV selectKey selectKeyCtx selectKeyframeRegionCtx selectMode selectPref selectPriority selectType selectedNodes selectionConnection separator setAttr setAttrEnumResource setAttrMapping setAttrNiceNameResource setConstraintRestPosition setDefaultShadingGroup setDrivenKeyframe setDynamic setEditCtx setEditor setFluidAttr setFocus setInfinity setInputDeviceMapping setKeyCtx setKeyPath setKeyframe setKeyframeBlendshapeTargetWts setMenuMode setNodeNiceNameResource setNodeTypeFlag setParent setParticleAttr setPfxToPolyCamera setPluginResource setProject setStampDensity setStartupMessage setState setToolTo setUITemplate setXformManip sets shadingConnection shadingGeometryRelCtx shadingLightRelCtx shadingNetworkCompare shadingNode shapeCompare shelfButton shelfLayout shelfTabLayout shellField shortNameOf showHelp showHidden showManipCtx showSelectionInTitle showShadingGroupAttrEditor showWindow sign simplify sin singleProfileBirailSurface size sizeBytes skinCluster skinPercent smoothCurve smoothTangentSurface smoothstep snap2to2 snapKey snapMode snapTogetherCtx snapshot soft softMod softModCtx sort sound soundControl source spaceLocator sphere sphrand spotLight spotLightPreviewPort spreadSheetEditor spring sqrt squareSurface srtContext stackTrace startString startsWith stitchAndExplodeShell stitchSurface stitchSurfacePoints strcmp stringArrayCatenate stringArrayContains stringArrayCount stringArrayInsertAtIndex stringArrayIntersector stringArrayRemove stringArrayRemoveAtIndex stringArrayRemoveDuplicates stringArrayRemoveExact stringArrayToString stringToStringArray strip stripPrefixFromName stroke subdAutoProjection subdCleanTopology subdCollapse subdDuplicateAndConnect subdEditUV subdListComponentConversion subdMapCut subdMapSewMove subdMatchTopology subdMirror subdToBlind subdToPoly subdTransferUVsToCache subdiv subdivCrease subdivDisplaySmoothness substitute substituteAllString substituteGeometry substring surface surfaceSampler surfaceShaderList swatchDisplayPort switchTable symbolButton symbolCheckBox sysFile system tabLayout tan tangentConstraint texLatticeDeformContext texManipContext texMoveContext texMoveUVShellContext texRotateContext texScaleContext texSelectContext texSelectShortestPathCtx texSmudgeUVContext texWinToolCtx text textCurves textField textFieldButtonGrp textFieldGrp textManip textScrollList textToShelf textureDisplacePlane textureHairColor texturePlacementContext textureWindow threadCount threePointArcCtx timeControl timePort timerX toNativePath toggle toggleAxis toggleWindowVisibility tokenize tokenizeList tolerance tolower toolButton toolCollection toolDropped toolHasOptions toolPropertyWindow torus toupper trace track trackCtx transferAttributes transformCompare transformLimits translator trim trunc truncateFluidCache truncateHairCache tumble tumbleCtx turbulence twoPointArcCtx uiRes uiTemplate unassignInputDevice undo undoInfo ungroup uniform unit unloadPlugin untangleUV untitledFileName untrim upAxis updateAE userCtx uvLink uvSnapshot validateShelfName vectorize view2dToolCtx viewCamera viewClipPlane viewFit viewHeadOn viewLookAt viewManip viewPlace viewSet visor volumeAxis vortex waitCursor warning webBrowser webBrowserPrefs whatIs window windowPref wire wireContext workspace wrinkle wrinkleContext writeTake xbmLangPathList xform",i:")?(\\[\\])?";return{aliases:["csharp"],k:i,i:/::/,c:[e.C("///","$",{rB:!0,c:[{cN:"doctag",v:[{b:"///",r:0},{b:""},{b:""}]}]}),e.CLCM,e.CBCM,{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},l,e.CNM,{bK:"class interface",e:/[{;=]/,i:/[^\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"namespace",e:/[{;=]/,i:/[^\s:]/,c:[e.inherit(e.TM,{b:"[a-zA-Z](\\.?\\w)*"}),e.CLCM,e.CBCM]},{bK:"new return throw await",r:0},{cN:"function",b:"("+b+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:i,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:i,r:0,c:[l,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage("julia",function(e){var r={keyword:"in abstract baremodule begin bitstype break catch ccall const continue do else elseif end export finally for function global if immutable import importall let local macro module quote return try type typealias using while",literal:"true false ARGS CPU_CORES C_NULL DL_LOAD_PATH DevNull ENDIAN_BOM ENV I|0 Inf Inf16 Inf32 InsertionSort JULIA_HOME LOAD_PATH MS_ASYNC MS_INVALIDATE MS_SYNC MergeSort NaN NaN16 NaN32 OS_NAME QuickSort RTLD_DEEPBIND RTLD_FIRST RTLD_GLOBAL RTLD_LAZY RTLD_LOCAL RTLD_NODELETE RTLD_NOLOAD RTLD_NOW RoundDown RoundFromZero RoundNearest RoundToZero RoundUp STDERR STDIN STDOUT VERSION WORD_SIZE catalan cglobal e|0 eu|0 eulergamma golden im nothing pi γ π φ Inf64 NaN64 RoundNearestTiesAway RoundNearestTiesUp ",built_in:"ANY ASCIIString AbstractArray AbstractRNG AbstractSparseArray Any ArgumentError Array Associative Base64Pipe Bidiagonal BigFloat BigInt BitArray BitMatrix BitVector Bool BoundsError Box CFILE Cchar Cdouble Cfloat Char CharString Cint Clong Clonglong ClusterManager Cmd Coff_t Colon Complex Complex128 Complex32 Complex64 Condition Cptrdiff_t Cshort Csize_t Cssize_t Cuchar Cuint Culong Culonglong Cushort Cwchar_t DArray DataType DenseArray Diagonal Dict DimensionMismatch DirectIndexString Display DivideError DomainError EOFError EachLine Enumerate ErrorException Exception Expr Factorization FileMonitor FileOffset Filter Float16 Float32 Float64 FloatRange FloatingPoint Function GetfieldNode GotoNode Hermitian IO IOBuffer IOStream IPv4 IPv6 InexactError Int Int128 Int16 Int32 Int64 Int8 IntSet Integer InterruptException IntrinsicFunction KeyError LabelNode LambdaStaticData LineNumberNode LoadError LocalProcess MIME MathConst MemoryError MersenneTwister Method MethodError MethodTable Module NTuple NewvarNode Nothing Number ObjectIdDict OrdinalRange OverflowError ParseError PollingFileWatcher ProcessExitedException ProcessGroup Ptr QuoteNode Range Range1 Ranges Rational RawFD Real Regex RegexMatch RemoteRef RepString RevString RopeString RoundingMode Set SharedArray Signed SparseMatrixCSC StackOverflowError Stat StatStruct StepRange String SubArray SubString SymTridiagonal Symbol SymbolNode Symmetric SystemError Task TextDisplay Timer TmStruct TopNode Triangular Tridiagonal Type TypeConstructor TypeError TypeName TypeVar UTF16String UTF32String UTF8String UdpSocket Uint Uint128 Uint16 Uint32 Uint64 Uint8 UndefRefError UndefVarError UniformScaling UnionType UnitRange Unsigned Vararg VersionNumber WString WeakKeyDict WeakRef Woodbury Zip AbstractChannel AbstractFloat AbstractString AssertionError Base64DecodePipe Base64EncodePipe BufferStream CapturedException CartesianIndex CartesianRange Channel Cintmax_t CompositeException Cstring Cuintmax_t Cwstring Date DateTime Dims Enum GenSym GlobalRef HTML InitError InvalidStateException Irrational LinSpace LowerTriangular NullException Nullable OutOfMemoryError Pair PartialQuickSort Pipe RandomDevice ReadOnlyMemoryError ReentrantLock Ref RemoteException SegmentationFault SerializationState SimpleVector TCPSocket Text Tuple UDPSocket UInt UInt128 UInt16 UInt32 UInt64 UInt8 UnicodeError Union UpperTriangular Val Void WorkerConfig AbstractMatrix AbstractSparseMatrix AbstractSparseVector AbstractVecOrMat AbstractVector DenseMatrix DenseVecOrMat DenseVector Matrix SharedMatrix SharedVector StridedArray StridedMatrix StridedVecOrMat StridedVector VecOrMat Vector "},t="[A-Za-z_\\u00A1-\\uFFFF][A-Za-z_0-9\\u00A1-\\uFFFF]*",a={l:t,k:r,i:/<\//},n={cN:"type",b:/::/},o={cN:"type",b:/<:/},i={cN:"number",b:/(\b0x[\d_]*(\.[\d_]*)?|0x\.\d[\d_]*)p[-+]?\d+|\b0[box][a-fA-F0-9][a-fA-F0-9_]*|(\b\d[\d_]*(\.[\d_]*)?|\.\d[\d_]*)([eEfF][-+]?\d+)?/,r:0},l={cN:"string",b:/'(.|\\[xXuU][a-zA-Z0-9]+)'/},c={cN:"subst",b:/\$\(/,e:/\)/,k:r},s={cN:"variable",b:"\\$"+t},d={cN:"string",c:[e.BE,c,s],v:[{b:/\w*"""/,e:/"""\w*/,r:10},{b:/\w*"/,e:/"\w*/}]},S={cN:"string",c:[e.BE,c,s],b:"`",e:"`"},u={cN:"meta",b:"@"+t},g={cN:"comment",v:[{b:"#=",e:"=#",r:10},{b:"#",e:"$"}]};return a.c=[i,l,n,o,d,S,u,g,e.HCM],c.c=a.c,a});hljs.registerLanguage("golo",function(e){return{k:{keyword:"println readln print import module function local return let var while for foreach times in case when match with break continue augment augmentation each find filter reduce if then else otherwise try catch finally raise throw orIfNull DynamicObject|10 DynamicVariable struct Observable map set vector list array",literal:"true false null"},c:[e.HCM,e.QSM,e.CNM,{cN:"meta",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("vim",function(e){return{l:/[!#@\w]+/,k:{keyword:"N|0 P|0 X|0 a|0 ab abc abo al am an|0 ar arga argd arge argdo argg argl argu as au aug aun b|0 bN ba bad bd be bel bf bl bm bn bo bp br brea breaka breakd breakl bro bufdo buffers bun bw c|0 cN cNf ca cabc caddb cad caddf cal cat cb cc ccl cd ce cex cf cfir cgetb cgete cg changes chd che checkt cl cla clo cm cmapc cme cn cnew cnf cno cnorea cnoreme co col colo com comc comp con conf cope cp cpf cq cr cs cst cu cuna cunme cw delm deb debugg delc delf dif diffg diffo diffp diffpu diffs diffthis dig di dl dell dj dli do doautoa dp dr ds dsp e|0 ea ec echoe echoh echom echon el elsei em en endfo endf endt endw ene ex exe exi exu f|0 files filet fin fina fini fir fix fo foldc foldd folddoc foldo for fu go gr grepa gu gv ha helpf helpg helpt hi hid his ia iabc if ij il im imapc ime ino inorea inoreme int is isp iu iuna iunme j|0 ju k|0 keepa kee keepj lN lNf l|0 lad laddb laddf la lan lat lb lc lch lcl lcs le lefta let lex lf lfir lgetb lgete lg lgr lgrepa lh ll lla lli lmak lm lmapc lne lnew lnf ln loadk lo loc lockv lol lope lp lpf lr ls lt lu lua luad luaf lv lvimgrepa lw m|0 ma mak map mapc marks mat me menut mes mk mks mksp mkv mkvie mod mz mzf nbc nb nbs new nm nmapc nme nn nnoreme noa no noh norea noreme norm nu nun nunme ol o|0 om omapc ome on ono onoreme opt ou ounme ow p|0 profd prof pro promptr pc ped pe perld po popu pp pre prev ps pt ptN ptf ptj ptl ptn ptp ptr pts pu pw py3 python3 py3d py3f py pyd pyf quita qa rec red redi redr redraws reg res ret retu rew ri rightb rub rubyd rubyf rund ru rv sN san sa sal sav sb sbN sba sbf sbl sbm sbn sbp sbr scrip scripte scs se setf setg setl sf sfir sh sim sig sil sl sla sm smap smapc sme sn sni sno snor snoreme sor so spelld spe spelli spellr spellu spellw sp spr sre st sta startg startr star stopi stj sts sun sunm sunme sus sv sw sy synti sync tN tabN tabc tabdo tabe tabf tabfir tabl tabm tabnew tabn tabo tabp tabr tabs tab ta tags tc tcld tclf te tf th tj tl tm tn to tp tr try ts tu u|0 undoj undol una unh unl unlo unm unme uns up ve verb vert vim vimgrepa vi viu vie vm vmapc vme vne vn vnoreme vs vu vunme windo w|0 wN wa wh wi winc winp wn wp wq wqa ws wu wv x|0 xa xmapc xm xme xn xnoreme xu xunme y|0 z|0 ~ Next Print append abbreviate abclear aboveleft all amenu anoremenu args argadd argdelete argedit argglobal arglocal argument ascii autocmd augroup aunmenu buffer bNext ball badd bdelete behave belowright bfirst blast bmodified bnext botright bprevious brewind break breakadd breakdel breaklist browse bunload bwipeout change cNext cNfile cabbrev cabclear caddbuffer caddexpr caddfile call catch cbuffer cclose center cexpr cfile cfirst cgetbuffer cgetexpr cgetfile chdir checkpath checktime clist clast close cmap cmapclear cmenu cnext cnewer cnfile cnoremap cnoreabbrev cnoremenu copy colder colorscheme command comclear compiler continue confirm copen cprevious cpfile cquit crewind cscope cstag cunmap cunabbrev cunmenu cwindow delete delmarks debug debuggreedy delcommand delfunction diffupdate diffget diffoff diffpatch diffput diffsplit digraphs display deletel djump dlist doautocmd doautoall deletep drop dsearch dsplit edit earlier echo echoerr echohl echomsg else elseif emenu endif endfor endfunction endtry endwhile enew execute exit exusage file filetype find finally finish first fixdel fold foldclose folddoopen folddoclosed foldopen function global goto grep grepadd gui gvim hardcopy help helpfind helpgrep helptags highlight hide history insert iabbrev iabclear ijump ilist imap imapclear imenu inoremap inoreabbrev inoremenu intro isearch isplit iunmap iunabbrev iunmenu join jumps keepalt keepmarks keepjumps lNext lNfile list laddexpr laddbuffer laddfile last language later lbuffer lcd lchdir lclose lcscope left leftabove lexpr lfile lfirst lgetbuffer lgetexpr lgetfile lgrep lgrepadd lhelpgrep llast llist lmake lmap lmapclear lnext lnewer lnfile lnoremap loadkeymap loadview lockmarks lockvar lolder lopen lprevious lpfile lrewind ltag lunmap luado luafile lvimgrep lvimgrepadd lwindow move mark make mapclear match menu menutranslate messages mkexrc mksession mkspell mkvimrc mkview mode mzscheme mzfile nbclose nbkey nbsart next nmap nmapclear nmenu nnoremap nnoremenu noautocmd noremap nohlsearch noreabbrev noremenu normal number nunmap nunmenu oldfiles open omap omapclear omenu only onoremap onoremenu options ounmap ounmenu ownsyntax print profdel profile promptfind promptrepl pclose pedit perl perldo pop popup ppop preserve previous psearch ptag ptNext ptfirst ptjump ptlast ptnext ptprevious ptrewind ptselect put pwd py3do py3file python pydo pyfile quit quitall qall read recover redo redir redraw redrawstatus registers resize retab return rewind right rightbelow ruby rubydo rubyfile rundo runtime rviminfo substitute sNext sandbox sargument sall saveas sbuffer sbNext sball sbfirst sblast sbmodified sbnext sbprevious sbrewind scriptnames scriptencoding scscope set setfiletype setglobal setlocal sfind sfirst shell simalt sign silent sleep slast smagic smapclear smenu snext sniff snomagic snoremap snoremenu sort source spelldump spellgood spellinfo spellrepall spellundo spellwrong split sprevious srewind stop stag startgreplace startreplace startinsert stopinsert stjump stselect sunhide sunmap sunmenu suspend sview swapname syntax syntime syncbind tNext tabNext tabclose tabedit tabfind tabfirst tablast tabmove tabnext tabonly tabprevious tabrewind tag tcl tcldo tclfile tearoff tfirst throw tjump tlast tmenu tnext topleft tprevious trewind tselect tunmenu undo undojoin undolist unabbreviate unhide unlet unlockvar unmap unmenu unsilent update vglobal version verbose vertical vimgrep vimgrepadd visual viusage view vmap vmapclear vmenu vnew vnoremap vnoremenu vsplit vunmap vunmenu write wNext wall while winsize wincmd winpos wnext wprevious wqall wsverb wundo wviminfo xit xall xmapclear xmap xmenu xnoremap xnoremenu xunmap xunmenu yank",built_in:"synIDtrans atan2 range matcharg did_filetype asin feedkeys xor argv complete_check add getwinposx getqflist getwinposy screencol clearmatches empty extend getcmdpos mzeval garbagecollect setreg ceil sqrt diff_hlID inputsecret get getfperm getpid filewritable shiftwidth max sinh isdirectory synID system inputrestore winline atan visualmode inputlist tabpagewinnr round getregtype mapcheck hasmapto histdel argidx findfile sha256 exists toupper getcmdline taglist string getmatches bufnr strftime winwidth bufexists strtrans tabpagebuflist setcmdpos remote_read printf setloclist getpos getline bufwinnr float2nr len getcmdtype diff_filler luaeval resolve libcallnr foldclosedend reverse filter has_key bufname str2float strlen setline getcharmod setbufvar index searchpos shellescape undofile foldclosed setqflist buflisted strchars str2nr virtcol floor remove undotree remote_expr winheight gettabwinvar reltime cursor tabpagenr finddir localtime acos getloclist search tanh matchend rename gettabvar strdisplaywidth type abs py3eval setwinvar tolower wildmenumode log10 spellsuggest bufloaded synconcealed nextnonblank server2client complete settabwinvar executable input wincol setmatches getftype hlID inputsave searchpair or screenrow line settabvar histadd deepcopy strpart remote_peek and eval getftime submatch screenchar winsaveview matchadd mkdir screenattr getfontname libcall reltimestr getfsize winnr invert pow getbufline byte2line soundfold repeat fnameescape tagfiles sin strwidth spellbadword trunc maparg log lispindent hostname setpos globpath remote_foreground getchar synIDattr fnamemodify cscope_connection stridx winbufnr indent min complete_add nr2char searchpairpos inputdialog values matchlist items hlexists strridx browsedir expand fmod pathshorten line2byte argc count getwinvar glob foldtextresult getreg foreground cosh matchdelete has char2nr simplify histget searchdecl iconv winrestcmd pumvisible writefile foldlevel haslocaldir keys cos matchstr foldtext histnr tan tempname getcwd byteidx getbufvar islocked escape eventhandler remote_send serverlist winrestview synstack pyeval prevnonblank readfile cindent filereadable changenr exp"},i:/;/,c:[e.NM,e.ASM,{cN:"string",b:/"(\\"|\n\\|[^"\n])*"/},e.C('"',"$"),{cN:"variable",b:/[bwtglsav]:[\w\d_]*/},{cN:"function",bK:"function function!",e:"$",r:0,c:[e.TM,{cN:"params",b:"\\(",e:"\\)"}]},{cN:"symbol",b:/<[\w-]+>/}]}});hljs.registerLanguage("perl",function(e){var t="getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when",r={cN:"subst",b:"[$@]\\{",e:"\\}",k:t},s={b:"->{",e:"}"},n={v:[{b:/\$\d/},{b:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{b:/[\$%@][^\s\w{]/,r:0}]},i=[e.BE,r,n],o=[n,e.HCM,e.C("^\\=\\w","\\=cut",{eW:!0}),s,{cN:"string",c:i,v:[{b:"q[qwxr]?\\s*\\(",e:"\\)",r:5},{b:"q[qwxr]?\\s*\\[",e:"\\]",r:5},{b:"q[qwxr]?\\s*\\{",e:"\\}",r:5},{b:"q[qwxr]?\\s*\\|",e:"\\|",r:5},{b:"q[qwxr]?\\s*\\<",e:"\\>",r:5},{b:"qw\\s+q",e:"q",r:5},{b:"'",e:"'",c:[e.BE]},{b:'"',e:'"'},{b:"`",e:"`",c:[e.BE]},{b:"{\\w+}",c:[],r:0},{b:"-?\\w+\\s*\\=\\>",c:[],r:0}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\/\\/|"+e.RSR+"|\\b(split|return|print|reverse|grep)\\b)\\s*",k:"split return print reverse grep",r:0,c:[e.HCM,{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[e.BE],r:0}]},{cN:"function",bK:"sub",e:"(\\s*\\(.*?\\))?[;{]",eE:!0,r:5,c:[e.TM]},{b:"-\\w\\b",r:0},{b:"^__DATA__$",e:"^__END__$",sL:"mojolicious",c:[{b:"^@@.*",e:"$",cN:"comment"}]}];return r.c=o,s.c=o,{aliases:["pl","pm"],l:/[\w\.]+/,k:t,c:o}});hljs.registerLanguage("ruby",function(e){var b="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",r={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},c={cN:"doctag",b:"@[A-Za-z]+"},a={b:"#<",e:">"},s=[e.C("#","$",{c:[c]}),e.C("^\\=begin","^\\=end",{c:[c],r:10}),e.C("^__END__","\\n$")],n={cN:"subst",b:"#\\{",e:"}",k:r},t={cN:"string",c:[e.BE,n],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%[qQwWx]?\\(",e:"\\)"},{b:"%[qQwWx]?\\[",e:"\\]"},{b:"%[qQwWx]?{",e:"}"},{b:"%[qQwWx]?<",e:">"},{b:"%[qQwWx]?/",e:"/"},{b:"%[qQwWx]?%",e:"%"},{b:"%[qQwWx]?-",e:"-"},{b:"%[qQwWx]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{b:/<<(-?)\w+$/,e:/^\s*\w+$/}]},i={cN:"params",b:"\\(",e:"\\)",endsParent:!0,k:r},d=[t,a,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{b:"<\\s*",c:[{b:"("+e.IR+"::)?"+e.IR}]}].concat(s)},{cN:"function",bK:"def",e:"$|;",c:[e.inherit(e.TM,{b:b}),i].concat(s)},{b:e.IR+"::"},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":(?!\\s)",c:[t,{b:b}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{cN:"params",b:/\|/,e:/\|/,k:r},{b:"("+e.RSR+"|unless)\\s*",c:[a,{cN:"regexp",c:[e.BE,n],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}].concat(s),r:0}].concat(s);n.c=d,i.c=d;var l="[>?]>",o="[\\w#]+\\(\\w+\\):\\d+:\\d+>",u="(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>",w=[{b:/^\s*=>/,starts:{e:"$",c:d}},{cN:"meta",b:"^("+l+"|"+o+"|"+u+")",starts:{e:"$",c:d}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:r,i:/\/\*/,c:s.concat(w).concat(d)}});hljs.registerLanguage("yaml",function(e){var b="true false yes no null",a="^[ \\-]*",r="[a-zA-Z_][\\w\\-]*",t={cN:"attr",v:[{b:a+r+":"},{b:a+'"'+r+'":'},{b:a+"'"+r+"':"}]},c={cN:"template-variable",v:[{b:"{{",e:"}}"},{b:"%{",e:"}"}]},l={cN:"string",r:0,v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/\S+/}],c:[e.BE,c]};return{cI:!0,aliases:["yml","YAML","yaml"],c:[t,{cN:"meta",b:"^---s*$",r:10},{cN:"string",b:"[\\|>] *$",rE:!0,c:l.c,e:t.v[0].b},{b:"<%[%=-]?",e:"[%-]?%>",sL:"ruby",eB:!0,eE:!0,r:0},{cN:"type",b:"!!"+e.UIR},{cN:"meta",b:"&"+e.UIR+"$"},{cN:"meta",b:"\\*"+e.UIR+"$"},{cN:"bullet",b:"^ *-",r:0},e.HCM,{bK:b,k:{literal:b}},e.CNM,l]}});hljs.registerLanguage("bnf",function(e){return{c:[{cN:"attribute",b://},{b:/::=/,starts:{e:/$/,c:[{b://},e.CLCM,e.CBCM,e.ASM,e.QSM]}}]}});hljs.registerLanguage("applescript",function(e){var t=e.inherit(e.QSM,{i:""}),r={cN:"params",b:"\\(",e:"\\)",c:["self",e.CNM,t]},i=e.C("--","$"),o=e.C("\\(\\*","\\*\\)",{c:["self",i]}),n=[i,o,e.HCM];return{aliases:["osascript"],k:{keyword:"about above after against and around as at back before beginning behind below beneath beside between but by considering contain contains continue copy div does eighth else end equal equals error every exit fifth first for fourth from front get given global if ignoring in into is it its last local me middle mod my ninth not of on onto or over prop property put ref reference repeat returning script second set seventh since sixth some tell tenth that the|0 then third through thru timeout times to transaction try until where while whose with without",literal:"AppleScript false linefeed return pi quote result space tab true",built_in:"alias application boolean class constant date file integer list number real record string text activate beep count delay launch log offset read round run say summarize write character characters contents day frontmost id item length month name paragraph paragraphs rest reverse running time version weekday word words year"},c:[t,e.CNM,{cN:"built_in",b:"\\b(clipboard info|the clipboard|info for|list (disks|folder)|mount volume|path to|(close|open for) access|(get|set) eof|current date|do shell script|get volume settings|random number|set volume|system attribute|system info|time to GMT|(load|run|store) script|scripting components|ASCII (character|number)|localized string|choose (application|color|file|file name|folder|from list|remote application|URL)|display (alert|dialog))\\b|^\\s*return\\b"},{cN:"literal",b:"\\b(text item delimiters|current application|missing value)\\b"},{cN:"keyword",b:"\\b(apart from|aside from|instead of|out of|greater than|isn't|(doesn't|does not) (equal|come before|come after|contain)|(greater|less) than( or equal)?|(starts?|ends|begins?) with|contained by|comes (before|after)|a (ref|reference)|POSIX file|POSIX path|(date|time) string|quoted form)\\b"},{bK:"on",i:"[${=;\\n]",c:[e.UTM,r]}].concat(n),i:"//|->|=>|\\[\\["}});hljs.registerLanguage("vhdl",function(e){var r="\\d(_|\\d)*",t="[eE][-+]?"+r,n=r+"(\\."+r+")?("+t+")?",o="\\w+",i=r+"#"+o+"(\\."+o+")?#("+t+")?",a="\\b("+i+"|"+n+")";return{cI:!0,k:{keyword:"abs access after alias all and architecture array assert assume assume_guarantee attribute begin block body buffer bus case component configuration constant context cover disconnect downto default else elsif end entity exit fairness file for force function generate generic group guarded if impure in inertial inout is label library linkage literal loop map mod nand new next nor not null of on open or others out package port postponed procedure process property protected pure range record register reject release rem report restrict restrict_guarantee return rol ror select sequence severity shared signal sla sll sra srl strong subtype then to transport type unaffected units until use variable vmode vprop vunit wait when while with xnor xor",built_in:"boolean bit character integer time delay_length natural positive string bit_vector file_open_kind file_open_status std_logic std_logic_vector unsigned signed boolean_vector integer_vector std_ulogic std_ulogic_vector unresolved_unsigned u_unsigned unresolved_signed u_signedreal_vector time_vector",literal:"false true note warning error failure line text side width"},i:"{",c:[e.CBCM,e.C("--","$"),e.QSM,{cN:"number",b:a,r:0},{cN:"string",b:"'(U|X|0|1|Z|W|L|H|-)'",c:[e.BE]},{cN:"symbol",b:"'[A-Za-z](_?[A-Za-z0-9])*",c:[e.BE]}]}});hljs.registerLanguage("lisp",function(b){var e="[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*",c="\\|[^]*?\\|",r="(\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\+|\\-)?\\d+)?",a={cN:"meta",b:"^#!",e:"$"},l={cN:"literal",b:"\\b(t{1}|nil)\\b"},n={cN:"number",v:[{b:r,r:0},{b:"#(b|B)[0-1]+(/[0-1]+)?"},{b:"#(o|O)[0-7]+(/[0-7]+)?"},{b:"#(x|X)[0-9a-fA-F]+(/[0-9a-fA-F]+)?"},{b:"#(c|C)\\("+r+" +"+r,e:"\\)"}]},i=b.inherit(b.QSM,{i:null}),t=b.C(";","$",{r:0}),s={b:"\\*",e:"\\*"},u={cN:"symbol",b:"[:&]"+e},d={b:e,r:0},f={b:c},m={b:"\\(",e:"\\)",c:["self",l,i,n,d]},o={c:[n,i,s,u,m,d],v:[{b:"['`]\\(",e:"\\)"},{b:"\\(quote ",e:"\\)",k:{name:"quote"}},{b:"'"+c}]},v={v:[{b:"'"+e},{b:"#'"+e+"(::"+e+")*"}]},N={b:"\\(\\s*",e:"\\)"},A={eW:!0,r:0};return N.c=[{cN:"name",v:[{b:e},{b:c}]},A],A.c=[o,v,N,l,n,i,t,s,u,f,d],{i:/\S/,c:[n,a,l,i,t,o,v,N,d]}});hljs.registerLanguage("mathematica",function(e){return{aliases:["mma"],l:"(\\$|\\b)"+e.IR+"\\b",k:"AbelianGroup Abort AbortKernels AbortProtect Above Abs Absolute AbsoluteCorrelation AbsoluteCorrelationFunction AbsoluteCurrentValue AbsoluteDashing AbsoluteFileName AbsoluteOptions AbsolutePointSize AbsoluteThickness AbsoluteTime AbsoluteTiming AccountingForm Accumulate Accuracy AccuracyGoal ActionDelay ActionMenu ActionMenuBox ActionMenuBoxOptions Active ActiveItem ActiveStyle AcyclicGraphQ AddOnHelpPath AddTo AdjacencyGraph AdjacencyList AdjacencyMatrix AdjustmentBox AdjustmentBoxOptions AdjustTimeSeriesForecast AffineTransform After AiryAi AiryAiPrime AiryAiZero AiryBi AiryBiPrime AiryBiZero AlgebraicIntegerQ AlgebraicNumber AlgebraicNumberDenominator AlgebraicNumberNorm AlgebraicNumberPolynomial AlgebraicNumberTrace AlgebraicRules AlgebraicRulesData Algebraics AlgebraicUnitQ Alignment AlignmentMarker AlignmentPoint All AllowedDimensions AllowGroupClose AllowInlineCells AllowKernelInitialization AllowReverseGroupClose AllowScriptLevelChange AlphaChannel AlternatingGroup AlternativeHypothesis Alternatives AmbientLight Analytic AnchoredSearch And AndersonDarlingTest AngerJ AngleBracket AngularGauge Animate AnimationCycleOffset AnimationCycleRepetitions AnimationDirection AnimationDisplayTime AnimationRate AnimationRepetitions AnimationRunning Animator AnimatorBox AnimatorBoxOptions AnimatorElements Annotation Annuity AnnuityDue Antialiasing Antisymmetric Apart ApartSquareFree Appearance AppearanceElements AppellF1 Append AppendTo Apply ArcCos ArcCosh ArcCot ArcCoth ArcCsc ArcCsch ArcSec ArcSech ArcSin ArcSinDistribution ArcSinh ArcTan ArcTanh Arg ArgMax ArgMin ArgumentCountQ ARIMAProcess ArithmeticGeometricMean ARMAProcess ARProcess Array ArrayComponents ArrayDepth ArrayFlatten ArrayPad ArrayPlot ArrayQ ArrayReshape ArrayRules Arrays Arrow Arrow3DBox ArrowBox Arrowheads AspectRatio AspectRatioFixed Assert Assuming Assumptions AstronomicalData Asynchronous AsynchronousTaskObject AsynchronousTasks AtomQ Attributes AugmentedSymmetricPolynomial AutoAction AutoDelete AutoEvaluateEvents AutoGeneratedPackage AutoIndent AutoIndentSpacings AutoItalicWords AutoloadPath AutoMatch Automatic AutomaticImageSize AutoMultiplicationSymbol AutoNumberFormatting AutoOpenNotebooks AutoOpenPalettes AutorunSequencing AutoScaling AutoScroll AutoSpacing AutoStyleOptions AutoStyleWords Axes AxesEdge AxesLabel AxesOrigin AxesStyle Axis BabyMonsterGroupB Back Background BackgroundTasksSettings Backslash Backsubstitution Backward Band BandpassFilter BandstopFilter BarabasiAlbertGraphDistribution BarChart BarChart3D BarLegend BarlowProschanImportance BarnesG BarOrigin BarSpacing BartlettHannWindow BartlettWindow BaseForm Baseline BaselinePosition BaseStyle BatesDistribution BattleLemarieWavelet Because BeckmannDistribution Beep Before Begin BeginDialogPacket BeginFrontEndInteractionPacket BeginPackage BellB BellY Below BenfordDistribution BeniniDistribution BenktanderGibratDistribution BenktanderWeibullDistribution BernoulliB BernoulliDistribution BernoulliGraphDistribution BernoulliProcess BernsteinBasis BesselFilterModel BesselI BesselJ BesselJZero BesselK BesselY BesselYZero Beta BetaBinomialDistribution BetaDistribution BetaNegativeBinomialDistribution BetaPrimeDistribution BetaRegularized BetweennessCentrality BezierCurve BezierCurve3DBox BezierCurve3DBoxOptions BezierCurveBox BezierCurveBoxOptions BezierFunction BilateralFilter Binarize BinaryFormat BinaryImageQ BinaryRead BinaryReadList BinaryWrite BinCounts BinLists Binomial BinomialDistribution BinomialProcess BinormalDistribution BiorthogonalSplineWavelet BipartiteGraphQ BirnbaumImportance BirnbaumSaundersDistribution BitAnd BitClear BitGet BitLength BitNot BitOr BitSet BitShiftLeft BitShiftRight BitXor Black BlackmanHarrisWindow BlackmanNuttallWindow BlackmanWindow Blank BlankForm BlankNullSequence BlankSequence Blend Block BlockRandom BlomqvistBeta BlomqvistBetaTest Blue Blur BodePlot BohmanWindow Bold Bookmarks Boole BooleanConsecutiveFunction BooleanConvert BooleanCountingFunction BooleanFunction BooleanGraph BooleanMaxterms BooleanMinimize BooleanMinterms Booleans BooleanTable BooleanVariables BorderDimensions BorelTannerDistribution Bottom BottomHatTransform BoundaryStyle Bounds Box BoxBaselineShift BoxData BoxDimensions Boxed Boxes BoxForm BoxFormFormatTypes BoxFrame BoxID BoxMargins BoxMatrix BoxRatios BoxRotation BoxRotationPoint BoxStyle BoxWhiskerChart Bra BracketingBar BraKet BrayCurtisDistance BreadthFirstScan Break Brown BrownForsytheTest BrownianBridgeProcess BrowserCategory BSplineBasis BSplineCurve BSplineCurve3DBox BSplineCurveBox BSplineCurveBoxOptions BSplineFunction BSplineSurface BSplineSurface3DBox BubbleChart BubbleChart3D BubbleScale BubbleSizes BulletGauge BusinessDayQ ButterflyGraph ButterworthFilterModel Button ButtonBar ButtonBox ButtonBoxOptions ButtonCell ButtonContents ButtonData ButtonEvaluator ButtonExpandable ButtonFrame ButtonFunction ButtonMargins ButtonMinHeight ButtonNote ButtonNotebook ButtonSource ButtonStyle ButtonStyleMenuListing Byte ByteCount ByteOrdering C CachedValue CacheGraphics CalendarData CalendarType CallPacket CanberraDistance Cancel CancelButton CandlestickChart Cap CapForm CapitalDifferentialD CardinalBSplineBasis CarmichaelLambda Cases Cashflow Casoratian Catalan CatalanNumber Catch CauchyDistribution CauchyWindow CayleyGraph CDF CDFDeploy CDFInformation CDFWavelet Ceiling Cell CellAutoOverwrite CellBaseline CellBoundingBox CellBracketOptions CellChangeTimes CellContents CellContext CellDingbat CellDynamicExpression CellEditDuplicate CellElementsBoundingBox CellElementSpacings CellEpilog CellEvaluationDuplicate CellEvaluationFunction CellEventActions CellFrame CellFrameColor CellFrameLabelMargins CellFrameLabels CellFrameMargins CellGroup CellGroupData CellGrouping CellGroupingRules CellHorizontalScrolling CellID CellLabel CellLabelAutoDelete CellLabelMargins CellLabelPositioning CellMargins CellObject CellOpen CellPrint CellProlog Cells CellSize CellStyle CellTags CellularAutomaton CensoredDistribution Censoring Center CenterDot CentralMoment CentralMomentGeneratingFunction CForm ChampernowneNumber ChanVeseBinarize Character CharacterEncoding CharacterEncodingsPath CharacteristicFunction CharacteristicPolynomial CharacterRange Characters ChartBaseStyle ChartElementData ChartElementDataFunction ChartElementFunction ChartElements ChartLabels ChartLayout ChartLegends ChartStyle Chebyshev1FilterModel Chebyshev2FilterModel ChebyshevDistance ChebyshevT ChebyshevU Check CheckAbort CheckAll Checkbox CheckboxBar CheckboxBox CheckboxBoxOptions ChemicalData ChessboardDistance ChiDistribution ChineseRemainder ChiSquareDistribution ChoiceButtons ChoiceDialog CholeskyDecomposition Chop Circle CircleBox CircleDot CircleMinus CirclePlus CircleTimes CirculantGraph CityData Clear ClearAll ClearAttributes ClearSystemCache ClebschGordan ClickPane Clip ClipboardNotebook ClipFill ClippingStyle ClipPlanes ClipRange Clock ClockGauge ClockwiseContourIntegral Close Closed CloseKernels ClosenessCentrality Closing ClosingAutoSave ClosingEvent ClusteringComponents CMYKColor Coarse Coefficient CoefficientArrays CoefficientDomain CoefficientList CoefficientRules CoifletWavelet Collect Colon ColonForm ColorCombine ColorConvert ColorData ColorDataFunction ColorFunction ColorFunctionScaling Colorize ColorNegate ColorOutput ColorProfileData ColorQuantize ColorReplace ColorRules ColorSelectorSettings ColorSeparate ColorSetter ColorSetterBox ColorSetterBoxOptions ColorSlider ColorSpace Column ColumnAlignments ColumnBackgrounds ColumnForm ColumnLines ColumnsEqual ColumnSpacings ColumnWidths CommonDefaultFormatTypes Commonest CommonestFilter CommonUnits CommunityBoundaryStyle CommunityGraphPlot CommunityLabels CommunityRegionStyle CompatibleUnitQ CompilationOptions CompilationTarget Compile Compiled CompiledFunction Complement CompleteGraph CompleteGraphQ CompleteKaryTree CompletionsListPacket Complex Complexes ComplexExpand ComplexInfinity ComplexityFunction ComponentMeasurements ComponentwiseContextMenu Compose ComposeList ComposeSeries Composition CompoundExpression CompoundPoissonDistribution CompoundPoissonProcess CompoundRenewalProcess Compress CompressedData Condition ConditionalExpression Conditioned Cone ConeBox ConfidenceLevel ConfidenceRange ConfidenceTransform ConfigurationPath Congruent Conjugate ConjugateTranspose Conjunction Connect ConnectedComponents ConnectedGraphQ ConnesWindow ConoverTest ConsoleMessage ConsoleMessagePacket ConsolePrint Constant ConstantArray Constants ConstrainedMax ConstrainedMin ContentPadding ContentsBoundingBox ContentSelectable ContentSize Context ContextMenu Contexts ContextToFilename ContextToFileName Continuation Continue ContinuedFraction ContinuedFractionK ContinuousAction ContinuousMarkovProcess ContinuousTimeModelQ ContinuousWaveletData ContinuousWaveletTransform ContourDetect ContourGraphics ContourIntegral ContourLabels ContourLines ContourPlot ContourPlot3D Contours ContourShading ContourSmoothing ContourStyle ContraharmonicMean Control ControlActive ControlAlignment ControllabilityGramian ControllabilityMatrix ControllableDecomposition ControllableModelQ ControllerDuration ControllerInformation ControllerInformationData ControllerLinking ControllerManipulate ControllerMethod ControllerPath ControllerState ControlPlacement ControlsRendering ControlType Convergents ConversionOptions ConversionRules ConvertToBitmapPacket ConvertToPostScript ConvertToPostScriptPacket Convolve ConwayGroupCo1 ConwayGroupCo2 ConwayGroupCo3 CoordinateChartData CoordinatesToolOptions CoordinateTransform CoordinateTransformData CoprimeQ Coproduct CopulaDistribution Copyable CopyDirectory CopyFile CopyTag CopyToClipboard CornerFilter CornerNeighbors Correlation CorrelationDistance CorrelationFunction CorrelationTest Cos Cosh CoshIntegral CosineDistance CosineWindow CosIntegral Cot Coth Count CounterAssignments CounterBox CounterBoxOptions CounterClockwiseContourIntegral CounterEvaluator CounterFunction CounterIncrements CounterStyle CounterStyleMenuListing CountRoots CountryData Covariance CovarianceEstimatorFunction CovarianceFunction CoxianDistribution CoxIngersollRossProcess CoxModel CoxModelFit CramerVonMisesTest CreateArchive CreateDialog CreateDirectory CreateDocument CreateIntermediateDirectories CreatePalette CreatePalettePacket CreateScheduledTask CreateTemporary CreateWindow CriticalityFailureImportance CriticalitySuccessImportance CriticalSection Cross CrossingDetect CrossMatrix Csc Csch CubeRoot Cubics Cuboid CuboidBox Cumulant CumulantGeneratingFunction Cup CupCap Curl CurlyDoubleQuote CurlyQuote CurrentImage CurrentlySpeakingPacket CurrentValue CurvatureFlowFilter CurveClosed Cyan CycleGraph CycleIndexPolynomial Cycles CyclicGroup Cyclotomic Cylinder CylinderBox CylindricalDecomposition D DagumDistribution DamerauLevenshteinDistance DampingFactor Darker Dashed Dashing DataCompression DataDistribution DataRange DataReversed Date DateDelimiters DateDifference DateFunction DateList DateListLogPlot DateListPlot DatePattern DatePlus DateRange DateString DateTicksFormat DaubechiesWavelet DavisDistribution DawsonF DayCount DayCountConvention DayMatchQ DayName DayPlus DayRange DayRound DeBruijnGraph Debug DebugTag Decimal DeclareKnownSymbols DeclarePackage Decompose Decrement DedekindEta Default DefaultAxesStyle DefaultBaseStyle DefaultBoxStyle DefaultButton DefaultColor DefaultControlPlacement DefaultDuplicateCellStyle DefaultDuration DefaultElement DefaultFaceGridsStyle DefaultFieldHintStyle DefaultFont DefaultFontProperties DefaultFormatType DefaultFormatTypeForStyle DefaultFrameStyle DefaultFrameTicksStyle DefaultGridLinesStyle DefaultInlineFormatType DefaultInputFormatType DefaultLabelStyle DefaultMenuStyle DefaultNaturalLanguage DefaultNewCellStyle DefaultNewInlineCellStyle DefaultNotebook DefaultOptions DefaultOutputFormatType DefaultStyle DefaultStyleDefinitions DefaultTextFormatType DefaultTextInlineFormatType DefaultTicksStyle DefaultTooltipStyle DefaultValues Defer DefineExternal DefineInputStreamMethod DefineOutputStreamMethod Definition Degree DegreeCentrality DegreeGraphDistribution DegreeLexicographic DegreeReverseLexicographic Deinitialization Del Deletable Delete DeleteBorderComponents DeleteCases DeleteContents DeleteDirectory DeleteDuplicates DeleteFile DeleteSmallComponents DeleteWithContents DeletionWarning Delimiter DelimiterFlashTime DelimiterMatching Delimiters Denominator DensityGraphics DensityHistogram DensityPlot DependentVariables Deploy Deployed Depth DepthFirstScan Derivative DerivativeFilter DescriptorStateSpace DesignMatrix Det DGaussianWavelet DiacriticalPositioning Diagonal DiagonalMatrix Dialog DialogIndent DialogInput DialogLevel DialogNotebook DialogProlog DialogReturn DialogSymbols Diamond DiamondMatrix DiceDissimilarity DictionaryLookup DifferenceDelta DifferenceOrder DifferenceRoot DifferenceRootReduce Differences DifferentialD DifferentialRoot DifferentialRootReduce DifferentiatorFilter DigitBlock DigitBlockMinimum DigitCharacter DigitCount DigitQ DihedralGroup Dilation Dimensions DiracComb DiracDelta DirectedEdge DirectedEdges DirectedGraph DirectedGraphQ DirectedInfinity Direction Directive Directory DirectoryName DirectoryQ DirectoryStack DirichletCharacter DirichletConvolve DirichletDistribution DirichletL DirichletTransform DirichletWindow DisableConsolePrintPacket DiscreteChirpZTransform DiscreteConvolve DiscreteDelta DiscreteHadamardTransform DiscreteIndicator DiscreteLQEstimatorGains DiscreteLQRegulatorGains DiscreteLyapunovSolve DiscreteMarkovProcess DiscretePlot DiscretePlot3D DiscreteRatio DiscreteRiccatiSolve DiscreteShift DiscreteTimeModelQ DiscreteUniformDistribution DiscreteVariables DiscreteWaveletData DiscreteWaveletPacketTransform DiscreteWaveletTransform Discriminant Disjunction Disk DiskBox DiskMatrix Dispatch DispersionEstimatorFunction Display DisplayAllSteps DisplayEndPacket DisplayFlushImagePacket DisplayForm DisplayFunction DisplayPacket DisplayRules DisplaySetSizePacket DisplayString DisplayTemporary DisplayWith DisplayWithRef DisplayWithVariable DistanceFunction DistanceTransform Distribute Distributed DistributedContexts DistributeDefinitions DistributionChart DistributionDomain DistributionFitTest DistributionParameterAssumptions DistributionParameterQ Dithering Div Divergence Divide DivideBy Dividers Divisible Divisors DivisorSigma DivisorSum DMSList DMSString Do DockedCells DocumentNotebook DominantColors DOSTextFormat Dot DotDashed DotEqual Dotted DoubleBracketingBar DoubleContourIntegral DoubleDownArrow DoubleLeftArrow DoubleLeftRightArrow DoubleLeftTee DoubleLongLeftArrow DoubleLongLeftRightArrow DoubleLongRightArrow DoubleRightArrow DoubleRightTee DoubleUpArrow DoubleUpDownArrow DoubleVerticalBar DoublyInfinite Down DownArrow DownArrowBar DownArrowUpArrow DownLeftRightVector DownLeftTeeVector DownLeftVector DownLeftVectorBar DownRightTeeVector DownRightVector DownRightVectorBar Downsample DownTee DownTeeArrow DownValues DragAndDrop DrawEdges DrawFrontFaces DrawHighlighted Drop DSolve Dt DualLinearProgramming DualSystemsModel DumpGet DumpSave DuplicateFreeQ Dynamic DynamicBox DynamicBoxOptions DynamicEvaluationTimeout DynamicLocation DynamicModule DynamicModuleBox DynamicModuleBoxOptions DynamicModuleParent DynamicModuleValues DynamicName DynamicNamespace DynamicReference DynamicSetting DynamicUpdating DynamicWrapper DynamicWrapperBox DynamicWrapperBoxOptions E EccentricityCentrality EdgeAdd EdgeBetweennessCentrality EdgeCapacity EdgeCapForm EdgeColor EdgeConnectivity EdgeCost EdgeCount EdgeCoverQ EdgeDashing EdgeDelete EdgeDetect EdgeForm EdgeIndex EdgeJoinForm EdgeLabeling EdgeLabels EdgeLabelStyle EdgeList EdgeOpacity EdgeQ EdgeRenderingFunction EdgeRules EdgeShapeFunction EdgeStyle EdgeThickness EdgeWeight Editable EditButtonSettings EditCellTagsSettings EditDistance EffectiveInterest Eigensystem Eigenvalues EigenvectorCentrality Eigenvectors Element ElementData Eliminate EliminationOrder EllipticE EllipticExp EllipticExpPrime EllipticF EllipticFilterModel EllipticK EllipticLog EllipticNomeQ EllipticPi EllipticReducedHalfPeriods EllipticTheta EllipticThetaPrime EmitSound EmphasizeSyntaxErrors EmpiricalDistribution Empty EmptyGraphQ EnableConsolePrintPacket Enabled Encode End EndAdd EndDialogPacket EndFrontEndInteractionPacket EndOfFile EndOfLine EndOfString EndPackage EngineeringForm Enter EnterExpressionPacket EnterTextPacket Entropy EntropyFilter Environment Epilog Equal EqualColumns EqualRows EqualTilde EquatedTo Equilibrium EquirippleFilterKernel Equivalent Erf Erfc Erfi ErlangB ErlangC ErlangDistribution Erosion ErrorBox ErrorBoxOptions ErrorNorm ErrorPacket ErrorsDialogSettings EstimatedDistribution EstimatedProcess EstimatorGains EstimatorRegulator EuclideanDistance EulerE EulerGamma EulerianGraphQ EulerPhi Evaluatable Evaluate Evaluated EvaluatePacket EvaluationCell EvaluationCompletionAction EvaluationElements EvaluationMode EvaluationMonitor EvaluationNotebook EvaluationObject EvaluationOrder Evaluator EvaluatorNames EvenQ EventData EventEvaluator EventHandler EventHandlerTag EventLabels ExactBlackmanWindow ExactNumberQ ExactRootIsolation ExampleData Except ExcludedForms ExcludePods Exclusions ExclusionsStyle Exists Exit ExitDialog Exp Expand ExpandAll ExpandDenominator ExpandFileName ExpandNumerator Expectation ExpectationE ExpectedValue ExpGammaDistribution ExpIntegralE ExpIntegralEi Exponent ExponentFunction ExponentialDistribution ExponentialFamily ExponentialGeneratingFunction ExponentialMovingAverage ExponentialPowerDistribution ExponentPosition ExponentStep Export ExportAutoReplacements ExportPacket ExportString Expression ExpressionCell ExpressionPacket ExpToTrig ExtendedGCD Extension ExtentElementFunction ExtentMarkers ExtentSize ExternalCall ExternalDataCharacterEncoding Extract ExtractArchive ExtremeValueDistribution FaceForm FaceGrids FaceGridsStyle Factor FactorComplete Factorial Factorial2 FactorialMoment FactorialMomentGeneratingFunction FactorialPower FactorInteger FactorList FactorSquareFree FactorSquareFreeList FactorTerms FactorTermsList Fail FailureDistribution False FARIMAProcess FEDisableConsolePrintPacket FeedbackSector FeedbackSectorStyle FeedbackType FEEnableConsolePrintPacket Fibonacci FieldHint FieldHintStyle FieldMasked FieldSize File FileBaseName FileByteCount FileDate FileExistsQ FileExtension FileFormat FileHash FileInformation FileName FileNameDepth FileNameDialogSettings FileNameDrop FileNameJoin FileNames FileNameSetter FileNameSplit FileNameTake FilePrint FileType FilledCurve FilledCurveBox Filling FillingStyle FillingTransform FilterRules FinancialBond FinancialData FinancialDerivative FinancialIndicator Find FindArgMax FindArgMin FindClique FindClusters FindCurvePath FindDistributionParameters FindDivisions FindEdgeCover FindEdgeCut FindEulerianCycle FindFaces FindFile FindFit FindGeneratingFunction FindGeoLocation FindGeometricTransform FindGraphCommunities FindGraphIsomorphism FindGraphPartition FindHamiltonianCycle FindIndependentEdgeSet FindIndependentVertexSet FindInstance FindIntegerNullVector FindKClan FindKClique FindKClub FindKPlex FindLibrary FindLinearRecurrence FindList FindMaximum FindMaximumFlow FindMaxValue FindMinimum FindMinimumCostFlow FindMinimumCut FindMinValue FindPermutation FindPostmanTour FindProcessParameters FindRoot FindSequenceFunction FindSettings FindShortestPath FindShortestTour FindThreshold FindVertexCover FindVertexCut Fine FinishDynamic FiniteAbelianGroupCount FiniteGroupCount FiniteGroupData First FirstPassageTimeDistribution FischerGroupFi22 FischerGroupFi23 FischerGroupFi24Prime FisherHypergeometricDistribution FisherRatioTest FisherZDistribution Fit FitAll FittedModel FixedPoint FixedPointList FlashSelection Flat Flatten FlattenAt FlatTopWindow FlipView Floor FlushPrintOutputPacket Fold FoldList Font FontColor FontFamily FontForm FontName FontOpacity FontPostScriptName FontProperties FontReencoding FontSize FontSlant FontSubstitutions FontTracking FontVariations FontWeight For ForAll Format FormatRules FormatType FormatTypeAutoConvert FormatValues FormBox FormBoxOptions FortranForm Forward ForwardBackward Fourier FourierCoefficient FourierCosCoefficient FourierCosSeries FourierCosTransform FourierDCT FourierDCTFilter FourierDCTMatrix FourierDST FourierDSTMatrix FourierMatrix FourierParameters FourierSequenceTransform FourierSeries FourierSinCoefficient FourierSinSeries FourierSinTransform FourierTransform FourierTrigSeries FractionalBrownianMotionProcess FractionalPart FractionBox FractionBoxOptions FractionLine Frame FrameBox FrameBoxOptions Framed FrameInset FrameLabel Frameless FrameMargins FrameStyle FrameTicks FrameTicksStyle FRatioDistribution FrechetDistribution FreeQ FrequencySamplingFilterKernel FresnelC FresnelS Friday FrobeniusNumber FrobeniusSolve FromCharacterCode FromCoefficientRules FromContinuedFraction FromDate FromDigits FromDMS Front FrontEndDynamicExpression FrontEndEventActions FrontEndExecute FrontEndObject FrontEndResource FrontEndResourceString FrontEndStackSize FrontEndToken FrontEndTokenExecute FrontEndValueCache FrontEndVersion FrontFaceColor FrontFaceOpacity Full FullAxes FullDefinition FullForm FullGraphics FullOptions FullSimplify Function FunctionExpand FunctionInterpolation FunctionSpace FussellVeselyImportance GaborFilter GaborMatrix GaborWavelet GainMargins GainPhaseMargins Gamma GammaDistribution GammaRegularized GapPenalty Gather GatherBy GaugeFaceElementFunction GaugeFaceStyle GaugeFrameElementFunction GaugeFrameSize GaugeFrameStyle GaugeLabels GaugeMarkers GaugeStyle GaussianFilter GaussianIntegers GaussianMatrix GaussianWindow GCD GegenbauerC General GeneralizedLinearModelFit GenerateConditions GeneratedCell GeneratedParameters GeneratingFunction Generic GenericCylindricalDecomposition GenomeData GenomeLookup GeodesicClosing GeodesicDilation GeodesicErosion GeodesicOpening GeoDestination GeodesyData GeoDirection GeoDistance GeoGridPosition GeometricBrownianMotionProcess GeometricDistribution GeometricMean GeometricMeanFilter GeometricTransformation GeometricTransformation3DBox GeometricTransformation3DBoxOptions GeometricTransformationBox GeometricTransformationBoxOptions GeoPosition GeoPositionENU GeoPositionXYZ GeoProjectionData GestureHandler GestureHandlerTag Get GetBoundingBoxSizePacket GetContext GetEnvironment GetFileName GetFrontEndOptionsDataPacket GetLinebreakInformationPacket GetMenusPacket GetPageBreakInformationPacket Glaisher GlobalClusteringCoefficient GlobalPreferences GlobalSession Glow GoldenRatio GompertzMakehamDistribution GoodmanKruskalGamma GoodmanKruskalGammaTest Goto Grad Gradient GradientFilter GradientOrientationFilter Graph GraphAssortativity GraphCenter GraphComplement GraphData GraphDensity GraphDiameter GraphDifference GraphDisjointUnion GraphDistance GraphDistanceMatrix GraphElementData GraphEmbedding GraphHighlight GraphHighlightStyle GraphHub Graphics Graphics3D Graphics3DBox Graphics3DBoxOptions GraphicsArray GraphicsBaseline GraphicsBox GraphicsBoxOptions GraphicsColor GraphicsColumn GraphicsComplex GraphicsComplex3DBox GraphicsComplex3DBoxOptions GraphicsComplexBox GraphicsComplexBoxOptions GraphicsContents GraphicsData GraphicsGrid GraphicsGridBox GraphicsGroup GraphicsGroup3DBox GraphicsGroup3DBoxOptions GraphicsGroupBox GraphicsGroupBoxOptions GraphicsGrouping GraphicsHighlightColor GraphicsRow GraphicsSpacing GraphicsStyle GraphIntersection GraphLayout GraphLinkEfficiency GraphPeriphery GraphPlot GraphPlot3D GraphPower GraphPropertyDistribution GraphQ GraphRadius GraphReciprocity GraphRoot GraphStyle GraphUnion Gray GrayLevel GreatCircleDistance Greater GreaterEqual GreaterEqualLess GreaterFullEqual GreaterGreater GreaterLess GreaterSlantEqual GreaterTilde Green Grid GridBaseline GridBox GridBoxAlignment GridBoxBackground GridBoxDividers GridBoxFrame GridBoxItemSize GridBoxItemStyle GridBoxOptions GridBoxSpacings GridCreationSettings GridDefaultElement GridElementStyleOptions GridFrame GridFrameMargins GridGraph GridLines GridLinesStyle GroebnerBasis GroupActionBase GroupCentralizer GroupElementFromWord GroupElementPosition GroupElementQ GroupElements GroupElementToWord GroupGenerators GroupMultiplicationTable GroupOrbits GroupOrder GroupPageBreakWithin GroupSetwiseStabilizer GroupStabilizer GroupStabilizerChain Gudermannian GumbelDistribution HaarWavelet HadamardMatrix HalfNormalDistribution HamiltonianGraphQ HammingDistance HammingWindow HankelH1 HankelH2 HankelMatrix HannPoissonWindow HannWindow HaradaNortonGroupHN HararyGraph HarmonicMean HarmonicMeanFilter HarmonicNumber Hash HashTable Haversine HazardFunction Head HeadCompose Heads HeavisideLambda HeavisidePi HeavisideTheta HeldGroupHe HeldPart HelpBrowserLookup HelpBrowserNotebook HelpBrowserSettings HermiteDecomposition HermiteH HermitianMatrixQ HessenbergDecomposition Hessian HexadecimalCharacter Hexahedron HexahedronBox HexahedronBoxOptions HiddenSurface HighlightGraph HighlightImage HighpassFilter HigmanSimsGroupHS HilbertFilter HilbertMatrix Histogram Histogram3D HistogramDistribution HistogramList HistogramTransform HistogramTransformInterpolation HitMissTransform HITSCentrality HodgeDual HoeffdingD HoeffdingDTest Hold HoldAll HoldAllComplete HoldComplete HoldFirst HoldForm HoldPattern HoldRest HolidayCalendar HomeDirectory HomePage Horizontal HorizontalForm HorizontalGauge HorizontalScrollPosition HornerForm HotellingTSquareDistribution HoytDistribution HTMLSave Hue HumpDownHump HumpEqual HurwitzLerchPhi HurwitzZeta HyperbolicDistribution HypercubeGraph HyperexponentialDistribution Hyperfactorial Hypergeometric0F1 Hypergeometric0F1Regularized Hypergeometric1F1 Hypergeometric1F1Regularized Hypergeometric2F1 Hypergeometric2F1Regularized HypergeometricDistribution HypergeometricPFQ HypergeometricPFQRegularized HypergeometricU Hyperlink HyperlinkCreationSettings Hyphenation HyphenationOptions HypoexponentialDistribution HypothesisTestData I Identity IdentityMatrix If IgnoreCase Im Image Image3D Image3DSlices ImageAccumulate ImageAdd ImageAdjust ImageAlign ImageApply ImageAspectRatio ImageAssemble ImageCache ImageCacheValid ImageCapture ImageChannels ImageClip ImageColorSpace ImageCompose ImageConvolve ImageCooccurrence ImageCorners ImageCorrelate ImageCorrespondingPoints ImageCrop ImageData ImageDataPacket ImageDeconvolve ImageDemosaic ImageDifference ImageDimensions ImageDistance ImageEffect ImageFeatureTrack ImageFileApply ImageFileFilter ImageFileScan ImageFilter ImageForestingComponents ImageForwardTransformation ImageHistogram ImageKeypoints ImageLevels ImageLines ImageMargins ImageMarkers ImageMeasurements ImageMultiply ImageOffset ImagePad ImagePadding ImagePartition ImagePeriodogram ImagePerspectiveTransformation ImageQ ImageRangeCache ImageReflect ImageRegion ImageResize ImageResolution ImageRotate ImageRotated ImageScaled ImageScan ImageSize ImageSizeAction ImageSizeCache ImageSizeMultipliers ImageSizeRaw ImageSubtract ImageTake ImageTransformation ImageTrim ImageType ImageValue ImageValuePositions Implies Import ImportAutoReplacements ImportString ImprovementImportance In IncidenceGraph IncidenceList IncidenceMatrix IncludeConstantBasis IncludeFileExtension IncludePods IncludeSingularTerm Increment Indent IndentingNewlineSpacings IndentMaxFraction IndependenceTest IndependentEdgeSetQ IndependentUnit IndependentVertexSetQ Indeterminate IndexCreationOptions Indexed IndexGraph IndexTag Inequality InexactNumberQ InexactNumbers Infinity Infix Information Inherited InheritScope Initialization InitializationCell InitializationCellEvaluation InitializationCellWarning InlineCounterAssignments InlineCounterIncrements InlineRules Inner Inpaint Input InputAliases InputAssumptions InputAutoReplacements InputField InputFieldBox InputFieldBoxOptions InputForm InputGrouping InputNamePacket InputNotebook InputPacket InputSettings InputStream InputString InputStringPacket InputToBoxFormPacket Insert InsertionPointObject InsertResults Inset Inset3DBox Inset3DBoxOptions InsetBox InsetBoxOptions Install InstallService InString Integer IntegerDigits IntegerExponent IntegerLength IntegerPart IntegerPartitions IntegerQ Integers IntegerString Integral Integrate Interactive InteractiveTradingChart Interlaced Interleaving InternallyBalancedDecomposition InterpolatingFunction InterpolatingPolynomial Interpolation InterpolationOrder InterpolationPoints InterpolationPrecision Interpretation InterpretationBox InterpretationBoxOptions InterpretationFunction InterpretTemplate InterquartileRange Interrupt InterruptSettings Intersection Interval IntervalIntersection IntervalMemberQ IntervalUnion Inverse InverseBetaRegularized InverseCDF InverseChiSquareDistribution InverseContinuousWaveletTransform InverseDistanceTransform InverseEllipticNomeQ InverseErf InverseErfc InverseFourier InverseFourierCosTransform InverseFourierSequenceTransform InverseFourierSinTransform InverseFourierTransform InverseFunction InverseFunctions InverseGammaDistribution InverseGammaRegularized InverseGaussianDistribution InverseGudermannian InverseHaversine InverseJacobiCD InverseJacobiCN InverseJacobiCS InverseJacobiDC InverseJacobiDN InverseJacobiDS InverseJacobiNC InverseJacobiND InverseJacobiNS InverseJacobiSC InverseJacobiSD InverseJacobiSN InverseLaplaceTransform InversePermutation InverseRadon InverseSeries InverseSurvivalFunction InverseWaveletTransform InverseWeierstrassP InverseZTransform Invisible InvisibleApplication InvisibleTimes IrreduciblePolynomialQ IsolatingInterval IsomorphicGraphQ IsotopeData Italic Item ItemBox ItemBoxOptions ItemSize ItemStyle ItoProcess JaccardDissimilarity JacobiAmplitude Jacobian JacobiCD JacobiCN JacobiCS JacobiDC JacobiDN JacobiDS JacobiNC JacobiND JacobiNS JacobiP JacobiSC JacobiSD JacobiSN JacobiSymbol JacobiZeta JankoGroupJ1 JankoGroupJ2 JankoGroupJ3 JankoGroupJ4 JarqueBeraALMTest JohnsonDistribution Join Joined JoinedCurve JoinedCurveBox JoinForm JordanDecomposition JordanModelDecomposition K KagiChart KaiserBesselWindow KaiserWindow KalmanEstimator KalmanFilter KarhunenLoeveDecomposition KaryTree KatzCentrality KCoreComponents KDistribution KelvinBei KelvinBer KelvinKei KelvinKer KendallTau KendallTauTest KernelExecute KernelMixtureDistribution KernelObject Kernels Ket Khinchin KirchhoffGraph KirchhoffMatrix KleinInvariantJ KnightTourGraph KnotData KnownUnitQ KolmogorovSmirnovTest KroneckerDelta KroneckerModelDecomposition KroneckerProduct KroneckerSymbol KuiperTest KumaraswamyDistribution Kurtosis KuwaharaFilter Label Labeled LabeledSlider LabelingFunction LabelStyle LaguerreL LambdaComponents LambertW LanczosWindow LandauDistribution Language LanguageCategory LaplaceDistribution LaplaceTransform Laplacian LaplacianFilter LaplacianGaussianFilter Large Larger Last Latitude LatitudeLongitude LatticeData LatticeReduce Launch LaunchKernels LayeredGraphPlot LayerSizeFunction LayoutInformation LCM LeafCount LeapYearQ LeastSquares LeastSquaresFilterKernel Left LeftArrow LeftArrowBar LeftArrowRightArrow LeftDownTeeVector LeftDownVector LeftDownVectorBar LeftRightArrow LeftRightVector LeftTee LeftTeeArrow LeftTeeVector LeftTriangle LeftTriangleBar LeftTriangleEqual LeftUpDownVector LeftUpTeeVector LeftUpVector LeftUpVectorBar LeftVector LeftVectorBar LegendAppearance Legended LegendFunction LegendLabel LegendLayout LegendMargins LegendMarkers LegendMarkerSize LegendreP LegendreQ LegendreType Length LengthWhile LerchPhi Less LessEqual LessEqualGreater LessFullEqual LessGreater LessLess LessSlantEqual LessTilde LetterCharacter LetterQ Level LeveneTest LeviCivitaTensor LevyDistribution Lexicographic LibraryFunction LibraryFunctionError LibraryFunctionInformation LibraryFunctionLoad LibraryFunctionUnload LibraryLoad LibraryUnload LicenseID LiftingFilterData LiftingWaveletTransform LightBlue LightBrown LightCyan Lighter LightGray LightGreen Lighting LightingAngle LightMagenta LightOrange LightPink LightPurple LightRed LightSources LightYellow Likelihood Limit LimitsPositioning LimitsPositioningTokens LindleyDistribution Line Line3DBox LinearFilter LinearFractionalTransform LinearModelFit LinearOffsetFunction LinearProgramming LinearRecurrence LinearSolve LinearSolveFunction LineBox LineBreak LinebreakAdjustments LineBreakChart LineBreakWithin LineColor LineForm LineGraph LineIndent LineIndentMaxFraction LineIntegralConvolutionPlot LineIntegralConvolutionScale LineLegend LineOpacity LineSpacing LineWrapParts LinkActivate LinkClose LinkConnect LinkConnectedQ LinkCreate LinkError LinkFlush LinkFunction LinkHost LinkInterrupt LinkLaunch LinkMode LinkObject LinkOpen LinkOptions LinkPatterns LinkProtocol LinkRead LinkReadHeld LinkReadyQ Links LinkWrite LinkWriteHeld LiouvilleLambda List Listable ListAnimate ListContourPlot ListContourPlot3D ListConvolve ListCorrelate ListCurvePathPlot ListDeconvolve ListDensityPlot Listen ListFourierSequenceTransform ListInterpolation ListLineIntegralConvolutionPlot ListLinePlot ListLogLinearPlot ListLogLogPlot ListLogPlot ListPicker ListPickerBox ListPickerBoxBackground ListPickerBoxOptions ListPlay ListPlot ListPlot3D ListPointPlot3D ListPolarPlot ListQ ListStreamDensityPlot ListStreamPlot ListSurfacePlot3D ListVectorDensityPlot ListVectorPlot ListVectorPlot3D ListZTransform Literal LiteralSearch LocalClusteringCoefficient LocalizeVariables LocationEquivalenceTest LocationTest Locator LocatorAutoCreate LocatorBox LocatorBoxOptions LocatorCentering LocatorPane LocatorPaneBox LocatorPaneBoxOptions LocatorRegion Locked Log Log10 Log2 LogBarnesG LogGamma LogGammaDistribution LogicalExpand LogIntegral LogisticDistribution LogitModelFit LogLikelihood LogLinearPlot LogLogisticDistribution LogLogPlot LogMultinormalDistribution LogNormalDistribution LogPlot LogRankTest LogSeriesDistribution LongEqual Longest LongestAscendingSequence LongestCommonSequence LongestCommonSequencePositions LongestCommonSubsequence LongestCommonSubsequencePositions LongestMatch LongForm Longitude LongLeftArrow LongLeftRightArrow LongRightArrow Loopback LoopFreeGraphQ LowerCaseQ LowerLeftArrow LowerRightArrow LowerTriangularize LowpassFilter LQEstimatorGains LQGRegulator LQOutputRegulatorGains LQRegulatorGains LUBackSubstitution LucasL LuccioSamiComponents LUDecomposition LyapunovSolve LyonsGroupLy MachineID MachineName MachineNumberQ MachinePrecision MacintoshSystemPageSetup Magenta Magnification Magnify MainSolve MaintainDynamicCaches Majority MakeBoxes MakeExpression MakeRules MangoldtLambda ManhattanDistance Manipulate Manipulator MannWhitneyTest MantissaExponent Manual Map MapAll MapAt MapIndexed MAProcess MapThread MarcumQ MardiaCombinedTest MardiaKurtosisTest MardiaSkewnessTest MarginalDistribution MarkovProcessProperties Masking MatchingDissimilarity MatchLocalNameQ MatchLocalNames MatchQ Material MathematicaNotation MathieuC MathieuCharacteristicA MathieuCharacteristicB MathieuCharacteristicExponent MathieuCPrime MathieuGroupM11 MathieuGroupM12 MathieuGroupM22 MathieuGroupM23 MathieuGroupM24 MathieuS MathieuSPrime MathMLForm MathMLText Matrices MatrixExp MatrixForm MatrixFunction MatrixLog MatrixPlot MatrixPower MatrixQ MatrixRank Max MaxBend MaxDetect MaxExtraBandwidths MaxExtraConditions MaxFeatures MaxFilter Maximize MaxIterations MaxMemoryUsed MaxMixtureKernels MaxPlotPoints MaxPoints MaxRecursion MaxStableDistribution MaxStepFraction MaxSteps MaxStepSize MaxValue MaxwellDistribution McLaughlinGroupMcL Mean MeanClusteringCoefficient MeanDegreeConnectivity MeanDeviation MeanFilter MeanGraphDistance MeanNeighborDegree MeanShift MeanShiftFilter Median MedianDeviation MedianFilter Medium MeijerG MeixnerDistribution MemberQ MemoryConstrained MemoryInUse Menu MenuAppearance MenuCommandKey MenuEvaluator MenuItem MenuPacket MenuSortingValue MenuStyle MenuView MergeDifferences Mesh MeshFunctions MeshRange MeshShading MeshStyle Message MessageDialog MessageList MessageName MessageOptions MessagePacket Messages MessagesNotebook MetaCharacters MetaInformation Method MethodOptions MexicanHatWavelet MeyerWavelet Min MinDetect MinFilter MinimalPolynomial MinimalStateSpaceModel Minimize Minors MinRecursion MinSize MinStableDistribution Minus MinusPlus MinValue Missing MissingDataMethod MittagLefflerE MixedRadix MixedRadixQuantity MixtureDistribution Mod Modal Mode Modular ModularLambda Module Modulus MoebiusMu Moment Momentary MomentConvert MomentEvaluate MomentGeneratingFunction Monday Monitor MonomialList MonomialOrder MonsterGroupM MorletWavelet MorphologicalBinarize MorphologicalBranchPoints MorphologicalComponents MorphologicalEulerNumber MorphologicalGraph MorphologicalPerimeter MorphologicalTransform Most MouseAnnotation MouseAppearance MouseAppearanceTag MouseButtons Mouseover MousePointerNote MousePosition MovingAverage MovingMedian MoyalDistribution MultiedgeStyle MultilaunchWarning MultiLetterItalics MultiLetterStyle MultilineFunction Multinomial MultinomialDistribution MultinormalDistribution MultiplicativeOrder Multiplicity Multiselection MultivariateHypergeometricDistribution MultivariatePoissonDistribution MultivariateTDistribution N NakagamiDistribution NameQ Names NamespaceBox Nand NArgMax NArgMin NBernoulliB NCache NDSolve NDSolveValue Nearest NearestFunction NeedCurrentFrontEndPackagePacket NeedCurrentFrontEndSymbolsPacket NeedlemanWunschSimilarity Needs Negative NegativeBinomialDistribution NegativeMultinomialDistribution NeighborhoodGraph Nest NestedGreaterGreater NestedLessLess NestedScriptRules NestList NestWhile NestWhileList NevilleThetaC NevilleThetaD NevilleThetaN NevilleThetaS NewPrimitiveStyle NExpectation Next NextPrime NHoldAll NHoldFirst NHoldRest NicholsGridLines NicholsPlot NIntegrate NMaximize NMaxValue NMinimize NMinValue NominalVariables NonAssociative NoncentralBetaDistribution NoncentralChiSquareDistribution NoncentralFRatioDistribution NoncentralStudentTDistribution NonCommutativeMultiply NonConstants None NonlinearModelFit NonlocalMeansFilter NonNegative NonPositive Nor NorlundB Norm Normal NormalDistribution NormalGrouping Normalize NormalizedSquaredEuclideanDistance NormalsFunction NormFunction Not NotCongruent NotCupCap NotDoubleVerticalBar Notebook NotebookApply NotebookAutoSave NotebookClose NotebookConvertSettings NotebookCreate NotebookCreateReturnObject NotebookDefault NotebookDelete NotebookDirectory NotebookDynamicExpression NotebookEvaluate NotebookEventActions NotebookFileName NotebookFind NotebookFindReturnObject NotebookGet NotebookGetLayoutInformationPacket NotebookGetMisspellingsPacket NotebookInformation NotebookInterfaceObject NotebookLocate NotebookObject NotebookOpen NotebookOpenReturnObject NotebookPath NotebookPrint NotebookPut NotebookPutReturnObject NotebookRead NotebookResetGeneratedCells Notebooks NotebookSave NotebookSaveAs NotebookSelection NotebookSetupLayoutInformationPacket NotebooksMenu NotebookWrite NotElement NotEqualTilde NotExists NotGreater NotGreaterEqual NotGreaterFullEqual NotGreaterGreater NotGreaterLess NotGreaterSlantEqual NotGreaterTilde NotHumpDownHump NotHumpEqual NotLeftTriangle NotLeftTriangleBar NotLeftTriangleEqual NotLess NotLessEqual NotLessFullEqual NotLessGreater NotLessLess NotLessSlantEqual NotLessTilde NotNestedGreaterGreater NotNestedLessLess NotPrecedes NotPrecedesEqual NotPrecedesSlantEqual NotPrecedesTilde NotReverseElement NotRightTriangle NotRightTriangleBar NotRightTriangleEqual NotSquareSubset NotSquareSubsetEqual NotSquareSuperset NotSquareSupersetEqual NotSubset NotSubsetEqual NotSucceeds NotSucceedsEqual NotSucceedsSlantEqual NotSucceedsTilde NotSuperset NotSupersetEqual NotTilde NotTildeEqual NotTildeFullEqual NotTildeTilde NotVerticalBar NProbability NProduct NProductFactors NRoots NSolve NSum NSumTerms Null NullRecords NullSpace NullWords Number NumberFieldClassNumber NumberFieldDiscriminant NumberFieldFundamentalUnits NumberFieldIntegralBasis NumberFieldNormRepresentatives NumberFieldRegulator NumberFieldRootsOfUnity NumberFieldSignature NumberForm NumberFormat NumberMarks NumberMultiplier NumberPadding NumberPoint NumberQ NumberSeparator NumberSigns NumberString Numerator NumericFunction NumericQ NuttallWindow NValues NyquistGridLines NyquistPlot O ObservabilityGramian ObservabilityMatrix ObservableDecomposition ObservableModelQ OddQ Off Offset OLEData On ONanGroupON OneIdentity Opacity Open OpenAppend Opener OpenerBox OpenerBoxOptions OpenerView OpenFunctionInspectorPacket Opening OpenRead OpenSpecialOptions OpenTemporary OpenWrite Operate OperatingSystem OptimumFlowData Optional OptionInspectorSettings OptionQ Options OptionsPacket OptionsPattern OptionValue OptionValueBox OptionValueBoxOptions Or Orange Order OrderDistribution OrderedQ Ordering Orderless OrnsteinUhlenbeckProcess Orthogonalize Out Outer OutputAutoOverwrite OutputControllabilityMatrix OutputControllableModelQ OutputForm OutputFormData OutputGrouping OutputMathEditExpression OutputNamePacket OutputResponse OutputSizeLimit OutputStream Over OverBar OverDot Overflow OverHat Overlaps Overlay OverlayBox OverlayBoxOptions Overscript OverscriptBox OverscriptBoxOptions OverTilde OverVector OwenT OwnValues PackingMethod PaddedForm Padding PadeApproximant PadLeft PadRight PageBreakAbove PageBreakBelow PageBreakWithin PageFooterLines PageFooters PageHeaderLines PageHeaders PageHeight PageRankCentrality PageWidth PairedBarChart PairedHistogram PairedSmoothHistogram PairedTTest PairedZTest PaletteNotebook PalettePath Pane PaneBox PaneBoxOptions Panel PanelBox PanelBoxOptions Paneled PaneSelector PaneSelectorBox PaneSelectorBoxOptions PaperWidth ParabolicCylinderD ParagraphIndent ParagraphSpacing ParallelArray ParallelCombine ParallelDo ParallelEvaluate Parallelization Parallelize ParallelMap ParallelNeeds ParallelProduct ParallelSubmit ParallelSum ParallelTable ParallelTry Parameter ParameterEstimator ParameterMixtureDistribution ParameterVariables ParametricFunction ParametricNDSolve ParametricNDSolveValue ParametricPlot ParametricPlot3D ParentConnect ParentDirectory ParentForm Parenthesize ParentList ParetoDistribution Part PartialCorrelationFunction PartialD ParticleData Partition PartitionsP PartitionsQ ParzenWindow PascalDistribution PassEventsDown PassEventsUp Paste PasteBoxFormInlineCells PasteButton Path PathGraph PathGraphQ Pattern PatternSequence PatternTest PauliMatrix PaulWavelet Pause PausedTime PDF PearsonChiSquareTest PearsonCorrelationTest PearsonDistribution PerformanceGoal PeriodicInterpolation Periodogram PeriodogramArray PermutationCycles PermutationCyclesQ PermutationGroup PermutationLength PermutationList PermutationListQ PermutationMax PermutationMin PermutationOrder PermutationPower PermutationProduct PermutationReplace Permutations PermutationSupport Permute PeronaMalikFilter Perpendicular PERTDistribution PetersenGraph PhaseMargins Pi Pick PIDData PIDDerivativeFilter PIDFeedforward PIDTune Piecewise PiecewiseExpand PieChart PieChart3D PillaiTrace PillaiTraceTest Pink Pivoting PixelConstrained PixelValue PixelValuePositions Placed Placeholder PlaceholderReplace Plain PlanarGraphQ Play PlayRange Plot Plot3D Plot3Matrix PlotDivision PlotJoined PlotLabel PlotLayout PlotLegends PlotMarkers PlotPoints PlotRange PlotRangeClipping PlotRangePadding PlotRegion PlotStyle Plus PlusMinus Pochhammer PodStates PodWidth Point Point3DBox PointBox PointFigureChart PointForm PointLegend PointSize PoissonConsulDistribution PoissonDistribution PoissonProcess PoissonWindow PolarAxes PolarAxesOrigin PolarGridLines PolarPlot PolarTicks PoleZeroMarkers PolyaAeppliDistribution PolyGamma Polygon Polygon3DBox Polygon3DBoxOptions PolygonBox PolygonBoxOptions PolygonHoleScale PolygonIntersections PolygonScale PolyhedronData PolyLog PolynomialExtendedGCD PolynomialForm PolynomialGCD PolynomialLCM PolynomialMod PolynomialQ PolynomialQuotient PolynomialQuotientRemainder PolynomialReduce PolynomialRemainder Polynomials PopupMenu PopupMenuBox PopupMenuBoxOptions PopupView PopupWindow Position Positive PositiveDefiniteMatrixQ PossibleZeroQ Postfix PostScript Power PowerDistribution PowerExpand PowerMod PowerModList PowerSpectralDensity PowersRepresentations PowerSymmetricPolynomial Precedence PrecedenceForm Precedes PrecedesEqual PrecedesSlantEqual PrecedesTilde Precision PrecisionGoal PreDecrement PredictionRoot PreemptProtect PreferencesPath Prefix PreIncrement Prepend PrependTo PreserveImageOptions Previous PriceGraphDistribution PrimaryPlaceholder Prime PrimeNu PrimeOmega PrimePi PrimePowerQ PrimeQ Primes PrimeZetaP PrimitiveRoot PrincipalComponents PrincipalValue Print PrintAction PrintForm PrintingCopies PrintingOptions PrintingPageRange PrintingStartingPageNumber PrintingStyleEnvironment PrintPrecision PrintTemporary Prism PrismBox PrismBoxOptions PrivateCellOptions PrivateEvaluationOptions PrivateFontOptions PrivateFrontEndOptions PrivateNotebookOptions PrivatePaths Probability ProbabilityDistribution ProbabilityPlot ProbabilityPr ProbabilityScalePlot ProbitModelFit ProcessEstimator ProcessParameterAssumptions ProcessParameterQ ProcessStateDomain ProcessTimeDomain Product ProductDistribution ProductLog ProgressIndicator ProgressIndicatorBox ProgressIndicatorBoxOptions Projection Prolog PromptForm Properties Property PropertyList PropertyValue Proportion Proportional Protect Protected ProteinData Pruning PseudoInverse Purple Put PutAppend Pyramid PyramidBox PyramidBoxOptions QBinomial QFactorial QGamma QHypergeometricPFQ QPochhammer QPolyGamma QRDecomposition QuadraticIrrationalQ Quantile QuantilePlot Quantity QuantityForm QuantityMagnitude QuantityQ QuantityUnit Quartics QuartileDeviation Quartiles QuartileSkewness QueueingNetworkProcess QueueingProcess QueueProperties Quiet Quit Quotient QuotientRemainder RadialityCentrality RadicalBox RadicalBoxOptions RadioButton RadioButtonBar RadioButtonBox RadioButtonBoxOptions Radon RamanujanTau RamanujanTauL RamanujanTauTheta RamanujanTauZ Random RandomChoice RandomComplex RandomFunction RandomGraph RandomImage RandomInteger RandomPermutation RandomPrime RandomReal RandomSample RandomSeed RandomVariate RandomWalkProcess Range RangeFilter RangeSpecification RankedMax RankedMin Raster Raster3D Raster3DBox Raster3DBoxOptions RasterArray RasterBox RasterBoxOptions Rasterize RasterSize Rational RationalFunctions Rationalize Rationals Ratios Raw RawArray RawBoxes RawData RawMedium RayleighDistribution Re Read ReadList ReadProtected Real RealBlockDiagonalForm RealDigits RealExponent Reals Reap Record RecordLists RecordSeparators Rectangle RectangleBox RectangleBoxOptions RectangleChart RectangleChart3D RecurrenceFilter RecurrenceTable RecurringDigitsForm Red Reduce RefBox ReferenceLineStyle ReferenceMarkers ReferenceMarkerStyle Refine ReflectionMatrix ReflectionTransform Refresh RefreshRate RegionBinarize RegionFunction RegionPlot RegionPlot3D RegularExpression Regularization Reinstall Release ReleaseHold ReliabilityDistribution ReliefImage ReliefPlot Remove RemoveAlphaChannel RemoveAsynchronousTask Removed RemoveInputStreamMethod RemoveOutputStreamMethod RemoveProperty RemoveScheduledTask RenameDirectory RenameFile RenderAll RenderingOptions RenewalProcess RenkoChart Repeated RepeatedNull RepeatedString Replace ReplaceAll ReplaceHeldPart ReplaceImageValue ReplaceList ReplacePart ReplacePixelValue ReplaceRepeated Resampling Rescale RescalingTransform ResetDirectory ResetMenusPacket ResetScheduledTask Residue Resolve Rest Resultant ResumePacket Return ReturnExpressionPacket ReturnInputFormPacket ReturnPacket ReturnTextPacket Reverse ReverseBiorthogonalSplineWavelet ReverseElement ReverseEquilibrium ReverseGraph ReverseUpEquilibrium RevolutionAxis RevolutionPlot3D RGBColor RiccatiSolve RiceDistribution RidgeFilter RiemannR RiemannSiegelTheta RiemannSiegelZ Riffle Right RightArrow RightArrowBar RightArrowLeftArrow RightCosetRepresentative RightDownTeeVector RightDownVector RightDownVectorBar RightTee RightTeeArrow RightTeeVector RightTriangle RightTriangleBar RightTriangleEqual RightUpDownVector RightUpTeeVector RightUpVector RightUpVectorBar RightVector RightVectorBar RiskAchievementImportance RiskReductionImportance RogersTanimotoDissimilarity Root RootApproximant RootIntervals RootLocusPlot RootMeanSquare RootOfUnityQ RootReduce Roots RootSum Rotate RotateLabel RotateLeft RotateRight RotationAction RotationBox RotationBoxOptions RotationMatrix RotationTransform Round RoundImplies RoundingRadius Row RowAlignments RowBackgrounds RowBox RowHeights RowLines RowMinHeight RowReduce RowsEqual RowSpacings RSolve RudvalisGroupRu Rule RuleCondition RuleDelayed RuleForm RulerUnits Run RunScheduledTask RunThrough RuntimeAttributes RuntimeOptions RussellRaoDissimilarity SameQ SameTest SampleDepth SampledSoundFunction SampledSoundList SampleRate SamplingPeriod SARIMAProcess SARMAProcess SatisfiabilityCount SatisfiabilityInstances SatisfiableQ Saturday Save Saveable SaveAutoDelete SaveDefinitions SawtoothWave Scale Scaled ScaleDivisions ScaledMousePosition ScaleOrigin ScalePadding ScaleRanges ScaleRangeStyle ScalingFunctions ScalingMatrix ScalingTransform Scan ScheduledTaskActiveQ ScheduledTaskData ScheduledTaskObject ScheduledTasks SchurDecomposition ScientificForm ScreenRectangle ScreenStyleEnvironment ScriptBaselineShifts ScriptLevel ScriptMinSize ScriptRules ScriptSizeMultipliers Scrollbars ScrollingOptions ScrollPosition Sec Sech SechDistribution SectionGrouping SectorChart SectorChart3D SectorOrigin SectorSpacing SeedRandom Select Selectable SelectComponents SelectedCells SelectedNotebook Selection SelectionAnimate SelectionCell SelectionCellCreateCell SelectionCellDefaultStyle SelectionCellParentStyle SelectionCreateCell SelectionDebuggerTag SelectionDuplicateCell SelectionEvaluate SelectionEvaluateCreateCell SelectionMove SelectionPlaceholder SelectionSetStyle SelectWithContents SelfLoops SelfLoopStyle SemialgebraicComponentInstances SendMail Sequence SequenceAlignment SequenceForm SequenceHold SequenceLimit Series SeriesCoefficient SeriesData SessionTime Set SetAccuracy SetAlphaChannel SetAttributes Setbacks SetBoxFormNamesPacket SetDelayed SetDirectory SetEnvironment SetEvaluationNotebook SetFileDate SetFileLoadingContext SetNotebookStatusLine SetOptions SetOptionsPacket SetPrecision SetProperty SetSelectedNotebook SetSharedFunction SetSharedVariable SetSpeechParametersPacket SetStreamPosition SetSystemOptions Setter SetterBar SetterBox SetterBoxOptions Setting SetValue Shading Shallow ShannonWavelet ShapiroWilkTest Share Sharpen ShearingMatrix ShearingTransform ShenCastanMatrix Short ShortDownArrow Shortest ShortestMatch ShortestPathFunction ShortLeftArrow ShortRightArrow ShortUpArrow Show ShowAutoStyles ShowCellBracket ShowCellLabel ShowCellTags ShowClosedCellArea ShowContents ShowControls ShowCursorTracker ShowGroupOpenCloseIcon ShowGroupOpener ShowInvisibleCharacters ShowPageBreaks ShowPredictiveInterface ShowSelection ShowShortBoxForm ShowSpecialCharacters ShowStringCharacters ShowSyntaxStyles ShrinkingDelay ShrinkWrapBoundingBox SiegelTheta SiegelTukeyTest Sign Signature SignedRankTest SignificanceLevel SignPadding SignTest SimilarityRules SimpleGraph SimpleGraphQ Simplify Sin Sinc SinghMaddalaDistribution SingleEvaluation SingleLetterItalics SingleLetterStyle SingularValueDecomposition SingularValueList SingularValuePlot SingularValues Sinh SinhIntegral SinIntegral SixJSymbol Skeleton SkeletonTransform SkellamDistribution Skewness SkewNormalDistribution Skip SliceDistribution Slider Slider2D Slider2DBox Slider2DBoxOptions SliderBox SliderBoxOptions SlideView Slot SlotSequence Small SmallCircle Smaller SmithDelayCompensator SmithWatermanSimilarity SmoothDensityHistogram SmoothHistogram SmoothHistogram3D SmoothKernelDistribution SocialMediaData Socket SokalSneathDissimilarity Solve SolveAlways SolveDelayed Sort SortBy Sound SoundAndGraphics SoundNote SoundVolume Sow Space SpaceForm Spacer Spacings Span SpanAdjustments SpanCharacterRounding SpanFromAbove SpanFromBoth SpanFromLeft SpanLineThickness SpanMaxSize SpanMinSize SpanningCharacters SpanSymmetric SparseArray SpatialGraphDistribution Speak SpeakTextPacket SpearmanRankTest SpearmanRho Spectrogram SpectrogramArray Specularity SpellingCorrection SpellingDictionaries SpellingDictionariesPath SpellingOptions SpellingSuggestionsPacket Sphere SphereBox SphericalBesselJ SphericalBesselY SphericalHankelH1 SphericalHankelH2 SphericalHarmonicY SphericalPlot3D SphericalRegion SpheroidalEigenvalue SpheroidalJoiningFactor SpheroidalPS SpheroidalPSPrime SpheroidalQS SpheroidalQSPrime SpheroidalRadialFactor SpheroidalS1 SpheroidalS1Prime SpheroidalS2 SpheroidalS2Prime Splice SplicedDistribution SplineClosed SplineDegree SplineKnots SplineWeights Split SplitBy SpokenString Sqrt SqrtBox SqrtBoxOptions Square SquaredEuclideanDistance SquareFreeQ SquareIntersection SquaresR SquareSubset SquareSubsetEqual SquareSuperset SquareSupersetEqual SquareUnion SquareWave StabilityMargins StabilityMarginsStyle StableDistribution Stack StackBegin StackComplete StackInhibit StandardDeviation StandardDeviationFilter StandardForm Standardize StandbyDistribution Star StarGraph StartAsynchronousTask StartingStepSize StartOfLine StartOfString StartScheduledTask StartupSound StateDimensions StateFeedbackGains StateOutputEstimator StateResponse StateSpaceModel StateSpaceRealization StateSpaceTransform StationaryDistribution StationaryWaveletPacketTransform StationaryWaveletTransform StatusArea StatusCentrality StepMonitor StieltjesGamma StirlingS1 StirlingS2 StopAsynchronousTask StopScheduledTask StrataVariables StratonovichProcess StreamColorFunction StreamColorFunctionScaling StreamDensityPlot StreamPlot StreamPoints StreamPosition Streams StreamScale StreamStyle String StringBreak StringByteCount StringCases StringCount StringDrop StringExpression StringForm StringFormat StringFreeQ StringInsert StringJoin StringLength StringMatchQ StringPosition StringQ StringReplace StringReplaceList StringReplacePart StringReverse StringRotateLeft StringRotateRight StringSkeleton StringSplit StringTake StringToStream StringTrim StripBoxes StripOnInput StripWrapperBoxes StrokeForm StructuralImportance StructuredArray StructuredSelection StruveH StruveL Stub StudentTDistribution Style StyleBox StyleBoxAutoDelete StyleBoxOptions StyleData StyleDefinitions StyleForm StyleKeyMapping StyleMenuListing StyleNameDialogSettings StyleNames StylePrint StyleSheetPath Subfactorial Subgraph SubMinus SubPlus SubresultantPolynomialRemainders SubresultantPolynomials Subresultants Subscript SubscriptBox SubscriptBoxOptions Subscripted Subset SubsetEqual Subsets SubStar Subsuperscript SubsuperscriptBox SubsuperscriptBoxOptions Subtract SubtractFrom SubValues Succeeds SucceedsEqual SucceedsSlantEqual SucceedsTilde SuchThat Sum SumConvergence Sunday SuperDagger SuperMinus SuperPlus Superscript SuperscriptBox SuperscriptBoxOptions Superset SupersetEqual SuperStar Surd SurdForm SurfaceColor SurfaceGraphics SurvivalDistribution SurvivalFunction SurvivalModel SurvivalModelFit SuspendPacket SuzukiDistribution SuzukiGroupSuz SwatchLegend Switch Symbol SymbolName SymletWavelet Symmetric SymmetricGroup SymmetricMatrixQ SymmetricPolynomial SymmetricReduction Symmetrize SymmetrizedArray SymmetrizedArrayRules SymmetrizedDependentComponents SymmetrizedIndependentComponents SymmetrizedReplacePart SynchronousInitialization SynchronousUpdating Syntax SyntaxForm SyntaxInformation SyntaxLength SyntaxPacket SyntaxQ SystemDialogInput SystemException SystemHelpPath SystemInformation SystemInformationData SystemOpen SystemOptions SystemsModelDelay SystemsModelDelayApproximate SystemsModelDelete SystemsModelDimensions SystemsModelExtract SystemsModelFeedbackConnect SystemsModelLabels SystemsModelOrder SystemsModelParallelConnect SystemsModelSeriesConnect SystemsModelStateFeedbackConnect SystemStub Tab TabFilling Table TableAlignments TableDepth TableDirections TableForm TableHeadings TableSpacing TableView TableViewBox TabSpacings TabView TabViewBox TabViewBoxOptions TagBox TagBoxNote TagBoxOptions TaggingRules TagSet TagSetDelayed TagStyle TagUnset Take TakeWhile Tally Tan Tanh TargetFunctions TargetUnits TautologyQ TelegraphProcess TemplateBox TemplateBoxOptions TemplateSlotSequence TemporalData Temporary TemporaryVariable TensorContract TensorDimensions TensorExpand TensorProduct TensorQ TensorRank TensorReduce TensorSymmetry TensorTranspose TensorWedge Tetrahedron TetrahedronBox TetrahedronBoxOptions TeXForm TeXSave Text Text3DBox Text3DBoxOptions TextAlignment TextBand TextBoundingBox TextBox TextCell TextClipboardType TextData TextForm TextJustification TextLine TextPacket TextParagraph TextRecognize TextRendering TextStyle Texture TextureCoordinateFunction TextureCoordinateScaling Therefore ThermometerGauge Thick Thickness Thin Thinning ThisLink ThompsonGroupTh Thread ThreeJSymbol Threshold Through Throw Thumbnail Thursday Ticks TicksStyle Tilde TildeEqual TildeFullEqual TildeTilde TimeConstrained TimeConstraint Times TimesBy TimeSeriesForecast TimeSeriesInvertibility TimeUsed TimeValue TimeZone Timing Tiny TitleGrouping TitsGroupT ToBoxes ToCharacterCode ToColor ToContinuousTimeModel ToDate ToDiscreteTimeModel ToeplitzMatrix ToExpression ToFileName Together Toggle ToggleFalse Toggler TogglerBar TogglerBox TogglerBoxOptions ToHeldExpression ToInvertibleTimeSeries TokenWords Tolerance ToLowerCase ToNumberField TooBig Tooltip TooltipBox TooltipBoxOptions TooltipDelay TooltipStyle Top TopHatTransform TopologicalSort ToRadicals ToRules ToString Total TotalHeight TotalVariationFilter TotalWidth TouchscreenAutoZoom TouchscreenControlPlacement ToUpperCase Tr Trace TraceAbove TraceAction TraceBackward TraceDepth TraceDialog TraceForward TraceInternal TraceLevel TraceOff TraceOn TraceOriginal TracePrint TraceScan TrackedSymbols TradingChart TraditionalForm TraditionalFunctionNotation TraditionalNotation TraditionalOrder TransferFunctionCancel TransferFunctionExpand TransferFunctionFactor TransferFunctionModel TransferFunctionPoles TransferFunctionTransform TransferFunctionZeros TransformationFunction TransformationFunctions TransformationMatrix TransformedDistribution TransformedField Translate TranslationTransform TransparentColor Transpose TreeForm TreeGraph TreeGraphQ TreePlot TrendStyle TriangleWave TriangularDistribution Trig TrigExpand TrigFactor TrigFactorList Trigger TrigReduce TrigToExp TrimmedMean True TrueQ TruncatedDistribution TsallisQExponentialDistribution TsallisQGaussianDistribution TTest Tube TubeBezierCurveBox TubeBezierCurveBoxOptions TubeBox TubeBSplineCurveBox TubeBSplineCurveBoxOptions Tuesday TukeyLambdaDistribution TukeyWindow Tuples TuranGraph TuringMachine Transparent UnateQ Uncompress Undefined UnderBar Underflow Underlined Underoverscript UnderoverscriptBox UnderoverscriptBoxOptions Underscript UnderscriptBox UnderscriptBoxOptions UndirectedEdge UndirectedGraph UndirectedGraphQ UndocumentedTestFEParserPacket UndocumentedTestGetSelectionPacket Unequal Unevaluated UniformDistribution UniformGraphDistribution UniformSumDistribution Uninstall Union UnionPlus Unique UnitBox UnitConvert UnitDimensions Unitize UnitRootTest UnitSimplify UnitStep UnitTriangle UnitVector Unprotect UnsameQ UnsavedVariables Unset UnsetShared UntrackedVariables Up UpArrow UpArrowBar UpArrowDownArrow Update UpdateDynamicObjects UpdateDynamicObjectsSynchronous UpdateInterval UpDownArrow UpEquilibrium UpperCaseQ UpperLeftArrow UpperRightArrow UpperTriangularize Upsample UpSet UpSetDelayed UpTee UpTeeArrow UpValues URL URLFetch URLFetchAsynchronous URLSave URLSaveAsynchronous UseGraphicsRange Using UsingFrontEnd V2Get ValidationLength Value ValueBox ValueBoxOptions ValueForm ValueQ ValuesData Variables Variance VarianceEquivalenceTest VarianceEstimatorFunction VarianceGammaDistribution VarianceTest VectorAngle VectorColorFunction VectorColorFunctionScaling VectorDensityPlot VectorGlyphData VectorPlot VectorPlot3D VectorPoints VectorQ Vectors VectorScale VectorStyle Vee Verbatim Verbose VerboseConvertToPostScriptPacket VerifyConvergence VerifySolutions VerifyTestAssumptions Version VersionNumber VertexAdd VertexCapacity VertexColors VertexComponent VertexConnectivity VertexCoordinateRules VertexCoordinates VertexCorrelationSimilarity VertexCosineSimilarity VertexCount VertexCoverQ VertexDataCoordinates VertexDegree VertexDelete VertexDiceSimilarity VertexEccentricity VertexInComponent VertexInDegree VertexIndex VertexJaccardSimilarity VertexLabeling VertexLabels VertexLabelStyle VertexList VertexNormals VertexOutComponent VertexOutDegree VertexQ VertexRenderingFunction VertexReplace VertexShape VertexShapeFunction VertexSize VertexStyle VertexTextureCoordinates VertexWeight Vertical VerticalBar VerticalForm VerticalGauge VerticalSeparator VerticalSlider VerticalTilde ViewAngle ViewCenter ViewMatrix ViewPoint ViewPointSelectorSettings ViewPort ViewRange ViewVector ViewVertical VirtualGroupData Visible VisibleCell VoigtDistribution VonMisesDistribution WaitAll WaitAsynchronousTask WaitNext WaitUntil WakebyDistribution WalleniusHypergeometricDistribution WaringYuleDistribution WatershedComponents WatsonUSquareTest WattsStrogatzGraphDistribution WaveletBestBasis WaveletFilterCoefficients WaveletImagePlot WaveletListPlot WaveletMapIndexed WaveletMatrixPlot WaveletPhi WaveletPsi WaveletScale WaveletScalogram WaveletThreshold WeaklyConnectedComponents WeaklyConnectedGraphQ WeakStationarity WeatherData WeberE Wedge Wednesday WeibullDistribution WeierstrassHalfPeriods WeierstrassInvariants WeierstrassP WeierstrassPPrime WeierstrassSigma WeierstrassZeta WeightedAdjacencyGraph WeightedAdjacencyMatrix WeightedData WeightedGraphQ Weights WelchWindow WheelGraph WhenEvent Which While White Whitespace WhitespaceCharacter WhittakerM WhittakerW WienerFilter WienerProcess WignerD WignerSemicircleDistribution WilksW WilksWTest WindowClickSelect WindowElements WindowFloating WindowFrame WindowFrameElements WindowMargins WindowMovable WindowOpacity WindowSelected WindowSize WindowStatusArea WindowTitle WindowToolbars WindowWidth With WolframAlpha WolframAlphaDate WolframAlphaQuantity WolframAlphaResult Word WordBoundary WordCharacter WordData WordSearch WordSeparators WorkingPrecision Write WriteString Wronskian XMLElement XMLObject Xnor Xor Yellow YuleDissimilarity ZernikeR ZeroSymmetric ZeroTest ZeroWidthTimes Zeta ZetaZero ZipfDistribution ZTest ZTransform $Aborted $ActivationGroupID $ActivationKey $ActivationUserRegistered $AddOnsDirectory $AssertFunction $Assumptions $AsynchronousTask $BaseDirectory $BatchInput $BatchOutput $BoxForms $ByteOrdering $Canceled $CharacterEncoding $CharacterEncodings $CommandLine $CompilationTarget $ConditionHold $ConfiguredKernels $Context $ContextPath $ControlActiveSetting $CreationDate $CurrentLink $DateStringFormat $DefaultFont $DefaultFrontEnd $DefaultImagingDevice $DefaultPath $Display $DisplayFunction $DistributedContexts $DynamicEvaluation $Echo $Epilog $ExportFormats $Failed $FinancialDataSource $FormatType $FrontEnd $FrontEndSession $GeoLocation $HistoryLength $HomeDirectory $HTTPCookies $IgnoreEOF $ImagingDevices $ImportFormats $InitialDirectory $Input $InputFileName $InputStreamMethods $Inspector $InstallationDate $InstallationDirectory $InterfaceEnvironment $IterationLimit $KernelCount $KernelID $Language $LaunchDirectory $LibraryPath $LicenseExpirationDate $LicenseID $LicenseProcesses $LicenseServer $LicenseSubprocesses $LicenseType $Line $Linked $LinkSupported $LoadedFiles $MachineAddresses $MachineDomain $MachineDomains $MachineEpsilon $MachineID $MachineName $MachinePrecision $MachineType $MaxExtraPrecision $MaxLicenseProcesses $MaxLicenseSubprocesses $MaxMachineNumber $MaxNumber $MaxPiecewiseCases $MaxPrecision $MaxRootDegree $MessageGroups $MessageList $MessagePrePrint $Messages $MinMachineNumber $MinNumber $MinorReleaseNumber $MinPrecision $ModuleNumber $NetworkLicense $NewMessage $NewSymbol $Notebooks $NumberMarks $Off $OperatingSystem $Output $OutputForms $OutputSizeLimit $OutputStreamMethods $Packages $ParentLink $ParentProcessID $PasswordFile $PatchLevelID $Path $PathnameSeparator $PerformanceGoal $PipeSupported $Post $Pre $PreferencesDirectory $PrePrint $PreRead $PrintForms $PrintLiteral $ProcessID $ProcessorCount $ProcessorType $ProductInformation $ProgramName $RandomState $RecursionLimit $ReleaseNumber $RootDirectory $ScheduledTask $ScriptCommandLine $SessionID $SetParentLink $SharedFunctions $SharedVariables $SoundDisplay $SoundDisplayFunction $SuppressInputFormHeads $SynchronousEvaluation $SyntaxHandler $System $SystemCharacterEncoding $SystemID $SystemWordLength $TemporaryDirectory $TemporaryPrefix $TextStyle $TimedOut $TimeUnit $TimeZone $TopDirectory $TraceOff $TraceOn $TracePattern $TracePostAction $TracePreAction $Urgent $UserAddOnsDirectory $UserBaseDirectory $UserDocumentsDirectory $UserName $Version $VersionNumber", -c:[{cN:"comment",b:/\(\*/,e:/\*\)/},e.ASM,e.QSM,e.CNM,{b:/\{/,e:/\}/,i:/:/}]}});hljs.registerLanguage("tp",function(O){var R={cN:"number",b:"[1-9][0-9]*",r:0},E={cN:"symbol",b:":[^\\]]+"},T={cN:"built_in",b:"(AR|P|PAYLOAD|PR|R|SR|RSR|LBL|VR|UALM|MESSAGE|UTOOL|UFRAME|TIMER| TIMER_OVERFLOW|JOINT_MAX_SPEED|RESUME_PROG|DIAG_REC)\\[",e:"\\]",c:["self",R,E]},N={cN:"built_in",b:"(AI|AO|DI|DO|F|RI|RO|UI|UO|GI|GO|SI|SO)\\[",e:"\\]",c:["self",R,O.QSM,E]};return{k:{keyword:"ABORT ACC ADJUST AND AP_LD BREAK CALL CNT COL CONDITION CONFIG DA DB DIV DETECT ELSE END ENDFOR ERR_NUM ERROR_PROG FINE FOR GP GUARD INC IF JMP LINEAR_MAX_SPEED LOCK MOD MONITOR OFFSET Offset OR OVERRIDE PAUSE PREG PTH RT_LD RUN SELECT SKIP Skip TA TB TO TOOL_OFFSET Tool_Offset UF UT UFRAME_NUM UTOOL_NUM UNLOCK WAIT X Y Z W P R STRLEN SUBSTR FINDSTR VOFFSET PROG ATTR MN POS",literal:"ON OFF max_speed LPOS JPOS ENABLE DISABLE START STOP RESET"},c:[T,N,{cN:"keyword",b:"/(PROG|ATTR|MN|POS|END)\\b"},{cN:"keyword",b:"(CALL|RUN|POINT_LOGIC|LBL)\\b"},{cN:"keyword",b:"\\b(ACC|CNT|Skip|Offset|PSPD|RT_LD|AP_LD|Tool_Offset)"},{cN:"number",b:"\\d+(sec|msec|mm/sec|cm/min|inch/min|deg/sec|mm|in|cm)?\\b",r:0},O.C("//","[;$]"),O.C("!","[;$]"),O.C("--eg:","$"),O.QSM,{cN:"string",b:"'",e:"'"},O.CNM,{cN:"variable",b:"\\$[A-Za-z0-9_]+"}]}});hljs.registerLanguage("nimrod",function(t){return{aliases:["nim"],k:{keyword:"addr and as asm bind block break case cast const continue converter discard distinct div do elif else end enum except export finally for from generic if import in include interface is isnot iterator let macro method mixin mod nil not notin object of or out proc ptr raise ref return shl shr static template try tuple type using var when while with without xor yield",literal:"shared guarded stdin stdout stderr result true false",built_in:"int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 float float32 float64 bool char string cstring pointer expr stmt void auto any range array openarray varargs seq set clong culong cchar cschar cshort cint csize clonglong cfloat cdouble clongdouble cuchar cushort cuint culonglong cstringarray semistatic"},c:[{cN:"meta",b:/{\./,e:/\.}/,r:10},{cN:"string",b:/[a-zA-Z]\w*"/,e:/"/,c:[{b:/""/}]},{cN:"string",b:/([a-zA-Z]\w*)?"""/,e:/"""/},t.QSM,{cN:"type",b:/\b[A-Z]\w+\b/,r:0},{cN:"number",r:0,v:[{b:/\b(0[xX][0-9a-fA-F][_0-9a-fA-F]*)('?[iIuU](8|16|32|64))?/},{b:/\b(0o[0-7][_0-7]*)('?[iIuUfF](8|16|32|64))?/},{b:/\b(0(b|B)[01][_01]*)('?[iIuUfF](8|16|32|64))?/},{b:/\b(\d[_\d]*)('?[iIuUfF](8|16|32|64))?/}]},t.HCM]}});hljs.registerLanguage("1c",function(c){var e="[a-zA-Zа-яА-Я][a-zA-Z0-9_а-яА-Я]*",n="возврат дата для если и или иначе иначеесли исключение конецесли конецпопытки конецпроцедуры конецфункции конеццикла константа не перейти перем перечисление по пока попытка прервать продолжить процедура строка тогда фс функция цикл число экспорт",b="ansitooem oemtoansi ввестивидсубконто ввестидату ввестизначение ввестиперечисление ввестипериод ввестиплансчетов ввестистроку ввестичисло вопрос восстановитьзначение врег выбранныйплансчетов вызватьисключение датагод датамесяц датачисло добавитьмесяц завершитьработусистемы заголовоксистемы записьжурналарегистрации запуститьприложение зафиксироватьтранзакцию значениевстроку значениевстрокувнутр значениевфайл значениеизстроки значениеизстрокивнутр значениеизфайла имякомпьютера имяпользователя каталогвременныхфайлов каталогиб каталогпользователя каталогпрограммы кодсимв командасистемы конгода конецпериодаби конецрассчитанногопериодаби конецстандартногоинтервала конквартала конмесяца коннедели лев лог лог10 макс максимальноеколичествосубконто мин монопольныйрежим названиеинтерфейса названиенабораправ назначитьвид назначитьсчет найти найтипомеченныенаудаление найтиссылки началопериодаби началостандартногоинтервала начатьтранзакцию начгода начквартала начмесяца начнедели номерднягода номерднянедели номернеделигода нрег обработкаожидания окр описаниеошибки основнойжурналрасчетов основнойплансчетов основнойязык открытьформу открытьформумодально отменитьтранзакцию очиститьокносообщений периодстр полноеимяпользователя получитьвремята получитьдатута получитьдокументта получитьзначенияотбора получитьпозициюта получитьпустоезначение получитьта прав праводоступа предупреждение префиксавтонумерации пустаястрока пустоезначение рабочаядаттьпустоезначение рабочаядата разделительстраниц разделительстрок разм разобратьпозициюдокумента рассчитатьрегистрына рассчитатьрегистрыпо сигнал симв символтабуляции создатьобъект сокрл сокрлп сокрп сообщить состояние сохранитьзначение сред статусвозврата стрдлина стрзаменить стрколичествострок стрполучитьстроку стрчисловхождений сформироватьпозициюдокумента счетпокоду текущаядата текущеевремя типзначения типзначениястр удалитьобъекты установитьтана установитьтапо фиксшаблон формат цел шаблон",i={b:'""'},r={cN:"string",b:'"',e:'"|$',c:[i]},t={cN:"string",b:"\\|",e:'"|$',c:[i]};return{cI:!0,l:e,k:{keyword:n,built_in:b},c:[c.CLCM,c.NM,r,t,{cN:"function",b:"(процедура|функция)",e:"$",l:e,k:"процедура функция",c:[{b:"экспорт",eW:!0,l:e,k:"экспорт",c:[c.CLCM]},{cN:"params",b:"\\(",e:"\\)",l:e,k:"знач",c:[r,t]},c.CLCM,c.inherit(c.TM,{b:e})]},{cN:"meta",b:"#",e:"$"},{cN:"number",b:"'\\d{2}\\.\\d{2}\\.(\\d{2}|\\d{4})'"}]}});hljs.registerLanguage("twig",function(e){var t={cN:"params",b:"\\(",e:"\\)"},a="attribute block constant cycle date dump include max min parent random range source template_from_string",r={bK:a,k:{name:a},r:0,c:[t]},c={b:/\|[A-Za-z_]+:?/,k:"abs batch capitalize convert_encoding date date_modify default escape first format join json_encode keys last length lower merge nl2br number_format raw replace reverse round slice sort split striptags title trim upper url_encode",c:[r]},s="autoescape block do embed extends filter flush for if import include macro sandbox set spaceless use verbatim";return s=s+" "+s.split(" ").map(function(e){return"end"+e}).join(" "),{aliases:["craftcms"],cI:!0,sL:"xml",c:[e.C(/\{#/,/#}/),{cN:"template-tag",b:/\{%/,e:/%}/,c:[{cN:"name",b:/\w+/,k:s,starts:{eW:!0,c:[c,r],r:0}}]},{cN:"template-variable",b:/\{\{/,e:/}}/,c:["self",c,r]}]}});hljs.registerLanguage("dts",function(e){var a={cN:"string",v:[e.inherit(e.QSM,{b:'((u8?|U)|L)?"'}),{b:'(u8?|U)?R"',e:'"',c:[e.BE]},{b:"'\\\\?.",e:"'",i:"."}]},c={cN:"number",v:[{b:"\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)"},{b:e.CNR}],r:0},b={cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef ifdef ifndef"},c:[{b:/\\\n/,r:0},{bK:"include",e:"$",k:{"meta-keyword":"include"},c:[e.inherit(a,{cN:"meta-string"}),{cN:"meta-string",b:"<",e:">",i:"\\n"}]},a,e.CLCM,e.CBCM]},i={cN:"variable",b:"\\&[a-z\\d_]*\\b"},r={cN:"meta-keyword",b:"/[a-z][a-z\\d-]*/"},d={cN:"symbol",b:"^\\s*[a-zA-Z_][a-zA-Z\\d_]*:"},n={cN:"params",b:"<",e:">",c:[c,i]},s={cN:"class",b:/[a-zA-Z_][a-zA-Z\d_@]*\s{/,e:/[{;=]/,rB:!0,eE:!0},t={cN:"class",b:"/\\s*{",e:"};",r:10,c:[i,r,d,s,n,e.CLCM,e.CBCM,c,a]};return{k:"",c:[t,i,r,d,s,n,e.CLCM,e.CBCM,c,a,b,{b:e.IR+"::",k:""}]}});hljs.registerLanguage("scss",function(e){var t="[a-zA-Z-][a-zA-Z0-9_-]*",i={cN:"variable",b:"(\\$"+t+")\\b"},r={cN:"number",b:"#[0-9A-Fa-f]+"};({cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:!0,i:"[^\\s]",starts:{eW:!0,eE:!0,c:[r,e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"meta",b:"!important"}]}});return{cI:!0,i:"[=/|']",c:[e.CLCM,e.CBCM,{cN:"selector-id",b:"\\#[A-Za-z0-9_-]+",r:0},{cN:"selector-class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"selector-attr",b:"\\[",e:"\\]",i:"$"},{cN:"selector-tag",b:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b",r:0},{b:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)"},{b:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)"},i,{cN:"attribute",b:"\\b(z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b",i:"[^\\s]"},{b:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{b:":",e:";",c:[i,r,e.CSSNM,e.QSM,e.ASM,{cN:"meta",b:"!important"}]},{b:"@",e:"[{;]",k:"mixin include extend for if else each while charset import debug media page content font-face namespace warn",c:[i,e.QSM,e.ASM,r,e.CSSNM,{b:"\\s[A-Za-z0-9_.-]+",r:0}]}]}});hljs.registerLanguage("haml",function(s){return{cI:!0,c:[{cN:"meta",b:"^!!!( (5|1\\.1|Strict|Frameset|Basic|Mobile|RDFa|XML\\b.*))?$",r:10},s.C("^\\s*(!=#|=#|-#|/).*$",!1,{r:0}),{b:"^\\s*(-|=|!=)(?!#)",starts:{e:"\\n",sL:"ruby"}},{cN:"tag",b:"^\\s*%",c:[{cN:"selector-tag",b:"\\w+"},{cN:"selector-id",b:"#[\\w-]+"},{cN:"selector-class",b:"\\.[\\w-]+"},{b:"{\\s*",e:"\\s*}",c:[{b:":\\w+\\s*=>",e:",\\s+",rB:!0,eW:!0,c:[{cN:"attr",b:":\\w+"},s.ASM,s.QSM,{b:"\\w+",r:0}]}]},{b:"\\(\\s*",e:"\\s*\\)",eE:!0,c:[{b:"\\w+\\s*=",e:"\\s+",rB:!0,eW:!0,c:[{cN:"attr",b:"\\w+",r:0},s.ASM,s.QSM,{b:"\\w+",r:0}]}]}]},{b:"^\\s*[=~]\\s*"},{b:"#{",starts:{e:"}",sL:"ruby"}}]}});hljs.registerLanguage("openscad",function(e){var r={cN:"keyword",b:"\\$(f[asn]|t|vp[rtd]|children)"},n={cN:"literal",b:"false|true|PI|undef"},o={cN:"number",b:"\\b\\d+(\\.\\d+)?(e-?\\d+)?",r:0},i=e.inherit(e.QSM,{i:null}),t={cN:"meta",k:{"meta-keyword":"include use"},b:"include|use <",e:">"},s={cN:"params",b:"\\(",e:"\\)",c:["self",o,i,r,n]},c={b:"[*!#%]",r:0},a={cN:"function",bK:"module function",e:"\\=|\\{",c:[s,e.UTM]};return{aliases:["scad"],k:{keyword:"function module include use for intersection_for if else \\%",literal:"false true PI undef",built_in:"circle square polygon text sphere cube cylinder polyhedron translate rotate scale resize mirror multmatrix color offset hull minkowski union difference intersection abs sign sin cos tan acos asin atan atan2 floor round ceil ln log pow sqrt exp rands min max concat lookup str chr search version version_num norm cross parent_module echo import import_dxf dxf_linear_extrude linear_extrude rotate_extrude surface projection render children dxf_cross dxf_dim let assign"},c:[e.CLCM,e.CBCM,o,t,i,r,c,a]}});hljs.registerLanguage("gherkin",function(e){return{aliases:["feature"],k:"Feature Background Ability Business Need Scenario Scenarios Scenario Outline Scenario Template Examples Given And Then But When",c:[{cN:"symbol",b:"\\*",r:0},{cN:"meta",b:"@[^@\\s]+"},{b:"\\|",e:"\\|\\w*$",c:[{cN:"string",b:"[^|]+"}]},{cN:"variable",b:"<",e:">"},e.HCM,{cN:"string",b:'"""',e:'"""'},e.QSM]}});hljs.registerLanguage("cal",function(e){var r="div mod in and or not xor asserterror begin case do downto else end exit for if of repeat then to until while with var",t="false true",c=[e.CLCM,e.C(/\{/,/\}/,{r:0}),e.C(/\(\*/,/\*\)/,{r:10})],n={cN:"string",b:/'/,e:/'/,c:[{b:/''/}]},o={cN:"string",b:/(#\d+)+/},a={cN:"number",b:"\\b\\d+(\\.\\d+)?(DT|D|T)",r:0},i={cN:"string",b:'"',e:'"'},d={cN:"function",bK:"procedure",e:/[:;]/,k:"procedure|10",c:[e.TM,{cN:"params",b:/\(/,e:/\)/,k:r,c:[n,o]}].concat(c)},s={cN:"class",b:"OBJECT (Table|Form|Report|Dataport|Codeunit|XMLport|MenuSuite|Page|Query) (\\d+) ([^\\r\\n]+)",rB:!0,c:[e.TM,d]};return{cI:!0,k:{keyword:r,literal:t},i:/\/\*/,c:[n,o,a,i,e.NM,s,d]}});hljs.registerLanguage("autohotkey",function(e){var r={b:/`[\s\S]/};return{cI:!0,k:{keyword:"Break Continue Else Gosub If Loop Return While",literal:"A|0 true false NOT AND OR",built_in:"ComSpec Clipboard ClipboardAll ErrorLevel"},c:[{cN:"built_in",b:"A_[a-zA-Z0-9]+"},r,e.inherit(e.QSM,{c:[r]}),e.C(";","$",{r:0}),{cN:"number",b:e.NR,r:0},{cN:"variable",b:"%",e:"%",i:"\\n",c:[r]},{cN:"symbol",c:[r],v:[{b:'^[^\\n";]+::(?!=)'},{b:'^[^\\n";]+:(?!=)',r:0}]},{b:",\\s*,"}]}});hljs.registerLanguage("flix",function(e){var t={cN:"string",b:/'(.|\\[xXuU][a-zA-Z0-9]+)'/},i={cN:"string",v:[{b:'"',e:'"'}]},n={cN:"title",b:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/},c={cN:"function",bK:"def",e:/[:={\[(\n;]/,eE:!0,c:[n]};return{k:{literal:"true false",keyword:"case class def else enum if impl import in lat rel index let match namespace switch type yield with"},c:[e.CLCM,e.CBCM,t,i,c,e.CNM]}});hljs.registerLanguage("crmsh",function(t){var e="primitive rsc_template",r="group clone ms master location colocation order fencing_topology rsc_ticket acl_target acl_group user role tag xml",s="property rsc_defaults op_defaults",a="params meta operations op rule attributes utilization",i="read write deny defined not_defined in_range date spec in ref reference attribute type xpath version and or lt gt tag lte gte eq ne \\",o="number string",n="Master Started Slave Stopped start promote demote stop monitor true false";return{aliases:["crm","pcmk"],cI:!0,k:{keyword:a+" "+i+" "+o,literal:n},c:[t.HCM,{bK:"node",starts:{e:"\\s*([\\w_-]+:)?",starts:{cN:"title",e:"\\s*[\\$\\w_][\\w_-]*"}}},{bK:e,starts:{cN:"title",e:"\\s*[\\$\\w_][\\w_-]*",starts:{e:"\\s*@?[\\w_][\\w_\\.:-]*"}}},{b:"\\b("+r.split(" ").join("|")+")\\s+",k:r,starts:{cN:"title",e:"[\\$\\w_][\\w_-]*"}},{bK:s,starts:{cN:"title",e:"\\s*([\\w_-]+:)?"}},t.QSM,{cN:"meta",b:"(ocf|systemd|service|lsb):[\\w_:-]+",r:0},{cN:"number",b:"\\b\\d+(\\.\\d+)?(ms|s|h|m)?",r:0},{cN:"literal",b:"[-]?(infinity|inf)",r:0},{cN:"attr",b:/([A-Za-z\$_\#][\w_-]+)=/,r:0},{cN:"tag",b:"",r:0}]}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}});hljs.registerLanguage("dust",function(e){var t="if eq ne lt lte gt gte select default math sep";return{aliases:["dst"],cI:!0,sL:"xml",c:[{cN:"template-tag",b:/\{[#\/]/,e:/\}/,i:/;/,c:[{cN:"name",b:/[a-zA-Z\.-]+/,starts:{eW:!0,r:0,c:[e.QSM]}}]},{cN:"template-variable",b:/\{/,e:/\}/,i:/;/,k:t}]}});hljs.registerLanguage("tex",function(c){var e={cN:"tag",b:/\\/,r:0,c:[{cN:"name",v:[{b:/[a-zA-Zа-яА-я]+[*]?/},{b:/[^a-zA-Zа-яА-я0-9]/}],starts:{eW:!0,r:0,c:[{cN:"string",v:[{b:/\[/,e:/\]/},{b:/\{/,e:/\}/}]},{b:/\s*=\s*/,eW:!0,r:0,c:[{cN:"number",b:/-?\d*\.?\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?/}]}]}}]};return{c:[e,{cN:"formula",c:[e],r:0,v:[{b:/\$\$/,e:/\$\$/},{b:/\$/,e:/\$/}]},c.C("%","$",{r:0})]}});hljs.registerLanguage("pf",function(t){var o={cN:"variable",b:/\$[\w\d#@][\w\d_]*/},e={cN:"variable",b:/<(?!\/)/,e:/>/};return{aliases:["pf.conf"],l:/[a-z0-9_<>-]+/,k:{built_in:"block match pass load anchor|5 antispoof|10 set table",keyword:"in out log quick on rdomain inet inet6 proto from port os to routeallow-opts divert-packet divert-reply divert-to flags group icmp-typeicmp6-type label once probability recieved-on rtable prio queuetos tag tagged user keep fragment for os dropaf-to|10 binat-to|10 nat-to|10 rdr-to|10 bitmask least-stats random round-robinsource-hash static-portdup-to reply-to route-toparent bandwidth default min max qlimitblock-policy debug fingerprints hostid limit loginterface optimizationreassemble ruleset-optimization basic none profile skip state-defaultsstate-policy timeoutconst counters persistno modulate synproxy state|5 floating if-bound no-sync pflow|10 sloppysource-track global rule max-src-nodes max-src-states max-src-connmax-src-conn-rate overload flushscrub|5 max-mss min-ttl no-df|10 random-id",literal:"all any no-route self urpf-failed egress|5 unknown"},c:[t.HCM,t.NM,t.QSM,o,e]}});hljs.registerLanguage("fix",function(u){return{c:[{b:/[^\u2401\u0001]+/,e:/[\u2401\u0001]/,eE:!0,rB:!0,rE:!1,c:[{b:/([^\u2401\u0001=]+)/,e:/=([^\u2401\u0001=]+)/,rE:!0,rB:!1,cN:"attr"},{b:/=/,e:/([\u2401\u0001])/,eE:!0,eB:!0,cN:"string"}]}],cI:!0}});hljs.registerLanguage("swift",function(e){var t={keyword:"__COLUMN__ __FILE__ __FUNCTION__ __LINE__ as as! as? associativity break case catch class continue convenience default defer deinit didSet do dynamic dynamicType else enum extension fallthrough false final for func get guard if import in indirect infix init inout internal is lazy left let mutating nil none nonmutating operator optional override postfix precedence prefix private protocol Protocol public repeat required rethrows return right self Self set static struct subscript super switch throw throws true try try! try? Type typealias unowned var weak where while willSet",literal:"true false nil",built_in:"abs advance alignof alignofValue anyGenerator assert assertionFailure bridgeFromObjectiveC bridgeFromObjectiveCUnconditional bridgeToObjectiveC bridgeToObjectiveCUnconditional c contains count countElements countLeadingZeros debugPrint debugPrintln distance dropFirst dropLast dump encodeBitsAsWords enumerate equal fatalError filter find getBridgedObjectiveCType getVaList indices insertionSort isBridgedToObjectiveC isBridgedVerbatimToObjectiveC isUniquelyReferenced isUniquelyReferencedNonObjC join lazy lexicographicalCompare map max maxElement min minElement numericCast overlaps partition posix precondition preconditionFailure print println quickSort readLine reduce reflect reinterpretCast reverse roundUpToAlignment sizeof sizeofValue sort split startsWith stride strideof strideofValue swap toString transcode underestimateCount unsafeAddressOf unsafeBitCast unsafeDowncast unsafeUnwrap unsafeReflect withExtendedLifetime withObjectAtPlusZero withUnsafePointer withUnsafePointerToObject withUnsafeMutablePointer withUnsafeMutablePointers withUnsafePointer withUnsafePointers withVaList zip"},i={cN:"type",b:"\\b[A-Z][\\wÀ-ʸ']*",r:0},n=e.C("/\\*","\\*/",{c:["self"]}),r={cN:"subst",b:/\\\(/,e:"\\)",k:t,c:[]},a={cN:"number",b:"\\b([\\d_]+(\\.[\\deE_]+)?|0x[a-fA-F0-9_]+(\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\b",r:0},o=e.inherit(e.QSM,{c:[r,e.BE]});return r.c=[a],{k:t,c:[o,e.CLCM,n,i,a,{cN:"function",bK:"func",e:"{",eE:!0,c:[e.inherit(e.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{b://},{cN:"params",b:/\(/,e:/\)/,endsParent:!0,k:t,c:["self",a,o,e.CBCM,{b:":"}],i:/["']/}],i:/\[|%/},{cN:"class",bK:"struct protocol class extension enum",k:t,e:"\\{",eE:!0,c:[e.inherit(e.TM,{b:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/})]},{cN:"meta",b:"(@warn_unused_result|@exported|@lazy|@noescape|@NSCopying|@NSManaged|@objc|@convention|@required|@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|@infix|@prefix|@postfix|@autoclosure|@testable|@available|@nonobjc|@NSApplicationMain|@UIApplicationMain)"},{bK:"import",e:/$/,c:[e.CLCM,n]}]}});hljs.registerLanguage("livecodeserver",function(e){var r={b:"\\b[gtps][A-Z]+[A-Za-z0-9_\\-]*\\b|\\$_[A-Z]+",r:0},t=[e.CBCM,e.HCM,e.C("--","$"),e.C("[^:]//","$")],a=e.inherit(e.TM,{v:[{b:"\\b_*rig[A-Z]+[A-Za-z0-9_\\-]*"},{b:"\\b_[a-z0-9\\-]+"}]}),o=e.inherit(e.TM,{b:"\\b([A-Za-z0-9_\\-]+)\\b"});return{cI:!1,k:{keyword:"$_COOKIE $_FILES $_GET $_GET_BINARY $_GET_RAW $_POST $_POST_BINARY $_POST_RAW $_SESSION $_SERVER codepoint codepoints segment segments codeunit codeunits sentence sentences trueWord trueWords paragraph after byte bytes english the until http forever descending using line real8 with seventh for stdout finally element word words fourth before black ninth sixth characters chars stderr uInt1 uInt1s uInt2 uInt2s stdin string lines relative rel any fifth items from middle mid at else of catch then third it file milliseconds seconds second secs sec int1 int1s int4 int4s internet int2 int2s normal text item last long detailed effective uInt4 uInt4s repeat end repeat URL in try into switch to words https token binfile each tenth as ticks tick system real4 by dateItems without char character ascending eighth whole dateTime numeric short first ftp integer abbreviated abbr abbrev private case while if div mod wrap and or bitAnd bitNot bitOr bitXor among not in a an within contains ends with begins the keys of keys",literal:"SIX TEN FORMFEED NINE ZERO NONE SPACE FOUR FALSE COLON CRLF PI COMMA ENDOFFILE EOF EIGHT FIVE QUOTE EMPTY ONE TRUE RETURN CR LINEFEED RIGHT BACKSLASH NULL SEVEN TAB THREE TWO six ten formfeed nine zero none space four false colon crlf pi comma endoffile eof eight five quote empty one true return cr linefeed right backslash null seven tab three two RIVERSION RISTATE FILE_READ_MODE FILE_WRITE_MODE FILE_WRITE_MODE DIR_WRITE_MODE FILE_READ_UMASK FILE_WRITE_UMASK DIR_READ_UMASK DIR_WRITE_UMASK",built_in:"put abs acos aliasReference annuity arrayDecode arrayEncode asin atan atan2 average avg avgDev base64Decode base64Encode baseConvert binaryDecode binaryEncode byteOffset byteToNum cachedURL cachedURLs charToNum cipherNames codepointOffset codepointProperty codepointToNum codeunitOffset commandNames compound compress constantNames cos date dateFormat decompress directories diskSpace DNSServers exp exp1 exp2 exp10 extents files flushEvents folders format functionNames geometricMean global globals hasMemory harmonicMean hostAddress hostAddressToName hostName hostNameToAddress isNumber ISOToMac itemOffset keys len length libURLErrorData libUrlFormData libURLftpCommand libURLLastHTTPHeaders libURLLastRHHeaders libUrlMultipartFormAddPart libUrlMultipartFormData libURLVersion lineOffset ln ln1 localNames log log2 log10 longFilePath lower macToISO matchChunk matchText matrixMultiply max md5Digest median merge millisec millisecs millisecond milliseconds min monthNames nativeCharToNum normalizeText num number numToByte numToChar numToCodepoint numToNativeChar offset open openfiles openProcesses openProcessIDs openSockets paragraphOffset paramCount param params peerAddress pendingMessages platform popStdDev populationStandardDeviation populationVariance popVariance processID random randomBytes replaceText result revCreateXMLTree revCreateXMLTreeFromFile revCurrentRecord revCurrentRecordIsFirst revCurrentRecordIsLast revDatabaseColumnCount revDatabaseColumnIsNull revDatabaseColumnLengths revDatabaseColumnNames revDatabaseColumnNamed revDatabaseColumnNumbered revDatabaseColumnTypes revDatabaseConnectResult revDatabaseCursors revDatabaseID revDatabaseTableNames revDatabaseType revDataFromQuery revdb_closeCursor revdb_columnbynumber revdb_columncount revdb_columnisnull revdb_columnlengths revdb_columnnames revdb_columntypes revdb_commit revdb_connect revdb_connections revdb_connectionerr revdb_currentrecord revdb_cursorconnection revdb_cursorerr revdb_cursors revdb_dbtype revdb_disconnect revdb_execute revdb_iseof revdb_isbof revdb_movefirst revdb_movelast revdb_movenext revdb_moveprev revdb_query revdb_querylist revdb_recordcount revdb_rollback revdb_tablenames revGetDatabaseDriverPath revNumberOfRecords revOpenDatabase revOpenDatabases revQueryDatabase revQueryDatabaseBlob revQueryResult revQueryIsAtStart revQueryIsAtEnd revUnixFromMacPath revXMLAttribute revXMLAttributes revXMLAttributeValues revXMLChildContents revXMLChildNames revXMLCreateTreeFromFileWithNamespaces revXMLCreateTreeWithNamespaces revXMLDataFromXPathQuery revXMLEvaluateXPath revXMLFirstChild revXMLMatchingNode revXMLNextSibling revXMLNodeContents revXMLNumberOfChildren revXMLParent revXMLPreviousSibling revXMLRootNode revXMLRPC_CreateRequest revXMLRPC_Documents revXMLRPC_Error revXMLRPC_GetHost revXMLRPC_GetMethod revXMLRPC_GetParam revXMLText revXMLRPC_Execute revXMLRPC_GetParamCount revXMLRPC_GetParamNode revXMLRPC_GetParamType revXMLRPC_GetPath revXMLRPC_GetPort revXMLRPC_GetProtocol revXMLRPC_GetRequest revXMLRPC_GetResponse revXMLRPC_GetSocket revXMLTree revXMLTrees revXMLValidateDTD revZipDescribeItem revZipEnumerateItems revZipOpenArchives round sampVariance sec secs seconds sentenceOffset sha1Digest shell shortFilePath sin specialFolderPath sqrt standardDeviation statRound stdDev sum sysError systemVersion tan tempName textDecode textEncode tick ticks time to tokenOffset toLower toUpper transpose truewordOffset trunc uniDecode uniEncode upper URLDecode URLEncode URLStatus uuid value variableNames variance version waitDepth weekdayNames wordOffset xsltApplyStylesheet xsltApplyStylesheetFromFile xsltLoadStylesheet xsltLoadStylesheetFromFile add breakpoint cancel clear local variable file word line folder directory URL close socket process combine constant convert create new alias folder directory decrypt delete variable word line folder directory URL dispatch divide do encrypt filter get include intersect kill libURLDownloadToFile libURLFollowHttpRedirects libURLftpUpload libURLftpUploadFile libURLresetAll libUrlSetAuthCallback libURLSetCustomHTTPHeaders libUrlSetExpect100 libURLSetFTPListCommand libURLSetFTPMode libURLSetFTPStopTime libURLSetStatusCallback load multiply socket prepare process post seek rel relative read from process rename replace require resetAll resolve revAddXMLNode revAppendXML revCloseCursor revCloseDatabase revCommitDatabase revCopyFile revCopyFolder revCopyXMLNode revDeleteFolder revDeleteXMLNode revDeleteAllXMLTrees revDeleteXMLTree revExecuteSQL revGoURL revInsertXMLNode revMoveFolder revMoveToFirstRecord revMoveToLastRecord revMoveToNextRecord revMoveToPreviousRecord revMoveToRecord revMoveXMLNode revPutIntoXMLNode revRollBackDatabase revSetDatabaseDriverPath revSetXMLAttribute revXMLRPC_AddParam revXMLRPC_DeleteAllDocuments revXMLAddDTD revXMLRPC_Free revXMLRPC_FreeAll revXMLRPC_DeleteDocument revXMLRPC_DeleteParam revXMLRPC_SetHost revXMLRPC_SetMethod revXMLRPC_SetPort revXMLRPC_SetProtocol revXMLRPC_SetSocket revZipAddItemWithData revZipAddItemWithFile revZipAddUncompressedItemWithData revZipAddUncompressedItemWithFile revZipCancel revZipCloseArchive revZipDeleteItem revZipExtractItemToFile revZipExtractItemToVariable revZipSetProgressCallback revZipRenameItem revZipReplaceItemWithData revZipReplaceItemWithFile revZipOpenArchive send set sort split start stop subtract union unload wait write"},c:[r,{cN:"keyword",b:"\\bend\\sif\\b"},{cN:"function",bK:"function",e:"$",c:[r,o,e.ASM,e.QSM,e.BNM,e.CNM,a]},{cN:"function",b:"\\bend\\s+",e:"$",k:"end",c:[o,a],r:0},{bK:"command on",e:"$",c:[r,o,e.ASM,e.QSM,e.BNM,e.CNM,a]},{cN:"meta",v:[{b:"<\\?(rev|lc|livecode)",r:10},{b:"<\\?"},{b:"\\?>"}]},e.ASM,e.QSM,e.BNM,e.CNM,a].concat(t),i:";$|^\\[|^=|&|{"}});hljs.registerLanguage("armasm",function(s){return{cI:!0,aliases:["arm"],l:"\\.?"+s.IR,k:{meta:".2byte .4byte .align .ascii .asciz .balign .byte .code .data .else .end .endif .endm .endr .equ .err .exitm .extern .global .hword .if .ifdef .ifndef .include .irp .long .macro .rept .req .section .set .skip .space .text .word .arm .thumb .code16 .code32 .force_thumb .thumb_func .ltorg ALIAS ALIGN ARM AREA ASSERT ATTR CN CODE CODE16 CODE32 COMMON CP DATA DCB DCD DCDU DCDO DCFD DCFDU DCI DCQ DCQU DCW DCWU DN ELIF ELSE END ENDFUNC ENDIF ENDP ENTRY EQU EXPORT EXPORTAS EXTERN FIELD FILL FUNCTION GBLA GBLL GBLS GET GLOBAL IF IMPORT INCBIN INCLUDE INFO KEEP LCLA LCLL LCLS LTORG MACRO MAP MEND MEXIT NOFP OPT PRESERVE8 PROC QN READONLY RELOC REQUIRE REQUIRE8 RLIST FN ROUT SETA SETL SETS SN SPACE SUBT THUMB THUMBX TTL WHILE WEND ",built_in:"r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 pc lr sp ip sl sb fp a1 a2 a3 a4 v1 v2 v3 v4 v5 v6 v7 v8 f0 f1 f2 f3 f4 f5 f6 f7 p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 q10 q11 q12 q13 q14 q15 cpsr_c cpsr_x cpsr_s cpsr_f cpsr_cx cpsr_cxs cpsr_xs cpsr_xsf cpsr_sf cpsr_cxsf spsr_c spsr_x spsr_s spsr_f spsr_cx spsr_cxs spsr_xs spsr_xsf spsr_sf spsr_cxsf s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 s16 s17 s18 s19 s20 s21 s22 s23 s24 s25 s26 s27 s28 s29 s30 s31 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 {PC} {VAR} {TRUE} {FALSE} {OPT} {CONFIG} {ENDIAN} {CODESIZE} {CPU} {FPU} {ARCHITECTURE} {PCSTOREOFFSET} {ARMASM_VERSION} {INTER} {ROPI} {RWPI} {SWST} {NOSWST} . @"},c:[{cN:"keyword",b:"\\b(adc|(qd?|sh?|u[qh]?)?add(8|16)?|usada?8|(q|sh?|u[qh]?)?(as|sa)x|and|adrl?|sbc|rs[bc]|asr|b[lx]?|blx|bxj|cbn?z|tb[bh]|bic|bfc|bfi|[su]bfx|bkpt|cdp2?|clz|clrex|cmp|cmn|cpsi[ed]|cps|setend|dbg|dmb|dsb|eor|isb|it[te]{0,3}|lsl|lsr|ror|rrx|ldm(([id][ab])|f[ds])?|ldr((s|ex)?[bhd])?|movt?|mvn|mra|mar|mul|[us]mull|smul[bwt][bt]|smu[as]d|smmul|smmla|mla|umlaal|smlal?([wbt][bt]|d)|mls|smlsl?[ds]|smc|svc|sev|mia([bt]{2}|ph)?|mrr?c2?|mcrr2?|mrs|msr|orr|orn|pkh(tb|bt)|rbit|rev(16|sh)?|sel|[su]sat(16)?|nop|pop|push|rfe([id][ab])?|stm([id][ab])?|str(ex)?[bhd]?|(qd?)?sub|(sh?|q|u[qh]?)?sub(8|16)|[su]xt(a?h|a?b(16)?)|srs([id][ab])?|swpb?|swi|smi|tst|teq|wfe|wfi|yield)(eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al|hs|lo)?[sptrx]?",e:"\\s"},s.C("[;@]","$",{r:0}),s.CBCM,s.QSM,{cN:"string",b:"'",e:"[^\\\\]'",r:0},{cN:"title",b:"\\|",e:"\\|",i:"\\n",r:0},{cN:"number",v:[{b:"[#$=]?0x[0-9a-f]+"},{b:"[#$=]?0b[01]+"},{b:"[#$=]\\d+"},{b:"\\b\\d+"}],r:0},{cN:"symbol",v:[{b:"^[a-z_\\.\\$][a-z0-9_\\.\\$]+"},{b:"^\\s*[a-z_\\.\\$][a-z0-9_\\.\\$]+:"},{b:"[=#]\\w+"}],r:0}]}});hljs.registerLanguage("go",function(e){var t={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",literal:"true false iota nil",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};return{aliases:["golang"],k:t,i:"{}*#]/,c:[{bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment",e:/;/,eW:!0,l:/[\w\.]+/,k:{keyword:"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[e.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}});hljs.registerLanguage("cmake",function(e){return{aliases:["cmake.in"],cI:!0,k:{keyword:"add_custom_command add_custom_target add_definitions add_dependencies add_executable add_library add_subdirectory add_test aux_source_directory break build_command cmake_minimum_required cmake_policy configure_file create_test_sourcelist define_property else elseif enable_language enable_testing endforeach endfunction endif endmacro endwhile execute_process export find_file find_library find_package find_path find_program fltk_wrap_ui foreach function get_cmake_property get_directory_property get_filename_component get_property get_source_file_property get_target_property get_test_property if include include_directories include_external_msproject include_regular_expression install link_directories load_cache load_command macro mark_as_advanced message option output_required_files project qt_wrap_cpp qt_wrap_ui remove_definitions return separate_arguments set set_directory_properties set_property set_source_files_properties set_target_properties set_tests_properties site_name source_group string target_link_libraries try_compile try_run unset variable_watch while build_name exec_program export_library_dependencies install_files install_programs install_targets link_libraries make_directory remove subdir_depends subdirs use_mangled_mesa utility_source variable_requires write_file qt5_use_modules qt5_use_package qt5_wrap_cpp on off true false and or equal less greater strless strgreater strequal matches"},c:[{cN:"variable",b:"\\${",e:"}"},e.HCM,e.QSM,e.NM]}});hljs.registerLanguage("erb",function(e){return{sL:"xml",c:[e.C("<%#","%>"),{b:"<%[%=-]?",e:"[%-]?%>",sL:"ruby",eB:!0,eE:!0}]}});hljs.registerLanguage("gradle",function(e){return{cI:!0,k:{keyword:"task project allprojects subprojects artifacts buildscript configurations dependencies repositories sourceSets description delete from into include exclude source classpath destinationDir includes options sourceCompatibility targetCompatibility group flatDir doLast doFirst flatten todir fromdir ant def abstract break case catch continue default do else extends final finally for if implements instanceof native new private protected public return static switch synchronized throw throws transient try volatile while strictfp package import false null super this true antlrtask checkstyle codenarc copy boolean byte char class double float int interface long short void compile runTime file fileTree abs any append asList asWritable call collect compareTo count div dump each eachByte eachFile eachLine every find findAll flatten getAt getErr getIn getOut getText grep immutable inject inspect intersect invokeMethods isCase join leftShift minus multiply newInputStream newOutputStream newPrintWriter newReader newWriter next plus pop power previous print println push putAt read readBytes readLines reverse reverseEach round size sort splitEachLine step subMap times toInteger toList tokenize upto waitForOrKill withPrintWriter withReader withStream withWriter withWriterAppend write writeLine"},c:[e.CLCM,e.CBCM,e.ASM,e.QSM,e.NM,e.RM]}});hljs.registerLanguage("lua",function(e){var t="\\[=*\\[",a="\\]=*\\]",r={b:t,e:a,c:["self"]},n=[e.C("--(?!"+t+")","$"),e.C("--"+t,a,{c:[r],r:10})];return{l:e.UIR,k:{literal:"true false nil",keyword:"and break do else elseif end for goto if in local not or repeat return then until while",built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstringmodule next pairs pcall print rawequal rawget rawset require select setfenvsetmetatable tonumber tostring type unpack xpcall arg selfcoroutine resume yield status wrap create running debug getupvaluedebug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenvio lines write close flush open output type read stderr stdin input stdout popen tmpfilemath, log, max, acos, huge, ldexp, pi, cos, tanh, pow, deg, tan, cosh, sinh, random, randomseed, frexp, ceil, floor, rad, abs, sqrt, modf, asin, min, mod, fmod, log10, atan2, exp, sin, atanos, exit, setlocale, date, getenv, difftime, remove, time, clock, tmpname, rename, execute, package, preload, loadlib, loaded, loaders, cpath, config path, seeallstring, sub, upper, len, gfind, rep, find, match, char, dump, gmatch, reverse, byte, format, gsub, lowertable, setn, insert, getn, foreachi, maxn, foreach, concat, sort, remove"},c:n.concat([{cN:"function",bK:"function",e:"\\)",c:[e.inherit(e.TM,{b:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{cN:"params",b:"\\(",eW:!0,c:n}].concat(n)},e.CNM,e.ASM,e.QSM,{cN:"string",b:t,e:a,c:[r],r:5}])}});hljs.registerLanguage("mipsasm",function(s){return{cI:!0,aliases:["mips"],l:"\\.?"+s.IR,k:{meta:".2byte .4byte .align .ascii .asciz .balign .byte .code .data .else .end .endif .endm .endr .equ .err .exitm .extern .global .hword .if .ifdef .ifndef .include .irp .long .macro .rept .req .section .set .skip .space .text .word .ltorg ",built_in:"$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 $17 $18 $19 $20 $21 $22 $23 $24 $25 $26 $27 $28 $29 $30 $31 zero at v0 v1 a0 a1 a2 a3 a4 a5 a6 a7 t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 s0 s1 s2 s3 s4 s5 s6 s7 s8 k0 k1 gp sp fp ra $f0 $f1 $f2 $f2 $f4 $f5 $f6 $f7 $f8 $f9 $f10 $f11 $f12 $f13 $f14 $f15 $f16 $f17 $f18 $f19 $f20 $f21 $f22 $f23 $f24 $f25 $f26 $f27 $f28 $f29 $f30 $f31 Context Random EntryLo0 EntryLo1 Context PageMask Wired EntryHi HWREna BadVAddr Count Compare SR IntCtl SRSCtl SRSMap Cause EPC PRId EBase Config Config1 Config2 Config3 LLAddr Debug DEPC DESAVE CacheErr ECC ErrorEPC TagLo DataLo TagHi DataHi WatchLo WatchHi PerfCtl PerfCnt "},c:[{cN:"keyword",b:"\\b(addi?u?|andi?|b(al)?|beql?|bgez(al)?l?|bgtzl?|blezl?|bltz(al)?l?|bnel?|cl[oz]|divu?|ext|ins|j(al)?|jalr(.hb)?|jr(.hb)?|lbu?|lhu?|ll|lui|lw[lr]?|maddu?|mfhi|mflo|movn|movz|move|msubu?|mthi|mtlo|mul|multu?|nop|nor|ori?|rotrv?|sb|sc|se[bh]|sh|sllv?|slti?u?|srav?|srlv?|subu?|sw[lr]?|xori?|wsbh|abs.[sd]|add.[sd]|alnv.ps|bc1[ft]l?|c.(s?f|un|u?eq|[ou]lt|[ou]le|ngle?|seq|l[et]|ng[et]).[sd]|(ceil|floor|round|trunc).[lw].[sd]|cfc1|cvt.d.[lsw]|cvt.l.[dsw]|cvt.ps.s|cvt.s.[dlw]|cvt.s.p[lu]|cvt.w.[dls]|div.[ds]|ldx?c1|luxc1|lwx?c1|madd.[sd]|mfc1|mov[fntz]?.[ds]|msub.[sd]|mth?c1|mul.[ds]|neg.[ds]|nmadd.[ds]|nmsub.[ds]|p[lu][lu].ps|recip.fmt|r?sqrt.[ds]|sdx?c1|sub.[ds]|suxc1|swx?c1|break|cache|d?eret|[de]i|ehb|mfc0|mtc0|pause|prefx?|rdhwr|rdpgpr|sdbbp|ssnop|synci?|syscall|teqi?|tgei?u?|tlb(p|r|w[ir])|tlti?u?|tnei?|wait|wrpgpr)",e:"\\s"},s.C("[;#]","$"),s.CBCM,s.QSM,{cN:"string",b:"'",e:"[^\\\\]'",r:0},{cN:"title",b:"\\|",e:"\\|",i:"\\n",r:0},{cN:"number",v:[{b:"0x[0-9a-f]+"},{b:"\\b-?\\d+"}],r:0},{cN:"symbol",v:[{b:"^\\s*[a-z_\\.\\$][a-z0-9_\\.\\$]+:"},{b:"^\\s*[0-9]+:"},{b:"[0-9]+[bf]"}],r:0}],i:"/"}});hljs.registerLanguage("arduino",function(e){var t=e.getLanguage("cpp").exports;return{k:{keyword:"boolean byte word string String array "+t.k.keyword,built_in:"setup loop while catch for if do goto try switch case else default break continue return KeyboardController MouseController SoftwareSerial EthernetServer EthernetClient LiquidCrystal RobotControl GSMVoiceCall EthernetUDP EsploraTFT HttpClient RobotMotor WiFiClient GSMScanner FileSystem Scheduler GSMServer YunClient YunServer IPAddress GSMClient GSMModem Keyboard Ethernet Console GSMBand Esplora Stepper Process WiFiUDP GSM_SMS Mailbox USBHost Firmata PImage Client Server GSMPIN FileIO Bridge Serial EEPROM Stream Mouse Audio Servo File Task GPRS WiFi Wire TFT GSM SPI SD runShellCommandAsynchronously analogWriteResolution retrieveCallingNumber printFirmwareVersion analogReadResolution sendDigitalPortPair noListenOnLocalhost readJoystickButton setFirmwareVersion readJoystickSwitch scrollDisplayRight getVoiceCallStatus scrollDisplayLeft writeMicroseconds delayMicroseconds beginTransmission getSignalStrength runAsynchronously getAsynchronously listenOnLocalhost getCurrentCarrier readAccelerometer messageAvailable sendDigitalPorts lineFollowConfig countryNameWrite runShellCommand readStringUntil rewindDirectory readTemperature setClockDivider readLightSensor endTransmission analogReference detachInterrupt countryNameRead attachInterrupt encryptionType readBytesUntil robotNameWrite readMicrophone robotNameRead cityNameWrite userNameWrite readJoystickY readJoystickX mouseReleased openNextFile scanNetworks noInterrupts digitalWrite beginSpeaker mousePressed isActionDone mouseDragged displayLogos noAutoscroll addParameter remoteNumber getModifiers keyboardRead userNameRead waitContinue processInput parseCommand printVersion readNetworks writeMessage blinkVersion cityNameRead readMessage setDataMode parsePacket isListening setBitOrder beginPacket isDirectory motorsWrite drawCompass digitalRead clearScreen serialEvent rightToLeft setTextSize leftToRight requestFrom keyReleased compassRead analogWrite interrupts WiFiServer disconnect playMelody parseFloat autoscroll getPINUsed setPINUsed setTimeout sendAnalog readSlider analogRead beginWrite createChar motorsStop keyPressed tempoWrite readButton subnetMask debugPrint macAddress writeGreen randomSeed attachGPRS readString sendString remotePort releaseAll mouseMoved background getXChange getYChange answerCall getResult voiceCall endPacket constrain getSocket writeJSON getButton available connected findUntil readBytes exitValue readGreen writeBlue startLoop IPAddress isPressed sendSysex pauseMode gatewayIP setCursor getOemKey tuneWrite noDisplay loadImage switchPIN onRequest onReceive changePIN playFile noBuffer parseInt overflow checkPIN knobRead beginTFT bitClear updateIR bitWrite position writeRGB highByte writeRed setSpeed readBlue noStroke remoteIP transfer shutdown hangCall beginSMS endWrite attached maintain noCursor checkReg checkPUK shiftOut isValid shiftIn pulseIn connect println localIP pinMode getIMEI display noBlink process getBand running beginSD drawBMP lowByte setBand release bitRead prepare pointTo readRed setMode noFill remove listen stroke detach attach noTone exists buffer height bitSet circle config cursor random IRread setDNS endSMS getKey micros millis begin print write ready flush width isPIN blink clear press mkdir rmdir close point yield image BSSID click delay read text move peek beep rect line open seek fill size turn stop home find step tone sqrt RSSI SSID end bit tan cos sin pow map abs max min get run put",literal:"DIGITAL_MESSAGE FIRMATA_STRING ANALOG_MESSAGE REPORT_DIGITAL REPORT_ANALOG INPUT_PULLUP SET_PIN_MODE INTERNAL2V56 SYSTEM_RESET LED_BUILTIN INTERNAL1V1 SYSEX_START INTERNAL EXTERNAL DEFAULT OUTPUT INPUT HIGH LOW"},c:[t.preprocessor,e.CLCM,e.CBCM,e.ASM,e.QSM,e.CNM]}});hljs.registerLanguage("excel",function(E){return{aliases:["xlsx","xls"],cI:!0,l:/[a-zA-Z][\w\.]*/,k:{built_in:"ABS ACCRINT ACCRINTM ACOS ACOSH ACOT ACOTH AGGREGATE ADDRESS AMORDEGRC AMORLINC AND ARABIC AREAS ASC ASIN ASINH ATAN ATAN2 ATANH AVEDEV AVERAGE AVERAGEA AVERAGEIF AVERAGEIFS BAHTTEXT BASE BESSELI BESSELJ BESSELK BESSELY BETADIST BETA.DIST BETAINV BETA.INV BIN2DEC BIN2HEX BIN2OCT BINOMDIST BINOM.DIST BINOM.DIST.RANGE BINOM.INV BITAND BITLSHIFT BITOR BITRSHIFT BITXOR CALL CEILING CEILING.MATH CEILING.PRECISE CELL CHAR CHIDIST CHIINV CHITEST CHISQ.DIST CHISQ.DIST.RT CHISQ.INV CHISQ.INV.RT CHISQ.TEST CHOOSE CLEAN CODE COLUMN COLUMNS COMBIN COMBINA COMPLEX CONCAT CONCATENATE CONFIDENCE CONFIDENCE.NORM CONFIDENCE.T CONVERT CORREL COS COSH COT COTH COUNT COUNTA COUNTBLANK COUNTIF COUNTIFS COUPDAYBS COUPDAYS COUPDAYSNC COUPNCD COUPNUM COUPPCD COVAR COVARIANCE.P COVARIANCE.S CRITBINOM CSC CSCH CUBEKPIMEMBER CUBEMEMBER CUBEMEMBERPROPERTY CUBERANKEDMEMBER CUBESET CUBESETCOUNT CUBEVALUE CUMIPMT CUMPRINC DATE DATEDIF DATEVALUE DAVERAGE DAY DAYS DAYS360 DB DBCS DCOUNT DCOUNTA DDB DEC2BIN DEC2HEX DEC2OCT DECIMAL DEGREES DELTA DEVSQ DGET DISC DMAX DMIN DOLLAR DOLLARDE DOLLARFR DPRODUCT DSTDEV DSTDEVP DSUM DURATION DVAR DVARP EDATE EFFECT ENCODEURL EOMONTH ERF ERF.PRECISE ERFC ERFC.PRECISE ERROR.TYPE EUROCONVERT EVEN EXACT EXP EXPON.DIST EXPONDIST FACT FACTDOUBLE FALSE|0 F.DIST FDIST F.DIST.RT FILTERXML FIND FINDB F.INV F.INV.RT FINV FISHER FISHERINV FIXED FLOOR FLOOR.MATH FLOOR.PRECISE FORECAST FORECAST.ETS FORECAST.ETS.CONFINT FORECAST.ETS.SEASONALITY FORECAST.ETS.STAT FORECAST.LINEAR FORMULATEXT FREQUENCY F.TEST FTEST FV FVSCHEDULE GAMMA GAMMA.DIST GAMMADIST GAMMA.INV GAMMAINV GAMMALN GAMMALN.PRECISE GAUSS GCD GEOMEAN GESTEP GETPIVOTDATA GROWTH HARMEAN HEX2BIN HEX2DEC HEX2OCT HLOOKUP HOUR HYPERLINK HYPGEOM.DIST HYPGEOMDIST IF|0 IFERROR IFNA IFS IMABS IMAGINARY IMARGUMENT IMCONJUGATE IMCOS IMCOSH IMCOT IMCSC IMCSCH IMDIV IMEXP IMLN IMLOG10 IMLOG2 IMPOWER IMPRODUCT IMREAL IMSEC IMSECH IMSIN IMSINH IMSQRT IMSUB IMSUM IMTAN INDEX INDIRECT INFO INT INTERCEPT INTRATE IPMT IRR ISBLANK ISERR ISERROR ISEVEN ISFORMULA ISLOGICAL ISNA ISNONTEXT ISNUMBER ISODD ISREF ISTEXT ISO.CEILING ISOWEEKNUM ISPMT JIS KURT LARGE LCM LEFT LEFTB LEN LENB LINEST LN LOG LOG10 LOGEST LOGINV LOGNORM.DIST LOGNORMDIST LOGNORM.INV LOOKUP LOWER MATCH MAX MAXA MAXIFS MDETERM MDURATION MEDIAN MID MIDBs MIN MINIFS MINA MINUTE MINVERSE MIRR MMULT MOD MODE MODE.MULT MODE.SNGL MONTH MROUND MULTINOMIAL MUNIT N NA NEGBINOM.DIST NEGBINOMDIST NETWORKDAYS NETWORKDAYS.INTL NOMINAL NORM.DIST NORMDIST NORMINV NORM.INV NORM.S.DIST NORMSDIST NORM.S.INV NORMSINV NOT NOW NPER NPV NUMBERVALUE OCT2BIN OCT2DEC OCT2HEX ODD ODDFPRICE ODDFYIELD ODDLPRICE ODDLYIELD OFFSET OR PDURATION PEARSON PERCENTILE.EXC PERCENTILE.INC PERCENTILE PERCENTRANK.EXC PERCENTRANK.INC PERCENTRANK PERMUT PERMUTATIONA PHI PHONETIC PI PMT POISSON.DIST POISSON POWER PPMT PRICE PRICEDISC PRICEMAT PROB PRODUCT PROPER PV QUARTILE QUARTILE.EXC QUARTILE.INC QUOTIENT RADIANS RAND RANDBETWEEN RANK.AVG RANK.EQ RANK RATE RECEIVED REGISTER.ID REPLACE REPLACEB REPT RIGHT RIGHTB ROMAN ROUND ROUNDDOWN ROUNDUP ROW ROWS RRI RSQ RTD SEARCH SEARCHB SEC SECH SECOND SERIESSUM SHEET SHEETS SIGN SIN SINH SKEW SKEW.P SLN SLOPE SMALL SQL.REQUEST SQRT SQRTPI STANDARDIZE STDEV STDEV.P STDEV.S STDEVA STDEVP STDEVPA STEYX SUBSTITUTE SUBTOTAL SUM SUMIF SUMIFS SUMPRODUCT SUMSQ SUMX2MY2 SUMX2PY2 SUMXMY2 SWITCH SYD T TAN TANH TBILLEQ TBILLPRICE TBILLYIELD T.DIST T.DIST.2T T.DIST.RT TDIST TEXT TEXTJOIN TIME TIMEVALUE T.INV T.INV.2T TINV TODAY TRANSPOSE TREND TRIM TRIMMEAN TRUE|0 TRUNC T.TEST TTEST TYPE UNICHAR UNICODE UPPER VALUE VAR VAR.P VAR.S VARA VARP VARPA VDB VLOOKUP WEBSERVICE WEEKDAY WEEKNUM WEIBULL WEIBULL.DIST WORKDAY WORKDAY.INTL XIRR XNPV XOR YEAR YEARFRAC YIELD YIELDDISC YIELDMAT Z.TEST ZTEST"},c:[{b:/^=/,e:/[^=]/,rE:!0,i:/=/,r:10},{cN:"symbol",b:/\b[A-Z]{1,2}\d+\b/,e:/[^\d]/,eE:!0,r:0},{cN:"symbol",b:/[A-Z]{0,2}\d*:[A-Z]{0,2}\d*/,r:0},E.BE,E.QSM,{cN:"number",b:E.NR+"(%)?",r:0},E.C(/\bN\(/,/\)/,{eB:!0,eE:!0,i:/\n/})]}});hljs.registerLanguage("rust",function(e){var t="([ui](8|16|32|64|128|size)|f(32|64))?",r="alignof as be box break const continue crate do else enum extern false fn for if impl in let loop match mod mut offsetof once priv proc pub pure ref return self Self sizeof static struct super trait true type typeof unsafe unsized use virtual while where yield move default",n="drop i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 str char bool Box Option Result String Vec Copy Send Sized Sync Drop Fn FnMut FnOnce ToOwned Clone Debug PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator SliceConcatExt ToString assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules! assert_ne! debug_assert_ne!";return{aliases:["rs"],k:{keyword:r,literal:"true false Some None Ok Err",built_in:n},l:e.IR+"!?",i:""}]}});hljs.registerLanguage("actionscript",function(e){var a="[a-zA-Z_$][a-zA-Z0-9_$]*",t="([*]|[a-zA-Z_$][a-zA-Z0-9_$]*)",c={cN:"rest_arg",b:"[.]{3}",e:a,r:10};return{aliases:["as"],k:{keyword:"as break case catch class const continue default delete do dynamic each else extends final finally for function get if implements import in include instanceof interface internal is namespace native new override package private protected public return set static super switch this throw try typeof use var void while with",literal:"true false null undefined"},c:[e.ASM,e.QSM,e.CLCM,e.CBCM,e.CNM,{cN:"class",bK:"package",e:"{",c:[e.TM]},{cN:"class",bK:"class interface",e:"{",eE:!0,c:[{bK:"extends implements"},e.TM]},{cN:"meta",bK:"import include",e:";",k:{"meta-keyword":"import include"}},{cN:"function",bK:"function",e:"[{;]",eE:!0,i:"\\S",c:[e.TM,{cN:"params",b:"\\(",e:"\\)",c:[e.ASM,e.QSM,e.CLCM,e.CBCM,c]},{b:":\\s*"+t}]},e.METHOD_GUARD],i:/#/}});hljs.registerLanguage("prolog",function(c){var b={b:/[a-z][A-Za-z0-9_]*/,r:0},r={cN:"symbol",v:[{b:/[A-Z][a-zA-Z0-9_]*/},{b:/_[A-Za-z0-9_]*/}],r:0},e={b:/\(/,e:/\)/,r:0},n={b:/\[/,e:/\]/},a={cN:"comment",b:/%/,e:/$/,c:[c.PWM]},t={cN:"string",b:/`/,e:/`/,c:[c.BE]},g={cN:"string",b:/0\'(\\\'|.)/},s={cN:"string",b:/0\'\\s/},o={b:/:-/},N=[b,r,e,o,n,a,c.CBCM,c.QSM,c.ASM,t,g,s,c.CNM];return e.c=N,n.c=N,{c:N.concat([{b:/\.$/}])}});hljs.registerLanguage("taggerscript",function(e){var c={cN:"comment",b:/\$noop\(/,e:/\)/,c:[{b:/\(/,e:/\)/,c:["self",{b:/\\./}]}],r:10},r={cN:"keyword",b:/\$(?!noop)[a-zA-Z][_a-zA-Z0-9]*/,e:/\(/,eE:!0},a={cN:"variable",b:/%[_a-zA-Z0-9:]*/,e:"%"},b={cN:"symbol",b:/\\./};return{c:[c,r,a,b]}});hljs.registerLanguage("llvm",function(e){var n="([-a-zA-Z$._][\\w\\-$.]*)";return{k:"begin end true false declare define global constant private linker_private internal available_externally linkonce linkonce_odr weak weak_odr appending dllimport dllexport common default hidden protected extern_weak external thread_local zeroinitializer undef null to tail target triple datalayout volatile nuw nsw nnan ninf nsz arcp fast exact inbounds align addrspace section alias module asm sideeffect gc dbg linker_private_weak attributes blockaddress initialexec localdynamic localexec prefix unnamed_addr ccc fastcc coldcc x86_stdcallcc x86_fastcallcc arm_apcscc arm_aapcscc arm_aapcs_vfpcc ptx_device ptx_kernel intel_ocl_bicc msp430_intrcc spir_func spir_kernel x86_64_sysvcc x86_64_win64cc x86_thiscallcc cc c signext zeroext inreg sret nounwind noreturn noalias nocapture byval nest readnone readonly inlinehint noinline alwaysinline optsize ssp sspreq noredzone noimplicitfloat naked builtin cold nobuiltin noduplicate nonlazybind optnone returns_twice sanitize_address sanitize_memory sanitize_thread sspstrong uwtable returned type opaque eq ne slt sgt sle sge ult ugt ule uge oeq one olt ogt ole oge ord uno ueq une x acq_rel acquire alignstack atomic catch cleanup filter inteldialect max min monotonic nand personality release seq_cst singlethread umax umin unordered xchg add fadd sub fsub mul fmul udiv sdiv fdiv urem srem frem shl lshr ashr and or xor icmp fcmp phi call trunc zext sext fptrunc fpext uitofp sitofp fptoui fptosi inttoptr ptrtoint bitcast addrspacecast select va_arg ret br switch invoke unwind unreachable indirectbr landingpad resume malloc alloca free load store getelementptr extractelement insertelement shufflevector getresult extractvalue insertvalue atomicrmw cmpxchg fence argmemonly double",c:[{cN:"keyword",b:"i\\d+"},e.C(";","\\n",{r:0}),e.QSM,{cN:"string",v:[{b:'"',e:'[^\\\\]"'}],r:0},{cN:"title",v:[{b:"@"+n},{b:"@\\d+"},{b:"!"+n},{b:"!\\d+"+n}]},{cN:"symbol",v:[{b:"%"+n},{b:"%\\d+"},{b:"#\\d+"}]},{cN:"number",v:[{b:"0[xX][a-fA-F0-9]+"},{b:"-?\\d+(?:[.]\\d+)?(?:[eE][-+]?\\d+(?:[.]\\d+)?)?"}],r:0}]}});hljs.registerLanguage("axapta",function(e){return{k:"false int abstract private char boolean static null if for true while long throw finally protected final return void enum else break new catch byte super case short default double public try this switch continue reverse firstfast firstonly forupdate nofetch sum avg minof maxof count order group by asc desc index hint like dispaly edit client server ttsbegin ttscommit str real date container anytype common div mod",c:[e.CLCM,e.CBCM,e.ASM,e.QSM,e.CNM,{cN:"meta",b:"#",e:"$"},{cN:"class",bK:"class interface",e:"{",eE:!0,i:":",c:[{bK:"extends implements"},e.UTM]}]}});hljs.registerLanguage("clean",function(e){return{aliases:["clean","icl","dcl"],k:{keyword:"if let in with where case of class instance otherwise implementation definition system module from import qualified as special code inline foreign export ccall stdcall generic derive infix infixl infixr",literal:"True False"},c:[e.CLCM,e.CBCM,e.ASM,e.QSM,e.CNM,{b:"->|<-[|:]?|::|#!?|>>=|\\{\\||\\|\\}|:==|=:|\\.\\.|<>|`"}]}});hljs.registerLanguage("kotlin",function(e){var t={keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit initinterface annotation data sealed internal infix operator out by constructor super trait volatile transient native default",built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing",literal:"true false null"},r={cN:"keyword",b:/\b(break|continue|return|this)\b/,starts:{c:[{cN:"symbol",b:/@\w+/}]}},i={cN:"symbol",b:e.UIR+"@"},n={cN:"subst",v:[{b:"\\$"+e.UIR},{b:"\\${",e:"}",c:[e.ASM,e.CNM]}]},a={cN:"string",v:[{b:'"""',e:'"""',c:[n]},{b:"'",e:"'",i:/\n/,c:[e.BE]},{b:'"',e:'"',i:/\n/,c:[e.BE,n]}]},c={cN:"meta",b:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UIR+")?"},s={cN:"meta",b:"@"+e.UIR,c:[{b:/\(/,e:/\)/,c:[e.inherit(a,{cN:"meta-string"})]}]};return{k:t,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,r,i,c,s,{cN:"function",bK:"fun",e:"[(]|$",rB:!0,eE:!0,k:t,i:/fun\s+(<.*>)?[^\s\(]+(\s+[^\s\(]+)\s*=/,r:5,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"type",b://,k:"reified",r:0},{cN:"params",b:/\(/,e:/\)/,endsParent:!0,k:t,r:0,c:[{b:/:/,e:/[=,\/]/,eW:!0,c:[{cN:"type",b:e.UIR},e.CLCM,e.CBCM],r:0},e.CLCM,e.CBCM,c,s,a,e.CNM]},e.CBCM]},{cN:"class",bK:"class interface trait",e:/[:\{(]|$/,eE:!0,i:"extends implements",c:[{bK:"public protected internal private constructor"},e.UTM,{cN:"type",b://,eB:!0,eE:!0,r:0},{cN:"type",b:/[,:]\s*/,e:/[<\(,]|$/,eB:!0,rE:!0},c,s]},a,{cN:"meta",b:"^#!/usr/bin/env",e:"$",i:"\n"},e.CNM]}});hljs.registerLanguage("stylus",function(e){var t={cN:"variable",b:"\\$"+e.IR},o={cN:"number",b:"#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})"},i=["charset","css","debug","extend","font-face","for","import","include","media","mixin","page","warn","while"],r=["after","before","first-letter","first-line","active","first-child","focus","hover","lang","link","visited"],n=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","mark","menu","nav","object","ol","p","q","quote","samp","section","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],a="[\\.\\s\\n\\[\\:,]",l=["align-content","align-items","align-self","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","auto","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","clip-path","color","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","cursor","direction","display","empty-cells","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","font","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-variant-ligatures","font-weight","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inherit","initial","justify-content","left","letter-spacing","line-height","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","mask","max-height","max-width","min-height","min-width","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","perspective","perspective-origin","pointer-events","position","quotes","resize","right","tab-size","table-layout","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-indent","text-overflow","text-rendering","text-shadow","text-transform","text-underline-position","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","white-space","widows","width","word-break","word-spacing","word-wrap","z-index"],d=["\\?","(\\bReturn\\b)","(\\bEnd\\b)","(\\bend\\b)","(\\bdef\\b)",";","#\\s","\\*\\s","===\\s","\\|","%"];return{aliases:["styl"],cI:!1,k:"if else for in",i:"("+d.join("|")+")",c:[e.QSM,e.ASM,e.CLCM,e.CBCM,o,{b:"\\.[a-zA-Z][a-zA-Z0-9_-]*"+a,rB:!0,c:[{cN:"selector-class",b:"\\.[a-zA-Z][a-zA-Z0-9_-]*"}]},{b:"\\#[a-zA-Z][a-zA-Z0-9_-]*"+a,rB:!0,c:[{cN:"selector-id",b:"\\#[a-zA-Z][a-zA-Z0-9_-]*"}]},{b:"\\b("+n.join("|")+")"+a,rB:!0,c:[{cN:"selector-tag",b:"\\b[a-zA-Z][a-zA-Z0-9_-]*"}]},{b:"&?:?:\\b("+r.join("|")+")"+a},{b:"@("+i.join("|")+")\\b"},t,e.CSSNM,e.NM,{cN:"function",b:"^[a-zA-Z][a-zA-Z0-9_-]*\\(.*\\)",i:"[\\n]",rB:!0,c:[{cN:"title",b:"\\b[a-zA-Z][a-zA-Z0-9_-]*"},{cN:"params",b:/\(/,e:/\)/,c:[o,t,e.ASM,e.CSSNM,e.NM,e.QSM]}]},{cN:"attribute",b:"\\b("+l.reverse().join("|")+")\\b",starts:{e:/;|$/,c:[o,t,e.ASM,e.QSM,e.CSSNM,e.NM,e.CBCM],i:/\./,r:0}}]}});hljs.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:/^\[[^\n]+\]:/,rB:!0,c:[{cN:"symbol",b:/\[/,e:/\]/,eB:!0,eE:!0},{cN:"link",b:/:\s*/,e:/$/,eB:!0}]}]}});hljs.registerLanguage("zephir",function(e){var i={cN:"string",c:[e.BE],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},n={v:[e.BNM,e.CNM]};return{aliases:["zep"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var let while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally int uint long ulong char uchar double float bool boolean stringlikely unlikely",c:[e.CLCM,e.HCM,e.C("/\\*","\\*/",{c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.C("__halt_compiler.+?;",!1,{eW:!0,k:"__halt_compiler",l:e.UIR}),{cN:"string",b:"<<<['\"]?\\w+['\"]?$",e:"^\\w+;",c:[e.BE]},{b:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",e.CBCM,i,n]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},i,n]}});hljs.registerLanguage("mercury",function(e){var i={keyword:"module use_module import_module include_module end_module initialise mutable initialize finalize finalise interface implementation pred mode func type inst solver any_pred any_func is semidet det nondet multi erroneous failure cc_nondet cc_multi typeclass instance where pragma promise external trace atomic or_else require_complete_switch require_det require_semidet require_multi require_nondet require_cc_multi require_cc_nondet require_erroneous require_failure",meta:"inline no_inline type_spec source_file fact_table obsolete memo loop_check minimal_model terminates does_not_terminate check_termination promise_equivalent_clauses foreign_proc foreign_decl foreign_code foreign_type foreign_import_module foreign_export_enum foreign_export foreign_enum may_call_mercury will_not_call_mercury thread_safe not_thread_safe maybe_thread_safe promise_pure promise_semipure tabled_for_io local untrailed trailed attach_to_io_state can_pass_as_mercury_type stable will_not_throw_exception may_modify_trail will_not_modify_trail may_duplicate may_not_duplicate affects_liveness does_not_affect_liveness doesnt_affect_liveness no_sharing unknown_sharing sharing",built_in:"some all not if then else true fail false try catch catch_any semidet_true semidet_false semidet_fail impure_true impure semipure"},r=e.C("%","$"),t={cN:"number",b:"0'.\\|0[box][0-9a-fA-F]*"},_=e.inherit(e.ASM,{r:0}),n=e.inherit(e.QSM,{r:0}),a={cN:"subst",b:"\\\\[abfnrtv]\\|\\\\x[0-9a-fA-F]*\\\\\\|%[-+# *.0-9]*[dioxXucsfeEgGp]",r:0};n.c.push(a);var o={cN:"built_in",v:[{b:"<=>"},{b:"<=",r:0},{b:"=>",r:0},{b:"/\\\\"},{b:"\\\\/"}]},l={cN:"built_in",v:[{b:":-\\|-->"},{b:"=",r:0}]};return{aliases:["m","moo"],k:i,c:[o,l,r,e.CBCM,t,e.NM,_,n,{b:/:-/}]}});hljs.registerLanguage("diff",function(e){return{aliases:["patch"],c:[{cN:"meta",r:10,v:[{b:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"comment",v:[{b:/Index: /,e:/$/},{b:/={3,}/,e:/$/},{b:/^\-{3}/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+{3}/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"addition",b:"^\\!",e:"$"}]}});hljs.registerLanguage("delphi",function(e){var r="exports register file shl array record property for mod while set ally label uses raise not stored class safecall var interface or private static exit index inherited to else stdcall override shr asm far resourcestring finalization packed virtual out and protected library do xorwrite goto near function end div overload object unit begin string on inline repeat until destructor write message program with read initialization except default nil if case cdecl in downto threadvar of try pascal const external constructor type public then implementation finally published procedure absolute reintroduce operator as is abstract alias assembler bitpacked break continue cppdecl cvar enumerator experimental platform deprecated unimplemented dynamic export far16 forward generic helper implements interrupt iochecks local name nodefault noreturn nostackframe oldfpccall otherwise saveregisters softfloat specialize strict unaligned varargs ",t=[e.CLCM,e.C(/\{/,/\}/,{r:0}),e.C(/\(\*/,/\*\)/,{r:10})],a={cN:"meta",v:[{b:/\{\$/,e:/\}/},{b:/\(\*\$/,e:/\*\)/}]},c={cN:"string",b:/'/,e:/'/,c:[{b:/''/}]},i={cN:"string",b:/(#\d+)+/},o={b:e.IR+"\\s*=\\s*class\\s*\\(",rB:!0,c:[e.TM]},n={cN:"function",bK:"function constructor destructor procedure",e:/[:;]/,k:"function constructor|10 destructor|10 procedure|10",c:[e.TM,{cN:"params",b:/\(/,e:/\)/,k:r,c:[c,i,a].concat(t)},a].concat(t)};return{aliases:["dpr","dfm","pas","pascal","freepascal","lazarus","lpr","lfm"],cI:!0,k:r,i:/"|\$[G-Zg-z]|\/\*|<\/|\|/,c:[c,i,e.NM,o,n,a].concat(t)}});hljs.registerLanguage("awk",function(e){var r={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},b="BEGIN END if else while do for in break continue delete next nextfile function func exit|10",n={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,r:10},{b:/(u|b)?r?"""/,e:/"""/,r:10},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},e.ASM,e.QSM]};return{k:{keyword:b},c:[r,n,e.RM,e.HCM,e.NM]}});hljs.registerLanguage("htmlbars",function(e){var a="action collection component concat debugger each each-in else get hash if input link-to loc log mut outlet partial query-params render textarea unbound unless with yield view",t={i:/\}\}/,b:/[a-zA-Z0-9_]+=/,rB:!0,r:0,c:[{cN:"attr",b:/[a-zA-Z0-9_]+/}]},i=({i:/\}\}/,b:/\)/,e:/\)/,c:[{b:/[a-zA-Z\.\-]+/,k:{built_in:a},starts:{eW:!0,r:0,c:[e.QSM]}}]},{eW:!0,r:0,k:{keyword:"as",built_in:a},c:[e.QSM,t,e.NM]});return{cI:!0,sL:"xml",c:[e.C("{{!(--)?","(--)?}}"),{cN:"template-tag",b:/\{\{[#\/]/,e:/\}\}/,c:[{cN:"name",b:/[a-zA-Z\.\-]+/,k:{"builtin-name":a},starts:i}]},{cN:"template-variable",b:/\{\{[a-zA-Z][a-zA-Z\-]+/,e:/\}\}/,k:{keyword:"as",built_in:a},c:[e.QSM]}]}});hljs.registerLanguage("subunit",function(s){var r={cN:"string",b:"\\[\n(multipart)?",e:"\\]\n"},t={cN:"string",b:"\\d{4}-\\d{2}-\\d{2}(\\s+)\\d{2}:\\d{2}:\\d{2}.\\d+Z"},e={cN:"string",b:"(\\+|-)\\d+"},c={cN:"keyword",r:10,v:[{b:"^(test|testing|success|successful|failure|error|skip|xfail|uxsuccess)(:?)\\s+(test)?"},{b:"^progress(:?)(\\s+)?(pop|push)?"},{b:"^tags:"},{b:"^time:"}]};return{cI:!0,c:[r,t,e,c]}});hljs.registerLanguage("haxe",function(e){var t="Int Float String Bool Dynamic Void Array ";return{aliases:["hx"],k:{keyword:"break callback case cast catch continue default do dynamic else enum extern for function here if import in inline never new override package private get set public return static super switch this throw trace try typedef untyped using var while "+t,built_in:"trace this",literal:"true false null _"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{cN:"subst",b:"\\$\\{",e:"\\}"},{cN:"subst",b:"\\$",e:"\\W}"}]},e.QSM,e.CLCM,e.CBCM,e.CNM,{cN:"meta",b:"@:",e:"$"},{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elseif end error"}},{cN:"type",b:":[ ]*",e:"[^A-Za-z0-9_ \\->]",eB:!0,eE:!0,r:0},{cN:"type",b:":[ ]*",e:"\\W",eB:!0,eE:!0},{cN:"type",b:"new *",e:"\\W",eB:!0,eE:!0},{cN:"class",bK:"enum",e:"\\{",c:[e.TM]},{cN:"class",bK:"abstract",e:"[\\{$]",c:[{cN:"type",b:"\\(",e:"\\)",eB:!0,eE:!0},{cN:"type",b:"from +",e:"\\W",eB:!0,eE:!0},{cN:"type",b:"to +",e:"\\W",eB:!0,eE:!0},e.TM],k:{keyword:"abstract from to"}},{cN:"class",b:"\\b(class|interface) +",e:"[\\{$]",eE:!0,k:"class interface",c:[{cN:"keyword",b:"\\b(extends|implements) +",k:"extends implements",c:[{cN:"type",b:e.IR,r:0}]},e.TM]},{cN:"function",bK:"function",e:"\\(",eE:!0,i:"\\S",c:[e.TM]}],i:/<\//}});hljs.registerLanguage("n1ql",function(e){return{cI:!0,c:[{bK:"build create index delete drop explain infer|10 insert merge prepare select update upsert|10",e:/;/,eW:!0,k:{keyword:"all alter analyze and any array as asc begin between binary boolean break bucket build by call case cast cluster collate collection commit connect continue correlate cover create database dataset datastore declare decrement delete derived desc describe distinct do drop each element else end every except exclude execute exists explain fetch first flatten for force from function grant group gsi having if ignore ilike in include increment index infer inline inner insert intersect into is join key keys keyspace known last left let letting like limit lsm map mapping matched materialized merge minus namespace nest not number object offset on option or order outer over parse partition password path pool prepare primary private privilege procedure public raw realm reduce rename return returning revoke right role rollback satisfies schema select self semi set show some start statistics string system then to transaction trigger truncate under union unique unknown unnest unset update upsert use user using validate value valued values via view when where while with within work xor",literal:"true false null missing|5",built_in:"array_agg array_append array_concat array_contains array_count array_distinct array_ifnull array_length array_max array_min array_position array_prepend array_put array_range array_remove array_repeat array_replace array_reverse array_sort array_sum avg count max min sum greatest least ifmissing ifmissingornull ifnull missingif nullif ifinf ifnan ifnanorinf naninf neginfif posinfif clock_millis clock_str date_add_millis date_add_str date_diff_millis date_diff_str date_part_millis date_part_str date_trunc_millis date_trunc_str duration_to_str millis str_to_millis millis_to_str millis_to_utc millis_to_zone_name now_millis now_str str_to_duration str_to_utc str_to_zone_name decode_json encode_json encoded_size poly_length base64 base64_encode base64_decode meta uuid abs acos asin atan atan2 ceil cos degrees e exp ln log floor pi power radians random round sign sin sqrt tan trunc object_length object_names object_pairs object_inner_pairs object_values object_inner_values object_add object_put object_remove object_unwrap regexp_contains regexp_like regexp_position regexp_replace contains initcap length lower ltrim position repeat replace rtrim split substr title trim upper isarray isatom isboolean isnumber isobject isstring type toarray toatom toboolean tonumber toobject tostring"},c:[{cN:"string",b:"'",e:"'",c:[e.BE],r:0},{cN:"string",b:'"',e:'"',c:[e.BE],r:0},{cN:"symbol",b:"`",e:"`",c:[e.BE],r:2},e.CNM,e.CBCM]},e.CBCM]}});hljs.registerLanguage("django",function(e){var t={b:/\|[A-Za-z]+:?/,k:{name:"truncatewords removetags linebreaksbr yesno get_digit timesince random striptags filesizeformat escape linebreaks length_is ljust rjust cut urlize fix_ampersands title floatformat capfirst pprint divisibleby add make_list unordered_list urlencode timeuntil urlizetrunc wordcount stringformat linenumbers slice date dictsort dictsortreversed default_if_none pluralize lower join center default truncatewords_html upper length phone2numeric wordwrap time addslashes slugify first escapejs force_escape iriencode last safe safeseq truncatechars localize unlocalize localtime utc timezone"},c:[e.QSM,e.ASM]};return{aliases:["jinja"],cI:!0,sL:"xml",c:[e.C(/\{%\s*comment\s*%}/,/\{%\s*endcomment\s*%}/),e.C(/\{#/,/#}/),{cN:"template-tag",b:/\{%/,e:/%}/,c:[{cN:"name",b:/\w+/,k:{name:"comment endcomment load templatetag ifchanged endifchanged if endif firstof for endfor ifnotequal endifnotequal widthratio extends include spaceless endspaceless regroup ifequal endifequal ssi now with cycle url filter endfilter debug block endblock else autoescape endautoescape csrf_token empty elif endwith static trans blocktrans endblocktrans get_static_prefix get_media_prefix plural get_current_language language get_available_languages get_current_language_bidi get_language_info get_language_info_list localize endlocalize localtime endlocaltime timezone endtimezone get_current_timezone verbatim"},starts:{eW:!0,k:"in by as",c:[t],r:0}}]},{cN:"template-variable",b:/\{\{/,e:/}}/,c:[t]}]}});hljs.registerLanguage("handlebars",function(e){var a={"builtin-name":"each in with if else unless bindattr action collection debugger log outlet template unbound view yield"};return{aliases:["hbs","html.hbs","html.handlebars"],cI:!0,sL:"xml",c:[e.C("{{!(--)?","(--)?}}"),{cN:"template-tag",b:/\{\{[#\/]/,e:/\}\}/,c:[{cN:"name",b:/[a-zA-Z\.-]+/,k:a,starts:{eW:!0,r:0,c:[e.QSM]}}]},{cN:"template-variable",b:/\{\{/,e:/\}\}/,k:a}]}});hljs.registerLanguage("roboconf",function(a){var e="[a-zA-Z-_][^\\n{]+\\{",n={cN:"attribute",b:/[a-zA-Z-_]+/,e:/\s*:/,eE:!0,starts:{e:";",r:0,c:[{cN:"variable",b:/\.[a-zA-Z-_]+/},{cN:"keyword",b:/\(optional\)/}]}};return{aliases:["graph","instances"],cI:!0,k:"import",c:[{b:"^facet "+e,e:"}",k:"facet",c:[n,a.HCM]},{b:"^\\s*instance of "+e,e:"}",k:"name count channels instance-data instance-state instance of",i:/\S/,c:["self",n,a.HCM]},{b:"^"+e,e:"}",c:[n,a.HCM]},a.HCM]}});hljs.registerLanguage("autoit",function(e){var t="ByRef Case Const ContinueCase ContinueLoop Default Dim Do Else ElseIf EndFunc EndIf EndSelect EndSwitch EndWith Enum Exit ExitLoop For Func Global If In Local Next ReDim Return Select Static Step Switch Then To Until Volatile WEnd While With",r="True False And Null Not Or",i="Abs ACos AdlibRegister AdlibUnRegister Asc AscW ASin Assign ATan AutoItSetOption AutoItWinGetTitle AutoItWinSetTitle Beep Binary BinaryLen BinaryMid BinaryToString BitAND BitNOT BitOR BitRotate BitShift BitXOR BlockInput Break Call CDTray Ceiling Chr ChrW ClipGet ClipPut ConsoleRead ConsoleWrite ConsoleWriteError ControlClick ControlCommand ControlDisable ControlEnable ControlFocus ControlGetFocus ControlGetHandle ControlGetPos ControlGetText ControlHide ControlListView ControlMove ControlSend ControlSetText ControlShow ControlTreeView Cos Dec DirCopy DirCreate DirGetSize DirMove DirRemove DllCall DllCallAddress DllCallbackFree DllCallbackGetPtr DllCallbackRegister DllClose DllOpen DllStructCreate DllStructGetData DllStructGetPtr DllStructGetSize DllStructSetData DriveGetDrive DriveGetFileSystem DriveGetLabel DriveGetSerial DriveGetType DriveMapAdd DriveMapDel DriveMapGet DriveSetLabel DriveSpaceFree DriveSpaceTotal DriveStatus EnvGet EnvSet EnvUpdate Eval Execute Exp FileChangeDir FileClose FileCopy FileCreateNTFSLink FileCreateShortcut FileDelete FileExists FileFindFirstFile FileFindNextFile FileFlush FileGetAttrib FileGetEncoding FileGetLongName FileGetPos FileGetShortcut FileGetShortName FileGetSize FileGetTime FileGetVersion FileInstall FileMove FileOpen FileOpenDialog FileRead FileReadLine FileReadToArray FileRecycle FileRecycleEmpty FileSaveDialog FileSelectFolder FileSetAttrib FileSetEnd FileSetPos FileSetTime FileWrite FileWriteLine Floor FtpSetProxy FuncName GUICreate GUICtrlCreateAvi GUICtrlCreateButton GUICtrlCreateCheckbox GUICtrlCreateCombo GUICtrlCreateContextMenu GUICtrlCreateDate GUICtrlCreateDummy GUICtrlCreateEdit GUICtrlCreateGraphic GUICtrlCreateGroup GUICtrlCreateIcon GUICtrlCreateInput GUICtrlCreateLabel GUICtrlCreateList GUICtrlCreateListView GUICtrlCreateListViewItem GUICtrlCreateMenu GUICtrlCreateMenuItem GUICtrlCreateMonthCal GUICtrlCreateObj GUICtrlCreatePic GUICtrlCreateProgress GUICtrlCreateRadio GUICtrlCreateSlider GUICtrlCreateTab GUICtrlCreateTabItem GUICtrlCreateTreeView GUICtrlCreateTreeViewItem GUICtrlCreateUpdown GUICtrlDelete GUICtrlGetHandle GUICtrlGetState GUICtrlRead GUICtrlRecvMsg GUICtrlRegisterListViewSort GUICtrlSendMsg GUICtrlSendToDummy GUICtrlSetBkColor GUICtrlSetColor GUICtrlSetCursor GUICtrlSetData GUICtrlSetDefBkColor GUICtrlSetDefColor GUICtrlSetFont GUICtrlSetGraphic GUICtrlSetImage GUICtrlSetLimit GUICtrlSetOnEvent GUICtrlSetPos GUICtrlSetResizing GUICtrlSetState GUICtrlSetStyle GUICtrlSetTip GUIDelete GUIGetCursorInfo GUIGetMsg GUIGetStyle GUIRegisterMsg GUISetAccelerators GUISetBkColor GUISetCoord GUISetCursor GUISetFont GUISetHelp GUISetIcon GUISetOnEvent GUISetState GUISetStyle GUIStartGroup GUISwitch Hex HotKeySet HttpSetProxy HttpSetUserAgent HWnd InetClose InetGet InetGetInfo InetGetSize InetRead IniDelete IniRead IniReadSection IniReadSectionNames IniRenameSection IniWrite IniWriteSection InputBox Int IsAdmin IsArray IsBinary IsBool IsDeclared IsDllStruct IsFloat IsFunc IsHWnd IsInt IsKeyword IsNumber IsObj IsPtr IsString Log MemGetStats Mod MouseClick MouseClickDrag MouseDown MouseGetCursor MouseGetPos MouseMove MouseUp MouseWheel MsgBox Number ObjCreate ObjCreateInterface ObjEvent ObjGet ObjName OnAutoItExitRegister OnAutoItExitUnRegister Ping PixelChecksum PixelGetColor PixelSearch ProcessClose ProcessExists ProcessGetStats ProcessList ProcessSetPriority ProcessWait ProcessWaitClose ProgressOff ProgressOn ProgressSet Ptr Random RegDelete RegEnumKey RegEnumVal RegRead RegWrite Round Run RunAs RunAsWait RunWait Send SendKeepActive SetError SetExtended ShellExecute ShellExecuteWait Shutdown Sin Sleep SoundPlay SoundSetWaveVolume SplashImageOn SplashOff SplashTextOn Sqrt SRandom StatusbarGetText StderrRead StdinWrite StdioClose StdoutRead String StringAddCR StringCompare StringFormat StringFromASCIIArray StringInStr StringIsAlNum StringIsAlpha StringIsASCII StringIsDigit StringIsFloat StringIsInt StringIsLower StringIsSpace StringIsUpper StringIsXDigit StringLeft StringLen StringLower StringMid StringRegExp StringRegExpReplace StringReplace StringReverse StringRight StringSplit StringStripCR StringStripWS StringToASCIIArray StringToBinary StringTrimLeft StringTrimRight StringUpper Tan TCPAccept TCPCloseSocket TCPConnect TCPListen TCPNameToIP TCPRecv TCPSend TCPShutdown, UDPShutdown TCPStartup, UDPStartup TimerDiff TimerInit ToolTip TrayCreateItem TrayCreateMenu TrayGetMsg TrayItemDelete TrayItemGetHandle TrayItemGetState TrayItemGetText TrayItemSetOnEvent TrayItemSetState TrayItemSetText TraySetClick TraySetIcon TraySetOnEvent TraySetPauseIcon TraySetState TraySetToolTip TrayTip UBound UDPBind UDPCloseSocket UDPOpen UDPRecv UDPSend VarGetType WinActivate WinActive WinClose WinExists WinFlash WinGetCaretPos WinGetClassList WinGetClientSize WinGetHandle WinGetPos WinGetProcess WinGetState WinGetText WinGetTitle WinKill WinList WinMenuSelectItem WinMinimizeAll WinMinimizeAllUndo WinMove WinSetOnTop WinSetState WinSetTitle WinSetTrans WinWait",l={v:[e.C(";","$",{r:0}),e.C("#cs","#ce"),e.C("#comments-start","#comments-end")]},n={b:"\\$[A-z0-9_]+"},o={cN:"string",v:[{b:/"/,e:/"/,c:[{b:/""/,r:0}]},{b:/'/,e:/'/,c:[{b:/''/,r:0}]}]},a={v:[e.BNM,e.CNM]},S={cN:"meta",b:"#",e:"$",k:{"meta-keyword":"comments include include-once NoTrayIcon OnAutoItStartRegister pragma compile RequireAdmin"},c:[{b:/\\\n/,r:0},{bK:"include",k:{"meta-keyword":"include"},e:"$",c:[o,{cN:"meta-string",v:[{b:"<",e:">"},{b:/"/,e:/"/,c:[{b:/""/,r:0}]},{b:/'/,e:/'/,c:[{b:/''/,r:0}]}]}]},o,l]},C={cN:"symbol",b:"@[A-z0-9_]+"},s={cN:"function",bK:"Func",e:"$",i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:[n,o,a]}]};return{cI:!0,i:/\/\*/,k:{keyword:t,built_in:i,literal:r},c:[l,n,o,a,S,C,s]}});hljs.registerLanguage("apache",function(e){var r={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"section",b:""},{cN:"attribute",b:/\w+/,r:0,k:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"meta",b:"\\s\\[",e:"\\]$"},{cN:"variable",b:"[\\$%]\\{",e:"\\}",c:["self",r]},r,e.QSM]}}],i:/\S/}});hljs.registerLanguage("abnf",function(e){var r={ruleDeclaration:"^[a-zA-Z][a-zA-Z0-9-]*",unexpectedChars:"[!@#$^&',?+~`|:]"},a=["ALPHA","BIT","CHAR","CR","CRLF","CTL","DIGIT","DQUOTE","HEXDIG","HTAB","LF","LWSP","OCTET","SP","VCHAR","WSP"],b=e.C(";","$"),c={cN:"symbol",b:/%b[0-1]+(-[0-1]+|(\.[0-1]+)+){0,1}/},l={cN:"symbol",b:/%d[0-9]+(-[0-9]+|(\.[0-9]+)+){0,1}/},n={cN:"symbol",b:/%x[0-9A-F]+(-[0-9A-F]+|(\.[0-9A-F]+)+){0,1}/},t={cN:"symbol",b:/%[si]/},s={b:r.ruleDeclaration+"\\s*=",rB:!0,e:/=/,r:0,c:[{cN:"attribute",b:r.ruleDeclaration}]};return{i:r.unexpectedChars,k:a.join(" "),c:[s,b,c,l,n,t,e.QSM,e.NM]}});hljs.registerLanguage("mojolicious",function(e){return{sL:"xml",c:[{cN:"meta",b:"^__(END|DATA)__$"},{b:"^\\s*%{1,2}={0,2}",e:"$",sL:"perl"},{b:"<%{1,2}={0,2}",e:"={0,1}%>",sL:"perl",eB:!0,eE:!0}]}});hljs.registerLanguage("typescript",function(e){var r={keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class public private protected get set super static implements enum export import declare type namespace abstract as from extends async await",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document any number boolean string void Promise"};return{aliases:["ts"],k:r,c:[{cN:"meta",b:/^\s*['"]use strict['"]/},e.ASM,e.QSM,{cN:"string",b:"`",e:"`",c:[e.BE,{cN:"subst",b:"\\$\\{",e:"\\}"}]},e.CLCM,e.CBCM,{cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+e.IR+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:e.IR},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:r,c:["self",e.CLCM,e.CBCM]}]}]}],r:0},{cN:"function",b:"function",e:/[\{;]/,eE:!0,k:r,c:["self",e.inherit(e.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:r,c:[e.CLCM,e.CBCM],i:/["'\(]/}],i:/%/,r:0},{bK:"constructor",e:/\{/,eE:!0,c:["self",{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:r,c:[e.CLCM,e.CBCM],i:/["'\(]/}]},{b:/module\./,k:{built_in:"module"},r:0},{bK:"module",e:/\{/,eE:!0},{bK:"interface",e:/\{/,eE:!0,k:"interface extends"},{b:/\$[(.]/},{b:"\\."+e.IR,r:0},{cN:"meta",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("vbnet",function(e){return{aliases:["vb"],cI:!0,k:{keyword:"addhandler addressof alias and andalso aggregate ansi as assembly auto binary by byref byval call case catch class compare const continue custom declare default delegate dim distinct do each equals else elseif end enum erase error event exit explicit finally for friend from function get global goto group handles if implements imports in inherits interface into is isfalse isnot istrue join key let lib like loop me mid mod module mustinherit mustoverride mybase myclass namespace narrowing new next not notinheritable notoverridable of off on operator option optional or order orelse overloads overridable overrides paramarray partial preserve private property protected public raiseevent readonly redim rem removehandler resume return select set shadows shared skip static step stop structure strict sub synclock take text then throw to try unicode until using when where while widening with withevents writeonly xor",built_in:"boolean byte cbool cbyte cchar cdate cdec cdbl char cint clng cobj csbyte cshort csng cstr ctype date decimal directcast double gettype getxmlnamespace iif integer long object sbyte short single string trycast typeof uinteger ulong ushort",literal:"true false nothing"},i:"//|{|}|endif|gosub|variant|wend",c:[e.inherit(e.QSM,{c:[{b:'""'}]}),e.C("'","$",{rB:!0,c:[{cN:"doctag",b:"'''|",c:[e.PWM]},{cN:"doctag",b:"",c:[e.PWM]}]}),e.CNM,{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elseif end region externalsource"}}]}});hljs.registerLanguage("oxygene",function(e){var r="abstract add and array as asc aspect assembly async begin break block by case class concat const copy constructor continue create default delegate desc distinct div do downto dynamic each else empty end ensure enum equals event except exit extension external false final finalize finalizer finally flags for forward from function future global group has if implementation implements implies in index inherited inline interface into invariants is iterator join locked locking loop matching method mod module namespace nested new nil not notify nullable of old on operator or order out override parallel params partial pinned private procedure property protected public queryable raise read readonly record reintroduce remove repeat require result reverse sealed select self sequence set shl shr skip static step soft take then to true try tuple type union unit unsafe until uses using var virtual raises volatile where while with write xor yield await mapped deprecated stdcall cdecl pascal register safecall overload library platform reference packed strict published autoreleasepool selector strong weak unretained",t=e.C("{","}",{r:0}),a=e.C("\\(\\*","\\*\\)",{r:10}),n={cN:"string",b:"'",e:"'",c:[{b:"''"}]},o={cN:"string",b:"(#\\d+)+"},i={cN:"function",bK:"function constructor destructor procedure method",e:"[:;]",k:"function constructor|10 destructor|10 procedure|10 method|10",c:[e.TM,{cN:"params",b:"\\(",e:"\\)",k:r,c:[n,o]},t,a]};return{cI:!0,l:/\.?\w+/,k:r,i:'("|\\$[G-Zg-z]|\\/\\*||->)',c:[t,a,e.CLCM,n,o,e.NM,i,{cN:"class",b:"=\\bclass\\b",e:"end;",k:r,c:[n,o,t,a,e.CLCM,i]}]}});hljs.registerLanguage("rib",function(e){return{k:"ArchiveRecord AreaLightSource Atmosphere Attribute AttributeBegin AttributeEnd Basis Begin Blobby Bound Clipping ClippingPlane Color ColorSamples ConcatTransform Cone CoordinateSystem CoordSysTransform CropWindow Curves Cylinder DepthOfField Detail DetailRange Disk Displacement Display End ErrorHandler Exposure Exterior Format FrameAspectRatio FrameBegin FrameEnd GeneralPolygon GeometricApproximation Geometry Hider Hyperboloid Identity Illuminate Imager Interior LightSource MakeCubeFaceEnvironment MakeLatLongEnvironment MakeShadow MakeTexture Matte MotionBegin MotionEnd NuPatch ObjectBegin ObjectEnd ObjectInstance Opacity Option Orientation Paraboloid Patch PatchMesh Perspective PixelFilter PixelSamples PixelVariance Points PointsGeneralPolygons PointsPolygons Polygon Procedural Projection Quantize ReadArchive RelativeDetail ReverseOrientation Rotate Scale ScreenWindow ShadingInterpolation ShadingRate Shutter Sides Skew SolidBegin SolidEnd Sphere SubdivisionMesh Surface TextureCoordinates Torus Transform TransformBegin TransformEnd TransformPoints Translate TrimCurve WorldBegin WorldEnd",i:" \r\n]","[\\[\\]\\.,\\+\\-<> \r\n]",{rE:!0,r:0}),{cN:"title",b:"[\\[\\]]",r:0},{cN:"string",b:"[\\.,]",r:0},{b:/\+\+|\-\-/,rB:!0,c:[n]},n]}});hljs.registerLanguage("tap",function(b){return{cI:!0,c:[b.HCM,{cN:"meta",v:[{b:"^TAP version (\\d+)$"},{b:"^1\\.\\.(\\d+)$"}]},{b:"(s+)?---$",e:"\\.\\.\\.$",sL:"yaml",r:0},{cN:"number",b:" (\\d+) "},{cN:"symbol",v:[{b:"^ok"},{b:"^not ok"}]}]}});hljs.registerLanguage("ini",function(e){var b={cN:"string",c:[e.BE],v:[{b:"'''",e:"'''",r:10},{b:'"""',e:'"""',r:10},{b:'"',e:'"'},{b:"'",e:"'"}]};return{aliases:["toml"],cI:!0,i:/\S/,c:[e.C(";","$"),e.HCM,{cN:"section",b:/^\s*\[+/,e:/\]+/},{b:/^[a-z0-9\[\]_-]+\s*=\s*/,e:"$",rB:!0,c:[{cN:"attr",b:/[a-z0-9\[\]_-]+/},{b:/=/,eW:!0,r:0,c:[{cN:"literal",b:/\bon|off|true|false|yes|no\b/},{cN:"variable",v:[{b:/\$[\w\d"][\w\d_]*/},{b:/\$\{(.*?)}/}]},b,{cN:"number",b:/([\+\-]+)?[\d]+_[\d_]+/},e.NM]}]}]}});hljs.registerLanguage("dockerfile",function(e){return{aliases:["docker"],cI:!0,k:"from maintainer expose env user onbuild",c:[e.HCM,e.ASM,e.QSM,e.NM,{bK:"run cmd entrypoint volume add copy workdir label healthcheck",starts:{e:/[^\\]\n/,sL:"bash"}}],i:"",c:[e.TM,{b:/\(/,e:/\)/,c:[n,s,e.CNM,e.CBCM]},{b:/:/,eW:!0,c:[n]},e.CLCM]};return{k:r,c:[a,o,n,t,c,i,s,e.CNM,e.CLCM,e.CBCM]}});hljs.registerLanguage("puppet",function(e){var s={keyword:"and case default else elsif false if in import enherits node or true undef unless main settings $string ",literal:"alias audit before loglevel noop require subscribe tag owner ensure group mode name|0 changes context force incl lens load_path onlyif provider returns root show_diff type_check en_address ip_address realname command environment hour monute month monthday special target weekday creates cwd ogoutput refresh refreshonly tries try_sleep umask backup checksum content ctime force ignore links mtime purge recurse recurselimit replace selinux_ignore_defaults selrange selrole seltype seluser source souirce_permissions sourceselect validate_cmd validate_replacement allowdupe attribute_membership auth_membership forcelocal gid ia_load_module members system host_aliases ip allowed_trunk_vlans description device_url duplex encapsulation etherchannel native_vlan speed principals allow_root auth_class auth_type authenticate_user k_of_n mechanisms rule session_owner shared options device fstype enable hasrestart directory present absent link atboot blockdevice device dump pass remounts poller_tag use message withpath adminfile allow_virtual allowcdrom category configfiles flavor install_options instance package_settings platform responsefile status uninstall_options vendor unless_system_user unless_uid binary control flags hasstatus manifest pattern restart running start stop allowdupe auths expiry gid groups home iterations key_membership keys managehome membership password password_max_age password_min_age profile_membership profiles project purge_ssh_keys role_membership roles salt shell uid baseurl cost descr enabled enablegroups exclude failovermethod gpgcheck gpgkey http_caching include includepkgs keepalive metadata_expire metalink mirrorlist priority protect proxy proxy_password proxy_username repo_gpgcheck s3_enabled skip_if_unavailable sslcacert sslclientcert sslclientkey sslverify mounted",built_in:"architecture augeasversion blockdevices boardmanufacturer boardproductname boardserialnumber cfkey dhcp_servers domain ec2_ ec2_userdata facterversion filesystems ldom fqdn gid hardwareisa hardwaremodel hostname id|0 interfaces ipaddress ipaddress_ ipaddress6 ipaddress6_ iphostnumber is_virtual kernel kernelmajversion kernelrelease kernelversion kernelrelease kernelversion lsbdistcodename lsbdistdescription lsbdistid lsbdistrelease lsbmajdistrelease lsbminordistrelease lsbrelease macaddress macaddress_ macosx_buildversion macosx_productname macosx_productversion macosx_productverson_major macosx_productversion_minor manufacturer memoryfree memorysize netmask metmask_ network_ operatingsystem operatingsystemmajrelease operatingsystemrelease osfamily partitions path physicalprocessorcount processor processorcount productname ps puppetversion rubysitedir rubyversion selinux selinux_config_mode selinux_config_policy selinux_current_mode selinux_current_mode selinux_enforced selinux_policyversion serialnumber sp_ sshdsakey sshecdsakey sshrsakey swapencrypted swapfree swapsize timezone type uniqueid uptime uptime_days uptime_hours uptime_seconds uuid virtual vlans xendomains zfs_version zonenae zones zpool_version"},r=e.C("#","$"),a="([A-Za-z_]|::)(\\w|::)*",i=e.inherit(e.TM,{b:a}),o={cN:"variable",b:"\\$"+a},t={cN:"string",c:[e.BE,o],v:[{b:/'/,e:/'/},{b:/"/,e:/"/}]};return{aliases:["pp"],c:[r,o,t,{bK:"class",e:"\\{|;",i:/=/,c:[i,r]},{bK:"define",e:/\{/,c:[{cN:"section",b:e.IR,endsParent:!0}]},{b:e.IR+"\\s+\\{",rB:!0,e:/\S/,c:[{cN:"keyword",b:e.IR},{b:/\{/,e:/\}/,k:s,r:0,c:[t,r,{b:"[a-zA-Z_]+\\s*=>",rB:!0,e:"=>",c:[{cN:"attr",b:e.IR}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},o]}],r:0}]}});hljs.registerLanguage("erlang-repl",function(e){return{k:{built_in:"spawn spawn_link self",keyword:"after and andalso|10 band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse|10 query receive rem try when xor"},c:[{cN:"meta",b:"^[0-9]+> ",r:10},e.C("%","$"),{cN:"number",b:"\\b(\\d+#[a-fA-F0-9]+|\\d+(\\.\\d+)?([eE][-+]?\\d+)?)",r:0},e.ASM,e.QSM,{b:"\\?(::)?([A-Z]\\w*(::)?)+"},{b:"->"},{b:"ok"},{b:"!"},{b:"(\\b[a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*)|(\\b[a-z'][a-zA-Z0-9_']*)",r:0},{b:"[A-Z][a-zA-Z0-9_']*",r:0}]}});hljs.registerLanguage("gauss",function(e){var t={keyword:"and bool break call callexe checkinterrupt clear clearg closeall cls comlog compile continue create debug declare delete disable dlibrary dllcall do dos ed edit else elseif enable end endfor endif endp endo errorlog errorlogat expr external fn for format goto gosub graph if keyword let lib library line load loadarray loadexe loadf loadk loadm loadp loads loadx local locate loopnextindex lprint lpwidth lshow matrix msym ndpclex new not open or output outwidth plot plotsym pop prcsn print printdos proc push retp return rndcon rndmod rndmult rndseed run save saveall screen scroll setarray show sparse stop string struct system trace trap threadfor threadendfor threadbegin threadjoin threadstat threadend until use while winprint",built_in:"abs acf aconcat aeye amax amean AmericanBinomCall AmericanBinomCall_Greeks AmericanBinomCall_ImpVol AmericanBinomPut AmericanBinomPut_Greeks AmericanBinomPut_ImpVol AmericanBSCall AmericanBSCall_Greeks AmericanBSCall_ImpVol AmericanBSPut AmericanBSPut_Greeks AmericanBSPut_ImpVol amin amult annotationGetDefaults annotationSetBkd annotationSetFont annotationSetLineColor annotationSetLineStyle annotationSetLineThickness annualTradingDays arccos arcsin areshape arrayalloc arrayindex arrayinit arraytomat asciiload asclabel astd astds asum atan atan2 atranspose axmargin balance band bandchol bandcholsol bandltsol bandrv bandsolpd bar base10 begwind besselj bessely beta box boxcox cdfBeta cdfBetaInv cdfBinomial cdfBinomialInv cdfBvn cdfBvn2 cdfBvn2e cdfCauchy cdfCauchyInv cdfChic cdfChii cdfChinc cdfChincInv cdfExp cdfExpInv cdfFc cdfFnc cdfFncInv cdfGam cdfGenPareto cdfHyperGeo cdfLaplace cdfLaplaceInv cdfLogistic cdfLogisticInv cdfmControlCreate cdfMvn cdfMvn2e cdfMvnce cdfMvne cdfMvt2e cdfMvtce cdfMvte cdfN cdfN2 cdfNc cdfNegBinomial cdfNegBinomialInv cdfNi cdfPoisson cdfPoissonInv cdfRayleigh cdfRayleighInv cdfTc cdfTci cdfTnc cdfTvn cdfWeibull cdfWeibullInv cdir ceil ChangeDir chdir chiBarSquare chol choldn cholsol cholup chrs close code cols colsf combinate combinated complex con cond conj cons ConScore contour conv convertsatostr convertstrtosa corrm corrms corrvc corrx corrxs cos cosh counts countwts crossprd crout croutp csrcol csrlin csvReadM csvReadSA cumprodc cumsumc curve cvtos datacreate datacreatecomplex datalist dataload dataloop dataopen datasave date datestr datestring datestrymd dayinyr dayofweek dbAddDatabase dbClose dbCommit dbCreateQuery dbExecQuery dbGetConnectOptions dbGetDatabaseName dbGetDriverName dbGetDrivers dbGetHostName dbGetLastErrorNum dbGetLastErrorText dbGetNumericalPrecPolicy dbGetPassword dbGetPort dbGetTableHeaders dbGetTables dbGetUserName dbHasFeature dbIsDriverAvailable dbIsOpen dbIsOpenError dbOpen dbQueryBindValue dbQueryClear dbQueryCols dbQueryExecPrepared dbQueryFetchAllM dbQueryFetchAllSA dbQueryFetchOneM dbQueryFetchOneSA dbQueryFinish dbQueryGetBoundValue dbQueryGetBoundValues dbQueryGetField dbQueryGetLastErrorNum dbQueryGetLastErrorText dbQueryGetLastInsertID dbQueryGetLastQuery dbQueryGetPosition dbQueryIsActive dbQueryIsForwardOnly dbQueryIsNull dbQueryIsSelect dbQueryIsValid dbQueryPrepare dbQueryRows dbQuerySeek dbQuerySeekFirst dbQuerySeekLast dbQuerySeekNext dbQuerySeekPrevious dbQuerySetForwardOnly dbRemoveDatabase dbRollback dbSetConnectOptions dbSetDatabaseName dbSetHostName dbSetNumericalPrecPolicy dbSetPort dbSetUserName dbTransaction DeleteFile delif delrows denseToSp denseToSpRE denToZero design det detl dfft dffti diag diagrv digamma doswin DOSWinCloseall DOSWinOpen dotfeq dotfeqmt dotfge dotfgemt dotfgt dotfgtmt dotfle dotflemt dotflt dotfltmt dotfne dotfnemt draw drop dsCreate dstat dstatmt dstatmtControlCreate dtdate dtday dttime dttodtv dttostr dttoutc dtvnormal dtvtodt dtvtoutc dummy dummybr dummydn eig eigh eighv eigv elapsedTradingDays endwind envget eof eqSolve eqSolvemt eqSolvemtControlCreate eqSolvemtOutCreate eqSolveset erf erfc erfccplx erfcplx error etdays ethsec etstr EuropeanBinomCall EuropeanBinomCall_Greeks EuropeanBinomCall_ImpVol EuropeanBinomPut EuropeanBinomPut_Greeks EuropeanBinomPut_ImpVol EuropeanBSCall EuropeanBSCall_Greeks EuropeanBSCall_ImpVol EuropeanBSPut EuropeanBSPut_Greeks EuropeanBSPut_ImpVol exctsmpl exec execbg exp extern eye fcheckerr fclearerr feq feqmt fflush fft ffti fftm fftmi fftn fge fgemt fgets fgetsa fgetsat fgetst fgt fgtmt fileinfo filesa fle flemt floor flt fltmt fmod fne fnemt fonts fopen formatcv formatnv fputs fputst fseek fstrerror ftell ftocv ftos ftostrC gamma gammacplx gammaii gausset gdaAppend gdaCreate gdaDStat gdaDStatMat gdaGetIndex gdaGetName gdaGetNames gdaGetOrders gdaGetType gdaGetTypes gdaGetVarInfo gdaIsCplx gdaLoad gdaPack gdaRead gdaReadByIndex gdaReadSome gdaReadSparse gdaReadStruct gdaReportVarInfo gdaSave gdaUpdate gdaUpdateAndPack gdaVars gdaWrite gdaWrite32 gdaWriteSome getarray getdims getf getGAUSShome getmatrix getmatrix4D getname getnamef getNextTradingDay getNextWeekDay getnr getorders getpath getPreviousTradingDay getPreviousWeekDay getRow getscalar3D getscalar4D getTrRow getwind glm gradcplx gradMT gradMTm gradMTT gradMTTm gradp graphprt graphset hasimag header headermt hess hessMT hessMTg hessMTgw hessMTm hessMTmw hessMTT hessMTTg hessMTTgw hessMTTm hessMTw hessp hist histf histp hsec imag indcv indexcat indices indices2 indicesf indicesfn indnv indsav integrate1d integrateControlCreate intgrat2 intgrat3 inthp1 inthp2 inthp3 inthp4 inthpControlCreate intquad1 intquad2 intquad3 intrleav intrleavsa intrsect intsimp inv invpd invswp iscplx iscplxf isden isinfnanmiss ismiss key keyav keyw lag lag1 lagn lapEighb lapEighi lapEighvb lapEighvi lapgEig lapgEigh lapgEighv lapgEigv lapgSchur lapgSvdcst lapgSvds lapgSvdst lapSvdcusv lapSvds lapSvdusv ldlp ldlsol linSolve listwise ln lncdfbvn lncdfbvn2 lncdfmvn lncdfn lncdfn2 lncdfnc lnfact lngammacplx lnpdfmvn lnpdfmvt lnpdfn lnpdft loadd loadstruct loadwind loess loessmt loessmtControlCreate log loglog logx logy lower lowmat lowmat1 ltrisol lu lusol machEpsilon make makevars makewind margin matalloc matinit mattoarray maxbytes maxc maxindc maxv maxvec mbesselei mbesselei0 mbesselei1 mbesseli mbesseli0 mbesseli1 meanc median mergeby mergevar minc minindc minv miss missex missrv moment momentd movingave movingaveExpwgt movingaveWgt nextindex nextn nextnevn nextwind ntos null null1 numCombinations ols olsmt olsmtControlCreate olsqr olsqr2 olsqrmt ones optn optnevn orth outtyp pacf packedToSp packr parse pause pdfCauchy pdfChi pdfExp pdfGenPareto pdfHyperGeo pdfLaplace pdfLogistic pdfn pdfPoisson pdfRayleigh pdfWeibull pi pinv pinvmt plotAddArrow plotAddBar plotAddBox plotAddHist plotAddHistF plotAddHistP plotAddPolar plotAddScatter plotAddShape plotAddTextbox plotAddTS plotAddXY plotArea plotBar plotBox plotClearLayout plotContour plotCustomLayout plotGetDefaults plotHist plotHistF plotHistP plotLayout plotLogLog plotLogX plotLogY plotOpenWindow plotPolar plotSave plotScatter plotSetAxesPen plotSetBar plotSetBarFill plotSetBarStacked plotSetBkdColor plotSetFill plotSetGrid plotSetLegend plotSetLineColor plotSetLineStyle plotSetLineSymbol plotSetLineThickness plotSetNewWindow plotSetTitle plotSetWhichYAxis plotSetXAxisShow plotSetXLabel plotSetXRange plotSetXTicInterval plotSetXTicLabel plotSetYAxisShow plotSetYLabel plotSetYRange plotSetZAxisShow plotSetZLabel plotSurface plotTS plotXY polar polychar polyeval polygamma polyint polymake polymat polymroot polymult polyroot pqgwin previousindex princomp printfm printfmt prodc psi putarray putf putvals pvCreate pvGetIndex pvGetParNames pvGetParVector pvLength pvList pvPack pvPacki pvPackm pvPackmi pvPacks pvPacksi pvPacksm pvPacksmi pvPutParVector pvTest pvUnpack QNewton QNewtonmt QNewtonmtControlCreate QNewtonmtOutCreate QNewtonSet QProg QProgmt QProgmtInCreate qqr qqre qqrep qr qre qrep qrsol qrtsol qtyr qtyre qtyrep quantile quantiled qyr qyre qyrep qz rank rankindx readr real reclassify reclassifyCuts recode recserar recsercp recserrc rerun rescale reshape rets rev rfft rffti rfftip rfftn rfftnp rfftp rndBernoulli rndBeta rndBinomial rndCauchy rndChiSquare rndCon rndCreateState rndExp rndGamma rndGeo rndGumbel rndHyperGeo rndi rndKMbeta rndKMgam rndKMi rndKMn rndKMnb rndKMp rndKMu rndKMvm rndLaplace rndLCbeta rndLCgam rndLCi rndLCn rndLCnb rndLCp rndLCu rndLCvm rndLogNorm rndMTu rndMVn rndMVt rndn rndnb rndNegBinomial rndp rndPoisson rndRayleigh rndStateSkip rndu rndvm rndWeibull rndWishart rotater round rows rowsf rref sampleData satostrC saved saveStruct savewind scale scale3d scalerr scalinfnanmiss scalmiss schtoc schur searchsourcepath seekr select selif seqa seqm setdif setdifsa setvars setvwrmode setwind shell shiftr sin singleindex sinh sleep solpd sortc sortcc sortd sorthc sorthcc sortind sortindc sortmc sortr sortrc spBiconjGradSol spChol spConjGradSol spCreate spDenseSubmat spDiagRvMat spEigv spEye spLDL spline spLU spNumNZE spOnes spreadSheetReadM spreadSheetReadSA spreadSheetWrite spScale spSubmat spToDense spTrTDense spTScalar spZeros sqpSolve sqpSolveMT sqpSolveMTControlCreate sqpSolveMTlagrangeCreate sqpSolveMToutCreate sqpSolveSet sqrt statements stdc stdsc stocv stof strcombine strindx strlen strput strrindx strsect strsplit strsplitPad strtodt strtof strtofcplx strtriml strtrimr strtrunc strtruncl strtruncpad strtruncr submat subscat substute subvec sumc sumr surface svd svd1 svd2 svdcusv svds svdusv sysstate tab tan tanh tempname threadBegin threadEnd threadEndFor threadFor threadJoin threadStat time timedt timestr timeutc title tkf2eps tkf2ps tocart todaydt toeplitz token topolar trapchk trigamma trimr trunc type typecv typef union unionsa uniqindx uniqindxsa unique uniquesa upmat upmat1 upper utctodt utctodtv utrisol vals varCovMS varCovXS varget vargetl varmall varmares varput varputl vartypef vcm vcms vcx vcxs vec vech vecr vector vget view viewxyz vlist vnamecv volume vput vread vtypecv wait waitc walkindex where window writer xlabel xlsGetSheetCount xlsGetSheetSize xlsGetSheetTypes xlsMakeRange xlsReadM xlsReadSA xlsWrite xlsWriteM xlsWriteSA xpnd xtics xy xyz ylabel ytics zeros zeta zlabel ztics cdfEmpirical dot h5create h5open h5read h5readAttribute h5write h5writeAttribute ldl plotAddErrorBar plotAddSurface plotCDFEmpirical plotSetColormap plotSetContourLabels plotSetLegendFont plotSetTextInterpreter plotSetXTicCount plotSetYTicCount plotSetZLevels powerm strjoin strtrim sylvester",literal:"DB_AFTER_LAST_ROW DB_ALL_TABLES DB_BATCH_OPERATIONS DB_BEFORE_FIRST_ROW DB_BLOB DB_EVENT_NOTIFICATIONS DB_FINISH_QUERY DB_HIGH_PRECISION DB_LAST_INSERT_ID DB_LOW_PRECISION_DOUBLE DB_LOW_PRECISION_INT32 DB_LOW_PRECISION_INT64 DB_LOW_PRECISION_NUMBERS DB_MULTIPLE_RESULT_SETS DB_NAMED_PLACEHOLDERS DB_POSITIONAL_PLACEHOLDERS DB_PREPARED_QUERIES DB_QUERY_SIZE DB_SIMPLE_LOCKING DB_SYSTEM_TABLES DB_TABLES DB_TRANSACTIONS DB_UNICODE DB_VIEWS"},a={cN:"meta",b:"#",e:"$",k:{"meta-keyword":"define definecs|10 undef ifdef ifndef iflight ifdllcall ifmac ifos2win ifunix else endif lineson linesoff srcfile srcline"},c:[{b:/\\\n/,r:0},{bK:"include",e:"$",k:{"meta-keyword":"include"},c:[{cN:"meta-string",b:'"',e:'"',i:"\\n"}]},e.CLCM,e.CBCM]},r=e.UIR+"\\s*\\(?",o=[{cN:"params",b:/\(/,e:/\)/,k:t,r:0,c:[e.CNM,e.CLCM,e.CBCM]}];return{aliases:["gss"],cI:!0,k:t,i:"(\\{[%#]|[%#]\\})",c:[e.CNM,e.CLCM,e.CBCM,e.C("@","@"),a,{cN:"string",b:'"',e:'"',c:[e.BE]},{cN:"function",bK:"proc keyword",e:";",eE:!0,k:t,c:[{b:r,rB:!0,c:[e.UTM],r:0},e.CNM,e.CLCM,e.CBCM,a].concat(o)},{cN:"function",bK:"fn",e:";",eE:!0,k:t,c:[{b:r+e.IR+"\\)?\\s*\\=\\s*",rB:!0,c:[e.UTM],r:0},e.CNM,e.CLCM,e.CBCM].concat(o)},{cN:"function",b:"\\bexternal (proc|keyword|fn)\\s+",e:";",eE:!0,k:t,c:[{b:r,rB:!0,c:[e.UTM],r:0},e.CLCM,e.CBCM]},{cN:"function",b:"\\bexternal (matrix|string|array|sparse matrix|struct "+e.IR+")\\s+",e:";",eE:!0,k:t,c:[e.CLCM,e.CBCM]}]}});hljs.registerLanguage("processing",function(e){return{k:{keyword:"BufferedReader PVector PFont PImage PGraphics HashMap boolean byte char color double float int long String Array FloatDict FloatList IntDict IntList JSONArray JSONObject Object StringDict StringList Table TableRow XML false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private",literal:"P2D P3D HALF_PI PI QUARTER_PI TAU TWO_PI",title:"setup draw",built_in:"displayHeight displayWidth mouseY mouseX mousePressed pmouseX pmouseY key keyCode pixels focused frameCount frameRate height width size createGraphics beginDraw createShape loadShape PShape arc ellipse line point quad rect triangle bezier bezierDetail bezierPoint bezierTangent curve curveDetail curvePoint curveTangent curveTightness shape shapeMode beginContour beginShape bezierVertex curveVertex endContour endShape quadraticVertex vertex ellipseMode noSmooth rectMode smooth strokeCap strokeJoin strokeWeight mouseClicked mouseDragged mouseMoved mousePressed mouseReleased mouseWheel keyPressed keyPressedkeyReleased keyTyped print println save saveFrame day hour millis minute month second year background clear colorMode fill noFill noStroke stroke alpha blue brightness color green hue lerpColor red saturation modelX modelY modelZ screenX screenY screenZ ambient emissive shininess specular add createImage beginCamera camera endCamera frustum ortho perspective printCamera printProjection cursor frameRate noCursor exit loop noLoop popStyle pushStyle redraw binary boolean byte char float hex int str unbinary unhex join match matchAll nf nfc nfp nfs split splitTokens trim append arrayCopy concat expand reverse shorten sort splice subset box sphere sphereDetail createInput createReader loadBytes loadJSONArray loadJSONObject loadStrings loadTable loadXML open parseXML saveTable selectFolder selectInput beginRaw beginRecord createOutput createWriter endRaw endRecord PrintWritersaveBytes saveJSONArray saveJSONObject saveStream saveStrings saveXML selectOutput popMatrix printMatrix pushMatrix resetMatrix rotate rotateX rotateY rotateZ scale shearX shearY translate ambientLight directionalLight lightFalloff lights lightSpecular noLights normal pointLight spotLight image imageMode loadImage noTint requestImage tint texture textureMode textureWrap blend copy filter get loadPixels set updatePixels blendMode loadShader PShaderresetShader shader createFont loadFont text textFont textAlign textLeading textMode textSize textWidth textAscent textDescent abs ceil constrain dist exp floor lerp log mag map max min norm pow round sq sqrt acos asin atan atan2 cos degrees radians sin tan noise noiseDetail noiseSeed random randomGaussian randomSeed"},c:[e.CLCM,e.CBCM,e.ASM,e.QSM,e.CNM]}});hljs.registerLanguage("powershell",function(e){var t={b:"`[\\s\\S]",r:0},o={cN:"variable",v:[{b:/\$[\w\d][\w\d_:]*/}]},r={cN:"literal",b:/\$(null|true|false)\b/},n={cN:"string",v:[{b:/"/,e:/"/},{b:/@"/,e:/^"@/}],c:[t,o,{cN:"variable",b:/\$[A-z]/,e:/[^A-z]/}]},a={cN:"string",v:[{b:/'/,e:/'/},{b:/@'/,e:/^'@/}]},i={cN:"doctag",v:[{b:/\.(synopsis|description|example|inputs|outputs|notes|link|component|role|functionality)/},{b:/\.(parameter|forwardhelptargetname|forwardhelpcategory|remotehelprunspace|externalhelp)\s+\S+/}]},s=e.inherit(e.C(null,null),{v:[{b:/#/,e:/$/},{b:/<#/,e:/#>/}],c:[i]});return{aliases:["ps"],l:/-?[A-z\.\-]+/,cI:!0,k:{keyword:"if else foreach return function do while until elseif begin for trap data dynamicparam end break throw param continue finally in switch exit filter try process catch",built_in:"Add-Computer Add-Content Add-History Add-JobTrigger Add-Member Add-PSSnapin Add-Type Checkpoint-Computer Clear-Content Clear-EventLog Clear-History Clear-Host Clear-Item Clear-ItemProperty Clear-Variable Compare-Object Complete-Transaction Connect-PSSession Connect-WSMan Convert-Path ConvertFrom-Csv ConvertFrom-Json ConvertFrom-SecureString ConvertFrom-StringData ConvertTo-Csv ConvertTo-Html ConvertTo-Json ConvertTo-SecureString ConvertTo-Xml Copy-Item Copy-ItemProperty Debug-Process Disable-ComputerRestore Disable-JobTrigger Disable-PSBreakpoint Disable-PSRemoting Disable-PSSessionConfiguration Disable-WSManCredSSP Disconnect-PSSession Disconnect-WSMan Disable-ScheduledJob Enable-ComputerRestore Enable-JobTrigger Enable-PSBreakpoint Enable-PSRemoting Enable-PSSessionConfiguration Enable-ScheduledJob Enable-WSManCredSSP Enter-PSSession Exit-PSSession Export-Alias Export-Clixml Export-Console Export-Counter Export-Csv Export-FormatData Export-ModuleMember Export-PSSession ForEach-Object Format-Custom Format-List Format-Table Format-Wide Get-Acl Get-Alias Get-AuthenticodeSignature Get-ChildItem Get-Command Get-ComputerRestorePoint Get-Content Get-ControlPanelItem Get-Counter Get-Credential Get-Culture Get-Date Get-Event Get-EventLog Get-EventSubscriber Get-ExecutionPolicy Get-FormatData Get-Host Get-HotFix Get-Help Get-History Get-IseSnippet Get-Item Get-ItemProperty Get-Job Get-JobTrigger Get-Location Get-Member Get-Module Get-PfxCertificate Get-Process Get-PSBreakpoint Get-PSCallStack Get-PSDrive Get-PSProvider Get-PSSession Get-PSSessionConfiguration Get-PSSnapin Get-Random Get-ScheduledJob Get-ScheduledJobOption Get-Service Get-TraceSource Get-Transaction Get-TypeData Get-UICulture Get-Unique Get-Variable Get-Verb Get-WinEvent Get-WmiObject Get-WSManCredSSP Get-WSManInstance Group-Object Import-Alias Import-Clixml Import-Counter Import-Csv Import-IseSnippet Import-LocalizedData Import-PSSession Import-Module Invoke-AsWorkflow Invoke-Command Invoke-Expression Invoke-History Invoke-Item Invoke-RestMethod Invoke-WebRequest Invoke-WmiMethod Invoke-WSManAction Join-Path Limit-EventLog Measure-Command Measure-Object Move-Item Move-ItemProperty New-Alias New-Event New-EventLog New-IseSnippet New-Item New-ItemProperty New-JobTrigger New-Object New-Module New-ModuleManifest New-PSDrive New-PSSession New-PSSessionConfigurationFile New-PSSessionOption New-PSTransportOption New-PSWorkflowExecutionOption New-PSWorkflowSession New-ScheduledJobOption New-Service New-TimeSpan New-Variable New-WebServiceProxy New-WinEvent New-WSManInstance New-WSManSessionOption Out-Default Out-File Out-GridView Out-Host Out-Null Out-Printer Out-String Pop-Location Push-Location Read-Host Receive-Job Register-EngineEvent Register-ObjectEvent Register-PSSessionConfiguration Register-ScheduledJob Register-WmiEvent Remove-Computer Remove-Event Remove-EventLog Remove-Item Remove-ItemProperty Remove-Job Remove-JobTrigger Remove-Module Remove-PSBreakpoint Remove-PSDrive Remove-PSSession Remove-PSSnapin Remove-TypeData Remove-Variable Remove-WmiObject Remove-WSManInstance Rename-Computer Rename-Item Rename-ItemProperty Reset-ComputerMachinePassword Resolve-Path Restart-Computer Restart-Service Restore-Computer Resume-Job Resume-Service Save-Help Select-Object Select-String Select-Xml Send-MailMessage Set-Acl Set-Alias Set-AuthenticodeSignature Set-Content Set-Date Set-ExecutionPolicy Set-Item Set-ItemProperty Set-JobTrigger Set-Location Set-PSBreakpoint Set-PSDebug Set-PSSessionConfiguration Set-ScheduledJob Set-ScheduledJobOption Set-Service Set-StrictMode Set-TraceSource Set-Variable Set-WmiInstance Set-WSManInstance Set-WSManQuickConfig Show-Command Show-ControlPanelItem Show-EventLog Sort-Object Split-Path Start-Job Start-Process Start-Service Start-Sleep Start-Transaction Start-Transcript Stop-Computer Stop-Job Stop-Process Stop-Service Stop-Transcript Suspend-Job Suspend-Service Tee-Object Test-ComputerSecureChannel Test-Connection Test-ModuleManifest Test-Path Test-PSSessionConfigurationFile Trace-Command Unblock-File Undo-Transaction Unregister-Event Unregister-PSSessionConfiguration Unregister-ScheduledJob Update-FormatData Update-Help Update-List Update-TypeData Use-Transaction Wait-Event Wait-Job Wait-Process Where-Object Write-Debug Write-Error Write-EventLog Write-Host Write-Output Write-Progress Write-Verbose Write-Warning Add-MDTPersistentDrive Disable-MDTMonitorService Enable-MDTMonitorService Get-MDTDeploymentShareStatistics Get-MDTMonitorData Get-MDTOperatingSystemCatalog Get-MDTPersistentDrive Import-MDTApplication Import-MDTDriver Import-MDTOperatingSystem Import-MDTPackage Import-MDTTaskSequence New-MDTDatabase Remove-MDTMonitorData Remove-MDTPersistentDrive Restore-MDTPersistentDrive Set-MDTMonitorData Test-MDTDeploymentShare Test-MDTMonitorData Update-MDTDatabaseSchema Update-MDTDeploymentShare Update-MDTLinkedDS Update-MDTMedia Update-MDTMedia Add-VamtProductKey Export-VamtData Find-VamtManagedMachine Get-VamtConfirmationId Get-VamtProduct Get-VamtProductKey Import-VamtData Initialize-VamtData Install-VamtConfirmationId Install-VamtProductActivation Install-VamtProductKey Update-VamtProduct",nomarkup:"-ne -eq -lt -gt -ge -le -not -like -notlike -match -notmatch -contains -notcontains -in -notin -replace"},c:[t,e.NM,n,a,r,o,s]}});hljs.registerLanguage("coffeescript",function(e){var c={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super yield import export from as default await then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",built_in:"npm require console print module global window document"},n="[A-Za-z$_][0-9A-Za-z$_]*",r={cN:"subst",b:/#\{/,e:/}/,k:c},i=[e.BNM,e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,r]},{b:/"/,e:/"/,c:[e.BE,r]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[r,e.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{b:"@"+n},{sL:"javascript",eB:!0,eE:!0,v:[{b:"```",e:"```"},{b:"`",e:"`"}]}];r.c=i;var s=e.inherit(e.TM,{b:n}),t="(\\(.*\\))?\\s*\\B[-=]>",o={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:c,c:["self"].concat(i)}]};return{aliases:["coffee","cson","iced"],k:c,i:/\/\*/,c:i.concat([e.C("###","###"),e.HCM,{cN:"function",b:"^\\s*"+n+"\\s*=\\s*"+t,e:"[-=]>",rB:!0,c:[s,o]},{b:/[:\(,=]\s*/,r:0,c:[{cN:"function",b:t,e:"[-=]>",rB:!0,c:[o]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[s]},s]},{b:n+":",e:":",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage("coq",function(e){return{k:{keyword:"_ as at cofix else end exists exists2 fix for forall fun if IF in let match mod Prop return Set then Type using where with Abort About Add Admit Admitted All Arguments Assumptions Axiom Back BackTo Backtrack Bind Blacklist Canonical Cd Check Class Classes Close Coercion Coercions CoFixpoint CoInductive Collection Combined Compute Conjecture Conjectures Constant constr Constraint Constructors Context Corollary CreateHintDb Cut Declare Defined Definition Delimit Dependencies DependentDerive Drop eauto End Equality Eval Example Existential Existentials Existing Export exporting Extern Extract Extraction Fact Field Fields File Fixpoint Focus for From Function Functional Generalizable Global Goal Grab Grammar Graph Guarded Heap Hint HintDb Hints Hypotheses Hypothesis ident Identity If Immediate Implicit Import Include Inductive Infix Info Initial Inline Inspect Instance Instances Intro Intros Inversion Inversion_clear Language Left Lemma Let Libraries Library Load LoadPath Local Locate Ltac ML Mode Module Modules Monomorphic Morphism Next NoInline Notation Obligation Obligations Opaque Open Optimize Options Parameter Parameters Parametric Path Paths pattern Polymorphic Preterm Print Printing Program Projections Proof Proposition Pwd Qed Quit Rec Record Recursive Redirect Relation Remark Remove Require Reserved Reset Resolve Restart Rewrite Right Ring Rings Save Scheme Scope Scopes Script Search SearchAbout SearchHead SearchPattern SearchRewrite Section Separate Set Setoid Show Solve Sorted Step Strategies Strategy Structure SubClass Table Tables Tactic Term Test Theorem Time Timeout Transparent Type Typeclasses Types Undelimit Undo Unfocus Unfocused Unfold Universe Universes Unset Unshelve using Variable Variables Variant Verbose Visibility where with",built_in:"abstract absurd admit after apply as assert assumption at auto autorewrite autounfold before bottom btauto by case case_eq cbn cbv change classical_left classical_right clear clearbody cofix compare compute congruence constr_eq constructor contradict contradiction cut cutrewrite cycle decide decompose dependent destruct destruction dintuition discriminate discrR do double dtauto eapply eassumption eauto ecase econstructor edestruct ediscriminate eelim eexact eexists einduction einjection eleft elim elimtype enough equality erewrite eright esimplify_eq esplit evar exact exactly_once exfalso exists f_equal fail field field_simplify field_simplify_eq first firstorder fix fold fourier functional generalize generalizing gfail give_up has_evar hnf idtac in induction injection instantiate intro intro_pattern intros intuition inversion inversion_clear is_evar is_var lapply lazy left lia lra move native_compute nia nsatz omega once pattern pose progress proof psatz quote record red refine reflexivity remember rename repeat replace revert revgoals rewrite rewrite_strat right ring ring_simplify rtauto set setoid_reflexivity setoid_replace setoid_rewrite setoid_symmetry setoid_transitivity shelve shelve_unifiable simpl simple simplify_eq solve specialize split split_Rabs split_Rmult stepl stepr subst sum swap symmetry tactic tauto time timeout top transitivity trivial try tryif unfold unify until using vm_compute with"},c:[e.QSM,e.C("\\(\\*","\\*\\)"),e.CNM,{cN:"type",eB:!0,b:"\\|\\s*",e:"\\w+"},{b:/[-=]>/}]}});hljs.registerLanguage("less",function(e){var r="[\\w-]+",t="("+r+"|@{"+r+"})",a=[],c=[],s=function(e){return{cN:"string",b:"~?"+e+".*?"+e}},b=function(e,r,t){return{cN:e,b:r,r:t}},n={b:"\\(",e:"\\)",c:c,r:0};c.push(e.CLCM,e.CBCM,s("'"),s('"'),e.CSSNM,{b:"(url|data-uri)\\(",starts:{cN:"string",e:"[\\)\\n]",eE:!0}},b("number","#[0-9A-Fa-f]+\\b"),n,b("variable","@@?"+r,10),b("variable","@{"+r+"}"),b("built_in","~?`[^`]*?`"),{cN:"attribute",b:r+"\\s*:",e:":",rB:!0,eE:!0},{cN:"meta",b:"!important"});var i=c.concat({b:"{",e:"}",c:a}),o={bK:"when",eW:!0,c:[{bK:"and not"}].concat(c)},u={b:t+"\\s*:",rB:!0,e:"[;}]",r:0,c:[{cN:"attribute",b:t,e:":",eE:!0,starts:{eW:!0,i:"[<=$]",r:0,c:c}}]},l={cN:"keyword",b:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b",starts:{e:"[;{}]",rE:!0,c:c,r:0}},C={cN:"variable",v:[{b:"@"+r+"\\s*:",r:15},{b:"@"+r}],starts:{e:"[;}]",rE:!0,c:i}},p={v:[{b:"[\\.#:&\\[>]",e:"[;{}]"},{b:t,e:"{"}],rB:!0,rE:!0,i:"[<='$\"]",r:0,c:[e.CLCM,e.CBCM,o,b("keyword","all\\b"),b("variable","@{"+r+"}"),b("selector-tag",t+"%?",0),b("selector-id","#"+t),b("selector-class","\\."+t,0),b("selector-tag","&",0),{cN:"selector-attr",b:"\\[",e:"\\]"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"\\(",e:"\\)",c:i},{b:"!important"}]};return a.push(e.CLCM,e.CBCM,l,C,u,p),{cI:!0,i:"[=>'/<($\"]",c:a}});hljs.registerLanguage("dart",function(e){var t={cN:"subst",b:"\\$\\{",e:"}",k:"true false null this is new super"},r={cN:"string",v:[{b:"r'''",e:"'''"},{b:'r"""',e:'"""'},{b:"r'",e:"'",i:"\\n"},{b:'r"',e:'"',i:"\\n"},{b:"'''",e:"'''",c:[e.BE,t]},{b:'"""',e:'"""',c:[e.BE,t]},{b:"'",e:"'",i:"\\n",c:[e.BE,t]},{b:'"',e:'"',i:"\\n",c:[e.BE,t]}]};t.c=[e.CNM,r];var n={keyword:"assert async await break case catch class const continue default do else enum extends false final finally for if in is new null rethrow return super switch sync this throw true try var void while with yield abstract as dynamic export external factory get implements import library operator part set static typedef",built_in:"print Comparable DateTime Duration Function Iterable Iterator List Map Match Null Object Pattern RegExp Set Stopwatch String StringBuffer StringSink Symbol Type Uri bool double int num document window querySelector querySelectorAll Element ElementList"};return{k:n,c:[r,e.C("/\\*\\*","\\*/",{sL:"markdown"}),e.C("///","$",{sL:"markdown"}),e.CLCM,e.CBCM,{cN:"class",bK:"class interface",e:"{",eE:!0,c:[{bK:"extends implements"},e.UTM]},e.CNM,{cN:"meta",b:"@[A-Za-z]+"},{b:"=>"}]}});hljs.registerLanguage("capnproto",function(t){return{aliases:["capnp"],k:{keyword:"struct enum interface union group import using const annotation extends in of on as with from fixed",built_in:"Void Bool Int8 Int16 Int32 Int64 UInt8 UInt16 UInt32 UInt64 Float32 Float64 Text Data AnyPointer AnyStruct Capability List",literal:"true false"},c:[t.QSM,t.NM,t.HCM,{cN:"meta",b:/@0x[\w\d]{16};/,i:/\n/},{cN:"symbol",b:/@\d+\b/},{cN:"class",bK:"struct enum",e:/\{/,i:/\n/,c:[t.inherit(t.TM,{starts:{eW:!0,eE:!0}})]},{cN:"class",bK:"interface",e:/\{/,i:/\n/,c:[t.inherit(t.TM,{starts:{eW:!0,eE:!0}})]}]}});hljs.registerLanguage("livescript",function(e){var t={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger case default function var with then unless until loop of by when and or is isnt not it that otherwise from to til fallthrough super case default function var void const let enum export import native __hasProp __extends __slice __bind __indexOf",literal:"true false null undefined yes no on off it that void",built_in:"npm require console print module global window document"},s="[A-Za-z$_](?:-[0-9A-Za-z$_]|[0-9A-Za-z$_])*",n=e.inherit(e.TM,{b:s}),i={cN:"subst",b:/#\{/,e:/}/,k:t},r={cN:"subst",b:/#[A-Za-z$_]/,e:/(?:\-[0-9A-Za-z$_]|[0-9A-Za-z$_])*/,k:t},c=[e.BNM,{cN:"number",b:"(\\b0[xX][a-fA-F0-9_]+)|(\\b\\d(\\d|_\\d)*(\\.(\\d(\\d|_\\d)*)?)?(_*[eE]([-+]\\d(_\\d|\\d)*)?)?[_a-z]*)",r:0,starts:{e:"(\\s*/)?",r:0}},{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,i,r]},{b:/"/,e:/"/,c:[e.BE,i,r]},{b:/\\/,e:/(\s|$)/,eE:!0}]},{cN:"regexp",v:[{b:"//",e:"//[gim]*",c:[i,e.HCM]},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{b:"@"+s},{b:"``",e:"``",eB:!0,eE:!0,sL:"javascript"}];i.c=c;var a={cN:"params",b:"\\(",rB:!0,c:[{b:/\(/,e:/\)/,k:t,c:["self"].concat(c)}]};return{aliases:["ls"],k:t,i:/\/\*/,c:c.concat([e.C("\\/\\*","\\*\\/"),e.HCM,{cN:"function",c:[n,a],rB:!0,v:[{b:"("+s+"\\s*(?:=|:=)\\s*)?(\\(.*\\))?\\s*\\B\\->\\*?",e:"\\->\\*?"},{b:"("+s+"\\s*(?:=|:=)\\s*)?!?(\\(.*\\))?\\s*\\B[-~]{1,2}>\\*?",e:"[-~]{1,2}>\\*?"},{b:"("+s+"\\s*(?:=|:=)\\s*)?(\\(.*\\))?\\s*\\B!?[-~]{1,2}>\\*?",e:"!?[-~]{1,2}>\\*?"}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[n]},n]},{b:s+":",e:":",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage("scheme",function(e){var t="[^\\(\\)\\[\\]\\{\\}\",'`;#|\\\\\\s]+",r="(\\-|\\+)?\\d+([./]\\d+)?",a=r+"[+\\-]"+r+"i",i={"builtin-name":"case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules ' * + , ,@ - ... / ; < <= = => > >= ` abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string=? string>? string? substring symbol->string symbol? tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?"},n={cN:"meta",b:"^#!",e:"$"},c={cN:"literal",b:"(#t|#f|#\\\\"+t+"|#\\\\.)"},l={cN:"number",v:[{b:r,r:0},{b:a,r:0},{b:"#b[0-1]+(/[0-1]+)?"},{b:"#o[0-7]+(/[0-7]+)?"},{b:"#x[0-9a-f]+(/[0-9a-f]+)?"}]},s=e.QSM,o=[e.C(";","$",{r:0}),e.C("#\\|","\\|#")],u={b:t,r:0},p={cN:"symbol",b:"'"+t},d={eW:!0,r:0},m={v:[{b:/'/},{b:"`"}],c:[{b:"\\(",e:"\\)",c:["self",c,s,l,u,p]}]},g={cN:"name",b:t,l:t,k:i},h={b:/lambda/,eW:!0,rB:!0,c:[g,{b:/\(/,e:/\)/,endsParent:!0,c:[u]}]},b={v:[{b:"\\(",e:"\\)"},{b:"\\[",e:"\\]"}],c:[h,g,d]};return d.c=[c,l,s,u,p,m,b].concat(o),{i:/\S/,c:[n,l,s,p,m,b].concat(o)}});hljs.registerLanguage("asciidoc",function(e){return{aliases:["adoc"],c:[e.C("^/{4,}\\n","\\n/{4,}$",{r:10}),e.C("^//","$",{r:0}),{cN:"title",b:"^\\.\\w.*$"},{b:"^[=\\*]{4,}\\n",e:"\\n^[=\\*]{4,}$",r:10},{cN:"section",r:10,v:[{b:"^(={1,5}) .+?( \\1)?$"},{b:"^[^\\[\\]\\n]+?\\n[=\\-~\\^\\+]{2,}$"}]},{cN:"meta",b:"^:.+?:",e:"\\s",eE:!0,r:10},{cN:"meta",b:"^\\[.+?\\]$",r:0},{cN:"quote",b:"^_{4,}\\n",e:"\\n_{4,}$",r:10},{cN:"code",b:"^[\\-\\.]{4,}\\n",e:"\\n[\\-\\.]{4,}$",r:10},{b:"^\\+{4,}\\n",e:"\\n\\+{4,}$",c:[{b:"<",e:">",sL:"xml",r:0}],r:10},{cN:"bullet",b:"^(\\*+|\\-+|\\.+|[^\\n]+?::)\\s+"},{cN:"symbol",b:"^(NOTE|TIP|IMPORTANT|WARNING|CAUTION):\\s+",r:10},{cN:"strong",b:"\\B\\*(?![\\*\\s])",e:"(\\n{2}|\\*)",c:[{b:"\\\\*\\w",r:0}]},{cN:"emphasis",b:"\\B'(?!['\\s])",e:"(\\n{2}|')",c:[{b:"\\\\'\\w",r:0}],r:0},{cN:"emphasis",b:"_(?![_\\s])",e:"(\\n{2}|_)",r:0},{cN:"string",v:[{b:"``.+?''"},{b:"`.+?'"}]},{cN:"code",b:"(`.+?`|\\+.+?\\+)",r:0},{cN:"code",b:"^[ \\t]",e:"$",r:0},{b:"^'{3,}[ \\t]*$",r:10},{b:"(link:)?(http|https|ftp|file|irc|image:?):\\S+\\[.*?\\]",rB:!0,c:[{b:"(link|image:?):",r:0},{cN:"link",b:"\\w",e:"[^\\[]+",r:0},{cN:"string",b:"\\[",e:"\\]",eB:!0,eE:!0,r:0}],r:10}]}});hljs.registerLanguage("crystal",function(e){function r(e,r){var b=[{b:e,e:r}];return b[0].c=b,b}var b="(_[uif](8|16|32|64))?",c="[a-zA-Z_]\\w*[!?=]?",n="!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",i="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\][=?]?",s={keyword:"abstract alias as asm begin break case class def do else elsif end ensure enum extend for fun if ifdef include instance_sizeof is_a? lib macro module next of out pointerof private protected rescue responds_to? return require self sizeof struct super then type typeof union unless until when while with yield __DIR__ __FILE__ __LINE__",literal:"false nil true"},t={cN:"subst",b:"#{",e:"}",k:s},a={cN:"template-variable",v:[{b:"\\{\\{",e:"\\}\\}"},{b:"\\{%",e:"%\\}"}],k:s},l={cN:"string",c:[e.BE,t],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%w?\\(",e:"\\)",c:r("\\(","\\)")},{b:"%w?\\[",e:"\\]",c:r("\\[","\\]")},{b:"%w?{",e:"}",c:r("{","}")},{b:"%w?<",e:">",c:r("<",">")},{b:"%w?/",e:"/"},{b:"%w?%",e:"%"},{b:"%w?-",e:"-"},{b:"%w?\\|",e:"\\|"}],r:0},u={b:"("+n+")\\s*",c:[{cN:"regexp",c:[e.BE,t],v:[{b:"//[a-z]*",r:0},{b:"/",e:"/[a-z]*"},{b:"%r\\(",e:"\\)",c:r("\\(","\\)")},{b:"%r\\[",e:"\\]",c:r("\\[","\\]")},{b:"%r{",e:"}",c:r("{","}")},{b:"%r<",e:">",c:r("<",">")},{b:"%r/",e:"/"},{b:"%r%",e:"%"},{b:"%r-",e:"-"},{b:"%r\\|",e:"\\|"}]}],r:0},o={cN:"regexp",c:[e.BE,t],v:[{b:"%r\\(",e:"\\)",c:r("\\(","\\)")},{b:"%r\\[",e:"\\]",c:r("\\[","\\]")},{b:"%r{",e:"}",c:r("{","}")},{b:"%r<",e:">",c:r("<",">")},{b:"%r/",e:"/"},{b:"%r%",e:"%"},{b:"%r-",e:"-"},{b:"%r\\|",e:"\\|"}],r:0},_={cN:"meta",b:"@\\[",e:"\\]",c:[e.inherit(e.QSM,{cN:"meta-string"})]},f=[a,l,u,o,_,e.HCM,{cN:"class",bK:"class module struct",e:"$|;",i:/=/,c:[e.HCM,e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{b:"<"}]},{cN:"class",bK:"lib enum union",e:"$|;",i:/=/,c:[e.HCM,e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"})],r:10},{cN:"function",bK:"def",e:/\B\b/,c:[e.inherit(e.TM,{b:i,endsParent:!0})]},{cN:"function",bK:"fun macro",e:/\B\b/,c:[e.inherit(e.TM,{b:i,endsParent:!0})],r:5},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":",c:[l,{b:i}],r:0},{cN:"number",v:[{b:"\\b0b([01_]*[01])"+b},{b:"\\b0o([0-7_]*[0-7])"+b},{b:"\\b0x([A-Fa-f0-9_]*[A-Fa-f0-9])"+b},{b:"\\b(([0-9][0-9_]*[0-9]|[0-9])(\\.[0-9_]*[0-9])?([eE][+-]?[0-9_]*[0-9])?)"+b}],r:0}];return t.c=f,a.c=f.slice(1),{aliases:["cr"],l:c,k:s,c:f}}); \ No newline at end of file diff --git a/app/src/main/assets/highlight/js/prettify_line_number.js b/app/src/main/assets/highlight/js/prettify_line_number.js deleted file mode 100644 index 17cecfb8c..000000000 --- a/app/src/main/assets/highlight/js/prettify_line_number.js +++ /dev/null @@ -1,88 +0,0 @@ -(function (w) { - 'use strict'; - - var TABLE_NAME = 'hljs-ln', - LINE_NAME = 'hljs-ln-line', - CODE_BLOCK_NAME = 'hljs-ln-code', - NUMBERS_BLOCK_NAME = 'hljs-ln-numbers', - NUMBER_LINE_NAME = 'hljs-ln-n', - DATA_ATTR_NAME = 'data-line-number'; - - // https://wcoder.github.io/notes/string-format-for-string-formating-in-javascript - String.prototype.format = String.prototype.f = function () { - var args = arguments; - return this.replace(/\{(\d+)\}/g, function(m, n){ - return args[n] ? args[n] : m; - }); - }; - - if (typeof w.hljs === 'undefined') { - console.error('highlight.js not detected!'); - } else { - w.hljs.initLineNumbersOnLoad = initLineNumbersOnLoad; - w.hljs.lineNumbersBlock = lineNumbersBlock; - - addStyles(); - } - - function addStyles () { - var css = document.createElement('style'); - css.type = 'text/css'; - css.innerHTML = ('.{0}{border-collapse:collapse}' + - '.{0} td{padding:0}' + - '.{1}:before{content:attr({2})}').format(TABLE_NAME, NUMBER_LINE_NAME, DATA_ATTR_NAME); - document.getElementsByTagName('head')[0].appendChild(css); - } - - function initLineNumbersOnLoad () { - if (document.readyState === 'complete') { - documentReady(); - } else { - w.addEventListener('DOMContentLoaded', documentReady); - } - } - - function documentReady () { - try { - var blocks = document.querySelectorAll('code.hljs'); - - for (var i in blocks) { - if (blocks.hasOwnProperty(i)) { - lineNumbersBlock(blocks[i]); - } - } - } catch (e) { - console.error('LineNumbers error: ', e); - } - } - - function lineNumbersBlock (element) { - if (typeof element !== 'object') return; - - var lines = getLines(element.innerHTML); - - if (lines.length > 1) { - var html = ''; - - for (var i = 0; i < lines.length; i++) { - html += ('
    ' + - '
    {6}
    ').format( - NUMBERS_BLOCK_NAME, - LINE_NAME, - NUMBER_LINE_NAME, - DATA_ATTR_NAME, - CODE_BLOCK_NAME, - i + 1, - lines[i].length > 0 ? lines[i] : ' '); - } - - element.innerHTML = '{1}
    '.format(TABLE_NAME, html); - } - } - - function getLines(text) { - if (text.length === 0) return []; - return text.split(/\r\n|\r|\n/g); - } - -}(window)); \ No newline at end of file diff --git a/app/src/main/assets/highlight/js/scrollto.js b/app/src/main/assets/highlight/js/scrollto.js deleted file mode 100644 index 93f64baff..000000000 --- a/app/src/main/assets/highlight/js/scrollto.js +++ /dev/null @@ -1,65 +0,0 @@ -function scrollToLineNumber(lineNo, secondLineNo) { - console.log(lineNo + "\n" + secondLineNo); - var scrollTo = secondLineNo > lineNo ? secondLineNo : lineNo; - var div = document.querySelector('div[data-line-number="' + scrollTo + '"]'); - var scrollToPosition = scrollTo > 5 ? (scrollTo - 5) : scrollTo; - var toScrollTo = document.querySelector('div[data-line-number="' + scrollToPosition + '"]'); - if (secondLineNo > lineNo) { - for (var i = lineNo; i < secondLineNo + 1; i++) { - var highlighted = document.querySelector('div[data-line-number="' + i + '"]'); - if(highlighted != null) - highlighted.parentElement.style.backgroundColor = "rgb(3, 102, 214)"; - - if(secondLineNo == i) break; - } - } else { - div.parentElement.style.backgroundColor = "rgb(248, 238, 199)"; - } - if (toScrollTo != null) smoothScroll(toScrollTo); -} - -function currentYPosition() { - if (document.body.scrollTop) return document.body.scrollTop; - return 0; -} - -function elmYPosition(element) { - var elm = element; - var y = elm.offsetTop; - var node = elm; - while (node.offsetParent && node.offsetParent != document.body) { - node = node.offsetParent; - y += node.offsetTop; - } - return y; -} - -function smoothScroll(element) { - var startY = currentYPosition(); - var stopY = elmYPosition(element); - var distance = stopY > startY ? stopY - startY : startY - stopY; - if (distance < 100) { - scrollTo(0, stopY); - return; - } - var speed = Math.round(distance / 100); - if (speed >= 20) speed = 20; - var step = Math.round(distance / 25); - var leapY = stopY > startY ? startY + step : startY - step; - var timer = 0; - if (stopY > startY) { - for (var i = startY; i < stopY; i += step) { - setTimeout("window.scrollTo(0, " + leapY + ")", timer * speed); - leapY += step; - if (leapY > stopY) leapY = stopY; - timer++; - } - return; - } - for (var i = startY; i > stopY; i -= step) { - setTimeout("window.scrollTo(0, " + leapY + ")", timer * speed); - leapY -= step; - if (leapY < stopY) leapY = stopY; - timer++; - } -} \ No newline at end of file diff --git a/app/src/main/assets/highlight/styles/prettify.css b/app/src/main/assets/highlight/styles/prettify.css deleted file mode 100644 index e3e6606f2..000000000 --- a/app/src/main/assets/highlight/styles/prettify.css +++ /dev/null @@ -1,98 +0,0 @@ -/* - -Original highlight.js style (c) Ivan Sagalaev - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: #333; -} - -.hljs-comment, -.hljs-quote { - color: #998; - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-subst { - color: #333; - font-weight: bold; -} - -.hljs-number, -.hljs-literal, -.hljs-variable, -.hljs-template-variable, -.hljs-tag .hljs-attr { - color: #008080; -} - -.hljs-string, -.hljs-doctag { - color: #d14; -} - -.hljs-title, -.hljs-section, -.hljs-selector-id { - color: #900; - font-weight: bold; -} - -.hljs-subst { - font-weight: normal; -} - -.hljs-type, -.hljs-class .hljs-title { - color: #458; - font-weight: bold; -} - -.hljs-tag, -.hljs-name, -.hljs-attribute { - color: #000080; - font-weight: normal; -} - -.hljs-regexp, -.hljs-link { - color: #009926; -} - -.hljs-symbol, -.hljs-bullet { - color: #990073; -} - -.hljs-built_in, -.hljs-builtin-name { - color: #0086b3; -} - -.hljs-meta { - color: #999; - font-weight: bold; -} - -.hljs-deletion { - background: #fdd; -} - -.hljs-addition { - background: #dfd; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} \ No newline at end of file diff --git a/app/src/main/assets/highlight/styles/prettify_dark.css b/app/src/main/assets/highlight/styles/prettify_dark.css deleted file mode 100644 index b7ae2f3df..000000000 --- a/app/src/main/assets/highlight/styles/prettify_dark.css +++ /dev/null @@ -1,74 +0,0 @@ -/* - -Original highlight.js style (c) Ivan Sagalaev - -*/ - -.hljs-comment, -.hljs-quote { - color: #969896; -} - -/* Tomorrow Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-deletion { - color: #cc6666; -} - -/* Tomorrow Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-meta, -.hljs-link { - color: #de935f; -} - -/* Tomorrow Yellow */ -.hljs-attribute { - color: #f0c674; -} - -/* Tomorrow Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #b5bd68; -} - -/* Tomorrow Blue */ -.hljs-title, -.hljs-section { - color: #81a2be; -} - -/* Tomorrow Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #b294bb; -} - -.hljs { - display: block; - overflow-x: auto; - color: #c5c8c6; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} \ No newline at end of file diff --git a/app/src/main/assets/highlight/styles/themes/agate.css b/app/src/main/assets/highlight/styles/themes/agate.css deleted file mode 100644 index 6021c901e..000000000 --- a/app/src/main/assets/highlight/styles/themes/agate.css +++ /dev/null @@ -1,107 +0,0 @@ -/*! - * Agate by Taufik Nurrohman - * ---------------------------------------------------- - * - * #ade5fc - * #a2fca2 - * #c6b4f0 - * #d36363 - * #fcc28c - * #fc9b9b - * #ffa - * #fff - * #333 - * #62c8f3 - * #888 - * - */ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: white; -} - -.hljs-name, -.hljs-strong { - font-weight: bold; -} - -.hljs-code, -.hljs-emphasis { - font-style: italic; -} - -.hljs-tag { - color: #62c8f3; -} - -.hljs-variable, -.hljs-template-variable, -.hljs-selector-id, -.hljs-selector-class { - color: #ade5fc; -} - -.hljs-string, -.hljs-bullet { - color: #a2fca2; -} - -.hljs-type, -.hljs-title, -.hljs-section, -.hljs-attribute, -.hljs-quote, -.hljs-built_in, -.hljs-builtin-name { - color: #ffa; -} - -.hljs-number, -.hljs-symbol, -.hljs-bullet { - color: #d36363; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal { - color: #fcc28c; -} - -.hljs-comment, -.hljs-deletion, -.hljs-code { - color: #888; -} - -.hljs-regexp, -.hljs-link { - color: #c6b4f0; -} - -.hljs-meta { - color: #fc9b9b; -} - -.hljs-deletion { - background-color: #fc9b9b; - color: #333; -} - -.hljs-addition { - background-color: #a2fca2; - color: #333; -} - -.hljs a { - color: inherit; -} - -.hljs a:focus, -.hljs a:hover { - color: inherit; - text-decoration: underline; -} diff --git a/app/src/main/assets/highlight/styles/themes/androidstudio.css b/app/src/main/assets/highlight/styles/themes/androidstudio.css deleted file mode 100644 index c1ce9d374..000000000 --- a/app/src/main/assets/highlight/styles/themes/androidstudio.css +++ /dev/null @@ -1,65 +0,0 @@ -/* -Date: 24 Fev 2015 -Author: Pedro Oliveira -*/ - -.hljs { - color: #a9b7c6; - display: block; - overflow-x: auto; - padding: 0px; -} - -.hljs-number, -.hljs-literal, -.hljs-symbol, -.hljs-bullet { - color: #6897BB; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-deletion { - color: #cc7832; -} - -.hljs-variable, -.hljs-template-variable, -.hljs-link { - color: #629755; -} - -.hljs-comment, -.hljs-quote { - color: #808080; -} - -.hljs-meta { - color: #bbb529; -} - -.hljs-string, -.hljs-attribute, -.hljs-addition { - color: #6A8759; -} - -.hljs-section, -.hljs-title, -.hljs-type { - color: #ffc66d; -} - -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #e8bf6a; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/arduino-light.css b/app/src/main/assets/highlight/styles/themes/arduino-light.css deleted file mode 100644 index a80f5f7a4..000000000 --- a/app/src/main/assets/highlight/styles/themes/arduino-light.css +++ /dev/null @@ -1,87 +0,0 @@ -/* - -Arduino® Light Theme - Stefania Mellai - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; -} - -.hljs, -.hljs-subst { - color: #434f54; -} - -.hljs-keyword, -.hljs-attribute, -.hljs-selector-tag, -.hljs-doctag, -.hljs-name { - color: #00979D; -} - -.hljs-built_in, -.hljs-literal, -.hljs-bullet, -.hljs-code, -.hljs-addition { - color: #D35400; -} - -.hljs-regexp, -.hljs-symbol, -.hljs-variable, -.hljs-template-variable, -.hljs-link, -.hljs-selector-attr, -.hljs-selector-pseudo { - color: #00979D; -} - -.hljs-type, -.hljs-string, -.hljs-selector-id, -.hljs-selector-class, -.hljs-quote, -.hljs-template-tag, -.hljs-deletion { - color: #005C5F; -} - -.hljs-title, -.hljs-section { - color: #880000; - font-weight: bold; -} - -.hljs-comment { - color: rgba(149,165,166,.8); -} - -.hljs-meta-keyword { - color: #728E00; -} - -.hljs-meta { - color: #728E00; - color: #434f54; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} - -.hljs-function { - color: #728E00; -} - -.hljs-number { - color: #8A7B52; -} diff --git a/app/src/main/assets/highlight/styles/themes/arta.css b/app/src/main/assets/highlight/styles/themes/arta.css deleted file mode 100644 index 7b3bad032..000000000 --- a/app/src/main/assets/highlight/styles/themes/arta.css +++ /dev/null @@ -1,73 +0,0 @@ -/* -Date: 17.V.2011 -Author: pumbur -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs, -.hljs-subst { - color: #aaa; -} - -.hljs-section { - color: #fff; -} - -.hljs-comment, -.hljs-quote, -.hljs-meta { - color: #444; -} - -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-regexp { - color: #ffcc33; -} - -.hljs-number, -.hljs-addition { - color: #00cc66; -} - -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-template-variable, -.hljs-attribute, -.hljs-link { - color: #32aaee; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #6644aa; -} - -.hljs-title, -.hljs-variable, -.hljs-deletion, -.hljs-template-tag { - color: #bb1166; -} - -.hljs-section, -.hljs-doctag, -.hljs-strong { - font-weight: bold; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/ascetic.css b/app/src/main/assets/highlight/styles/themes/ascetic.css deleted file mode 100644 index a668b8e34..000000000 --- a/app/src/main/assets/highlight/styles/themes/ascetic.css +++ /dev/null @@ -1,44 +0,0 @@ -/* - -Original style from softwaremaniacs.org (c) Ivan Sagalaev - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: black; -} - -.hljs-string, -.hljs-variable, -.hljs-template-variable, -.hljs-symbol, -.hljs-bullet, -.hljs-section, -.hljs-addition, -.hljs-attribute, -.hljs-link { - color: #888; -} - -.hljs-comment, -.hljs-quote, -.hljs-meta, -.hljs-deletion { - color: #ccc; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-section, -.hljs-name, -.hljs-type, -.hljs-strong { - font-weight: bold; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-cave-dark.css b/app/src/main/assets/highlight/styles/themes/atelier-cave-dark.css deleted file mode 100644 index 110e1440d..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-cave-dark.css +++ /dev/null @@ -1,83 +0,0 @@ -/* Base16 Atelier Cave Dark - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Cave Comment */ -.hljs-comment, -.hljs-quote { - color: #7e7887; -} - -/* Atelier-Cave Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-regexp, -.hljs-link, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #be4678; -} - -/* Atelier-Cave Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #aa573c; -} - -/* Atelier-Cave Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #2a9292; -} - -/* Atelier-Cave Blue */ -.hljs-title, -.hljs-section { - color: #576ddb; -} - -/* Atelier-Cave Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #955ae7; -} - -.hljs-deletion, -.hljs-addition { - color: #19171c; - display: inline-block; - width: 100%; -} - -.hljs-deletion { - background-color: #be4678; -} - -.hljs-addition { - background-color: #2a9292; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #8b8792; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-cave-light.css b/app/src/main/assets/highlight/styles/themes/atelier-cave-light.css deleted file mode 100644 index 67ea1c31f..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-cave-light.css +++ /dev/null @@ -1,85 +0,0 @@ -/* Base16 Atelier Cave Light - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/cave) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Cave Comment */ -.hljs-comment, -.hljs-quote { - color: #655f6d; -} - -/* Atelier-Cave Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #be4678; -} - -/* Atelier-Cave Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #aa573c; -} - -/* Atelier-Cave Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #2a9292; -} - -/* Atelier-Cave Blue */ -.hljs-title, -.hljs-section { - color: #576ddb; -} - -/* Atelier-Cave Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #955ae7; -} - -.hljs-deletion, -.hljs-addition { - color: #19171c; - display: inline-block; - width: 100%; -} - -.hljs-deletion { - background-color: #be4678; -} - -.hljs-addition { - background-color: #2a9292; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #585260; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-dune-dark.css b/app/src/main/assets/highlight/styles/themes/atelier-dune-dark.css deleted file mode 100644 index 1c0312f8b..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-dune-dark.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Dune Dark - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Dune Comment */ -.hljs-comment, -.hljs-quote { - color: #999580; -} - -/* Atelier-Dune Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #d73737; -} - -/* Atelier-Dune Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #b65611; -} - -/* Atelier-Dune Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #60ac39; -} - -/* Atelier-Dune Blue */ -.hljs-title, -.hljs-section { - color: #6684e1; -} - -/* Atelier-Dune Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #b854d4; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #a6a28c; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-dune-light.css b/app/src/main/assets/highlight/styles/themes/atelier-dune-light.css deleted file mode 100644 index f7815d920..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-dune-light.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Dune Light - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Dune Comment */ -.hljs-comment, -.hljs-quote { - color: #7d7a68; -} - -/* Atelier-Dune Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #d73737; -} - -/* Atelier-Dune Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #b65611; -} - -/* Atelier-Dune Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #60ac39; -} - -/* Atelier-Dune Blue */ -.hljs-title, -.hljs-section { - color: #6684e1; -} - -/* Atelier-Dune Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #b854d4; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #6e6b5e; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-estuary-dark.css b/app/src/main/assets/highlight/styles/themes/atelier-estuary-dark.css deleted file mode 100644 index 232639410..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-estuary-dark.css +++ /dev/null @@ -1,84 +0,0 @@ -/* Base16 Atelier Estuary Dark - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/estuary) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Estuary Comment */ -.hljs-comment, -.hljs-quote { - color: #878573; -} - -/* Atelier-Estuary Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #ba6236; -} - -/* Atelier-Estuary Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #ae7313; -} - -/* Atelier-Estuary Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #7d9726; -} - -/* Atelier-Estuary Blue */ -.hljs-title, -.hljs-section { - color: #36a166; -} - -/* Atelier-Estuary Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #5f9182; -} - -.hljs-deletion, -.hljs-addition { - color: #22221b; - display: inline-block; - width: 100%; -} - -.hljs-deletion { - background-color: #ba6236; -} - -.hljs-addition { - background-color: #7d9726; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #929181; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-estuary-light.css b/app/src/main/assets/highlight/styles/themes/atelier-estuary-light.css deleted file mode 100644 index 13c5164f4..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-estuary-light.css +++ /dev/null @@ -1,84 +0,0 @@ -/* Base16 Atelier Estuary Light - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/estuary) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Estuary Comment */ -.hljs-comment, -.hljs-quote { - color: #6c6b5a; -} - -/* Atelier-Estuary Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #ba6236; -} - -/* Atelier-Estuary Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #ae7313; -} - -/* Atelier-Estuary Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #7d9726; -} - -/* Atelier-Estuary Blue */ -.hljs-title, -.hljs-section { - color: #36a166; -} - -/* Atelier-Estuary Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #5f9182; -} - -.hljs-deletion, -.hljs-addition { - color: #22221b; - display: inline-block; - width: 100%; -} - -.hljs-deletion { - background-color: #ba6236; -} - -.hljs-addition { - background-color: #7d9726; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #5f5e4e; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-forest-dark.css b/app/src/main/assets/highlight/styles/themes/atelier-forest-dark.css deleted file mode 100644 index 9f485444e..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-forest-dark.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Forest Dark - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/forest) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Forest Comment */ -.hljs-comment, -.hljs-quote { - color: #9c9491; -} - -/* Atelier-Forest Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #f22c40; -} - -/* Atelier-Forest Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #df5320; -} - -/* Atelier-Forest Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #7b9726; -} - -/* Atelier-Forest Blue */ -.hljs-title, -.hljs-section { - color: #407ee7; -} - -/* Atelier-Forest Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #6666ea; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #a8a19f; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-forest-light.css b/app/src/main/assets/highlight/styles/themes/atelier-forest-light.css deleted file mode 100644 index 748643c41..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-forest-light.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Forest Light - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/forest) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Forest Comment */ -.hljs-comment, -.hljs-quote { - color: #766e6b; -} - -/* Atelier-Forest Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #f22c40; -} - -/* Atelier-Forest Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #df5320; -} - -/* Atelier-Forest Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #7b9726; -} - -/* Atelier-Forest Blue */ -.hljs-title, -.hljs-section { - color: #407ee7; -} - -/* Atelier-Forest Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #6666ea; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #68615e; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-heath-dark.css b/app/src/main/assets/highlight/styles/themes/atelier-heath-dark.css deleted file mode 100644 index e9a676147..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-heath-dark.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Heath Dark - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/heath) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Heath Comment */ -.hljs-comment, -.hljs-quote { - color: #9e8f9e; -} - -/* Atelier-Heath Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #ca402b; -} - -/* Atelier-Heath Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #a65926; -} - -/* Atelier-Heath Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #918b3b; -} - -/* Atelier-Heath Blue */ -.hljs-title, -.hljs-section { - color: #516aec; -} - -/* Atelier-Heath Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #7b59c0; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #ab9bab; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-heath-light.css b/app/src/main/assets/highlight/styles/themes/atelier-heath-light.css deleted file mode 100644 index e4d7a2976..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-heath-light.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Heath Light - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/heath) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Heath Comment */ -.hljs-comment, -.hljs-quote { - color: #776977; -} - -/* Atelier-Heath Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #ca402b; -} - -/* Atelier-Heath Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #a65926; -} - -/* Atelier-Heath Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #918b3b; -} - -/* Atelier-Heath Blue */ -.hljs-title, -.hljs-section { - color: #516aec; -} - -/* Atelier-Heath Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #7b59c0; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #695d69; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-lakeside-dark.css b/app/src/main/assets/highlight/styles/themes/atelier-lakeside-dark.css deleted file mode 100644 index e448ea4bd..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-lakeside-dark.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Lakeside Dark - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/lakeside) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Lakeside Comment */ -.hljs-comment, -.hljs-quote { - color: #7195a8; -} - -/* Atelier-Lakeside Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #d22d72; -} - -/* Atelier-Lakeside Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #935c25; -} - -/* Atelier-Lakeside Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #568c3b; -} - -/* Atelier-Lakeside Blue */ -.hljs-title, -.hljs-section { - color: #257fad; -} - -/* Atelier-Lakeside Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #6b6bb8; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #7ea2b4; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-lakeside-light.css b/app/src/main/assets/highlight/styles/themes/atelier-lakeside-light.css deleted file mode 100644 index bdca412f6..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-lakeside-light.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Lakeside Light - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/lakeside) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Lakeside Comment */ -.hljs-comment, -.hljs-quote { - color: #5a7b8c; -} - -/* Atelier-Lakeside Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #d22d72; -} - -/* Atelier-Lakeside Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #935c25; -} - -/* Atelier-Lakeside Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #568c3b; -} - -/* Atelier-Lakeside Blue */ -.hljs-title, -.hljs-section { - color: #257fad; -} - -/* Atelier-Lakeside Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #6b6bb8; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #516d7b; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-plateau-dark.css b/app/src/main/assets/highlight/styles/themes/atelier-plateau-dark.css deleted file mode 100644 index 22f970ea2..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-plateau-dark.css +++ /dev/null @@ -1,84 +0,0 @@ -/* Base16 Atelier Plateau Dark - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/plateau) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Plateau Comment */ -.hljs-comment, -.hljs-quote { - color: #7e7777; -} - -/* Atelier-Plateau Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #ca4949; -} - -/* Atelier-Plateau Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #b45a3c; -} - -/* Atelier-Plateau Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #4b8b8b; -} - -/* Atelier-Plateau Blue */ -.hljs-title, -.hljs-section { - color: #7272ca; -} - -/* Atelier-Plateau Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #8464c4; -} - -.hljs-deletion, -.hljs-addition { - color: #1b1818; - display: inline-block; - width: 100%; -} - -.hljs-deletion { - background-color: #ca4949; -} - -.hljs-addition { - background-color: #4b8b8b; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #8a8585; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-plateau-light.css b/app/src/main/assets/highlight/styles/themes/atelier-plateau-light.css deleted file mode 100644 index a7a29335d..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-plateau-light.css +++ /dev/null @@ -1,84 +0,0 @@ -/* Base16 Atelier Plateau Light - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/plateau) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Plateau Comment */ -.hljs-comment, -.hljs-quote { - color: #655d5d; -} - -/* Atelier-Plateau Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #ca4949; -} - -/* Atelier-Plateau Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #b45a3c; -} - -/* Atelier-Plateau Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #4b8b8b; -} - -/* Atelier-Plateau Blue */ -.hljs-title, -.hljs-section { - color: #7272ca; -} - -/* Atelier-Plateau Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #8464c4; -} - -.hljs-deletion, -.hljs-addition { - color: #1b1818; - display: inline-block; - width: 100%; -} - -.hljs-deletion { - background-color: #ca4949; -} - -.hljs-addition { - background-color: #4b8b8b; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #585050; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-savanna-dark.css b/app/src/main/assets/highlight/styles/themes/atelier-savanna-dark.css deleted file mode 100644 index 089ea7c2b..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-savanna-dark.css +++ /dev/null @@ -1,84 +0,0 @@ -/* Base16 Atelier Savanna Dark - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/savanna) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Savanna Comment */ -.hljs-comment, -.hljs-quote { - color: #78877d; -} - -/* Atelier-Savanna Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #b16139; -} - -/* Atelier-Savanna Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #9f713c; -} - -/* Atelier-Savanna Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #489963; -} - -/* Atelier-Savanna Blue */ -.hljs-title, -.hljs-section { - color: #478c90; -} - -/* Atelier-Savanna Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #55859b; -} - -.hljs-deletion, -.hljs-addition { - color: #171c19; - display: inline-block; - width: 100%; -} - -.hljs-deletion { - background-color: #b16139; -} - -.hljs-addition { - background-color: #489963; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #87928a; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-savanna-light.css b/app/src/main/assets/highlight/styles/themes/atelier-savanna-light.css deleted file mode 100644 index c2177a8c8..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-savanna-light.css +++ /dev/null @@ -1,84 +0,0 @@ -/* Base16 Atelier Savanna Light - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/savanna) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Savanna Comment */ -.hljs-comment, -.hljs-quote { - color: #5f6d64; -} - -/* Atelier-Savanna Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #b16139; -} - -/* Atelier-Savanna Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #9f713c; -} - -/* Atelier-Savanna Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #489963; -} - -/* Atelier-Savanna Blue */ -.hljs-title, -.hljs-section { - color: #478c90; -} - -/* Atelier-Savanna Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #55859b; -} - -.hljs-deletion, -.hljs-addition { - color: #171c19; - display: inline-block; - width: 100%; -} - -.hljs-deletion { - background-color: #b16139; -} - -.hljs-addition { - background-color: #489963; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #526057; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-seaside-dark.css b/app/src/main/assets/highlight/styles/themes/atelier-seaside-dark.css deleted file mode 100644 index a2cfce247..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-seaside-dark.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Seaside Dark - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/seaside) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Seaside Comment */ -.hljs-comment, -.hljs-quote { - color: #809980; -} - -/* Atelier-Seaside Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #e6193c; -} - -/* Atelier-Seaside Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #87711d; -} - -/* Atelier-Seaside Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #29a329; -} - -/* Atelier-Seaside Blue */ -.hljs-title, -.hljs-section { - color: #3d62f5; -} - -/* Atelier-Seaside Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #ad2bee; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #8ca68c; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-seaside-light.css b/app/src/main/assets/highlight/styles/themes/atelier-seaside-light.css deleted file mode 100644 index 5854b0b55..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-seaside-light.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Seaside Light - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/seaside) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Seaside Comment */ -.hljs-comment, -.hljs-quote { - color: #687d68; -} - -/* Atelier-Seaside Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #e6193c; -} - -/* Atelier-Seaside Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #87711d; -} - -/* Atelier-Seaside Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #29a329; -} - -/* Atelier-Seaside Blue */ -.hljs-title, -.hljs-section { - color: #3d62f5; -} - -/* Atelier-Seaside Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #ad2bee; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #5e6e5e; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-sulphurpool-dark.css b/app/src/main/assets/highlight/styles/themes/atelier-sulphurpool-dark.css deleted file mode 100644 index ecb87243b..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-sulphurpool-dark.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Sulphurpool Dark - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Sulphurpool Comment */ -.hljs-comment, -.hljs-quote { - color: #898ea4; -} - -/* Atelier-Sulphurpool Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #c94922; -} - -/* Atelier-Sulphurpool Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #c76b29; -} - -/* Atelier-Sulphurpool Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #ac9739; -} - -/* Atelier-Sulphurpool Blue */ -.hljs-title, -.hljs-section { - color: #3d8fd1; -} - -/* Atelier-Sulphurpool Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #6679cc; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #979db4; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atelier-sulphurpool-light.css b/app/src/main/assets/highlight/styles/themes/atelier-sulphurpool-light.css deleted file mode 100644 index 4b3d2ac03..000000000 --- a/app/src/main/assets/highlight/styles/themes/atelier-sulphurpool-light.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Base16 Atelier Sulphurpool Light - Theme */ -/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool) */ -/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */ - -/* Atelier-Sulphurpool Comment */ -.hljs-comment, -.hljs-quote { - color: #6b7394; -} - -/* Atelier-Sulphurpool Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-regexp, -.hljs-link, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #c94922; -} - -/* Atelier-Sulphurpool Orange */ -.hljs-number, -.hljs-meta, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #c76b29; -} - -/* Atelier-Sulphurpool Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet { - color: #ac9739; -} - -/* Atelier-Sulphurpool Blue */ -.hljs-title, -.hljs-section { - color: #3d8fd1; -} - -/* Atelier-Sulphurpool Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #6679cc; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #5e6687; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/atom-one-dark.css b/app/src/main/assets/highlight/styles/themes/atom-one-dark.css deleted file mode 100644 index 4fd1695f2..000000000 --- a/app/src/main/assets/highlight/styles/themes/atom-one-dark.css +++ /dev/null @@ -1,96 +0,0 @@ -/* - -Atom One Dark by Daniel Gamage -Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax - -base: #282c34 -mono-1: #abb2bf -mono-2: #818896 -mono-3: #5c6370 -hue-1: #56b6c2 -hue-2: #61aeee -hue-3: #c678dd -hue-4: #98c379 -hue-5: #e06c75 -hue-5-2: #be5046 -hue-6: #d19a66 -hue-6-2: #e6c07b - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: #abb2bf; - -} - -.hljs-comment, -.hljs-quote { - color: #5c6370; - font-style: italic; -} - -.hljs-doctag, -.hljs-keyword, -.hljs-formula { - color: #c678dd; -} - -.hljs-section, -.hljs-name, -.hljs-selector-tag, -.hljs-deletion, -.hljs-subst { - color: #e06c75; -} - -.hljs-literal { - color: #56b6c2; -} - -.hljs-string, -.hljs-regexp, -.hljs-addition, -.hljs-attribute, -.hljs-meta-string { - color: #98c379; -} - -.hljs-built_in, -.hljs-class .hljs-title { - color: #e6c07b; -} - -.hljs-attr, -.hljs-variable, -.hljs-template-variable, -.hljs-type, -.hljs-selector-class, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-number { - color: #d19a66; -} - -.hljs-symbol, -.hljs-bullet, -.hljs-link, -.hljs-meta, -.hljs-selector-id, -.hljs-title { - color: #61aeee; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} - -.hljs-link { - text-decoration: underline; -} diff --git a/app/src/main/assets/highlight/styles/themes/atom-one-light.css b/app/src/main/assets/highlight/styles/themes/atom-one-light.css deleted file mode 100644 index 7dddf2d3c..000000000 --- a/app/src/main/assets/highlight/styles/themes/atom-one-light.css +++ /dev/null @@ -1,96 +0,0 @@ -/* - -Atom One Light by Daniel Gamage -Original One Light Syntax theme from https://github.com/atom/one-light-syntax - -base: #fafafa -mono-1: #383a42 -mono-2: #686b77 -mono-3: #a0a1a7 -hue-1: #0184bb -hue-2: #4078f2 -hue-3: #a626a4 -hue-4: #50a14f -hue-5: #e45649 -hue-5-2: #c91243 -hue-6: #986801 -hue-6-2: #c18401 - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: #383a42; - -} - -.hljs-comment, -.hljs-quote { - color: #a0a1a7; - font-style: italic; -} - -.hljs-doctag, -.hljs-keyword, -.hljs-formula { - color: #a626a4; -} - -.hljs-section, -.hljs-name, -.hljs-selector-tag, -.hljs-deletion, -.hljs-subst { - color: #e45649; -} - -.hljs-literal { - color: #0184bb; -} - -.hljs-string, -.hljs-regexp, -.hljs-addition, -.hljs-attribute, -.hljs-meta-string { - color: #50a14f; -} - -.hljs-built_in, -.hljs-class .hljs-title { - color: #c18401; -} - -.hljs-attr, -.hljs-variable, -.hljs-template-variable, -.hljs-type, -.hljs-selector-class, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-number { - color: #986801; -} - -.hljs-symbol, -.hljs-bullet, -.hljs-link, -.hljs-meta, -.hljs-selector-id, -.hljs-title { - color: #4078f2; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} - -.hljs-link { - text-decoration: underline; -} diff --git a/app/src/main/assets/highlight/styles/themes/brown-paper.css b/app/src/main/assets/highlight/styles/themes/brown-paper.css deleted file mode 100644 index e168ddc13..000000000 --- a/app/src/main/assets/highlight/styles/themes/brown-paper.css +++ /dev/null @@ -1,63 +0,0 @@ -/* - -Brown Paper style from goldblog.com.ua (c) Zaripov Yura - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal { - color:#005599; - font-weight:bold; -} - -.hljs, -.hljs-subst { - color: #363c69; -} - -.hljs-string, -.hljs-title, -.hljs-section, -.hljs-type, -.hljs-attribute, -.hljs-symbol, -.hljs-bullet, -.hljs-built_in, -.hljs-addition, -.hljs-variable, -.hljs-template-tag, -.hljs-template-variable, -.hljs-link, -.hljs-name { - color: #2c009f; -} - -.hljs-comment, -.hljs-quote, -.hljs-meta, -.hljs-deletion { - color: #802022; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-doctag, -.hljs-title, -.hljs-section, -.hljs-type, -.hljs-name, -.hljs-strong { - font-weight: bold; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/codepen-embed.css b/app/src/main/assets/highlight/styles/themes/codepen-embed.css deleted file mode 100644 index 199d4890f..000000000 --- a/app/src/main/assets/highlight/styles/themes/codepen-embed.css +++ /dev/null @@ -1,60 +0,0 @@ -/* - codepen.io Embed Theme - Author: Justin Perry - Original theme - https://github.com/chriskempson/tomorrow-theme -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - - color: #fff; -} - -.hljs-comment, -.hljs-quote { - color: #777; -} - -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-regexp, -.hljs-meta, -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-params, -.hljs-symbol, -.hljs-bullet, -.hljs-link, -.hljs-deletion { - color: #ab875d; -} - -.hljs-section, -.hljs-title, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-type, -.hljs-attribute { - color: #9b869b; -} - -.hljs-string, -.hljs-keyword, -.hljs-selector-tag, -.hljs-addition { - color: #8f9c6c; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/color-brewer.css b/app/src/main/assets/highlight/styles/themes/color-brewer.css deleted file mode 100644 index 5f1b13072..000000000 --- a/app/src/main/assets/highlight/styles/themes/color-brewer.css +++ /dev/null @@ -1,71 +0,0 @@ -/* - -Colorbrewer theme -Original: https://github.com/mbostock/colorbrewer-theme (c) Mike Bostock -Ported by Fabrício Tavares de Oliveira - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs, -.hljs-subst { - color: #000; -} - -.hljs-string, -.hljs-meta, -.hljs-symbol, -.hljs-template-tag, -.hljs-template-variable, -.hljs-addition { - color: #756bb1; -} - -.hljs-comment, -.hljs-quote { - color: #636363; -} - -.hljs-number, -.hljs-regexp, -.hljs-literal, -.hljs-bullet, -.hljs-link { - color: #31a354; -} - -.hljs-deletion, -.hljs-variable { - color: #88f; -} - - - -.hljs-keyword, -.hljs-selector-tag, -.hljs-title, -.hljs-section, -.hljs-built_in, -.hljs-doctag, -.hljs-type, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-strong { - color: #3182bd; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-attribute { - color: #e6550d; -} diff --git a/app/src/main/assets/highlight/styles/themes/darcula.css b/app/src/main/assets/highlight/styles/themes/darcula.css deleted file mode 100644 index eb40ab086..000000000 --- a/app/src/main/assets/highlight/styles/themes/darcula.css +++ /dev/null @@ -1,77 +0,0 @@ -/* - -Darcula color scheme from the JetBrains family of IDEs - -*/ - - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs { - color: #bababa; -} - -.hljs-strong, -.hljs-emphasis { - color: #a8a8a2; -} - -.hljs-bullet, -.hljs-quote, -.hljs-link, -.hljs-number, -.hljs-regexp, -.hljs-literal { - color: #6896ba; -} - -.hljs-code, -.hljs-selector-class { - color: #a6e22e; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-section, -.hljs-attribute, -.hljs-name, -.hljs-variable { - color: #cb7832; -} - -.hljs-params { - color: #b9b9b9; -} - -.hljs-string { - color: #6a8759; -} - -.hljs-subst, -.hljs-type, -.hljs-built_in, -.hljs-builtin-name, -.hljs-symbol, -.hljs-selector-id, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-template-tag, -.hljs-template-variable, -.hljs-addition { - color: #e0c46c; -} - -.hljs-comment, -.hljs-deletion, -.hljs-meta { - color: #7f7f7f; -} diff --git a/app/src/main/assets/highlight/styles/themes/dark.css b/app/src/main/assets/highlight/styles/themes/dark.css deleted file mode 100644 index e99826c42..000000000 --- a/app/src/main/assets/highlight/styles/themes/dark.css +++ /dev/null @@ -1,63 +0,0 @@ -/* - -Dark style from softwaremaniacs.org (c) Ivan Sagalaev - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-section, -.hljs-link { - color: white; -} - -.hljs, -.hljs-subst { - color: #ddd; -} - -.hljs-string, -.hljs-title, -.hljs-name, -.hljs-type, -.hljs-attribute, -.hljs-symbol, -.hljs-bullet, -.hljs-built_in, -.hljs-addition, -.hljs-variable, -.hljs-template-tag, -.hljs-template-variable { - color: #d88; -} - -.hljs-comment, -.hljs-quote, -.hljs-deletion, -.hljs-meta { - color: #777; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-title, -.hljs-section, -.hljs-doctag, -.hljs-type, -.hljs-name, -.hljs-strong { - font-weight: bold; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/darkula.css b/app/src/main/assets/highlight/styles/themes/darkula.css deleted file mode 100644 index f4646c3c5..000000000 --- a/app/src/main/assets/highlight/styles/themes/darkula.css +++ /dev/null @@ -1,6 +0,0 @@ -/* - Deprecated due to a typo in the name and left here for compatibility purpose only. - Please use darcula.css instead. -*/ - -@import url('darcula.css'); diff --git a/app/src/main/assets/highlight/styles/themes/default.css b/app/src/main/assets/highlight/styles/themes/default.css deleted file mode 100644 index b27a2ff88..000000000 --- a/app/src/main/assets/highlight/styles/themes/default.css +++ /dev/null @@ -1,99 +0,0 @@ -/* - -Original highlight.js style (c) Ivan Sagalaev - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - - -/* Base color: saturation 0; */ - -.hljs, -.hljs-subst { - color: #444; -} - -.hljs-comment { - color: #888888; -} - -.hljs-keyword, -.hljs-attribute, -.hljs-selector-tag, -.hljs-meta-keyword, -.hljs-doctag, -.hljs-name { - font-weight: bold; -} - - -/* User color: hue: 0 */ - -.hljs-type, -.hljs-string, -.hljs-number, -.hljs-selector-id, -.hljs-selector-class, -.hljs-quote, -.hljs-template-tag, -.hljs-deletion { - color: #880000; -} - -.hljs-title, -.hljs-section { - color: #880000; - font-weight: bold; -} - -.hljs-regexp, -.hljs-symbol, -.hljs-variable, -.hljs-template-variable, -.hljs-link, -.hljs-selector-attr, -.hljs-selector-pseudo { - color: #BC6060; -} - - -/* Language color: hue: 90; */ - -.hljs-literal { - color: #78A960; -} - -.hljs-built_in, -.hljs-bullet, -.hljs-code, -.hljs-addition { - color: #397300; -} - - -/* Meta color: hue: 200 */ - -.hljs-meta { - color: #1f7199; -} - -.hljs-meta-string { - color: #4d99bf; -} - - -/* Misc effects */ - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/docco.css b/app/src/main/assets/highlight/styles/themes/docco.css deleted file mode 100644 index f4e1cabce..000000000 --- a/app/src/main/assets/highlight/styles/themes/docco.css +++ /dev/null @@ -1,97 +0,0 @@ -/* -Docco style used in http://jashkenas.github.com/docco/ converted by Simon Madine (@thingsinjars) -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: #000; - -} - -.hljs-comment, -.hljs-quote { - color: #408080; - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-subst { - color: #954121; -} - -.hljs-number { - color: #40a070; -} - -.hljs-string, -.hljs-doctag { - color: #219161; -} - -.hljs-selector-id, -.hljs-selector-class, -.hljs-section, -.hljs-type { - color: #19469d; -} - -.hljs-params { - color: #00f; -} - -.hljs-title { - color: #458; - font-weight: bold; -} - -.hljs-tag, -.hljs-name, -.hljs-attribute { - color: #000080; - font-weight: normal; -} - -.hljs-variable, -.hljs-template-variable { - color: #008080; -} - -.hljs-regexp, -.hljs-link { - color: #b68; -} - -.hljs-symbol, -.hljs-bullet { - color: #990073; -} - -.hljs-built_in, -.hljs-builtin-name { - color: #0086b3; -} - -.hljs-meta { - color: #999; - font-weight: bold; -} - -.hljs-deletion { - -} - -.hljs-addition { - -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/dracula.css b/app/src/main/assets/highlight/styles/themes/dracula.css deleted file mode 100644 index ed96263e6..000000000 --- a/app/src/main/assets/highlight/styles/themes/dracula.css +++ /dev/null @@ -1,76 +0,0 @@ -/* - -Dracula Theme v1.2.0 - -https://github.com/zenorocha/dracula-theme - -Copyright 2015, All rights reserved - -Code licensed under the MIT license -http://zenorocha.mit-license.org - -@author Éverton Ribeiro -@author Zeno Rocha - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-section, -.hljs-link { - color: #8be9fd; -} - -.hljs-function .hljs-keyword { - color: #ff79c6; -} - -.hljs, -.hljs-subst { - color: #f8f8f2; -} - -.hljs-string, -.hljs-title, -.hljs-name, -.hljs-type, -.hljs-attribute, -.hljs-symbol, -.hljs-bullet, -.hljs-addition, -.hljs-variable, -.hljs-template-tag, -.hljs-template-variable { - color: #f1fa8c; -} - -.hljs-comment, -.hljs-quote, -.hljs-deletion, -.hljs-meta { - color: #6272a4; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-title, -.hljs-section, -.hljs-doctag, -.hljs-type, -.hljs-name, -.hljs-strong { - font-weight: bold; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/far.css b/app/src/main/assets/highlight/styles/themes/far.css deleted file mode 100644 index 454937e5f..000000000 --- a/app/src/main/assets/highlight/styles/themes/far.css +++ /dev/null @@ -1,71 +0,0 @@ -/* - -FAR Style (c) MajestiC - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs, -.hljs-subst { - color: #0ff; -} - -.hljs-string, -.hljs-attribute, -.hljs-symbol, -.hljs-bullet, -.hljs-built_in, -.hljs-builtin-name, -.hljs-template-tag, -.hljs-template-variable, -.hljs-addition { - color: #ff0; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-section, -.hljs-type, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-variable { - color: #fff; -} - -.hljs-comment, -.hljs-quote, -.hljs-doctag, -.hljs-deletion { - color: #888; -} - -.hljs-number, -.hljs-regexp, -.hljs-literal, -.hljs-link { - color: #0f0; -} - -.hljs-meta { - color: #008080; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-title, -.hljs-section, -.hljs-name, -.hljs-strong { - font-weight: bold; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/foundation.css b/app/src/main/assets/highlight/styles/themes/foundation.css deleted file mode 100644 index 92509c6b6..000000000 --- a/app/src/main/assets/highlight/styles/themes/foundation.css +++ /dev/null @@ -1,88 +0,0 @@ -/* -Description: Foundation 4 docs style for highlight.js -Author: Dan Allen -Website: http://foundation.zurb.com/docs/ -Version: 1.0 -Date: 2013-04-02 -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: black; -} - -.hljs-link, -.hljs-emphasis, -.hljs-attribute, -.hljs-addition { - color: #070; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong, -.hljs-string, -.hljs-deletion { - color: #d14; -} - -.hljs-strong { - font-weight: bold; -} - -.hljs-quote, -.hljs-comment { - color: #998; - font-style: italic; -} - -.hljs-section, -.hljs-title { - color: #900; -} - -.hljs-class .hljs-title, -.hljs-type { - color: #458; -} - -.hljs-variable, -.hljs-template-variable { - color: #336699; -} - -.hljs-bullet { - color: #997700; -} - -.hljs-meta { - color: #3344bb; -} - -.hljs-code, -.hljs-number, -.hljs-literal, -.hljs-keyword, -.hljs-selector-tag { - color: #099; -} - -.hljs-regexp { - background-color: #fff0ff; - color: #880088; -} - -.hljs-symbol { - color: #990073; -} - -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #007700; -} diff --git a/app/src/main/assets/highlight/styles/themes/github-gist.css b/app/src/main/assets/highlight/styles/themes/github-gist.css deleted file mode 100644 index 218b52d47..000000000 --- a/app/src/main/assets/highlight/styles/themes/github-gist.css +++ /dev/null @@ -1,70 +0,0 @@ -/** - * GitHub Gist Theme - * Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro - */ - -.hljs { - display: block; - padding: 0px; - color: #333333; - overflow-x: auto; -} - -.hljs-comment, -.hljs-meta { - color: #969896; -} - -.hljs-string, -.hljs-variable, -.hljs-template-variable, -.hljs-strong, -.hljs-emphasis, -.hljs-quote { - color: #df5000; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-type { - color: #a71d5d; -} - -.hljs-literal, -.hljs-symbol, -.hljs-bullet, -.hljs-attribute { - color: #0086b3; -} - -.hljs-section, -.hljs-name { - color: #63a35c; -} - -.hljs-tag { - color: #333333; -} - -.hljs-title, -.hljs-attr, -.hljs-selector-id, -.hljs-selector-class, -.hljs-selector-attr, -.hljs-selector-pseudo { - color: #795da3; -} - -.hljs-addition { - color: #55a532; - background-color: #eaffea; -} - -.hljs-deletion { - color: #bd2c00; - background-color: #ffecec; -} - -.hljs-link { - text-decoration: underline; -} diff --git a/app/src/main/assets/highlight/styles/themes/github.css b/app/src/main/assets/highlight/styles/themes/github.css deleted file mode 100644 index ebddd786a..000000000 --- a/app/src/main/assets/highlight/styles/themes/github.css +++ /dev/null @@ -1,99 +0,0 @@ -/* - -github.com style (c) Vasily Polovnyov - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: #333; - -} - -.hljs-comment, -.hljs-quote { - color: #998; - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-subst { - color: #333; - font-weight: bold; -} - -.hljs-number, -.hljs-literal, -.hljs-variable, -.hljs-template-variable, -.hljs-tag .hljs-attr { - color: #008080; -} - -.hljs-string, -.hljs-doctag { - color: #d14; -} - -.hljs-title, -.hljs-section, -.hljs-selector-id { - color: #900; - font-weight: bold; -} - -.hljs-subst { - font-weight: normal; -} - -.hljs-type, -.hljs-class .hljs-title { - color: #458; - font-weight: bold; -} - -.hljs-tag, -.hljs-name, -.hljs-attribute { - color: #000080; - font-weight: normal; -} - -.hljs-regexp, -.hljs-link { - color: #009926; -} - -.hljs-symbol, -.hljs-bullet { - color: #990073; -} - -.hljs-built_in, -.hljs-builtin-name { - color: #0086b3; -} - -.hljs-meta { - color: #999; - font-weight: bold; -} - -.hljs-deletion { - -} - -.hljs-addition { - -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/googlecode.css b/app/src/main/assets/highlight/styles/themes/googlecode.css deleted file mode 100644 index 9453ecb99..000000000 --- a/app/src/main/assets/highlight/styles/themes/googlecode.css +++ /dev/null @@ -1,88 +0,0 @@ -/* - -Google Code style (c) Aahan Krish - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: black; -} - -.hljs-comment, -.hljs-quote { - color: #800; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-section, -.hljs-title, -.hljs-name { - color: #008; -} - -.hljs-variable, -.hljs-template-variable { - color: #660; -} - -.hljs-string, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-regexp { - color: #080; -} - -.hljs-literal, -.hljs-symbol, -.hljs-bullet, -.hljs-meta, -.hljs-number, -.hljs-link { - color: #066; -} - -.hljs-title, -.hljs-doctag, -.hljs-type, -.hljs-attr, -.hljs-built_in, -.hljs-builtin-name, -.hljs-params { - color: #606; -} - -.hljs-attribute, -.hljs-subst { - color: #000; -} - -.hljs-formula { - background-color: #eee; - font-style: italic; -} - -.hljs-selector-id, -.hljs-selector-class { - color: #9B703F -} - -.hljs-addition { - background-color: #baeeba; -} - -.hljs-deletion { - background-color: #ffc8bd; -} - -.hljs-doctag, -.hljs-strong { - font-weight: bold; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/grayscale.css b/app/src/main/assets/highlight/styles/themes/grayscale.css deleted file mode 100644 index a4eb3aac2..000000000 --- a/app/src/main/assets/highlight/styles/themes/grayscale.css +++ /dev/null @@ -1,100 +0,0 @@ -/* - -grayscale style (c) MY Sun - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: #333; - -} - -.hljs-comment, -.hljs-quote { - color: #777; - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-subst { - color: #333; - font-weight: bold; -} - -.hljs-number, -.hljs-literal { - color: #777; -} - -.hljs-string, -.hljs-doctag, -.hljs-formula { - color: #333; -} - -.hljs-title, -.hljs-section, -.hljs-selector-id { - color: #000; - font-weight: bold; -} - -.hljs-subst { - font-weight: normal; -} - -.hljs-class .hljs-title, -.hljs-type, -.hljs-name { - color: #333; - font-weight: bold; -} - -.hljs-tag { - color: #333; -} - -.hljs-regexp { - color: #333; - background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAYAAADA+m62AAAAPUlEQVQYV2NkQAN37979r6yszIgujiIAU4RNMVwhuiQ6H6wQl3XI4oy4FMHcCJPHcDS6J2A2EqUQpJhohQDexSef15DBCwAAAABJRU5ErkJggg==) repeat; -} - -.hljs-symbol, -.hljs-bullet, -.hljs-link { - color: #000; - background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAKElEQVQIW2NkQAO7d+/+z4gsBhJwdXVlhAvCBECKwIIwAbhKZBUwBQA6hBpm5efZsgAAAABJRU5ErkJggg==) repeat; -} - -.hljs-built_in, -.hljs-builtin-name { - color: #000; - text-decoration: underline; -} - -.hljs-meta { - color: #999; - font-weight: bold; -} - -.hljs-deletion { - color: #fff; - background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAADCAYAAABS3WWCAAAAE0lEQVQIW2MMDQ39zzhz5kwIAQAyxweWgUHd1AAAAABJRU5ErkJggg==) repeat; -} - -.hljs-addition { - color: #000; - background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAALUlEQVQYV2N89+7dfwYk8P79ewZBQUFkIQZGOiu6e/cuiptQHAPl0NtNxAQBAM97Oejj3Dg7AAAAAElFTkSuQmCC) repeat; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/gruvbox-dark.css b/app/src/main/assets/highlight/styles/themes/gruvbox-dark.css deleted file mode 100644 index 5695ef609..000000000 --- a/app/src/main/assets/highlight/styles/themes/gruvbox-dark.css +++ /dev/null @@ -1,108 +0,0 @@ -/* - -Gruvbox style (dark) (c) Pavel Pertsev (original style at https://github.com/morhetz/gruvbox) - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs, -.hljs-subst { - color: #ebdbb2; -} - -/* Gruvbox Red */ -.hljs-deletion, -.hljs-formula, -.hljs-keyword, -.hljs-link, -.hljs-selector-tag { - color: #fb4934; -} - -/* Gruvbox Blue */ -.hljs-built_in, -.hljs-emphasis, -.hljs-name, -.hljs-quote, -.hljs-strong, -.hljs-title, -.hljs-variable { - color: #83a598; -} - -/* Gruvbox Yellow */ -.hljs-attr, -.hljs-params, -.hljs-template-tag, -.hljs-type { - color: #fabd2f; -} - -/* Gruvbox Purple */ -.hljs-builtin-name, -.hljs-doctag, -.hljs-literal, -.hljs-number { - color: #8f3f71; -} - -/* Gruvbox Orange */ -.hljs-code, -.hljs-meta, -.hljs-regexp, -.hljs-selector-id, -.hljs-template-variable { - color: #fe8019; -} - -/* Gruvbox Green */ -.hljs-addition, -.hljs-meta-string, -.hljs-section, -.hljs-selector-attr, -.hljs-selector-class, -.hljs-string, -.hljs-symbol { - color: #b8bb26; -} - -/* Gruvbox Aqua */ -.hljs-attribute, -.hljs-bullet, -.hljs-class, -.hljs-function, -.hljs-function .hljs-keyword, -.hljs-meta-keyword, -.hljs-selector-pseudo, -.hljs-tag { - color: #8ec07c; -} - -/* Gruvbox Gray */ -.hljs-comment { - color: #928374; -} - -/* Gruvbox Purple */ -.hljs-link_label, -.hljs-literal, -.hljs-number { - color: #d3869b; -} - -.hljs-comment, -.hljs-emphasis { - font-style: italic; -} - -.hljs-section, -.hljs-strong, -.hljs-tag { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/gruvbox-light.css b/app/src/main/assets/highlight/styles/themes/gruvbox-light.css deleted file mode 100644 index 381522140..000000000 --- a/app/src/main/assets/highlight/styles/themes/gruvbox-light.css +++ /dev/null @@ -1,108 +0,0 @@ -/* - -Gruvbox style (light) (c) Pavel Pertsev (original style at https://github.com/morhetz/gruvbox) - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs, -.hljs-subst { - color: #3c3836; -} - -/* Gruvbox Red */ -.hljs-deletion, -.hljs-formula, -.hljs-keyword, -.hljs-link, -.hljs-selector-tag { - color: #9d0006; -} - -/* Gruvbox Blue */ -.hljs-built_in, -.hljs-emphasis, -.hljs-name, -.hljs-quote, -.hljs-strong, -.hljs-title, -.hljs-variable { - color: #076678; -} - -/* Gruvbox Yellow */ -.hljs-attr, -.hljs-params, -.hljs-template-tag, -.hljs-type { - color: #b57614; -} - -/* Gruvbox Purple */ -.hljs-builtin-name, -.hljs-doctag, -.hljs-literal, -.hljs-number { - color: #8f3f71; -} - -/* Gruvbox Orange */ -.hljs-code, -.hljs-meta, -.hljs-regexp, -.hljs-selector-id, -.hljs-template-variable { - color: #af3a03; -} - -/* Gruvbox Green */ -.hljs-addition, -.hljs-meta-string, -.hljs-section, -.hljs-selector-attr, -.hljs-selector-class, -.hljs-string, -.hljs-symbol { - color: #79740e; -} - -/* Gruvbox Aqua */ -.hljs-attribute, -.hljs-bullet, -.hljs-class, -.hljs-function, -.hljs-function .hljs-keyword, -.hljs-meta-keyword, -.hljs-selector-pseudo, -.hljs-tag { - color: #427b58; -} - -/* Gruvbox Gray */ -.hljs-comment { - color: #928374; -} - -/* Gruvbox Purple */ -.hljs-link_label, -.hljs-literal, -.hljs-number { - color: #8f3f71; -} - -.hljs-comment, -.hljs-emphasis { - font-style: italic; -} - -.hljs-section, -.hljs-strong, -.hljs-tag { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/hopscotch.css b/app/src/main/assets/highlight/styles/themes/hopscotch.css deleted file mode 100644 index 0f82c0bd7..000000000 --- a/app/src/main/assets/highlight/styles/themes/hopscotch.css +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Hopscotch - * by Jan T. Sott - * https://github.com/idleberg/Hopscotch - * - * This work is licensed under the Creative Commons CC0 1.0 Universal License - */ - -/* Comment */ -.hljs-comment, -.hljs-quote { - color: #989498; -} - -/* Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-attribute, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-link, -.hljs-deletion { - color: #dd464c; -} - -/* Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params { - color: #fd8b19; -} - -/* Yellow */ -.hljs-class .hljs-title { - color: #fdcc59; -} - -/* Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #8fc13e; -} - -/* Aqua */ -.hljs-meta { - color: #149b93; -} - -/* Blue */ -.hljs-function, -.hljs-section, -.hljs-title { - color: #1290bf; -} - -/* Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #c85e7c; -} - -.hljs { - display: block; - - color: #b9b5b8; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/hybrid.css b/app/src/main/assets/highlight/styles/themes/hybrid.css deleted file mode 100644 index 488b20db0..000000000 --- a/app/src/main/assets/highlight/styles/themes/hybrid.css +++ /dev/null @@ -1,102 +0,0 @@ -/* - -vim-hybrid theme by w0ng (https://github.com/w0ng/vim-hybrid) - -*/ - -/*background color*/ -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -/*selection color*/ -.hljs::selection, -.hljs span::selection { - -} - -.hljs::-moz-selection, -.hljs span::-moz-selection { - -} - -/*foreground color*/ -.hljs { - color: #c5c8c6; -} - -/*color: fg_yellow*/ -.hljs-title, -.hljs-name { - color: #f0c674; -} - -/*color: fg_comment*/ -.hljs-comment, -.hljs-meta, -.hljs-meta .hljs-keyword { - color: #707880; -} - -/*color: fg_red*/ -.hljs-number, -.hljs-symbol, -.hljs-literal, -.hljs-deletion, -.hljs-link { - color: #cc6666 -} - -/*color: fg_green*/ -.hljs-string, -.hljs-doctag, -.hljs-addition, -.hljs-regexp, -.hljs-selector-attr, -.hljs-selector-pseudo { - color: #b5bd68; -} - -/*color: fg_purple*/ -.hljs-attribute, -.hljs-code, -.hljs-selector-id { - color: #b294bb; -} - -/*color: fg_blue*/ -.hljs-keyword, -.hljs-selector-tag, -.hljs-bullet, -.hljs-tag { - color: #81a2be; -} - -/*color: fg_aqua*/ -.hljs-subst, -.hljs-variable, -.hljs-template-tag, -.hljs-template-variable { - color: #8abeb7; -} - -/*color: fg_orange*/ -.hljs-type, -.hljs-built_in, -.hljs-builtin-name, -.hljs-quote, -.hljs-section, -.hljs-selector-class { - color: #de935f; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/idea.css b/app/src/main/assets/highlight/styles/themes/idea.css deleted file mode 100644 index 33ad99405..000000000 --- a/app/src/main/assets/highlight/styles/themes/idea.css +++ /dev/null @@ -1,97 +0,0 @@ -/* - -Intellij Idea-like styling (c) Vasily Polovnyov - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: #000; - -} - -.hljs-subst, -.hljs-title { - font-weight: normal; - color: #000; -} - -.hljs-comment, -.hljs-quote { - color: #808080; - font-style: italic; -} - -.hljs-meta { - color: #808000; -} - -.hljs-tag { - -} - -.hljs-section, -.hljs-name, -.hljs-literal, -.hljs-keyword, -.hljs-selector-tag, -.hljs-type, -.hljs-selector-id, -.hljs-selector-class { - font-weight: bold; - color: #000080; -} - -.hljs-attribute, -.hljs-number, -.hljs-regexp, -.hljs-link { - font-weight: bold; - color: #0000ff; -} - -.hljs-number, -.hljs-regexp, -.hljs-link { - font-weight: normal; -} - -.hljs-string { - color: #008000; - font-weight: bold; -} - -.hljs-symbol, -.hljs-bullet, -.hljs-formula { - color: #000; - - font-style: italic; -} - -.hljs-doctag { - text-decoration: underline; -} - -.hljs-variable, -.hljs-template-variable { - color: #660e7a; -} - -.hljs-addition { - -} - -.hljs-deletion { - -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/ir-black.css b/app/src/main/assets/highlight/styles/themes/ir-black.css deleted file mode 100644 index 633ec7535..000000000 --- a/app/src/main/assets/highlight/styles/themes/ir-black.css +++ /dev/null @@ -1,73 +0,0 @@ -/* - IR_Black style (c) Vasily Mikhailitchenko -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - - color: #f8f8f8; -} - -.hljs-comment, -.hljs-quote, -.hljs-meta { - color: #7c7c7c; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-tag, -.hljs-name { - color: #96cbfe; -} - -.hljs-attribute, -.hljs-selector-id { - color: #ffffb6; -} - -.hljs-string, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-addition { - color: #a8ff60; -} - -.hljs-subst { - color: #daefa3; -} - -.hljs-regexp, -.hljs-link { - color: #e9c062; -} - -.hljs-title, -.hljs-section, -.hljs-type, -.hljs-doctag { - color: #ffffb6; -} - -.hljs-symbol, -.hljs-bullet, -.hljs-variable, -.hljs-template-variable, -.hljs-literal { - color: #c6c5fe; -} - -.hljs-number, -.hljs-deletion { - color:#ff73fd; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/kimbie.dark.css b/app/src/main/assets/highlight/styles/themes/kimbie.dark.css deleted file mode 100644 index a8a1d20d6..000000000 --- a/app/src/main/assets/highlight/styles/themes/kimbie.dark.css +++ /dev/null @@ -1,74 +0,0 @@ -/* - Name: Kimbie (dark) - Author: Jan T. Sott - License: Creative Commons Attribution-ShareAlike 4.0 Unported License - URL: https://github.com/idleberg/Kimbie-highlight.js -*/ - -/* Kimbie Comment */ -.hljs-comment, -.hljs-quote { - color: #d6baad; -} - -/* Kimbie Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-meta { - color: #dc3958; -} - -/* Kimbie Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-deletion, -.hljs-link { - color: #f79a32; -} - -/* Kimbie Yellow */ -.hljs-title, -.hljs-section, -.hljs-attribute { - color: #f06431; -} - -/* Kimbie Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #889b4a; -} - -/* Kimbie Purple */ -.hljs-keyword, -.hljs-selector-tag, -.hljs-function { - color: #98676a; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #d3af86; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/kimbie.light.css b/app/src/main/assets/highlight/styles/themes/kimbie.light.css deleted file mode 100644 index 9e2438ddb..000000000 --- a/app/src/main/assets/highlight/styles/themes/kimbie.light.css +++ /dev/null @@ -1,74 +0,0 @@ -/* - Name: Kimbie (light) - Author: Jan T. Sott - License: Creative Commons Attribution-ShareAlike 4.0 Unported License - URL: https://github.com/idleberg/Kimbie-highlight.js -*/ - -/* Kimbie Comment */ -.hljs-comment, -.hljs-quote { - color: #a57a4c; -} - -/* Kimbie Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-meta { - color: #dc3958; -} - -/* Kimbie Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-deletion, -.hljs-link { - color: #f79a32; -} - -/* Kimbie Yellow */ -.hljs-title, -.hljs-section, -.hljs-attribute { - color: #f06431; -} - -/* Kimbie Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #889b4a; -} - -/* Kimbie Purple */ -.hljs-keyword, -.hljs-selector-tag, -.hljs-function { - color: #98676a; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #84613d; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/magula.css b/app/src/main/assets/highlight/styles/themes/magula.css deleted file mode 100644 index d92ce9f86..000000000 --- a/app/src/main/assets/highlight/styles/themes/magula.css +++ /dev/null @@ -1,69 +0,0 @@ -/* -Description: Magula style for highligh.js -Author: Ruslan Keba -Website: http://rukeba.com/ -Version: 1.0 -Date: 2009-01-03 -Music: Aphex Twin / Xtal -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; -} - -.hljs, -.hljs-subst { - color: black; -} - -.hljs-string, -.hljs-title, -.hljs-symbol, -.hljs-bullet, -.hljs-attribute, -.hljs-addition, -.hljs-variable, -.hljs-template-tag, -.hljs-template-variable { - color: #050; -} - -.hljs-comment, -.hljs-quote { - color: #777; -} - -.hljs-number, -.hljs-regexp, -.hljs-literal, -.hljs-type, -.hljs-link { - color: #800; -} - -.hljs-deletion, -.hljs-meta { - color: #00e; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-doctag, -.hljs-title, -.hljs-section, -.hljs-built_in, -.hljs-tag, -.hljs-name { - font-weight: bold; - color: navy; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/mono-blue.css b/app/src/main/assets/highlight/styles/themes/mono-blue.css deleted file mode 100644 index ebf6eff06..000000000 --- a/app/src/main/assets/highlight/styles/themes/mono-blue.css +++ /dev/null @@ -1,59 +0,0 @@ -/* - Five-color theme from a single blue hue. -*/ -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs { - color: #00193a; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-title, -.hljs-section, -.hljs-doctag, -.hljs-name, -.hljs-strong { - font-weight: bold; -} - -.hljs-comment { - color: #738191; -} - -.hljs-string, -.hljs-title, -.hljs-section, -.hljs-built_in, -.hljs-literal, -.hljs-type, -.hljs-addition, -.hljs-tag, -.hljs-quote, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #0048ab; -} - -.hljs-meta, -.hljs-subst, -.hljs-symbol, -.hljs-regexp, -.hljs-attribute, -.hljs-deletion, -.hljs-variable, -.hljs-template-variable, -.hljs-link, -.hljs-bullet { - color: #4c81c9; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/monokai-sublime.css b/app/src/main/assets/highlight/styles/themes/monokai-sublime.css deleted file mode 100644 index aaef6b347..000000000 --- a/app/src/main/assets/highlight/styles/themes/monokai-sublime.css +++ /dev/null @@ -1,83 +0,0 @@ -/* - -Monokai Sublime style. Derived from Monokai by noformnocontent http://nn.mit-license.org/ - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs, -.hljs-tag, -.hljs-subst { - color: #f8f8f2; -} - -.hljs-strong, -.hljs-emphasis { - color: #a8a8a2; -} - -.hljs-bullet, -.hljs-quote, -.hljs-number, -.hljs-regexp, -.hljs-literal, -.hljs-link { - color: #ae81ff; -} - -.hljs-code, -.hljs-title, -.hljs-section, -.hljs-selector-class { - color: #a6e22e; -} - -.hljs-strong { - font-weight: bold; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-name, -.hljs-attr { - color: #f92672; -} - -.hljs-symbol, -.hljs-attribute { - color: #66d9ef; -} - -.hljs-params, -.hljs-class .hljs-title { - color: #f8f8f2; -} - -.hljs-string, -.hljs-type, -.hljs-built_in, -.hljs-builtin-name, -.hljs-selector-id, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-addition, -.hljs-variable, -.hljs-template-variable { - color: #e6db74; -} - -.hljs-comment, -.hljs-deletion, -.hljs-meta { - color: #75715e; -} diff --git a/app/src/main/assets/highlight/styles/themes/monokai.css b/app/src/main/assets/highlight/styles/themes/monokai.css deleted file mode 100644 index 03b62e45f..000000000 --- a/app/src/main/assets/highlight/styles/themes/monokai.css +++ /dev/null @@ -1,70 +0,0 @@ -/* -Monokai style - ported by Luigi Maselli - http://grigio.org -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: #ddd; -} - -.hljs-tag, -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-strong, -.hljs-name { - color: #f92672; -} - -.hljs-code { - color: #66d9ef; -} - -.hljs-class .hljs-title { - color: white; -} - -.hljs-attribute, -.hljs-symbol, -.hljs-regexp, -.hljs-link { - color: #bf79db; -} - -.hljs-string, -.hljs-bullet, -.hljs-subst, -.hljs-title, -.hljs-section, -.hljs-emphasis, -.hljs-type, -.hljs-built_in, -.hljs-builtin-name, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-addition, -.hljs-variable, -.hljs-template-tag, -.hljs-template-variable { - color: #a6e22e; -} - -.hljs-comment, -.hljs-quote, -.hljs-deletion, -.hljs-meta { - color: #75715e; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-doctag, -.hljs-title, -.hljs-section, -.hljs-type, -.hljs-selector-id { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/obsidian.css b/app/src/main/assets/highlight/styles/themes/obsidian.css deleted file mode 100644 index c32dff9a4..000000000 --- a/app/src/main/assets/highlight/styles/themes/obsidian.css +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Obsidian style - * ported by Alexander Marenin (http://github.com/ioncreature) - */ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-selector-id { - color: #93c763; -} - -.hljs-number { - color: #ffcd22; -} - -.hljs { - color: #e0e2e4; -} - -.hljs-attribute { - color: #668bb0; -} - -.hljs-code, -.hljs-class .hljs-title, -.hljs-section { - color: white; -} - -.hljs-regexp, -.hljs-link { - color: #d39745; -} - -.hljs-meta { - color: #557182; -} - -.hljs-tag, -.hljs-name, -.hljs-bullet, -.hljs-subst, -.hljs-emphasis, -.hljs-type, -.hljs-built_in, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-addition, -.hljs-variable, -.hljs-template-tag, -.hljs-template-variable { - color: #8cbbad; -} - -.hljs-string, -.hljs-symbol { - color: #ec7600; -} - -.hljs-comment, -.hljs-quote, -.hljs-deletion { - color: #818e96; -} - -.hljs-selector-class { - color: #A082BD -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-doctag, -.hljs-title, -.hljs-section, -.hljs-type, -.hljs-name, -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/ocean.css b/app/src/main/assets/highlight/styles/themes/ocean.css deleted file mode 100644 index a308fbe1d..000000000 --- a/app/src/main/assets/highlight/styles/themes/ocean.css +++ /dev/null @@ -1,74 +0,0 @@ -/* Ocean Dark Theme */ -/* https://github.com/gavsiu */ -/* Original theme - https://github.com/chriskempson/base16 */ - -/* Ocean Comment */ -.hljs-comment, -.hljs-quote { - color: #65737e; -} - -/* Ocean Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-deletion { - color: #bf616a; -} - -/* Ocean Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-meta, -.hljs-link { - color: #d08770; -} - -/* Ocean Yellow */ -.hljs-attribute { - color: #ebcb8b; -} - -/* Ocean Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #a3be8c; -} - -/* Ocean Blue */ -.hljs-title, -.hljs-section { - color: #8fa1b3; -} - -/* Ocean Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #b48ead; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #c0c5ce; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/paraiso-dark.css b/app/src/main/assets/highlight/styles/themes/paraiso-dark.css deleted file mode 100644 index 47fbcddb7..000000000 --- a/app/src/main/assets/highlight/styles/themes/paraiso-dark.css +++ /dev/null @@ -1,72 +0,0 @@ -/* - Paraíso (dark) - Created by Jan T. Sott (http://github.com/idleberg) - Inspired by the art of Rubens LP (http://www.rubenslp.com.br) -*/ - -/* Paraíso Comment */ -.hljs-comment, -.hljs-quote { - color: #8d8687; -} - -/* Paraíso Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-link, -.hljs-meta { - color: #ef6155; -} - -/* Paraíso Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-deletion { - color: #f99b15; -} - -/* Paraíso Yellow */ -.hljs-title, -.hljs-section, -.hljs-attribute { - color: #fec418; -} - -/* Paraíso Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #48b685; -} - -/* Paraíso Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #815ba4; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #a39e9b; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/paraiso-light.css b/app/src/main/assets/highlight/styles/themes/paraiso-light.css deleted file mode 100644 index 3128b642e..000000000 --- a/app/src/main/assets/highlight/styles/themes/paraiso-light.css +++ /dev/null @@ -1,72 +0,0 @@ -/* - Paraíso (light) - Created by Jan T. Sott (http://github.com/idleberg) - Inspired by the art of Rubens LP (http://www.rubenslp.com.br) -*/ - -/* Paraíso Comment */ -.hljs-comment, -.hljs-quote { - color: #776e71; -} - -/* Paraíso Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-link, -.hljs-meta { - color: #ef6155; -} - -/* Paraíso Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-deletion { - color: #f99b15; -} - -/* Paraíso Yellow */ -.hljs-title, -.hljs-section, -.hljs-attribute { - color: #fec418; -} - -/* Paraíso Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #48b685; -} - -/* Paraíso Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #815ba4; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #4f424c; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/pojoaque.css b/app/src/main/assets/highlight/styles/themes/pojoaque.css deleted file mode 100644 index 023e5d019..000000000 --- a/app/src/main/assets/highlight/styles/themes/pojoaque.css +++ /dev/null @@ -1,82 +0,0 @@ -/* - -Pojoaque Style by Jason Tate -http://web-cms-designs.com/ftopict-10-pojoaque-style-for-highlight-js-code-highlighter.html -Based on Solarized Style from http://ethanschoonover.com/solarized - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: #dccf8f; -} - -.hljs-comment, -.hljs-quote { - color: #586e75; - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-addition { - color: #b64926; -} - -.hljs-number, -.hljs-string, -.hljs-doctag, -.hljs-regexp { - color: #468966; -} - -.hljs-title, -.hljs-section, -.hljs-built_in, -.hljs-name { - color: #ffb03b; -} - -.hljs-variable, -.hljs-template-variable, -.hljs-class .hljs-title, -.hljs-type, -.hljs-tag { - color: #b58900; -} - -.hljs-attribute { - color: #b89859; -} - -.hljs-symbol, -.hljs-bullet, -.hljs-link, -.hljs-subst, -.hljs-meta { - color: #cb4b16; -} - -.hljs-deletion { - color: #dc322f; -} - -.hljs-selector-id, -.hljs-selector-class { - color: #d3a60c; -} - -.hljs-formula { - -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/purebasic.css b/app/src/main/assets/highlight/styles/themes/purebasic.css deleted file mode 100644 index 8373bfa54..000000000 --- a/app/src/main/assets/highlight/styles/themes/purebasic.css +++ /dev/null @@ -1,96 +0,0 @@ -/* - -PureBASIC native IDE style ( version 1.0 - April 2016 ) - -by Tristano Ajmone - -Public Domain - -NOTE_1: PureBASIC code syntax highlighting only applies the following classes: - .hljs-comment - .hljs-function - .hljs-keywords - .hljs-string - .hljs-symbol - - Other classes are added here for the benefit of styling other languages with the look and feel of PureBASIC native IDE style. - If you need to customize a stylesheet for PureBASIC only, remove all non-relevant classes -- PureBASIC-related classes are followed by - a "--- used for PureBASIC ... ---" comment on same line. - -NOTE_2: Color names provided in comments were derived using "Name that Color" online tool: - http://chir.ag/projects/name-that-color -*/ - -.hljs { /* Common set of rules required by highlight.js (don'r remove!) */ - display: block; - overflow-x: auto; - padding: 0px; - /* Half and Half (approx.) */ -/* --- Uncomment to add PureBASIC native IDE styled font! - font-family: Consolas; -*/ -} - -.hljs, /* --- used for PureBASIC base color --- */ -.hljs-type, /* --- used for PureBASIC Procedures return type --- */ -.hljs-function, /* --- used for wrapping PureBASIC Procedures definitions --- */ -.hljs-name, -.hljs-number, -.hljs-attr, -.hljs-params, -.hljs-subst { - color: #000000; /* Black */ -} - -.hljs-comment, /* --- used for PureBASIC Comments --- */ -.hljs-regexp, -.hljs-section, -.hljs-selector-pseudo, -.hljs-addition { - color: #00AAAA; /* Persian Green (approx.) */ -} - -.hljs-title, /* --- used for PureBASIC Procedures Names --- */ -.hljs-tag, -.hljs-variable, -.hljs-code { - color: #006666; /* Blue Stone (approx.) */ -} - -.hljs-keyword, /* --- used for PureBASIC Keywords --- */ -.hljs-class, -.hljs-meta-keyword, -.hljs-selector-class, -.hljs-built_in, -.hljs-builtin-name { - color: #006666; /* Blue Stone (approx.) */ - font-weight: bold; -} - -.hljs-string, /* --- used for PureBASIC Strings --- */ -.hljs-selector-attr { - color: #0080FF; /* Azure Radiance (approx.) */ -} - -.hljs-symbol, /* --- used for PureBASIC Constants --- */ -.hljs-link, -.hljs-deletion, -.hljs-attribute { - color: #924B72; /* Cannon Pink (approx.) */ -} - -.hljs-meta, -.hljs-literal, -.hljs-selector-id { - color: #924B72; /* Cannon Pink (approx.) */ - font-weight: bold; -} - -.hljs-strong, -.hljs-name { - font-weight: bold; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/qtcreator_dark.css b/app/src/main/assets/highlight/styles/themes/qtcreator_dark.css deleted file mode 100644 index 4ce2781b6..000000000 --- a/app/src/main/assets/highlight/styles/themes/qtcreator_dark.css +++ /dev/null @@ -1,83 +0,0 @@ -/* - -Qt Creator dark color scheme - -*/ - - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs, -.hljs-subst, -.hljs-tag, -.hljs-title { - color: #aaaaaa; -} - -.hljs-strong, -.hljs-emphasis { - color: #a8a8a2; -} - -.hljs-bullet, -.hljs-quote, -.hljs-number, -.hljs-regexp, -.hljs-literal { - color: #ff55ff; -} - -.hljs-code -.hljs-selector-class { - color: #aaaaff; -} - -.hljs-emphasis, -.hljs-stronge, -.hljs-type { - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-function, -.hljs-section, -.hljs-symbol, -.hljs-name { - color: #ffff55; -} - -.hljs-attribute { - color: #ff5555; -} - -.hljs-variable, -.hljs-params, -.hljs-class .hljs-title { - color: #8888ff; -} - -.hljs-string, -.hljs-selector-id, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-type, -.hljs-built_in, -.hljs-builtin-name, -.hljs-template-tag, -.hljs-template-variable, -.hljs-addition, -.hljs-link { - color: #ff55ff; -} - -.hljs-comment, -.hljs-meta, -.hljs-deletion { - color: #55ffff; -} diff --git a/app/src/main/assets/highlight/styles/themes/qtcreator_light.css b/app/src/main/assets/highlight/styles/themes/qtcreator_light.css deleted file mode 100644 index 0df3dd824..000000000 --- a/app/src/main/assets/highlight/styles/themes/qtcreator_light.css +++ /dev/null @@ -1,83 +0,0 @@ -/* - -Qt Creator light color scheme - -*/ - - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -.hljs, -.hljs-subst, -.hljs-tag, -.hljs-title { - color: #000000; -} - -.hljs-strong, -.hljs-emphasis { - color: #000000; -} - -.hljs-bullet, -.hljs-quote, -.hljs-number, -.hljs-regexp, -.hljs-literal { - color: #000080; -} - -.hljs-code -.hljs-selector-class { - color: #800080; -} - -.hljs-emphasis, -.hljs-stronge, -.hljs-type { - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-function, -.hljs-section, -.hljs-symbol, -.hljs-name { - color: #808000; -} - -.hljs-attribute { - color: #800000; -} - -.hljs-variable, -.hljs-params, -.hljs-class .hljs-title { - color: #0055AF; -} - -.hljs-string, -.hljs-selector-id, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-type, -.hljs-built_in, -.hljs-builtin-name, -.hljs-template-tag, -.hljs-template-variable, -.hljs-addition, -.hljs-link { - color: #008000; -} - -.hljs-comment, -.hljs-meta, -.hljs-deletion { - color: #008000; -} diff --git a/app/src/main/assets/highlight/styles/themes/railscasts.css b/app/src/main/assets/highlight/styles/themes/railscasts.css deleted file mode 100644 index be2c15cf3..000000000 --- a/app/src/main/assets/highlight/styles/themes/railscasts.css +++ /dev/null @@ -1,106 +0,0 @@ -/* - -Railscasts-like style (c) Visoft, Inc. (Damien White) - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - - color: #e6e1dc; -} - -.hljs-comment, -.hljs-quote { - color: #bc9458; - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag { - color: #c26230; -} - -.hljs-string, -.hljs-number, -.hljs-regexp, -.hljs-variable, -.hljs-template-variable { - color: #a5c261; -} - -.hljs-subst { - color: #519f50; -} - -.hljs-tag, -.hljs-name { - color: #e8bf6a; -} - -.hljs-type { - color: #da4939; -} - - -.hljs-symbol, -.hljs-bullet, -.hljs-built_in, -.hljs-builtin-name, -.hljs-attr, -.hljs-link { - color: #6d9cbe; -} - -.hljs-params { - color: #d0d0ff; -} - -.hljs-attribute { - color: #cda869; -} - -.hljs-meta { - color: #9b859d; -} - -.hljs-title, -.hljs-section { - color: #ffc66d; -} - -.hljs-addition { - background-color: #144212; - color: #e6e1dc; - display: inline-block; - width: 100%; -} - -.hljs-deletion { - background-color: #600; - color: #e6e1dc; - display: inline-block; - width: 100%; -} - -.hljs-selector-class { - color: #9b703f; -} - -.hljs-selector-id { - color: #8b98ab; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} - -.hljs-link { - text-decoration: underline; -} diff --git a/app/src/main/assets/highlight/styles/themes/rainbow.css b/app/src/main/assets/highlight/styles/themes/rainbow.css deleted file mode 100644 index 5bc848cf4..000000000 --- a/app/src/main/assets/highlight/styles/themes/rainbow.css +++ /dev/null @@ -1,85 +0,0 @@ -/* - -Style with support for rainbow parens - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - - color: #d1d9e1; -} - - -.hljs-comment, -.hljs-quote { - color: #969896; - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-type, -.hljs-addition { - color: #cc99cc; -} - -.hljs-number, -.hljs-selector-attr, -.hljs-selector-pseudo { - color: #f99157; -} - -.hljs-string, -.hljs-doctag, -.hljs-regexp { - color: #8abeb7; -} - -.hljs-title, -.hljs-name, -.hljs-section, -.hljs-built_in { - color: #b5bd68; -} - -.hljs-variable, -.hljs-template-variable, -.hljs-selector-id, -.hljs-class .hljs-title { - color: #ffcc66; -} - -.hljs-section, -.hljs-name, -.hljs-strong { - font-weight: bold; -} - -.hljs-symbol, -.hljs-bullet, -.hljs-subst, -.hljs-meta, -.hljs-link { - color: #f99157; -} - -.hljs-deletion { - color: #dc322f; -} - -.hljs-formula { - -} - -.hljs-attr, -.hljs-attribute { - color: #81a2be; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/routeros.css b/app/src/main/assets/highlight/styles/themes/routeros.css deleted file mode 100644 index a7a436e0b..000000000 --- a/app/src/main/assets/highlight/styles/themes/routeros.css +++ /dev/null @@ -1,108 +0,0 @@ -/* - - highlight.js style for Microtik RouterOS script - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - -} - -/* Base color: saturation 0; */ - -.hljs, -.hljs-subst { - color: #444; -} - -.hljs-comment { - color: #888888; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-meta-keyword, -.hljs-doctag, -.hljs-name { - font-weight: bold; -} - -.hljs-attribute { - color: #0E9A00; -} - -.hljs-function { - color: #99069A; -} - -.hljs-builtin-name { - color: #99069A; -} - -/* User color: hue: 0 */ - -.hljs-type, -.hljs-string, -.hljs-number, -.hljs-selector-id, -.hljs-selector-class, -.hljs-quote, -.hljs-template-tag, -.hljs-deletion { - color: #880000; -} - -.hljs-title, -.hljs-section { - color: #880000; - font-weight: bold; -} - -.hljs-regexp, -.hljs-symbol, -.hljs-variable, -.hljs-template-variable, -.hljs-link, -.hljs-selector-attr, -.hljs-selector-pseudo { - color: #BC6060; -} - - -/* Language color: hue: 90; */ - -.hljs-literal { - color: #78A960; -} - -.hljs-built_in, -.hljs-bullet, -.hljs-code, -.hljs-addition { - color: #0C9A9A; -} - - -/* Meta color: hue: 200 */ - -.hljs-meta { - color: #1f7199; -} - -.hljs-meta-string { - color: #4d99bf; -} - - -/* Misc effects */ - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/school-book.css b/app/src/main/assets/highlight/styles/themes/school-book.css deleted file mode 100644 index 3e1afc2f2..000000000 --- a/app/src/main/assets/highlight/styles/themes/school-book.css +++ /dev/null @@ -1,66 +0,0 @@ -/* - -School Book style from goldblog.com.ua (c) Zaripov Yura - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 15px 0.5em 0.5em 30px; - font-size: 11px; - line-height:16px; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal { - color:#005599; - font-weight:bold; -} - -.hljs, -.hljs-subst { - color: #3e5915; -} - -.hljs-string, -.hljs-title, -.hljs-section, -.hljs-type, -.hljs-symbol, -.hljs-bullet, -.hljs-attribute, -.hljs-built_in, -.hljs-builtin-name, -.hljs-addition, -.hljs-variable, -.hljs-template-tag, -.hljs-template-variable, -.hljs-link { - color: #2c009f; -} - -.hljs-comment, -.hljs-quote, -.hljs-deletion, -.hljs-meta { - color: #e60415; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal, -.hljs-doctag, -.hljs-title, -.hljs-section, -.hljs-type, -.hljs-name, -.hljs-selector-id, -.hljs-strong { - font-weight: bold; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/solarized-dark.css b/app/src/main/assets/highlight/styles/themes/solarized-dark.css deleted file mode 100644 index 9810cf5c4..000000000 --- a/app/src/main/assets/highlight/styles/themes/solarized-dark.css +++ /dev/null @@ -1,84 +0,0 @@ -/* - -Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - - color: #839496; -} - -.hljs-comment, -.hljs-quote { - color: #586e75; -} - -/* Solarized Green */ -.hljs-keyword, -.hljs-selector-tag, -.hljs-addition { - color: #859900; -} - -/* Solarized Cyan */ -.hljs-number, -.hljs-string, -.hljs-meta .hljs-meta-string, -.hljs-literal, -.hljs-doctag, -.hljs-regexp { - color: #2aa198; -} - -/* Solarized Blue */ -.hljs-title, -.hljs-section, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #268bd2; -} - -/* Solarized Yellow */ -.hljs-attribute, -.hljs-attr, -.hljs-variable, -.hljs-template-variable, -.hljs-class .hljs-title, -.hljs-type { - color: #b58900; -} - -/* Solarized Orange */ -.hljs-symbol, -.hljs-bullet, -.hljs-subst, -.hljs-meta, -.hljs-meta .hljs-keyword, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-link { - color: #cb4b16; -} - -/* Solarized Red */ -.hljs-built_in, -.hljs-deletion { - color: #dc322f; -} - -.hljs-formula { - -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/solarized-light.css b/app/src/main/assets/highlight/styles/themes/solarized-light.css deleted file mode 100644 index 8f6c19bfb..000000000 --- a/app/src/main/assets/highlight/styles/themes/solarized-light.css +++ /dev/null @@ -1,84 +0,0 @@ -/* - -Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - - color: #657b83; -} - -.hljs-comment, -.hljs-quote { - color: #93a1a1; -} - -/* Solarized Green */ -.hljs-keyword, -.hljs-selector-tag, -.hljs-addition { - color: #859900; -} - -/* Solarized Cyan */ -.hljs-number, -.hljs-string, -.hljs-meta .hljs-meta-string, -.hljs-literal, -.hljs-doctag, -.hljs-regexp { - color: #2aa198; -} - -/* Solarized Blue */ -.hljs-title, -.hljs-section, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class { - color: #268bd2; -} - -/* Solarized Yellow */ -.hljs-attribute, -.hljs-attr, -.hljs-variable, -.hljs-template-variable, -.hljs-class .hljs-title, -.hljs-type { - color: #b58900; -} - -/* Solarized Orange */ -.hljs-symbol, -.hljs-bullet, -.hljs-subst, -.hljs-meta, -.hljs-meta .hljs-keyword, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-link { - color: #cb4b16; -} - -/* Solarized Red */ -.hljs-built_in, -.hljs-deletion { - color: #dc322f; -} - -.hljs-formula { - -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/sunburst.css b/app/src/main/assets/highlight/styles/themes/sunburst.css deleted file mode 100644 index 75dea3afb..000000000 --- a/app/src/main/assets/highlight/styles/themes/sunburst.css +++ /dev/null @@ -1,101 +0,0 @@ -/* - -Sunburst-like style (c) Vasily Polovnyov - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: #f8f8f8; -} - -.hljs-comment, -.hljs-quote { - color: #aeaeae; - font-style: italic; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-type { - color: #e28964; -} - -.hljs-string { - color: #65b042; -} - -.hljs-subst { - color: #daefa3; -} - -.hljs-regexp, -.hljs-link { - color: #e9c062; -} - -.hljs-title, -.hljs-section, -.hljs-tag, -.hljs-name { - color: #89bdff; -} - -.hljs-class .hljs-title, -.hljs-doctag { - text-decoration: underline; -} - -.hljs-symbol, -.hljs-bullet, -.hljs-number { - color: #3387cc; -} - -.hljs-params, -.hljs-variable, -.hljs-template-variable { - color: #3e87e3; -} - -.hljs-attribute { - color: #cda869; -} - -.hljs-meta { - color: #8996a8; -} - -.hljs-formula { - background-color: #0e2231; - color: #f8f8f8; - font-style: italic; -} - -.hljs-addition { - background-color: #253b22; - color: #f8f8f8; -} - -.hljs-deletion { - background-color: #420e09; - color: #f8f8f8; -} - -.hljs-selector-class { - color: #9b703f; -} - -.hljs-selector-id { - color: #8b98ab; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/tomorrow-night-blue.css b/app/src/main/assets/highlight/styles/themes/tomorrow-night-blue.css deleted file mode 100644 index bec1e683d..000000000 --- a/app/src/main/assets/highlight/styles/themes/tomorrow-night-blue.css +++ /dev/null @@ -1,75 +0,0 @@ -/* Tomorrow Night Blue Theme */ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ -/* Original theme - https://github.com/chriskempson/tomorrow-theme */ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ - -/* Tomorrow Comment */ -.hljs-comment, -.hljs-quote { - color: #7285b7; -} - -/* Tomorrow Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-deletion { - color: #ff9da4; -} - -/* Tomorrow Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-meta, -.hljs-link { - color: #ffc58f; -} - -/* Tomorrow Yellow */ -.hljs-attribute { - color: #ffeead; -} - -/* Tomorrow Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #d1f1a9; -} - -/* Tomorrow Blue */ -.hljs-title, -.hljs-section { - color: #bbdaff; -} - -/* Tomorrow Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #ebbbff; -} - -.hljs { - display: block; - overflow-x: auto; - - color: white; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/tomorrow-night-bright.css b/app/src/main/assets/highlight/styles/themes/tomorrow-night-bright.css deleted file mode 100644 index c77793170..000000000 --- a/app/src/main/assets/highlight/styles/themes/tomorrow-night-bright.css +++ /dev/null @@ -1,73 +0,0 @@ -/* Tomorrow Night Bright Theme */ -/* Original theme - https://github.com/chriskempson/tomorrow-theme */ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ - -/* Tomorrow Comment */ -.hljs-comment, -.hljs-quote { - color: #969896; -} - -/* Tomorrow Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-deletion { - color: #d54e53; -} - -/* Tomorrow Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-meta, -.hljs-link { - color: #e78c45; -} - -/* Tomorrow Yellow */ -.hljs-attribute { - color: #e7c547; -} - -/* Tomorrow Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #b9ca4a; -} - -/* Tomorrow Blue */ -.hljs-title, -.hljs-section { - color: #7aa6da; -} - -/* Tomorrow Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #c397d8; -} - -.hljs { - display: block; - overflow-x: auto; - color: #eaeaea; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/tomorrow-night-eighties.css b/app/src/main/assets/highlight/styles/themes/tomorrow-night-eighties.css deleted file mode 100644 index a31f76bb1..000000000 --- a/app/src/main/assets/highlight/styles/themes/tomorrow-night-eighties.css +++ /dev/null @@ -1,74 +0,0 @@ -/* Tomorrow Night Eighties Theme */ -/* Original theme - https://github.com/chriskempson/tomorrow-theme */ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ - -/* Tomorrow Comment */ -.hljs-comment, -.hljs-quote { - color: #999999; -} - -/* Tomorrow Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-deletion { - color: #f2777a; -} - -/* Tomorrow Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-meta, -.hljs-link { - color: #f99157; -} - -/* Tomorrow Yellow */ -.hljs-attribute { - color: #ffcc66; -} - -/* Tomorrow Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #99cc99; -} - -/* Tomorrow Blue */ -.hljs-title, -.hljs-section { - color: #6699cc; -} - -/* Tomorrow Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #cc99cc; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #cccccc; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/tomorrow-night.css b/app/src/main/assets/highlight/styles/themes/tomorrow-night.css deleted file mode 100644 index 6e9164e0b..000000000 --- a/app/src/main/assets/highlight/styles/themes/tomorrow-night.css +++ /dev/null @@ -1,75 +0,0 @@ -/* Tomorrow Night Theme */ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ -/* Original theme - https://github.com/chriskempson/tomorrow-theme */ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ - -/* Tomorrow Comment */ -.hljs-comment, -.hljs-quote { - color: #969896; -} - -/* Tomorrow Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-deletion { - color: #cc6666; -} - -/* Tomorrow Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-meta, -.hljs-link { - color: #de935f; -} - -/* Tomorrow Yellow */ -.hljs-attribute { - color: #f0c674; -} - -/* Tomorrow Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #b5bd68; -} - -/* Tomorrow Blue */ -.hljs-title, -.hljs-section { - color: #81a2be; -} - -/* Tomorrow Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #b294bb; -} - -.hljs { - display: block; - overflow-x: auto; - - color: #c5c8c6; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/tomorrow.css b/app/src/main/assets/highlight/styles/themes/tomorrow.css deleted file mode 100644 index 82666e064..000000000 --- a/app/src/main/assets/highlight/styles/themes/tomorrow.css +++ /dev/null @@ -1,71 +0,0 @@ -/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ - -/* Tomorrow Comment */ -.hljs-comment, -.hljs-quote { - color: #8e908c; -} - -/* Tomorrow Red */ -.hljs-variable, -.hljs-template-variable, -.hljs-tag, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-regexp, -.hljs-deletion { - color: #c82829; -} - -/* Tomorrow Orange */ -.hljs-number, -.hljs-built_in, -.hljs-builtin-name, -.hljs-literal, -.hljs-type, -.hljs-params, -.hljs-meta, -.hljs-link { - color: #f5871f; -} - -/* Tomorrow Yellow */ -.hljs-attribute { - color: #eab700; -} - -/* Tomorrow Green */ -.hljs-string, -.hljs-symbol, -.hljs-bullet, -.hljs-addition { - color: #718c00; -} - -/* Tomorrow Blue */ -.hljs-title, -.hljs-section { - color: #4271ae; -} - -/* Tomorrow Purple */ -.hljs-keyword, -.hljs-selector-tag { - color: #8959a8; -} - -.hljs { - display: block; - overflow-x: auto; - color: #4d4d4c; - padding: 0px; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/vs.css b/app/src/main/assets/highlight/styles/themes/vs.css deleted file mode 100644 index 76f8e678e..000000000 --- a/app/src/main/assets/highlight/styles/themes/vs.css +++ /dev/null @@ -1,67 +0,0 @@ -/* - -Visual Studio-like style based on original C# coloring by Jason Diamond - -*/ -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: black; -} - -.hljs-comment, -.hljs-quote, -.hljs-variable { - color: #008000; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-built_in, -.hljs-name, -.hljs-tag { - color: #00f; -} - -.hljs-string, -.hljs-title, -.hljs-section, -.hljs-attribute, -.hljs-literal, -.hljs-template-tag, -.hljs-template-variable, -.hljs-type, -.hljs-addition { - color: #a31515; -} - -.hljs-deletion, -.hljs-selector-attr, -.hljs-selector-pseudo, -.hljs-meta { - color: #2b91af; -} - -.hljs-doctag { - color: #808080; -} - -.hljs-attr { - color: #f00; -} - -.hljs-symbol, -.hljs-bullet, -.hljs-link { - color: #00b0e8; -} - - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/highlight/styles/themes/vs2015.css b/app/src/main/assets/highlight/styles/themes/vs2015.css deleted file mode 100644 index 99cf22d1b..000000000 --- a/app/src/main/assets/highlight/styles/themes/vs2015.css +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Visual Studio 2015 dark style - * Author: Nicolas LLOBERA - */ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - - color: #DCDCDC; -} - -.hljs-keyword, -.hljs-literal, -.hljs-symbol, -.hljs-name { - color: #569CD6; -} -.hljs-link { - color: #569CD6; - text-decoration: underline; -} - -.hljs-built_in, -.hljs-type { - color: #4EC9B0; -} - -.hljs-number, -.hljs-class { - color: #B8D7A3; -} - -.hljs-string, -.hljs-meta-string { - color: #D69D85; -} - -.hljs-regexp, -.hljs-template-tag { - color: #9A5334; -} - -.hljs-subst, -.hljs-function, -.hljs-title, -.hljs-params, -.hljs-formula { - color: #DCDCDC; -} - -.hljs-comment, -.hljs-quote { - color: #57A64A; - font-style: italic; -} - -.hljs-doctag { - color: #608B4E; -} - -.hljs-meta, -.hljs-meta-keyword, -.hljs-tag { - color: #9B9B9B; -} - -.hljs-variable, -.hljs-template-variable { - color: #BD63C5; -} - -.hljs-attr, -.hljs-attribute, -.hljs-builtin-name { - color: #9CDCFE; -} - -.hljs-section { - color: gold; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} - -/*.hljs-code { - font-family:'Monospace'; -}*/ - -.hljs-bullet, -.hljs-selector-tag, -.hljs-selector-id, -.hljs-selector-class, -.hljs-selector-attr, -.hljs-selector-pseudo { - color: #D7BA7D; -} - -.hljs-addition { - background-color: #144212; - display: inline-block; - width: 100%; -} - -.hljs-deletion { - background-color: #600; - display: inline-block; - width: 100%; -} diff --git a/app/src/main/assets/highlight/styles/themes/xcode.css b/app/src/main/assets/highlight/styles/themes/xcode.css deleted file mode 100644 index 980ec3e4e..000000000 --- a/app/src/main/assets/highlight/styles/themes/xcode.css +++ /dev/null @@ -1,92 +0,0 @@ -/* - -XCode style (c) Angel Garcia - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - color: black; -} - -.hljs-comment, -.hljs-quote { - color: #006a00; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-literal { - color: #aa0d91; -} - -.hljs-name { - color: #008; -} - -.hljs-variable, -.hljs-template-variable { - color: #660; -} - -.hljs-string { - color: #c41a16; -} - -.hljs-regexp, -.hljs-link { - color: #080; -} - -.hljs-title, -.hljs-tag, -.hljs-symbol, -.hljs-bullet, -.hljs-number, -.hljs-meta { - color: #1c00cf; -} - -.hljs-section, -.hljs-class .hljs-title, -.hljs-type, -.hljs-attr, -.hljs-built_in, -.hljs-builtin-name, -.hljs-params { - color: #5c2699; -} - -.hljs-attribute, -.hljs-subst { - color: #000; -} - -.hljs-formula { - background-color: #eee; - font-style: italic; -} - -.hljs-addition { - background-color: #baeeba; -} - -.hljs-deletion { - background-color: #ffc8bd; -} - -.hljs-selector-id, -.hljs-selector-class { - color: #9b703f; -} - -.hljs-doctag, -.hljs-strong { - font-weight: bold; -} - -.hljs-emphasis { - font-style: italic; -} diff --git a/app/src/main/assets/highlight/styles/themes/xt256.css b/app/src/main/assets/highlight/styles/themes/xt256.css deleted file mode 100644 index 82a952392..000000000 --- a/app/src/main/assets/highlight/styles/themes/xt256.css +++ /dev/null @@ -1,92 +0,0 @@ - -/* - xt256.css - - Contact: initbar [at] protonmail [dot] ch - : github.com/initbar -*/ - -.hljs { - display: block; - overflow-x: auto; - color: #eaeaea; - - padding: 0.5; -} - -.hljs-subst { - color: #eaeaea; -} - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} - -.hljs-builtin-name, -.hljs-type { - color: #eaeaea; -} - -.hljs-params { - color: #da0000; -} - -.hljs-literal, -.hljs-number, -.hljs-name { - color: #ff0000; - font-weight: bolder; -} - -.hljs-comment { - color: #969896; -} - -.hljs-selector-id, -.hljs-quote { - color: #00ffff; -} - -.hljs-template-variable, -.hljs-variable, -.hljs-title { - color: #00ffff; - font-weight: bold; -} - -.hljs-selector-class, -.hljs-keyword, -.hljs-symbol { - color: #fff000; -} - -.hljs-string, -.hljs-bullet { - color: #00ff00; -} - -.hljs-tag, -.hljs-section { - color: #000fff; -} - -.hljs-selector-tag { - color: #000fff; - font-weight: bold; -} - -.hljs-attribute, -.hljs-built_in, -.hljs-regexp, -.hljs-link { - color: #ff00ff; -} - -.hljs-meta { - color: #fff; - font-weight: bolder; -} diff --git a/app/src/main/assets/highlight/styles/themes/zenburn.css b/app/src/main/assets/highlight/styles/themes/zenburn.css deleted file mode 100644 index 5e697a3fb..000000000 --- a/app/src/main/assets/highlight/styles/themes/zenburn.css +++ /dev/null @@ -1,80 +0,0 @@ -/* - -Zenburn style from voldmar.ru (c) Vladimir Epifanov -based on dark.css by Ivan Sagalaev - -*/ - -.hljs { - display: block; - overflow-x: auto; - padding: 0px; - - color: #dcdcdc; -} - -.hljs-keyword, -.hljs-selector-tag, -.hljs-tag { - color: #e3ceab; -} - -.hljs-template-tag { - color: #dcdcdc; -} - -.hljs-number { - color: #8cd0d3; -} - -.hljs-variable, -.hljs-template-variable, -.hljs-attribute { - color: #efdcbc; -} - -.hljs-literal { - color: #efefaf; -} - -.hljs-subst { - color: #8f8f8f; -} - -.hljs-title, -.hljs-name, -.hljs-selector-id, -.hljs-selector-class, -.hljs-section, -.hljs-type { - color: #efef8f; -} - -.hljs-symbol, -.hljs-bullet, -.hljs-link { - color: #dca3a3; -} - -.hljs-deletion, -.hljs-string, -.hljs-built_in, -.hljs-builtin-name { - color: #cc9393; -} - -.hljs-addition, -.hljs-comment, -.hljs-quote, -.hljs-meta { - color: #7f9f7f; -} - - -.hljs-emphasis { - font-style: italic; -} - -.hljs-strong { - font-weight: bold; -} diff --git a/app/src/main/assets/lottie/bounching_ball.json b/app/src/main/assets/lottie/bounching_ball.json deleted file mode 100644 index c7de61b8e..000000000 --- a/app/src/main/assets/lottie/bounching_ball.json +++ /dev/null @@ -1 +0,0 @@ -{"assets":[],"layers":[{"ddd":0,"ind":0,"ty":4,"nm":"形状图层 5","ks":{"o":{"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"n":["0p833_0p833_0p333_0"],"t":8,"s":[100],"e":[30]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"n":["0p833_0p833_0p333_0"],"t":24,"s":[30],"e":[100]},{"t":40}]},"r":{"k":0},"p":{"k":[187.875,77.125,0]},"a":{"k":[-76.375,-2.875,0]},"s":{"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_0p833_0p333_0p333"],"t":8,"s":[100,100,100],"e":[200,200,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_0p833_0p333_0p333"],"t":24,"s":[200,200,100],"e":[100,100,100]},{"t":40}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"k":[18,18]},"p":{"k":[0,0]},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"k":[1,1,1,1]},"o":{"k":100},"w":{"k":0},"lc":1,"lj":1,"ml":4,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"k":[0.87,0.42,0.56,1]},"o":{"k":100},"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"k":[-76.482,-3.482],"ix":2},"a":{"k":[0,0],"ix":1},"s":{"k":[100,100],"ix":3},"r":{"k":0,"ix":6},"o":{"k":100,"ix":7},"sk":{"k":0,"ix":4},"sa":{"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"mn":"ADBE Vector Group"}],"ip":0,"op":40,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 4","ks":{"o":{"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"n":["0p833_0p833_0p333_0"],"t":6,"s":[100],"e":[30]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"n":["0p833_0p833_0p333_0"],"t":22,"s":[30],"e":[100]},{"t":36}]},"r":{"k":0},"p":{"k":[162.125,76.625,0]},"a":{"k":[-76.375,-2.875,0]},"s":{"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_0p833_0p333_0p333"],"t":6,"s":[100,100,100],"e":[200,200,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_0p833_0p333_0p333"],"t":22,"s":[200,200,100],"e":[100,100,100]},{"t":36}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"k":[18,18]},"p":{"k":[0,0]},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"k":[1,1,1,1]},"o":{"k":100},"w":{"k":0},"lc":1,"lj":1,"ml":4,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"k":[0.81,0.55,0.82,1]},"o":{"k":100},"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"k":[-76.482,-3.482],"ix":2},"a":{"k":[0,0],"ix":1},"s":{"k":[100,100],"ix":3},"r":{"k":0,"ix":6},"o":{"k":100,"ix":7},"sk":{"k":0,"ix":4},"sa":{"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"mn":"ADBE Vector Group"}],"ip":0,"op":40,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":4,"nm":"形状图层 3","ks":{"o":{"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"n":["0p833_0p833_0p333_0"],"t":4,"s":[100],"e":[30]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"n":["0p833_0p833_0p333_0"],"t":20,"s":[30],"e":[100]},{"t":32}]},"r":{"k":0},"p":{"k":[135.625,76.625,0]},"a":{"k":[-76.375,-2.875,0]},"s":{"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_0p833_0p333_0p333"],"t":4,"s":[100,100,100],"e":[200,200,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_0p833_0p333_0p333"],"t":20,"s":[200,200,100],"e":[100,100,100]},{"t":32}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"k":[18,18]},"p":{"k":[0,0]},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"k":[1,1,1,1]},"o":{"k":100},"w":{"k":0},"lc":1,"lj":1,"ml":4,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"k":[0.47,0.31,0.62,1]},"o":{"k":100},"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"k":[-76.482,-3.482],"ix":2},"a":{"k":[0,0],"ix":1},"s":{"k":[100,100],"ix":3},"r":{"k":0,"ix":6},"o":{"k":100,"ix":7},"sk":{"k":0,"ix":4},"sa":{"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"mn":"ADBE Vector Group"}],"ip":0,"op":40,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"形状图层 2","ks":{"o":{"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"n":["0p833_0p833_0p333_0"],"t":2,"s":[100],"e":[30]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"n":["0p833_0p833_0p333_0"],"t":16,"s":[30],"e":[100]},{"t":28}]},"r":{"k":0},"p":{"k":[109.375,76.625,0]},"a":{"k":[-76.625,-3.125,0]},"s":{"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_0p833_0p333_0p333"],"t":2,"s":[100,100,100],"e":[200,200,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_0p833_0p333_0p333"],"t":16,"s":[200,200,100],"e":[100,100,100]},{"t":28}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"k":[18,18]},"p":{"k":[0,0]},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"k":[1,1,1,1]},"o":{"k":100},"w":{"k":0},"lc":1,"lj":1,"ml":4,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"k":[0.54,0.81,0.89,1]},"o":{"k":100},"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"k":[-76.482,-3.482],"ix":2},"a":{"k":[0,0],"ix":1},"s":{"k":[100,100],"ix":3},"r":{"k":0,"ix":6},"o":{"k":100,"ix":7},"sk":{"k":0,"ix":4},"sa":{"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"mn":"ADBE Vector Group"}],"ip":0,"op":40,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":4,"ty":4,"nm":"形状图层 1","ks":{"o":{"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"n":["0p833_0p833_0p333_0"],"t":0,"s":[100],"e":[30]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"n":["0p833_0p833_0p333_0"],"t":12,"s":[30],"e":[100]},{"t":24}]},"r":{"k":0},"p":{"k":[82.625,76.625,0]},"a":{"k":[-76.625,-3.375,0]},"s":{"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_0p833_0p333_0p333"],"t":0,"s":[100,100,100],"e":[200,200,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0.333]},"n":["0p833_0p833_0p333_0","0p833_0p833_0p333_0","0p833_0p833_0p333_0p333"],"t":12,"s":[200,200,100],"e":[100,100,100]},{"t":24}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"k":[18,18]},"p":{"k":[0,0]},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse"},{"ty":"st","c":{"k":[1,1,1,1]},"o":{"k":100},"w":{"k":0},"lc":1,"lj":1,"ml":4,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"k":[0.34,0.45,0.78,1]},"o":{"k":100},"nm":"填充 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"k":[-76.482,-3.482],"ix":2},"a":{"k":[0,0],"ix":1},"s":{"k":[100,100],"ix":3},"r":{"k":0,"ix":6},"o":{"k":100,"ix":7},"sk":{"k":0,"ix":4},"sa":{"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"mn":"ADBE Vector Group"}],"ip":0,"op":40,"st":0,"bm":0,"sr":1}],"v":"4.5.4","ddd":0,"ip":0,"op":40,"fr":24,"w":280,"h":160} \ No newline at end of file diff --git a/app/src/main/assets/lottie/code_invite_success.json b/app/src/main/assets/lottie/code_invite_success.json deleted file mode 100644 index d5882bd9b..000000000 --- a/app/src/main/assets/lottie/code_invite_success.json +++ /dev/null @@ -1 +0,0 @@ -{"v":"4.6.9","fr":60,"ip":0,"op":230,"w":220,"h":220,"nm":"Intro3","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Checker Outlines","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[131.817,171.725,0]},"a":{"a":0,"k":[22.562,22.633,0]},"s":{"a":1,"k":[{"i":{"x":[0.5,0.5,0.5],"y":[1,1,0.5]},"o":{"x":[0.84,0.84,0.84],"y":[0,0,0.84]},"n":["0p5_1_0p84_0","0p5_1_0p84_0","0p5_0p5_0p84_0p84"],"t":158,"s":[0,0,100],"e":[130,130,100]},{"i":{"x":[0.5,0.5,0.5],"y":[1,1,0.5]},"o":{"x":[0.84,0.84,0.84],"y":[0,0,0.84]},"n":["0p5_1_0p84_0","0p5_1_0p84_0","0p5_0p5_0p84_0p84"],"t":176,"s":[130,130,100],"e":[100,100,100]},{"t":183}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-7.643,1.576],[-2.486,5.923],[7.643,-5.923]],"c":false}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1.991},"lc":2,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[22.967,22.739],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-12.322,0],[0,0],[0,-12.323],[0,0],[12.322,0],[0,12.322],[0,0]],"o":[[0,0],[12.322,0],[0,0],[0,12.322],[-12.322,0],[0,0],[0,-12.323]],"v":[[-0.001,-22.383],[-0.001,-22.383],[22.312,-0.071],[22.312,0.07],[-0.001,22.383],[-22.312,0.07],[-22.312,-0.071]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0,0.639,0.231,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[22.562,22.633],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"ix":2,"mn":"ADBE Vector Group"}],"ip":0,"op":230,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":4,"nm":"P1 Outlines","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":14,"s":[0],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":76,"s":[0],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":140,"s":[0],"e":[100]},{"t":143}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[78.828,132.057,0]},"a":{"a":0,"k":[1.83,1.816,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.452,-1.566],[0.253,-0.406],[1.165,-1.143],[1.579,-0.389],[0.495,-0.001],[1.579,0.389],[1.141,1.161],[0.253,0.423],[0.445,1.566],[-0.419,1.566],[-0.236,0.423],[-1.124,1.167],[-1.579,0.381],[-0.501,-0.007],[-1.57,-0.38],[-1.148,-1.143],[-0.227,-0.406],[-0.419,-1.566]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.247,0.212,0.192,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[1.83,1.816],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":230,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"P2 Outlines","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":14,"s":[0],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":127,"s":[0],"e":[100]},{"t":130}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[74.772,132.057,0]},"a":{"a":0,"k":[1.83,1.816,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.452,-1.566],[0.253,-0.406],[1.165,-1.143],[1.579,-0.389],[0.495,-0.001],[1.579,0.389],[1.141,1.161],[0.253,0.423],[0.445,1.566],[-0.419,1.566],[-0.236,0.423],[-1.124,1.167],[-1.579,0.381],[-0.501,-0.007],[-1.57,-0.38],[-1.148,-1.143],[-0.227,-0.406],[-0.419,-1.566]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.247,0.212,0.192,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[1.83,1.816],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":230,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":4,"ty":4,"nm":"P2 Outlines","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":14,"s":[0],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":119,"s":[0],"e":[100]},{"t":122}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[70.715,132.057,0]},"a":{"a":0,"k":[1.829,1.816,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.452,-1.566],[0.253,-0.406],[1.165,-1.143],[1.579,-0.389],[0.493,-0.001],[1.579,0.389],[1.139,1.161],[0.253,0.423],[0.443,1.566],[-0.419,1.566],[-0.236,0.423],[-1.124,1.167],[-1.579,0.381],[-0.501,-0.007],[-1.572,-0.38],[-1.148,-1.143],[-0.229,-0.406],[-0.419,-1.566]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.247,0.212,0.192,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[1.829,1.816],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":230,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":5,"ty":4,"nm":"p3 Outlines","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":14,"s":[0],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":109,"s":[0],"e":[100]},{"t":112}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[66.659,132.057,0]},"a":{"a":0,"k":[1.829,1.816,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.452,-1.566],[0.253,-0.406],[1.165,-1.143],[1.579,-0.389],[0.493,-0.001],[1.579,0.389],[1.139,1.161],[0.253,0.423],[0.443,1.566],[-0.419,1.566],[-0.236,0.423],[-1.124,1.167],[-1.579,0.381],[-0.503,-0.007],[-1.572,-0.38],[-1.148,-1.143],[-0.229,-0.406],[-0.419,-1.566]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.247,0.212,0.192,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[1.829,1.816],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":230,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":6,"ty":4,"nm":"P4 Outlines","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":14,"s":[0],"e":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":87,"s":[0],"e":[100]},{"t":92}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[62.601,132.057,0]},"a":{"a":0,"k":[1.829,1.816,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.452,-1.566],[0.254,-0.406],[1.165,-1.143],[1.579,-0.389],[0.495,-0.001],[1.579,0.389],[1.141,1.161],[0.254,0.423],[0.445,1.566],[-0.419,1.566],[-0.236,0.423],[-1.124,1.167],[-1.579,0.381],[-0.501,-0.007],[-1.57,-0.38],[-1.148,-1.143],[-0.227,-0.406],[-0.419,-1.566]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.247,0.212,0.192,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[1.829,1.816],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":230,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":7,"ty":4,"nm":"p5 Outlines","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":14,"s":[0],"e":[2]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":76,"s":[2],"e":[100]},{"t":80}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[58.545,132.057,0]},"a":{"a":0,"k":[1.829,1.816,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[0.452,-1.566],[0.253,-0.406],[1.165,-1.143],[1.579,-0.389],[0.495,-0.001],[1.579,0.389],[1.141,1.161],[0.253,0.423],[0.445,1.566],[-0.419,1.566],[-0.236,0.423],[-1.124,1.167],[-1.579,0.381],[-0.501,-0.007],[-1.57,-0.38],[-1.148,-1.143],[-0.227,-0.406],[-0.419,-1.566]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.247,0.212,0.192,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[1.829,1.816],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":230,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":8,"ty":4,"nm":"Phone Outlines","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[68.515,144.03,0]},"a":{"a":0,"k":[29.842,56.541,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-6.469,-0.691],[6.469,-0.691],[6.469,0.691],[-6.469,0.691]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[29.694,60.956],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.146,0],[0,0],[0,-1.145],[0,0],[1.145,0],[0,0],[0,1.145],[0,0]],"o":[[0,0],[1.145,0],[0,0],[0,1.145],[0,0],[-1.146,0],[0,0],[0,-1.145]],"v":[[-16.583,-4.144],[16.583,-4.144],[18.656,-2.069],[18.656,2.07],[16.583,4.144],[-16.583,4.144],[-18.656,2.07],[-18.656,-2.069]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0,0.639,0.231,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[30.039,60.955],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"ix":2,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-11.747,-0.691],[11.747,-0.691],[11.747,0.691],[-11.747,0.691]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.792,0.776,0.745,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[23.13,36.097],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":2,"cix":2,"ix":3,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-18.657,-4.488],[18.657,-4.488],[18.657,4.488],[-18.657,4.488]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.878,0.878,0.878,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[30.04,44.729],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"ix":4,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.735,0],[0,0],[0,-0.735],[0.735,0],[0,0],[0,0.735]],"o":[[0,0],[0.735,0],[0,0.735],[0,0],[-0.735,0],[0,-0.735]],"v":[[-4.637,-1.331],[4.637,-1.331],[5.969,-0.001],[4.637,1.331],[-4.637,1.331],[-5.969,-0.001]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.49,0.451,0.424,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[29.842,6.649],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 5","np":2,"cix":2,"ix":5,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.838,0],[0,0],[0,-1.838],[1.838,0],[0,0],[0,1.838]],"o":[[0,0],[1.838,0],[0,1.838],[0,0],[-1.838,0],[0,-1.838]],"v":[[-1.313,-3.327],[1.314,-3.327],[4.641,-0.001],[1.314,3.327],[-1.313,3.327],[-4.641,-0.001]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"st","c":{"a":0,"k":[0.49,0.451,0.424,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1.327},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[29.179,105.104],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 6","np":2,"cix":2,"ix":6,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-2.205,0],[0,0],[0,-2.204],[2.205,0],[0,0],[0,2.204]],"o":[[0,0],[2.205,0],[0,2.204],[0,0],[-2.205,0],[0,-2.204]],"v":[[-1.313,-3.991],[1.314,-3.991],[5.305,0],[1.314,3.991],[-1.313,3.991],[-5.305,0]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.608,0.608,0.608,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[29.178,105.104],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 7","np":2,"cix":2,"ix":7,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-24.536,-43.24],[24.536,-43.24],[24.536,43.24],[-24.536,43.24]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"st","c":{"a":0,"k":[0.592,0.592,0.592,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1.327},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[29.842,55.211],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 8","np":3,"cix":2,"ix":8,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-3.665,0],[0,0],[0,-3.664],[0,0],[3.665,0],[0,0],[0,3.665],[0,0]],"o":[[0,0],[3.665,0],[0,0],[0,3.665],[0,0],[-3.665,0],[0,0],[0,-3.664]],"v":[[-21.879,-55.215],[21.879,-55.215],[28.515,-48.579],[28.515,48.579],[21.879,55.215],[-21.879,55.215],[-28.515,48.579],[-28.515,-48.579]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"st","c":{"a":0,"k":[0.588,0.588,0.588,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1.327},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[0.792,0.776,0.745,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[29.842,56.541],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 9","np":3,"cix":2,"ix":9,"mn":"ADBE Vector Group"}],"ip":0,"op":230,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":9,"ty":4,"nm":"Cupon Outlines","ks":{"o":{"a":0,"k":100},"r":{"a":1,"k":[{"i":{"x":[0.57],"y":[1]},"o":{"x":[0.16],"y":[0]},"n":["0p57_1_0p16_0"],"t":14,"s":[60],"e":[-3]},{"i":{"x":[0.51],"y":[1]},"o":{"x":[0.152],"y":[0]},"n":["0p51_1_0p152_0"],"t":44,"s":[-3],"e":[0]},{"t":72}]},"p":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.16,"y":0},"n":"0p833_1_0p16_0","t":14,"s":[93.826,135.572,0],"e":[113,84.635,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.16,"y":0},"n":"0p833_1_0p16_0","t":44,"s":[113,84.635,0],"e":[113.826,85.572,0],"to":[0,0,0],"ti":[0,0,0]},{"t":72}]},"a":{"a":0,"k":[41.867,23.511,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[24.029,3.622],[22.827,6.008],[25.297,5.013],[25.696,6.924],[23.08,7.049],[25.178,8.615],[23.714,9.996],[22.278,7.807],[21.932,10.414],[20.061,9.842],[21.216,7.482],[18.796,8.512],[18.328,6.501],[20.926,6.372],[18.852,4.852],[20.276,3.478],[21.784,5.689],[22.139,3.045]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[15.224,0.931],[14.022,3.316],[16.491,2.322],[16.891,4.232],[14.275,4.357],[16.374,5.924],[14.909,7.305],[13.473,5.115],[13.128,7.723],[11.257,7.15],[12.411,4.79],[9.991,5.821],[9.523,3.81],[12.121,3.68],[10.048,2.161],[11.47,0.786],[12.979,2.997],[13.335,0.353]],"c":true}},"nm":"Path 2","mn":"ADBE Vector Shape - Group"},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[6.42,-1.761],[5.217,0.625],[7.686,-0.371],[8.087,1.541],[5.47,1.666],[7.569,3.232],[6.104,4.613],[4.669,2.423],[4.323,5.032],[2.452,4.459],[3.606,2.099],[1.186,3.129],[0.718,1.118],[3.316,0.988],[1.242,-0.533],[2.666,-1.906],[4.175,0.306],[4.53,-2.339]],"c":true}},"nm":"Path 3","mn":"ADBE Vector Shape - Group"},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-2.385,-4.453],[-3.587,-2.067],[-1.118,-3.062],[-0.718,-1.15],[-3.334,-1.026],[-1.236,0.54],[-2.7,1.921],[-4.137,-0.27],[-4.482,2.34],[-6.353,1.768],[-5.199,-0.593],[-7.619,0.437],[-8.087,-1.574],[-5.489,-1.704],[-7.563,-3.223],[-6.139,-4.597],[-4.631,-2.386],[-4.275,-5.031]],"c":true}},"nm":"Path 4","mn":"ADBE Vector Shape - Group"},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-11.19,-7.145],[-12.392,-4.759],[-9.923,-5.755],[-9.523,-3.842],[-12.139,-3.718],[-10.04,-2.152],[-11.505,-0.771],[-12.942,-2.96],[-13.286,-0.352],[-15.158,-0.924],[-14.003,-3.285],[-16.424,-2.255],[-16.891,-4.266],[-14.293,-4.396],[-16.367,-5.916],[-14.944,-7.289],[-13.435,-5.078],[-13.08,-7.722]],"c":true}},"nm":"Path 5","mn":"ADBE Vector Shape - Group"},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-19.995,-9.837],[-21.197,-7.451],[-18.727,-8.447],[-18.328,-6.535],[-20.944,-6.41],[-18.845,-4.844],[-20.31,-3.464],[-21.746,-5.652],[-22.091,-3.044],[-23.963,-3.617],[-22.808,-5.977],[-25.229,-4.947],[-25.696,-6.958],[-23.098,-7.089],[-25.172,-8.607],[-23.748,-9.981],[-22.241,-7.77],[-21.885,-10.414]],"c":true}},"nm":"Path 6","mn":"ADBE Vector Shape - Group"},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge"},{"ty":"fl","c":{"a":0,"k":[0.247,0.212,0.192,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[41.941,23.286],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":8,"cix":2,"ix":1,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.73,-0.223],[0,0],[0.224,-0.73],[0,0],[0.731,0.223],[0,0],[-0.224,0.73],[0,0]],"o":[[0,0],[0.73,0.223],[0,0],[-0.224,0.73],[0,0],[-0.73,-0.224],[0,0],[0.224,-0.73]],"v":[[-32.681,-21.906],[39.344,0.115],[40.261,1.841],[34.408,20.988],[32.681,21.906],[-39.344,-0.114],[-40.261,-1.841],[-34.408,-20.988]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"st","c":{"a":0,"k":[0.588,0.588,0.588,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1.382},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[0.792,0.776,0.745,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[41.867,23.511],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":3,"cix":2,"ix":2,"mn":"ADBE Vector Group"}],"ip":0,"op":230,"st":0,"bm":0,"sr":1}]} \ No newline at end of file diff --git a/app/src/main/assets/md/github.css b/app/src/main/assets/md/github.css deleted file mode 100644 index dc87ff923..000000000 --- a/app/src/main/assets/md/github.css +++ /dev/null @@ -1,637 +0,0 @@ -body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - font-size: 16px; - padding: 10px; - line-height: 1.5; - word-wrap: break-word -} - -body::before { - display: table; - content: "" -} - -body::after { - display: table; - clear: both; - content: "" -} - -body>:first-child { - margin-top: 0!important -} - -body:last-child { - margin-bottom: 46px !important -} - -body a:not([href]) { - color: inherit; - text-decoration: none -} - -body .absent { - color: #c00 -} - -body .anchor { - float: left; - padding-right: 4px; - margin-left: -10px; - line-height: 1 -} - -body .anchor:focus { - outline: none -} - -body p, body blockquote, body ul, body ol, body dl, body table, body pre { - margin-top: 0; - margin-bottom: 10px -} - -body hr { - height: .25em; - padding: 0; - margin: 24px 0; - background-color: #e7e7e7; - border: 0 -} - -body blockquote { - padding: 0 1em; - color: #777; - border-left: .25em solid #ddd -} - -body blockquote>:first-child { - margin-top: 0 -} - -body blockquote>:last-child { - margin-bottom: 0 -} - -body kbd { - display: inline-block; - padding: 3px 5px; - font-size: 11px; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #fcfcfc; - border: solid 1px #ccc; - border-bottom-color: #bbb; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #bbb -} - -body .loweralpha { - list-style-type: lower-alpha -} - -body h1, body h2, body h3, body h4, body h5, body h6 { - margin-top: 24px; - margin-bottom: 16px; - font-weight: 600; - line-height: 1.25 -} - -body h1 .octicon-link, body h2 .octicon-link, body h3 .octicon-link, body h4 .octicon-link, body h5 .octicon-link, body h6 .octicon-link { - color: #000; - vertical-align: middle; - visibility: hidden -} - -body h1:hover .anchor, body h2:hover .anchor, body h3:hover .anchor, body h4:hover .anchor, body h5:hover .anchor, body h6:hover .anchor { - text-decoration: none -} - -body h1:hover .anchor .octicon-link, body h2:hover .anchor .octicon-link, body h3:hover .anchor .octicon-link, body h4:hover .anchor .octicon-link, body h5:hover .anchor .octicon-link, body h6:hover .anchor .octicon-link { - visibility: visible -} - -body h1 tt, body h1 code, body h2 tt, body h2 code, body h3 tt, body h3 code, body h4 tt, body h4 code, body h5 tt, body h5 code, body h6 tt, body h6 code { - font-size: inherit -} - -body h1 { - padding-bottom: .3em; - font-size: 2em; - border-bottom: 1px solid #eee -} - -.gh-header-meta { - padding-bottom: .3em; - margin-bottom: 6px; - border-bottom: 1px solid #eee -} - -body h2 { - padding-bottom: .3em; - font-size: 1.5em; - border-bottom: 1px solid #eee -} - -body h3 { - font-size: 1.25em -} - -body h4 { - font-size: 1em -} - -body h5 { - font-size: .875em -} - -body h6 { - font-size: .85em; - color: #777 -} - -body ul, body ol { - padding-left: 1em -} - -body ul.no-list, body ol.no-list { - padding: 0; - list-style-type: none -} - -body ul ul, body ul ol, body ol ol, body ol ul { - margin-top: 0; - margin-bottom: 0 -} - -body li>p { - margin-top: 16px -} - -body li+li { - margin-top: .25em -} - -body dl { - padding: 0 -} - -body dl dt { - padding: 0; - margin-top: 16px; - font-size: 1em; - font-style: italic; - font-weight: 700 -} - -body dl dd { - padding: 0 16px; - margin-bottom: 16px -} - -body table { - display: block; - width: 100%; - overflow: auto -} - -body table th { - font-weight: 700 -} - -body table th, body table td { - padding: 6px 13px; - border: 1px solid #ddd -} - -body table tr { - background-color: #fff; - border-top: 1px solid #ccc -} - -body table tr:nth-child(2n) { - background-color: #f8f8f8 -} - -body img { - max-width: 100%; - box-sizing: content-box; - background-color: #fff -} - -body img[align=right] { - padding-left: 10px -} - -body img[align=left] { - padding-right: 10px -} - -body .emoji { - max-width: none; - vertical-align: text-top; - background-color: transparent -} - -body span.frame { - display: block; - overflow: hidden -} - -body span.frame>span { - display: block; - float: left; - width: auto; - padding: 7px; - margin: 13px 0 0; - overflow: hidden; - border: 1px solid #ddd -} - -body span.frame span img { - display: block; - float: left -} - -body span.frame span span { - display: block; - padding: 5px 0 0; - clear: both; - color: #333 -} - -body span.align-center { - display: block; - overflow: hidden; - clear: both -} - -body span.align-center>span { - display: block; - margin: 8px auto 0; - overflow: hidden; - text-align: center -} - -body span.align-center span img { - margin: 0 auto; - text-align: center -} - -body span.align-right { - display: block; - overflow: hidden; - clear: both -} - -body span.align-right>span { - display: block; - margin: 8px 0 0; - overflow: hidden; - text-align: right -} - -body span.align-right span img { - margin: 0; - text-align: right -} - -body span.float-left { - display: block; - float: left; - margin-right: 8px; - overflow: hidden -} - -body span.float-left span { - margin: 8px 0 0 -} - -body span.float-right { - display: block; - float: right; - margin-left: 8px; - overflow: hidden -} - -body span.float-right>span { - display: block; - margin: 8px auto 0; - overflow: hidden; - text-align: right -} - -body code, body tt { - padding: 0; - padding-top: .1em; - padding-bottom: .1em; - margin: 0; - font-size: 85%; - background-color: rgba(0, 0, 0, 0.04); - border-radius: 3px -} - -body code::before, body code::after, body tt::before, body tt::after { - letter-spacing: -.1em; - content: "\00a0" -} - -body code br, body tt br { - display: none -} - -body del code { - text-decoration: inherit -} - -body pre { - word-wrap: normal -} - -body pre>code { - padding: 0; - margin: 0; - font-size: 100%; - word-break: normal; - white-space: pre; - background: transparent; - border: 0 -} - -body .highlight { - margin-bottom: 10px -} - -body .highlight pre { - margin-bottom: 0; - word-break: normal -} - -body .highlight pre, body pre { - padding: 10px; - overflow: auto; - font-size: 85%; - line-height: 1.45; - background-color: #f6f8fa; - border-radius: 3px -} - -body pre code, body pre tt { - display: inline; - max-width: auto; - padding: 0; - margin: 0; - overflow: visible; - line-height: inherit; - word-wrap: normal; - background-color: transparent; - border: 0 -} - -body pre code::before, body pre code::after, body pre tt::before, body pre tt::after { - content: normal -} - -body .csv-data td, body .csv-data th { - padding: 5px; - overflow: hidden; - font-size: 12px; - line-height: 1; - text-align: left; - white-space: nowrap -} - -body .csv-data .blob-num { - padding: 10px 8px 9px; - text-align: right; - background: #fff; - border: 0 -} - -body .csv-data tr { - border-top: 0 -} - -body .csv-data th { - font-weight: 700; - background: #f8f8f8; - border-top: 0 -} - -body { - font-size: 15px -} - -body blockquote { - margin-right: 0; - margin-left: 0 -} - -body code { - white-space: normal -} - -body.email-format { - line-height: 1.5em!important -} - -body.email-format div { - white-space: pre-wrap -} - -body .email-hidden-reply { - display: none; - white-space: pre-wrap -} - -body .email-hidden-reply.expanded { - display: block -} - -body .email-quoted-reply, body .email-signature-reply { - padding: 0 10px; - margin-bottom: 10px; - color: #767676; - border-left: 4px solid #ddd -} - -.pl-c { - color: #969896 -} - -.pl-c1, .pl-s .pl-v { - color: #0086b3 -} - -.pl-e, .pl-en { - color: #795da3 -} - -.pl-smi, .pl-s .pl-s1 { - color: #333 -} - -.pl-ent { - color: #63a35c -} - -.pl-k { - color: #a71d5d -} - -.pl-s, .pl-pds, .pl-s .pl-pse .pl-s1, .pl-sr, .pl-sr .pl-cce, .pl-sr .pl-sre, .pl-sr .pl-sra { - color: #183691 -} - -.pl-v { - color: #ed6a43 -} - -.pl-id { - color: #b52a1d -} - -.pl-ii { - color: #f8f8f8; - background-color: #b52a1d -} - -.pl-sr .pl-cce { - font-weight: 700; - color: #63a35c -} - -.pl-ml { - color: #693a17 -} - -.pl-mh, .pl-mh .pl-en, .pl-ms { - font-weight: 700; - color: #1d3e81 -} - -.pl-mq { - color: teal -} - -.pl-mi { - font-style: italic; - color: #333 -} - -.pl-mb { - font-weight: 700; - color: #333 -} - -.pl-md { - color: #bd2c00; - background-color: #ffecec -} - -.pl-mi1 { - color: #55a532; - background-color: #eaffea -} - -.pl-mdr { - font-weight: 700; - color: #795da3 -} - -.pl-mo { - color: #1d3e81 -} - -kbd { - display: inline-block; - padding: 3px 5px; - font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #fcfcfc; - border: solid 1px #ccc; - border-bottom-color: #bbb; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #bbb -} - -.badmono { - font-family: sans-serif; - font-weight: 700 -} -.task-list-item { - list-style-type: none -} -.task-list-item label { - font-weight: normal -} -.task-list-item.enabled label { - cursor: pointer -} -.task-list-item+.task-list-item { - margin-top: 3px -} -.task-list-item .handle { - display: none -} -.task-list-item-checkbox { - margin: 0 0.2em 0.25em -1.6em; - vertical-align: middle -} -.reorderable-task-lists .markdown-body .contains-task-list { - padding: 0 -} -.reorderable-task-lists .markdown-body li:not(.task-list-item) { - margin-left: 26px -} -.reorderable-task-lists .markdown-body .task-list-item { - padding-right: 15px; - padding-left: 42px; - margin-right: -15px; - margin-left: -15px; - border: 1px solid transparent -} -.reorderable-task-lists .markdown-body .task-list-item+.task-list-item { - margin-top: 0 -} -.reorderable-task-lists .markdown-body .task-list-item .contains-task-list { - padding-top: 4px -} -.reorderable-task-lists .markdown-body .task-list-item .handle { - display: block; - float: left; - width: 20px; - padding: 2px 0 0 2px; - margin-left: -43px; - opacity: 0 -} -.reorderable-task-lists .markdown-body .task-list-item .drag-handle { - fill: #333 -} -.reorderable-task-lists .markdown-body .task-list-item.hovered { - background: #fafafa; - border-top-color: #ededed; - border-bottom-color: #ededed -} -.reorderable-task-lists .markdown-body .task-list-item.hovered>.handle { - opacity: 1 -} -.reorderable-task-lists .markdown-body .task-list-item.is-dragging { - opacity: 0 -} -.reorderable-task-lists .markdown-body .task-list-item.is-ghost { - border-right-color: #ededed; - border-left-color: #ededed -} -.review-comment-contents .markdown-body .task-list-item { - padding-left: 42px; - margin-right: -12px; - margin-left: -12px; - border-top-left-radius: 3px; - border-bottom-left-radius: 3px -} -.review-comment-contents .markdown-body .task-list-item.hovered { - border-left-color: #ededed -} \ No newline at end of file diff --git a/app/src/main/assets/md/github_dark.css b/app/src/main/assets/md/github_dark.css deleted file mode 100644 index a695448c7..000000000 --- a/app/src/main/assets/md/github_dark.css +++ /dev/null @@ -1,642 +0,0 @@ -body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - font-size: 16px; - padding: 10px; - line-height: 1.5; - word-wrap: break-word; - color: #ccc; -} - -a { - color: #00E5FF !important; -} - -body::before { - display: table; - content: "" -} - -body::after { - display: table; - clear: both; - content: "" -} - -body>:first-child { - margin-top: 0!important -} - -body:last-child { - margin-bottom: 46px !important -} - -body a:not([href]) { - color: inherit; - text-decoration: none -} - -body .absent { - color: #c0392b -} - -body .anchor { - float: left; - padding-right: 4px; - margin-left: -10px; - line-height: 1 -} - -body .anchor:focus { - outline: none -} - -body p, body blockquote, body ul, body ol, body dl, body table, body pre { - margin-top: 0; - margin-bottom: 10px -} - -body hr { - height: .25em; - padding: 0; - margin: 24px 0; - background-color: #c0c0c0; - border: 0 -} - -body blockquote { - padding: 0 1em; - color: #78909C; - border-left: .25em solid #ddd -} - -body blockquote>:first-child { - margin-top: 0 -} - -body blockquote>:last-child { - margin-bottom: 0 -} - -body kbd { - display: inline-block; - padding: 3px 5px; - font-size: 11px; - line-height: 10px; - color: #fff; - vertical-align: middle; - border: solid 1px #656d78; - border-bottom-color: #bbb; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #656d78 -} - -body .loweralpha { - list-style-type: lower-alpha -} - -body h1, body h2, body h3, body h4, body h5, body h6 { - margin-top: 24px; - margin-bottom: 16px; - font-weight: 600; - line-height: 1.25; - color: #fff; -} - -body h1 .octicon-link, body h2 .octicon-link, body h3 .octicon-link, body h4 .octicon-link, body h5 .octicon-link, body h6 .octicon-link { - color: #fff; - vertical-align: middle; - visibility: hidden -} - -body h1:hover .anchor, body h2:hover .anchor, body h3:hover .anchor, body h4:hover .anchor, body h5:hover .anchor, body h6:hover .anchor { - text-decoration: none -} - -body h1:hover .anchor .octicon-link, body h2:hover .anchor .octicon-link, body h3:hover .anchor .octicon-link, body h4:hover .anchor .octicon-link, body h5:hover .anchor .octicon-link, body h6:hover .anchor .octicon-link { - visibility: visible -} - -body h1 tt, body h1 code, body h2 tt, body h2 code, body h3 tt, body h3 code, body h4 tt, body h4 code, body h5 tt, body h5 code, body h6 tt, body h6 code { - font-size: inherit -} - -body h1 { - padding-bottom: .3em; - font-size: 2em; - border-bottom: 1px solid #656d78 -} - -.gh-header-meta { - padding-bottom: .3em; - margin-bottom: 6px; - border-bottom: 1px solid #656d78 -} - -body h2 { - padding-bottom: .3em; - font-size: 1.5em; - border-bottom: 1px solid #656d78 -} - -body h3 { - font-size: 1.25em -} - -body h4 { - font-size: 1em -} - -body h5 { - font-size: .875em -} - -body h6 { - font-size: .85em; - color: #c0c0c0 -} - -body ul, body ol { - padding-left: 1em -} - -body ul.no-list, body ol.no-list { - padding: 0; - list-style-type: none -} - -body ul ul, body ul ol, body ol ol, body ol ul { - margin-top: 0; - margin-bottom: 0 -} - -body li>p { - margin-top: 16px -} - -body li+li { - margin-top: .25em -} - -body dl { - padding: 0 -} - -body dl dt { - padding: 0; - margin-top: 16px; - font-size: 1em; - font-style: italic; - font-weight: 700 -} - -body dl dd { - padding: 0 16px; - margin-bottom: 16px -} - -body table { - display: block; - width: 100%; - overflow: auto -} - -body table th { - font-weight: 700 -} - -body table th, body table td { - padding: 6px 13px; - border: 1px solid #656d78 -} - -body table tr { - background-color: transparent; - border-top: 1px solid #656d78 -} - -body table tr:nth-child(2n) { - background-color: #656d78 -} - -body img { - max-width: 100%; - box-sizing: content-box; - background-color: transparent; -} - -body img[align=right] { - padding-left: 10px -} - -body img[align=left] { - padding-right: 10px -} - -body .emoji { - max-width: none; - vertical-align: text-top; - background-color: transparent -} - -body span.frame { - display: block; - overflow: hidden -} - -body span.frame>span { - display: block; - float: left; - width: auto; - padding: 7px; - margin: 13px 0 0; - overflow: hidden; - border: 1px solid #656d78 -} - -body span.frame span img { - display: block; - float: left -} - -body span.frame span span { - display: block; - padding: 5px 0 0; - clear: both; - color: #ccc -} - -body span.align-center { - display: block; - overflow: hidden; - clear: both -} - -body span.align-center>span { - display: block; - margin: 13px auto 0; - overflow: hidden; - text-align: center -} - -body span.align-center span img { - margin: 0 auto; - text-align: center -} - -body span.align-right { - display: block; - overflow: hidden; - clear: both -} - -body span.align-right>span { - display: block; - margin: 13px 0 0; - overflow: hidden; - text-align: right -} - -body span.align-right span img { - margin: 0; - text-align: right -} - -body span.float-left { - display: block; - float: left; - margin-right: 8px; - overflow: hidden -} - -body span.float-left span { - margin: 8px 0 0 -} - -body span.float-right { - display: block; - float: right; - margin-left: 8px; - overflow: hidden -} - -body span.float-right>span { - display: block; - margin: 8px auto 0; - overflow: hidden; - text-align: right -} - -body code, body tt { - padding: 0; - padding-top: .1em; - padding-bottom: .2em; - margin: 0; - font-size: 85%; - background-color: rgba(84, 84, 84, 0.04); - border-radius: 3px -} - -body code::before, body code::after, body tt::before, body tt::after { - letter-spacing: -.2em; - content: "\00a0" -} - -body code br, body tt br { - display: none -} - -body del code { - text-decoration: inherit -} - -body pre { - word-wrap: normal -} - -body pre>code { - padding: 0; - margin: 0; - font-size: 100%; - word-break: normal; - white-space: pre; - background: transparent; - border: 0 -} - -body .highlight { - margin-bottom: 10px -} - -body .highlight pre { - margin-bottom: 0; - word-break: normal -} - -body .highlight pre, body pre { - padding: 16px; - overflow: auto; - font-size: 85%; - line-height: 1.45; - border-radius: 3px -} - -body pre code, body pre tt { - display: inline; - max-width: auto; - padding: 0; - margin: 0; - overflow: visible; - line-height: inherit; - word-wrap: normal; - background-color: transparent; - border: 0 -} - -body pre code::before, body pre code::after, body pre tt::before, body pre tt::after { - content: normal -} - -body .csv-data td, body .csv-data th { - padding: 5px; - overflow: hidden; - font-size: 12px; - line-height: 1; - text-align: left; - white-space: nowrap -} - -body .csv-data .blob-num { - padding: 10px 8px 9px; - text-align: right; - background: #656d78; - border: 0 -} - -body .csv-data tr { - border-top: 0 -} - -body .csv-data th { - font-weight: 700; - background: #656d78; - border-top: 0 -} - -body { - font-size: 15px -} - -body blockquote { - margin-right: 0; - margin-left: 0 -} - -body code { - white-space: normal -} - -body.email-format { - line-height: 1.5em!important -} - -body.email-format div { - white-space: pre-wrap -} - -body .email-hidden-reply { - display: none; - white-space: pre-wrap -} - -body .email-hidden-reply.expanded { - display: block -} - -body .email-quoted-reply, body .email-signature-reply { - padding: 0 10px; - margin-bottom: 10px; - color: #c0c0c0; - border-left: 4px solid #656d78 -} - -.pl-c { - color: #969896 -} - -.pl-c1, .pl-s .pl-v { - color: #0086b3 -} - -.pl-e, .pl-en { - color: #795da3 -} - -.pl-smi, .pl-s .pl-s1 { - color: #78909C -} - -.pl-ent { - color: #388E3C -} - -.pl-k { - color: #a71d5d -} - -.pl-s, .pl-pds, .pl-s .pl-pse .pl-s1, .pl-sr, .pl-sr .pl-cce, .pl-sr .pl-sre, .pl-sr .pl-sra { - color: #1976D2 -} - -.pl-v { - color: #ed6a43 -} - -.pl-id { - color: #b52a1d -} - -.pl-ii { - color: #f8f8f8; - background-color: #b52a1d -} - -.pl-sr .pl-cce { - font-weight: 700; - color: #388E3C -} - -.pl-ml { - color: #7f8c8d; -} - -.pl-mh, .pl-mh .pl-en, .pl-ms { - font-weight: 700; - color: #1976D2 -} - -.pl-mq { - color: #0097A7 -} - -.pl-mi { - font-style: italic; - color: #78909C -} - -.pl-mb { - font-weight: 700; - color: #78909C -} - -.pl-md { - color: #bd2c00; - background-color: #ffecec -} - -.pl-mi1 { - color: #55a532; - background-color: #eaffea -} - -.pl-mdr { - font-weight: 700; - color: #795da3 -} - -.pl-mo { - color: #1976D2 -} - -kbd { - display: inline-block; - padding: 3px 5px; - font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #656d78; - border: solid 1px #586b78; - border-bottom-color: #556578; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #656d78 -} - -.badmono { - font-family: sans-serif; - font-weight: 700 -} - -.task-list-item { - list-style-type: none -} -.task-list-item label { - font-weight: normal -} -.task-list-item.enabled label { - cursor: pointer -} -.task-list-item+.task-list-item { - margin-top: 3px -} -.task-list-item .handle { - display: none -} -.task-list-item-checkbox { - margin: 0 0.2em 0.25em -1.6em; - vertical-align: middle -} -.reorderable-task-lists .markdown-body .contains-task-list { - padding: 0 -} -.reorderable-task-lists .markdown-body li:not(.task-list-item) { - margin-left: 26px -} -.reorderable-task-lists .markdown-body .task-list-item { - padding-right: 15px; - padding-left: 42px; - margin-right: -15px; - margin-left: -15px; - border: 1px solid transparent -} -.reorderable-task-lists .markdown-body .task-list-item+.task-list-item { - margin-top: 0 -} -.reorderable-task-lists .markdown-body .task-list-item .contains-task-list { - padding-top: 4px -} -.reorderable-task-lists .markdown-body .task-list-item .handle { - display: block; - float: left; - width: 20px; - padding: 2px 0 0 2px; - margin-left: -43px; - opacity: 0 -} -.reorderable-task-lists .markdown-body .task-list-item .drag-handle { - fill: #333 -} -.reorderable-task-lists .markdown-body .task-list-item.hovered { - background: #fafafa; - border-top-color: #ededed; - border-bottom-color: #ededed -} -.reorderable-task-lists .markdown-body .task-list-item.hovered>.handle { - opacity: 1 -} -.reorderable-task-lists .markdown-body .task-list-item.is-dragging { - opacity: 0 -} -.reorderable-task-lists .markdown-body .task-list-item.is-ghost { - border-right-color: #ededed; - border-left-color: #ededed -} -.review-comment-contents .markdown-body .task-list-item { - padding-left: 42px; - margin-right: -12px; - margin-left: -12px; - border-top-left-radius: 3px; - border-bottom-left-radius: 3px -} -.review-comment-contents .markdown-body .task-list-item.hovered { - border-left-color: #ededed -} diff --git a/app/src/main/assets/md/intercept-hash.js b/app/src/main/assets/md/intercept-hash.js deleted file mode 100644 index f1cd0d17f..000000000 --- a/app/src/main/assets/md/intercept-hash.js +++ /dev/null @@ -1,43 +0,0 @@ -window.onload = function () { - var hash = window.location.hash.substr(1); - if (hash !== "") { - scrollTo(hash); - } -}; - -function scrollTo(hash) { - var element = document.getElementById("user-content-" + hash); - if (element) { - element.scrollIntoView(); - } else { - element = document.querySelector('[href="#' + hash + '"]'); - if (element) { - element.scrollIntoView(); - } else { - //HACK!!! - var names = hash.trim().split("-").join(" "); - if (names) { - var elements = document.querySelectorAll("h1"); - for (var index = 0; index < elements.length; index++) { - if (elements[index].innerText.toLowerCase() === names.toLowerCase()) { - elements[index].scrollIntoView(); - } - } - } - } - } -} - -window.onclick = function (e) { - if (e.target.localName === 'a') { - var href = e.target; - href = href.toString().replace("file:///android_asset/md/", ""); - if (hasHashtag(href)) { - scrollTo(href.substr(href.indexOf("#"), href.length).replace("#", "")); - } - } -}; - -function hasHashtag(url) { - return (url.indexOf("#") !== -1); -} diff --git a/app/src/main/assets/md/intercept-touch.js b/app/src/main/assets/md/intercept-touch.js deleted file mode 100644 index cf314bd15..000000000 --- a/app/src/main/assets/md/intercept-touch.js +++ /dev/null @@ -1,29 +0,0 @@ -document.addEventListener("DOMContentLoaded", function(event) { - document.querySelectorAll('img').forEach(function(img){ - img.onerror = function(){this.style.display='none';}; - }); -}); - -window.onload = function() { - addTouchEvents(document.getElementsByTagName("pre")); - addTouchEvents(document.getElementsByTagName("table")); - var hash = window.location.hash.substr(1); - if (hash != ""){ - scrollTo(hash); - } -}; - -function addTouchEvents(elements) { - for (var i = 0; i < elements.length; i++) { - elements[i].addEventListener("touchstart", touchStart, false); - elements[i].addEventListener("touchend", touchEnd, false); - } -} - -function touchStart(event) { - Android.startIntercept(); -} - -function touchEnd(event) { - Android.stopIntercept(); -} \ No newline at end of file diff --git a/app/src/main/graphql/github/PinnedRepos.graphql b/app/src/main/graphql/github/PinnedRepos.graphql deleted file mode 100644 index cd91505c2..000000000 --- a/app/src/main/graphql/github/PinnedRepos.graphql +++ /dev/null @@ -1,28 +0,0 @@ -query getPinnedRepos($login: String!) { - user(login: $login) { - pinnedRepositories(first: 100) { - edges { - node { - name - url - issues(states: OPEN) { - totalCount - } - pullRequests(states: OPEN) { - totalCount - } - stargazers { - totalCount - } - forks { - totalCount - } - primaryLanguage { - name - color - } - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/graphql/github/PullRequestTimeline.graphql b/app/src/main/graphql/github/PullRequestTimeline.graphql deleted file mode 100644 index ab11f4eea..000000000 --- a/app/src/main/graphql/github/PullRequestTimeline.graphql +++ /dev/null @@ -1,521 +0,0 @@ -query PullRequestTimeline($owner: String!, $name: String!, $number: Int!, $page: String) { - repository(owner: $owner, name: $name) { - pullRequest(number: $number) { - pullRequestCommits: commits(last: 1) { - pullRequestCommit: nodes { - commit { - status { - state - contexts { - state - context - description - targetUrl - } - } - } - } - } - timeline(first: 30 after: $page) { - edges { - cursor - } - pageInfo { - hasNextPage - startCursor - endCursor - } - totalCount - nodes { - ... on Commit { - id - oid - url - committedDate - messageHeadline - status { - state - } - author { - name - user { - login - url - avatarUrl - } - } - } - ... on CommitCommentThread { - path - position - commit { - oid - } - comments(first: 30) { - edges { - node { - id - authorAssociation - bodyHTML - body - createdAt - reactionGroups { - viewerHasReacted - content - users { - totalCount - } - } - lastEditedAt - author { - avatarUrl - login - url - } - } - } - } - } - ... on PullRequestReview { - id - url - bodyHTML - submittedAt - createdAt - state - author { - login - url - avatarUrl - } - comments(first: 30) { - edges { - node { - id - authorAssociation - bodyHTML - diffHunk - createdAt - url - originalPosition - path - position - author { - login - avatarUrl - url - } - reactionGroups { - viewerHasReacted - content - users { - totalCount - } - } - } - } - } - } - ... on IssueComment { - id - bodyHTML - createdAt - updatedAt - viewerCanReact - viewerCanDelete - viewerCanUpdate - viewerDidAuthor - authorAssociation - lastEditedAt - author { - login - url - avatarUrl - } - reactionGroups { - viewerHasReacted - content - users { - totalCount - } - } - } - ... on ClosedEvent { - createdAt - actor { - login - avatarUrl - url - } - commit { - oid - url - messageHeadline - } - } - ... on ReopenedEvent { - createdAt - actor { - login - avatarUrl - url - } - } - ... on MergedEvent { - id - url - createdAt - mergeRefName - commit { - oid - } - actor { - avatarUrl - login - url - } - } - ... on ReferencedEvent { - id - createdAt - isCrossRepository - isDirectReference - actor { - avatarUrl - login - url - } - commitRepository { - nameWithOwner - url - } - commit { - oid - } - subject { - __typename - ... on Issue { - title - number - } - ... on PullRequest { - title - number - } - } - } - ... on AssignedEvent { - id - createdAt - actor { - login - avatarUrl - url - } - user { - avatarUrl - login - url - } - } - ... on UnassignedEvent { - id - createdAt - actor { - login - avatarUrl - url - } - user { - avatarUrl - login - url - } - } - ... on LabeledEvent { - createdAt - actor { - login - avatarUrl - url - } - label { - color - name - } - } - ... on UnlabeledEvent { - createdAt - actor { - login - avatarUrl - url - } - label { - color - name - } - } - ... on MilestonedEvent { - createdAt - id - milestoneTitle - actor { - login - avatarUrl - url - } - } - ... on DemilestonedEvent { - createdAt - id - milestoneTitle - actor { - login - avatarUrl - url - } - } - ... on RenamedTitleEvent { - id - createdAt - currentTitle - previousTitle - actor { - login - avatarUrl - url - } - } - ... on LockedEvent { - createdAt - actor { - login - avatarUrl - url - } - } - ... on UnlockedEvent { - createdAt - actor { - login - avatarUrl - url - } - } - ... on DeployedEvent { - createdAt - actor { - login - avatarUrl - url - } - ref { - name - prefix - } - deployment { - createdAt - state - creator { - avatarUrl - login - url - } - latestStatus { - description - environmentUrl - state - } - statuses(first: 30) { - edges { - node { - creator { - avatarUrl - login - url - } - logUrl - state - description - environmentUrl - } - } - } - } - } - ... on HeadRefDeletedEvent { - createdAt - headRefName - actor { - avatarUrl - login - url - } - } - ... on HeadRefRestoredEvent { - actor { - avatarUrl - login - url - } - createdAt - pullRequest { - number - headRefName - } - } - ... on HeadRefForcePushedEvent { - createdAt - ref { - name - prefix - } - actor { - login - avatarUrl - url - } - afterCommit { - oid - url - } - beforeCommit { - oid - url - status { - state - contexts { - context - createdAt - description - state - targetUrl - creator { - avatarUrl - login - url - } - } - } - } - } - ... on BaseRefForcePushedEvent { - createdAt - ref { - name - prefix - } - actor { - login - avatarUrl - url - } - afterCommit { - oid - url - } - beforeCommit { - oid - url - status { - state - contexts { - context - createdAt - description - state - targetUrl - creator { - avatarUrl - login - url - } - } - } - } - } - ... on ReviewRequestedEvent { - id - createdAt - actor { - avatarUrl - login - url - } - subject { - avatarUrl - login - url - } - } - ... on ReviewRequestRemovedEvent { - id - createdAt - actor { - avatarUrl - login - url - } - subject { - avatarUrl - login - url - } - } - ... on ReviewDismissedEvent { - id - createdAt - messageHtml - previousReviewState - review { - id - submittedAt - authorAssociation - bodyHTML - state - viewerDidAuthor - author { - login - avatarUrl - url - } - comments(first: 30) { - edges { - node { - id - authorAssociation - bodyHTML - diffHunk - createdAt - url - originalPosition - path - position - author { - login - avatarUrl - url - } - reactionGroups { - viewerHasReacted - content - users { - totalCount - } - } - } - } - } - } - } - } - } - } - } - rateLimit { - cost - remaining - limit - } -} diff --git a/app/src/main/graphql/github/RepoProject.graphql b/app/src/main/graphql/github/RepoProject.graphql deleted file mode 100644 index f7c411175..000000000 --- a/app/src/main/graphql/github/RepoProject.graphql +++ /dev/null @@ -1,157 +0,0 @@ -query repoProjectsOpen($owner: String!, $name: String!, $page: String) { -repository(owner: $owner, name: $name) { - projects(first: 30, states: OPEN, after: $page, orderBy: {field: CREATED_AT, direction: DESC}) { - totalCount - edges { - cursor - } - pageInfo { - hasNextPage - startCursor - endCursor - } - nodes { - name - number - body - createdAt - id - viewerCanUpdate - columns(first: 1) { - totalCount - } - databaseId - } - } - } -} -query repoProjectsClosed($owner: String!, $name: String!, $page: String) { -repository(owner: $owner, name: $name) { - projects(first: 30, states: CLOSED, after: $page, orderBy: {field: CREATED_AT, direction: DESC}) { - totalCount - edges { - cursor - } - pageInfo { - hasNextPage - startCursor - endCursor - } - nodes { - name - number - body - createdAt - id - viewerCanUpdate - columns(first: 1) { - totalCount - } - databaseId - } - } - } -} - -query orgProjectsOpen($owner: String!, $page: String) { -organization(login: $owner) { - projects(first: 30, states: OPEN, after: $page, orderBy: {field: CREATED_AT, direction: DESC}) { - totalCount - edges { - cursor - } - pageInfo { - hasNextPage - startCursor - endCursor - } - nodes { - name - number - body - createdAt - id - viewerCanUpdate - columns(first: 1) { - totalCount - } - databaseId - } - } - } -} -query orgProjectsClosed($owner: String!, $page: String) { -organization(login: $owner) { - projects(first: 30, states: CLOSED, after: $page, orderBy: {field: CREATED_AT, direction: DESC}) { - totalCount - edges { - cursor - } - pageInfo { - hasNextPage - startCursor - endCursor - } - nodes { - name - number - body - createdAt - id - viewerCanUpdate - columns(first: 1) { - totalCount - } - databaseId - } - } - } -} - -query getColumns($owner: String!, $name:String!,$number:Int!) { -repository(owner: $owner, name: $name) { - project(number: $number) { - name - viewerCanUpdate - columns(first: 100) { - nodes { - name - createdAt - id - cards(first: 100) { - nodes { - note - createdAt - url - content { - ... on Node { - __typename - } - ... on Issue { - title - url - number - issueState: state - } - ... on PullRequest { - title - url - number - PrState: state - } - ... on Comment { - body - author { - login - avatarUrl - url - } - } - } - } - } - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/App.java b/app/src/main/java/com/fastaccess/App.java deleted file mode 100644 index e5e6006f4..000000000 --- a/app/src/main/java/com/fastaccess/App.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.fastaccess; - -import android.app.Application; -import android.support.annotation.NonNull; -import android.support.v7.preference.PreferenceManager; - -import com.fastaccess.data.dao.model.Models; -import com.fastaccess.helper.DeviceNameGetter; -import com.fastaccess.helper.TypeFaceHelper; -import com.fastaccess.provider.colors.ColorsProvider; -import com.fastaccess.provider.emoji.EmojiManager; -import com.fastaccess.provider.fabric.FabricProvider; -import com.fastaccess.provider.tasks.notification.NotificationSchedulerJobTask; -import com.google.firebase.messaging.FirebaseMessaging; -import com.miguelbcr.io.rx_billing_service.RxBillingService; - -import io.requery.Persistable; -import io.requery.android.sqlite.DatabaseSource; -import io.requery.meta.EntityModel; -import io.requery.reactivex.ReactiveEntityStore; -import io.requery.reactivex.ReactiveSupport; -import io.requery.sql.Configuration; -import io.requery.sql.EntityDataStore; -import io.requery.sql.TableCreationMode; -import shortbread.Shortbread; - - -/** - * Created by Kosh on 03 Feb 2017, 12:07 AM - */ - -public class App extends Application { - private static App instance; - private ReactiveEntityStore dataStore; - - @Override public void onCreate() { - super.onCreate(); - instance = this; - init(); - } - - @NonNull public static App getInstance() { - return instance; - } - - private void init() { - FabricProvider.INSTANCE.initFabric(this); - RxBillingService.register(this); - deleteDatabase("database.db"); - getDataStore(); - setupPreference(); - TypeFaceHelper.generateTypeface(this); - NotificationSchedulerJobTask.scheduleJob(this); - Shortbread.create(this); - EmojiManager.load(); - ColorsProvider.load(); - DeviceNameGetter.getInstance().loadDevice(); - try { - FirebaseMessaging.getInstance().subscribeToTopic("FastHub"); - } catch (Exception ignored) {} - } - - private void setupPreference() { - PreferenceManager.setDefaultValues(this, R.xml.fasthub_settings, false); - PreferenceManager.setDefaultValues(this, R.xml.about_settings, false); - PreferenceManager.setDefaultValues(this, R.xml.behaviour_settings, false); - PreferenceManager.setDefaultValues(this, R.xml.customization_settings, false); - PreferenceManager.setDefaultValues(this, R.xml.language_settings, false); - PreferenceManager.setDefaultValues(this, R.xml.notification_settings, false); - } - - public ReactiveEntityStore getDataStore() { - if (dataStore == null) { - EntityModel model = Models.DEFAULT; - DatabaseSource source = new DatabaseSource(this, model, "FastHub-DB", 18); - Configuration configuration = source.getConfiguration(); - if (BuildConfig.DEBUG) { - source.setTableCreationMode(TableCreationMode.CREATE_NOT_EXISTS); - } - dataStore = ReactiveSupport.toReactiveStore(new EntityDataStore(configuration)); - } - return dataStore; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/dao/AccessTokenModel.java b/app/src/main/java/com/fastaccess/data/dao/AccessTokenModel.java deleted file mode 100644 index 2766fa0eb..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/AccessTokenModel.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 09 Nov 2016, 11:28 PM - */ - - -@Getter @Setter @NoArgsConstructor -public class AccessTokenModel implements Parcelable { - private long id; - private String token; - private String hashedToken; - private String accessToken; - private String tokenType; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.token); - dest.writeString(this.hashedToken); - dest.writeString(this.accessToken); - dest.writeString(this.tokenType); - } - - private AccessTokenModel(Parcel in) { - this.id = in.readLong(); - this.token = in.readString(); - this.hashedToken = in.readString(); - this.accessToken = in.readString(); - this.tokenType = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public AccessTokenModel createFromParcel(Parcel source) {return new AccessTokenModel(source);} - - @Override public AccessTokenModel[] newArray(int size) {return new AccessTokenModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/AppLanguageModel.java b/app/src/main/java/com/fastaccess/data/dao/AppLanguageModel.java deleted file mode 100644 index 81350448f..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/AppLanguageModel.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -/** - * Created by kosh on 20/07/2017. - */ - -@Getter @Setter @AllArgsConstructor public class AppLanguageModel implements Parcelable { - private String value; - private String label; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.value); - dest.writeString(this.label); - } - - private AppLanguageModel(Parcel in) { - this.value = in.readString(); - this.label = in.readString(); - } - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - AppLanguageModel that = (AppLanguageModel) o; - - return label != null ? label.equals(that.label) : that.label == null; - } - - @Override public int hashCode() { - return label != null ? label.hashCode() : 0; - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public AppLanguageModel createFromParcel(Parcel source) {return new AppLanguageModel(source);} - - @Override public AppLanguageModel[] newArray(int size) {return new AppLanguageModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/AssigneesRequestModel.java b/app/src/main/java/com/fastaccess/data/dao/AssigneesRequestModel.java deleted file mode 100644 index 38258bbc2..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/AssigneesRequestModel.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.fastaccess.data.dao; - -import java.util.List; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 05 Mar 2017, 12:01 PM - */ - -@Getter @Setter @NoArgsConstructor -public class AssigneesRequestModel { - private List assignees; - private List reviewers; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/AuthModel.java b/app/src/main/java/com/fastaccess/data/dao/AuthModel.java deleted file mode 100644 index a37d066e9..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/AuthModel.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.google.gson.annotations.SerializedName; - -import java.util.List; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 12 Mar 2017, 3:16 AM - */ - -@Getter @Setter @NoArgsConstructor -public class AuthModel implements Parcelable { - - private String clientId; - private String clientSecret; - private String redirectUri; - private List scopes; - private String state; - private String note; - private String noteUrl; - @SerializedName("X-GitHub-OTP") private String otpCode; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.clientId); - dest.writeString(this.clientSecret); - dest.writeString(this.redirectUri); - dest.writeStringList(this.scopes); - dest.writeString(this.state); - dest.writeString(this.note); - dest.writeString(this.noteUrl); - dest.writeString(this.otpCode); - } - - private AuthModel(Parcel in) { - this.clientId = in.readString(); - this.clientSecret = in.readString(); - this.redirectUri = in.readString(); - this.scopes = in.createStringArrayList(); - this.state = in.readString(); - this.note = in.readString(); - this.noteUrl = in.readString(); - this.otpCode = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public AuthModel createFromParcel(Parcel source) {return new AuthModel(source);} - - @Override public AuthModel[] newArray(int size) {return new AuthModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/BranchesModel.java b/app/src/main/java/com/fastaccess/data/dao/BranchesModel.java deleted file mode 100644 index 77a08db46..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/BranchesModel.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.Commit; -import com.google.gson.annotations.SerializedName; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 03 Mar 2017, 9:08 PM - */ - -@Getter @Setter @NoArgsConstructor -public class BranchesModel implements Parcelable { - - public String name; - public Commit commit; - @SerializedName("protected") public boolean protectedBranch; - public String protectionUrl; - public boolean isTag; - - @Override public String toString() { - return name; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.name); - dest.writeParcelable(this.commit, flags); - dest.writeByte(this.protectedBranch ? (byte) 1 : (byte) 0); - dest.writeString(this.protectionUrl); - dest.writeByte(this.isTag ? (byte) 1 : (byte) 0); - } - - private BranchesModel(Parcel in) { - this.name = in.readString(); - this.commit = in.readParcelable(Commit.class.getClassLoader()); - this.protectedBranch = in.readByte() != 0; - this.protectionUrl = in.readString(); - this.isTag = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override public BranchesModel createFromParcel(Parcel source) {return new BranchesModel(source);} - - @Override public BranchesModel[] newArray(int size) {return new BranchesModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/CommentRequestModel.java b/app/src/main/java/com/fastaccess/data/dao/CommentRequestModel.java deleted file mode 100644 index f37e0739b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/CommentRequestModel.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.google.gson.annotations.SerializedName; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 20 Nov 2016, 10:40 AM - */ - -@Getter @Setter public class CommentRequestModel implements Parcelable { - public String body; - @SerializedName("in_reply_to") public Long inReplyTo; - public String path; - public Integer position; - public Integer line; - - public CommentRequestModel() {} - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - CommentRequestModel that = (CommentRequestModel) o; - return (path != null ? path.equals(that.path) : that.path == null) && - (position != null ? position.equals(that.position) : that.position == null); - } - - @Override public int hashCode() { - int result = path != null ? path.hashCode() : 0; - result = 31 * result + (position != null ? position.hashCode() : 0); - return result; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.body); - dest.writeValue(this.inReplyTo); - dest.writeString(this.path); - dest.writeValue(this.position); - dest.writeValue(this.line); - } - - @Override public String toString() { - return "CommentRequestModel{" + - "body='" + body + '\'' + - ", inReplyTo=" + inReplyTo + - ", path='" + path + '\'' + - ", position=" + position + - ", line=" + line + - '}'; - } - - private CommentRequestModel(Parcel in) { - this.body = in.readString(); - this.inReplyTo = (Long) in.readValue(Long.class.getClassLoader()); - this.path = in.readString(); - this.position = (Integer) in.readValue(Integer.class.getClassLoader()); - this.line = (Integer) in.readValue(Integer.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public CommentRequestModel createFromParcel(Parcel source) {return new CommentRequestModel(source);} - - @Override public CommentRequestModel[] newArray(int size) {return new CommentRequestModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/CommitCountModel.java b/app/src/main/java/com/fastaccess/data/dao/CommitCountModel.java deleted file mode 100644 index 8b74c7857..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/CommitCountModel.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.ArrayList; -import java.util.List; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 01 Apr 2017, 12:42 PM - */ -@Getter @Setter public class CommitCountModel implements Parcelable { - - private List all; - private List owner; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeList(this.all); - dest.writeList(this.owner); - } - - public CommitCountModel() {} - - private CommitCountModel(Parcel in) { - this.all = new ArrayList(); - in.readList(this.all, Integer.class.getClassLoader()); - this.owner = new ArrayList(); - in.readList(this.owner, Integer.class.getClassLoader()); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public CommitCountModel createFromParcel(Parcel source) {return new CommitCountModel(source);} - - @Override public CommitCountModel[] newArray(int size) {return new CommitCountModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/CommitFileChanges.java b/app/src/main/java/com/fastaccess/data/dao/CommitFileChanges.java deleted file mode 100644 index 66311685f..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/CommitFileChanges.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.annimon.stream.Stream; - -import java.util.ArrayList; -import java.util.List; - -import io.reactivex.Observable; -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 20 Jun 2017, 7:32 PM - */ - -@Getter @Setter public class CommitFileChanges implements Parcelable { - - public List linesModel; - public CommitFileModel commitFileModel; - - private CommitFileChanges() {} - - public static Observable constructToObservable(@Nullable ArrayList files) { - if (files == null || files.isEmpty()) return Observable.empty(); - return Observable.fromIterable(construct(files)); - } - - @NonNull public static List construct(@Nullable List files) { - if (files == null || files.isEmpty()) { - return new ArrayList<>(); - } - return Stream.of(files) - .map(CommitFileChanges::getCommitFileChanges) - .toList(); - } - - @NonNull private static CommitFileChanges getCommitFileChanges(CommitFileModel m) { - CommitFileChanges model = new CommitFileChanges(); - model.setLinesModel(CommitLinesModel.getLines(m.getPatch())); - if (m.getPatch() != null) { - m.setPatch("fake"); - } - model.setCommitFileModel(m); - return model; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeTypedList(this.linesModel); - dest.writeParcelable(this.commitFileModel, flags); - } - - private CommitFileChanges(Parcel in) { - this.linesModel = in.createTypedArrayList(CommitLinesModel.CREATOR); - this.commitFileModel = in.readParcelable(CommitFileModel.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public CommitFileChanges createFromParcel(Parcel source) {return new CommitFileChanges(source);} - - @Override public CommitFileChanges[] newArray(int size) {return new CommitFileChanges[size];} - }; - - public static boolean canAttachToBundle(CommitFileChanges model) { - Parcel parcel = Parcel.obtain(); - model.writeToParcel(parcel, 0); - int size = parcel.dataSize(); - return size < 600000; - } - - @Override public String toString() { - return "CommitFileChanges{" + - "linesModel=" + linesModel + - ", commitFileModel=" + commitFileModel + - '}'; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/CommitFileListModel.java b/app/src/main/java/com/fastaccess/data/dao/CommitFileListModel.java deleted file mode 100644 index 6bd6ed294..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/CommitFileListModel.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.data.dao; - -import java.util.ArrayList; - -/** - * Created by Kosh on 12 Feb 2017, 12:06 AM - */ - -public class CommitFileListModel extends ArrayList {} diff --git a/app/src/main/java/com/fastaccess/data/dao/CommitFileModel.java b/app/src/main/java/com/fastaccess/data/dao/CommitFileModel.java deleted file mode 100644 index b2a86f6af..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/CommitFileModel.java +++ /dev/null @@ -1,150 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Created by Kosh on 01 Jan 2017, 9:00 PM - */ -public class CommitFileModel implements Parcelable { - - private String sha; - private String filename; - private String status; - private int additions; - private int deletions; - private int changes; - private String blobUrl; - private String rawUrl; - private String contentsUrl; - private String patch; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.sha); - dest.writeString(this.filename); - dest.writeString(this.status); - dest.writeInt(this.additions); - dest.writeInt(this.deletions); - dest.writeInt(this.changes); - dest.writeString(this.blobUrl); - dest.writeString(this.rawUrl); - dest.writeString(this.contentsUrl); - dest.writeString(this.patch); - } - - @SuppressWarnings("WeakerAccess") protected CommitFileModel(Parcel in) { - this.sha = in.readString(); - this.filename = in.readString(); - this.status = in.readString(); - this.additions = in.readInt(); - this.deletions = in.readInt(); - this.changes = in.readInt(); - this.blobUrl = in.readString(); - this.rawUrl = in.readString(); - this.contentsUrl = in.readString(); - this.patch = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public CommitFileModel createFromParcel(Parcel source) {return new CommitFileModel(source);} - - @Override public CommitFileModel[] newArray(int size) {return new CommitFileModel[size];} - }; - - @Override public String toString() { - return "CommitFileModel{" + - "sha='" + sha + '\'' + - ", filename='" + filename + '\'' + - ", status='" + status + '\'' + - ", additions=" + additions + - ", deletions=" + deletions + - ", changes=" + changes + - ", blobUrl='" + blobUrl + '\'' + - ", rawUrl='" + rawUrl + '\'' + - ", contentsUrl='" + contentsUrl + '\'' + - ", patch='" + patch + '\'' + - '}'; - } - - public String getSha() { - return sha; - } - - public void setSha(String sha) { - this.sha = sha; - } - - public String getFilename() { - return filename; - } - - public void setFilename(String filename) { - this.filename = filename; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public int getAdditions() { - return additions; - } - - public void setAdditions(int additions) { - this.additions = additions; - } - - public int getDeletions() { - return deletions; - } - - public void setDeletions(int deletions) { - this.deletions = deletions; - } - - public int getChanges() { - return changes; - } - - public void setChanges(int changes) { - this.changes = changes; - } - - public String getBlobUrl() { - return blobUrl; - } - - public void setBlobUrl(String blobUrl) { - this.blobUrl = blobUrl; - } - - public String getRawUrl() { - return rawUrl; - } - - public void setRawUrl(String rawUrl) { - this.rawUrl = rawUrl; - } - - public String getContentsUrl() { - return contentsUrl; - } - - public void setContentsUrl(String contentsUrl) { - this.contentsUrl = contentsUrl; - } - - public String getPatch() { - return patch; - } - - public void setPatch(String patch) { - this.patch = patch; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/CommitLinesModel.java b/app/src/main/java/com/fastaccess/data/dao/CommitLinesModel.java deleted file mode 100644 index 89e9df3a6..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/CommitLinesModel.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.helper.InputHelper; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; - -import lombok.AllArgsConstructor; - -import static com.fastaccess.ui.widgets.DiffLineSpan.HUNK_TITLE; - -/** - * Created by Kosh on 20 Jun 2017, 7:32 PM - */ - -@AllArgsConstructor public class CommitLinesModel implements Parcelable { - - public static final int TRANSPARENT = 0; - public static final int ADDITION = 1; - public static final int DELETION = 2; - public static final int PATCH = 3; - - - public String text; - public int color; - public int leftLineNo; - public int rightLineNo; - public boolean noNewLine; - public int position; - private boolean hasCommentedOn; - - @NonNull public static List getLines(@Nullable String text) { - ArrayList models = new ArrayList<>(); - if (!InputHelper.isEmpty(text)) { - String[] split = text.split("\\r?\\n|\\r"); - if (split.length > 1) { - int leftLineNo = -1; - int rightLineNo = -1; - int position = 0; - for (String token : split) { - char firstChar = token.charAt(0); - boolean addLeft = false; - boolean addRight = false; - int color = TRANSPARENT; - if (token.startsWith("@@")) { - color = PATCH; - Matcher matcher = HUNK_TITLE.matcher(token.trim()); - if (matcher.matches()) { - try { - leftLineNo = Math.abs(Integer.parseInt(matcher.group(1))) - 1; - rightLineNo = Integer.parseInt(matcher.group(3)) - 1; - } catch (NumberFormatException e) {e.printStackTrace();} - } - } else if (firstChar == '+') { - position++; - color = ADDITION; - ++rightLineNo; - addRight = true; - addLeft = false; - } else if (firstChar == '-') { - position++; - color = DELETION; - ++leftLineNo; - addRight = false; - addLeft = true; - } else { - position++; - addLeft = true; - addRight = true; - ++rightLineNo; - ++leftLineNo; - } - int index = token.indexOf("\\ No newline at end of file"); - if (index != -1) { - token = token.replace("\\ No newline at end of file", ""); - } - models.add(new CommitLinesModel(token, color, token.startsWith("@@") || !addLeft ? -1 : leftLineNo, - token.startsWith("@@") || !addRight ? -1 : rightLineNo, index != -1, position, false)); - } - } - } - return models; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.text); - dest.writeInt(this.color); - dest.writeInt(this.leftLineNo); - dest.writeInt(this.rightLineNo); - dest.writeByte(this.noNewLine ? (byte) 1 : (byte) 0); - dest.writeInt(this.position); - } - - private CommitLinesModel(Parcel in) { - this.text = in.readString(); - this.color = in.readInt(); - this.leftLineNo = in.readInt(); - this.rightLineNo = in.readInt(); - this.noNewLine = in.readByte() != 0; - this.position = in.readInt(); - } - - public static final Creator CREATOR = new Creator() { - @Override public CommitLinesModel createFromParcel(Parcel source) {return new CommitLinesModel(source);} - - @Override public CommitLinesModel[] newArray(int size) {return new CommitLinesModel[size];} - }; - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public int getColor() { - return color; - } - - public void setColor(int color) { - this.color = color; - } - - public int getLeftLineNo() { - return leftLineNo; - } - - public void setLeftLineNo(int leftLineNo) { - this.leftLineNo = leftLineNo; - } - - public int getRightLineNo() { - return rightLineNo; - } - - public void setRightLineNo(int rightLineNo) { - this.rightLineNo = rightLineNo; - } - - public boolean isNoNewLine() { - return noNewLine; - } - - public void setNoNewLine(boolean noNewLine) { - this.noNewLine = noNewLine; - } - - public int getPosition() { - return position; - } - - public void setPosition(int position) { - this.position = position; - } - - public boolean isHasCommentedOn() { - return hasCommentedOn; - } - - public void setHasCommentedOn(boolean hasCommentedOn) { - this.hasCommentedOn = hasCommentedOn; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/CommitListModel.java b/app/src/main/java/com/fastaccess/data/dao/CommitListModel.java deleted file mode 100644 index 2b91db77b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/CommitListModel.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.fastaccess.data.dao; - -import com.fastaccess.data.dao.model.Commit; - -import java.util.ArrayList; - -/** - * Created by Kosh on 12 Feb 2017, 12:10 AM - */ - -public class CommitListModel extends ArrayList {} diff --git a/app/src/main/java/com/fastaccess/data/dao/CommitRequestModel.java b/app/src/main/java/com/fastaccess/data/dao/CommitRequestModel.java deleted file mode 100644 index 3baa2db84..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/CommitRequestModel.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.fastaccess.data.dao; - -/** - * Created by kosh on 31/08/2017. - */ - -public class CommitRequestModel { - - private String message; - private String content; - private String sha; - private String branch; - - public CommitRequestModel(String message, String content, String sha, String branch) { - this.message = message; - this.content = content; - this.sha = sha; - this.branch = branch; - } - - public String getSha() { - return sha; - } - - public void setSha(String sha) { - this.sha = sha; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public String getBranch() { - return branch; - } - - public void setBranch(String branch) { - this.branch = branch; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/CreateGistModel.java b/app/src/main/java/com/fastaccess/data/dao/CreateGistModel.java deleted file mode 100644 index 8beb28115..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/CreateGistModel.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.google.gson.annotations.SerializedName; - -import java.util.HashMap; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 18 Feb 2017, 11:15 PM - */ - -@Setter @Getter @NoArgsConstructor -public class CreateGistModel implements Parcelable { - private HashMap files; - private String description; - @SerializedName("public") private Boolean publicGist; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeSerializable(this.files); - dest.writeString(this.description); - dest.writeValue(this.publicGist); - } - - @SuppressWarnings("unchecked") private CreateGistModel(Parcel in) { - this.files = (HashMap) in.readSerializable(); - this.description = in.readString(); - this.publicGist = (Boolean) in.readValue(Boolean.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public CreateGistModel createFromParcel(Parcel source) {return new CreateGistModel(source);} - - @Override public CreateGistModel[] newArray(int size) {return new CreateGistModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/CreateIssueModel.java b/app/src/main/java/com/fastaccess/data/dao/CreateIssueModel.java deleted file mode 100644 index 35d165998..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/CreateIssueModel.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.ArrayList; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 19 Feb 2017, 12:13 PM - */ - -@Getter @Setter @NoArgsConstructor -public class CreateIssueModel implements Parcelable { - private String title; - private String body; - private ArrayList labels; - private ArrayList assignees; - private Long milestone; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.title); - dest.writeString(this.body); - dest.writeStringList(this.labels); - dest.writeStringList(this.assignees); - dest.writeValue(this.milestone); - } - - protected CreateIssueModel(Parcel in) { - this.title = in.readString(); - this.body = in.readString(); - this.labels = in.createStringArrayList(); - this.assignees = in.createStringArrayList(); - this.milestone = (Long) in.readValue(Long.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public CreateIssueModel createFromParcel(Parcel source) {return new CreateIssueModel(source);} - - @Override public CreateIssueModel[] newArray(int size) {return new CreateIssueModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/CreateMilestoneModel.java b/app/src/main/java/com/fastaccess/data/dao/CreateMilestoneModel.java deleted file mode 100644 index 40cc12847..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/CreateMilestoneModel.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.fastaccess.data.dao; - -import com.google.gson.annotations.SerializedName; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 05 Mar 2017, 2:30 AM - */ - -@Getter @Setter @NoArgsConstructor -public class CreateMilestoneModel { - private String title; - private String description; - @SerializedName("due_one") private String dueOn; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/EditRepoFileModel.kt b/app/src/main/java/com/fastaccess/data/dao/EditRepoFileModel.kt deleted file mode 100644 index 3489fbee6..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/EditRepoFileModel.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.fastaccess.data.dao - -import android.os.Parcel -import com.fastaccess.helper.KotlinParcelable -import com.fastaccess.helper.parcelableCreator -import com.fastaccess.helper.readBoolean -import com.fastaccess.helper.writeBoolean - -/** - * Created by Hashemsergani on 01/09/2017. - */ -data class EditRepoFileModel(val login: String, - val repoId: String, - val path: String?, - val ref: String, - val sha: String?, - val contentUrl: String?, - val fileName: String?, - val isEdit: Boolean) : KotlinParcelable { - constructor(parcel: Parcel) : this( - parcel.readString(), - parcel.readString(), - parcel.readString(), - parcel.readString(), - parcel.readString(), - parcel.readString(), - parcel.readString(), - parcel.readBoolean()) - - override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) { - writeString(login) - writeString(repoId) - writeString(path) - writeString(ref) - writeString(sha) - writeString(contentUrl) - writeString(fileName) - writeBoolean(isEdit) - } - - companion object { - @JvmField val CREATOR = parcelableCreator(::EditRepoFileModel) - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/EditReviewCommentModel.java b/app/src/main/java/com/fastaccess/data/dao/EditReviewCommentModel.java deleted file mode 100644 index e5dde19bf..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/EditReviewCommentModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.google.gson.annotations.SerializedName; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 22 May 2017, 8:36 PM - */ - -@Getter @Setter public class EditReviewCommentModel implements Parcelable { - - public int groupPosition; - public int commentPosition; - public String comment; - public ReviewCommentModel commentModel; - @SerializedName("in_reply_to") public long inReplyTo; - - - public EditReviewCommentModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.groupPosition); - dest.writeInt(this.commentPosition); - dest.writeString(this.comment); - dest.writeParcelable(this.commentModel, flags); - dest.writeLong(this.inReplyTo); - } - - private EditReviewCommentModel(Parcel in) { - this.groupPosition = in.readInt(); - this.commentPosition = in.readInt(); - this.comment = in.readString(); - this.commentModel = in.readParcelable(ReviewCommentModel.class.getClassLoader()); - this.inReplyTo = in.readLong(); - } - - public static final Creator CREATOR = new Creator() { - @Override public EditReviewCommentModel createFromParcel(Parcel source) {return new EditReviewCommentModel(source);} - - @Override public EditReviewCommentModel[] newArray(int size) {return new EditReviewCommentModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/FilesListModel.java b/app/src/main/java/com/fastaccess/data/dao/FilesListModel.java deleted file mode 100644 index 1ce1106e1..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/FilesListModel.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.io.Serializable; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 12 Nov 2016, 11:09 AM - */ - -@Getter @Setter -public class FilesListModel implements Parcelable, Serializable { - public String filename; - public String type; - public String rawUrl; - public Long size; - public String content; - public Boolean needFetching; - public String language; - - public FilesListModel() { - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.filename); - dest.writeString(this.type); - dest.writeString(this.rawUrl); - dest.writeValue(this.size); - dest.writeString(this.content); - dest.writeValue(this.needFetching); - dest.writeString(this.language); - } - - protected FilesListModel(Parcel in) { - this.filename = in.readString(); - this.type = in.readString(); - this.rawUrl = in.readString(); - this.size = (Long) in.readValue(Long.class.getClassLoader()); - this.content = in.readString(); - this.needFetching = (Boolean) in.readValue(Boolean.class.getClassLoader()); - this.language = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public FilesListModel createFromParcel(Parcel source) {return new FilesListModel(source);} - - @Override public FilesListModel[] newArray(int size) {return new FilesListModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/FilterOptionsModel.java b/app/src/main/java/com/fastaccess/data/dao/FilterOptionsModel.java deleted file mode 100644 index e74e41456..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/FilterOptionsModel.java +++ /dev/null @@ -1,174 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.annimon.stream.Stream; -import com.fastaccess.helper.InputHelper; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Serves a model for the filter in Repositories fragment - */ -public class FilterOptionsModel implements Parcelable { - - private static final String TYPE = "type"; - private static final String SORT = "sort"; - private static final String AFFILIATION = "affiliation"; - private static final String DIRECTION = "direction"; - - private String type; - private String sort = "Pushed"; - private String sortDirection = "descending"; - private Map queryMap; - private boolean isPersonalProfile; - - private List typesListForPersonalProfile = Stream.of("Select", "All", "Owner", "Public", "Private", "Member").toList(); - private List typesListForExternalProfile = Stream.of("Select", "All", "Owner", "Member").toList(); - private List typesListForOrganizationProfile = Stream.of("Select", "All", "Public", "Private", "Forks", "Sources", "Member").toList(); - private List sortOptionsList = Stream.of("Pushed", "Created", "Updated", "Full Name").toList(); - private List sortDirectionList = Stream.of("Descending", "Ascending").toList(); - private boolean isOrg; - - public FilterOptionsModel() { - } - - public void setType(String type) { - this.type = type; - } - - public void setSort(String sort) { - this.sort = sort; - } - - public void setSortDirection(String sortDirection) { - this.sortDirection = sortDirection; - } - - public Map getQueryMap() { - if (queryMap == null) { - queryMap = new HashMap<>(); - } else { - queryMap.clear(); - } - if (InputHelper.isEmpty(type) || "Select".equalsIgnoreCase(type)) { - queryMap.remove(TYPE); - queryMap.put(AFFILIATION, "owner,collaborator"); - } else { - queryMap.remove(AFFILIATION); - queryMap.put(TYPE, type.toLowerCase()); - } - //Not supported for organization repo - if (!isOrg) { - if (sort.contains(" ")) { - //full name should be full_name - queryMap.put(SORT, sort.replace(" ", "_").toLowerCase()); - } else { - queryMap.put(SORT, sort.toLowerCase()); - } - if (sortDirection.equals(sortDirectionList.get(0))) { - //Descending should be desc - queryMap.put(DIRECTION, sortDirection.toLowerCase().substring(0, 4)); - } else { - //Ascending should be asc - queryMap.put(DIRECTION, sortDirection.toLowerCase().substring(0, 3)); - } - } - return queryMap; - } - - public int getSelectedTypeIndex() { - if (isPersonalProfile) { - return typesListForPersonalProfile.indexOf(type); - } else { - return typesListForExternalProfile.indexOf(type); - } - } - - public int getSelectedSortOptionIndex() { - return sortOptionsList.indexOf(sort); - } - - public int getSelectedSortDirectionIndex() { - return sortDirectionList.indexOf(sortDirection); - } - - public List getTypesList() { - if (isPersonalProfile) { - return typesListForPersonalProfile; - } else if (isOrg) { - return typesListForOrganizationProfile; - } else { - return typesListForExternalProfile; - } - } - - public List getSortOptionList() { - return sortOptionsList; - } - - public List getSortDirectionList() { - return sortDirectionList; - } - - public void setIsPersonalProfile(boolean isPersonalProfile) { - this.isPersonalProfile = isPersonalProfile; - } - - public void setOrg(boolean org) { - this.isOrg = org; - } - - public boolean isOrg() { - return isOrg; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.type); - dest.writeString(this.sort); - dest.writeString(this.sortDirection); - dest.writeInt(this.queryMap.size()); - for (Map.Entry entry : this.queryMap.entrySet()) { - dest.writeString(entry.getKey()); - dest.writeString(entry.getValue()); - } - dest.writeByte(this.isPersonalProfile ? (byte) 1 : (byte) 0); - dest.writeStringList(this.typesListForPersonalProfile); - dest.writeStringList(this.typesListForExternalProfile); - dest.writeStringList(this.typesListForOrganizationProfile); - dest.writeStringList(this.sortOptionsList); - dest.writeStringList(this.sortDirectionList); - dest.writeByte(this.isOrg ? (byte) 1 : (byte) 0); - } - - private FilterOptionsModel(Parcel in) { - this.type = in.readString(); - this.sort = in.readString(); - this.sortDirection = in.readString(); - int queryMapSize = in.readInt(); - this.queryMap = new HashMap(queryMapSize); - for (int i = 0; i < queryMapSize; i++) { - String key = in.readString(); - String value = in.readString(); - this.queryMap.put(key, value); - } - this.isPersonalProfile = in.readByte() != 0; - this.typesListForPersonalProfile = in.createStringArrayList(); - this.typesListForExternalProfile = in.createStringArrayList(); - this.typesListForOrganizationProfile = in.createStringArrayList(); - this.sortOptionsList = in.createStringArrayList(); - this.sortDirectionList = in.createStringArrayList(); - this.isOrg = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override public FilterOptionsModel createFromParcel(Parcel source) {return new FilterOptionsModel(source);} - - @Override public FilterOptionsModel[] newArray(int size) {return new FilterOptionsModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/FragmentPagerAdapterModel.java b/app/src/main/java/com/fastaccess/data/dao/FragmentPagerAdapterModel.java deleted file mode 100644 index e15b13266..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/FragmentPagerAdapterModel.java +++ /dev/null @@ -1,294 +0,0 @@ -package com.fastaccess.data.dao; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.data.dao.types.MyIssuesType; -import com.fastaccess.ui.modules.feeds.FeedsFragment; -import com.fastaccess.ui.modules.gists.GistsFragment; -import com.fastaccess.ui.modules.gists.gist.comments.GistCommentsFragment; -import com.fastaccess.ui.modules.gists.gist.files.GistFilesListFragment; -import com.fastaccess.ui.modules.gists.starred.StarredGistsFragment; -import com.fastaccess.ui.modules.main.drawer.AccountDrawerFragment; -import com.fastaccess.ui.modules.main.drawer.MainDrawerFragment; -import com.fastaccess.ui.modules.main.issues.MyIssuesFragment; -import com.fastaccess.ui.modules.main.pullrequests.MyPullRequestFragment; -import com.fastaccess.ui.modules.notification.all.AllNotificationsFragment; -import com.fastaccess.ui.modules.notification.fasthub.FastHubNotificationsFragment; -import com.fastaccess.ui.modules.notification.unread.UnreadNotificationsFragment; -import com.fastaccess.ui.modules.pinned.gist.PinnedGistFragment; -import com.fastaccess.ui.modules.pinned.issue.PinnedIssueFragment; -import com.fastaccess.ui.modules.pinned.pullrequest.PinnedPullRequestFragment; -import com.fastaccess.ui.modules.pinned.repo.PinnedReposFragment; -import com.fastaccess.ui.modules.profile.followers.ProfileFollowersFragment; -import com.fastaccess.ui.modules.profile.following.ProfileFollowingFragment; -import com.fastaccess.ui.modules.profile.gists.ProfileGistsFragment; -import com.fastaccess.ui.modules.profile.org.OrgProfileOverviewFragment; -import com.fastaccess.ui.modules.profile.org.members.OrgMembersFragment; -import com.fastaccess.ui.modules.profile.org.repos.OrgReposFragment; -import com.fastaccess.ui.modules.profile.org.teams.OrgTeamFragment; -import com.fastaccess.ui.modules.profile.org.teams.details.members.TeamMembersFragment; -import com.fastaccess.ui.modules.profile.org.teams.details.repos.TeamReposFragment; -import com.fastaccess.ui.modules.profile.overview.ProfileOverviewFragment; -import com.fastaccess.ui.modules.profile.repos.ProfileReposFragment; -import com.fastaccess.ui.modules.profile.starred.ProfileStarredFragment; -import com.fastaccess.ui.modules.repos.code.commit.RepoCommitsFragment; -import com.fastaccess.ui.modules.repos.code.commit.details.comments.CommitCommentsFragment; -import com.fastaccess.ui.modules.repos.code.commit.details.files.CommitFilesFragment; -import com.fastaccess.ui.modules.repos.code.contributors.RepoContributorsFragment; -import com.fastaccess.ui.modules.repos.code.files.paths.RepoFilePathFragment; -import com.fastaccess.ui.modules.repos.code.prettifier.ViewerFragment; -import com.fastaccess.ui.modules.repos.code.releases.RepoReleasesFragment; -import com.fastaccess.ui.modules.repos.extras.branches.BranchesFragment; -import com.fastaccess.ui.modules.repos.issues.issue.RepoClosedIssuesFragment; -import com.fastaccess.ui.modules.repos.issues.issue.RepoOpenedIssuesFragment; -import com.fastaccess.ui.modules.repos.issues.issue.details.timeline.IssueTimelineFragment; -import com.fastaccess.ui.modules.repos.projects.columns.ProjectColumnFragment; -import com.fastaccess.ui.modules.repos.projects.list.RepoProjectFragment; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.RepoPullRequestFragment; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.commits.PullRequestCommitsFragment; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files.PullRequestFilesFragment; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.timeline.timeline.PullRequestTimelineFragment; -import com.fastaccess.ui.modules.search.code.SearchCodeFragment; -import com.fastaccess.ui.modules.search.issues.SearchIssuesFragment; -import com.fastaccess.ui.modules.search.repos.SearchReposFragment; -import com.fastaccess.ui.modules.search.users.SearchUsersFragment; -import com.fastaccess.ui.modules.theme.fragment.ThemeFragment; - -import java.util.List; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 03 Dec 2016, 9:26 AM - */ - -@Getter @Setter public class FragmentPagerAdapterModel { - - String title; - Fragment fragment; - String key; - - private FragmentPagerAdapterModel(String title, Fragment fragment) { - this(title, fragment, null); - } - - public FragmentPagerAdapterModel(String title, Fragment fragment, String key) { - this.title = title; - this.fragment = fragment; - this.key = key; - } - - @NonNull public static List buildForProfile(@NonNull Context context, @NonNull String login) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.overview), ProfileOverviewFragment.newInstance(login)), - new FragmentPagerAdapterModel(context.getString(R.string.feed), FeedsFragment.newInstance(login, false)), - new FragmentPagerAdapterModel(context.getString(R.string.repos), ProfileReposFragment.newInstance(login)), - new FragmentPagerAdapterModel(context.getString(R.string.starred), ProfileStarredFragment.newInstance(login)), - new FragmentPagerAdapterModel(context.getString(R.string.gists), ProfileGistsFragment.newInstance(login)), - new FragmentPagerAdapterModel(context.getString(R.string.followers), ProfileFollowersFragment.newInstance(login)), - new FragmentPagerAdapterModel(context.getString(R.string.following), ProfileFollowingFragment.newInstance(login))) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForRepoCode(@NonNull Context context, @NonNull String repoId, - @NonNull String login, @NonNull String url, - @NonNull String defaultBranch, - @NonNull String htmlUrl) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.readme), ViewerFragment.newInstance(url, htmlUrl, true)), - new FragmentPagerAdapterModel(context.getString(R.string.files), RepoFilePathFragment.newInstance(login, repoId, null, - defaultBranch)), - new FragmentPagerAdapterModel(context.getString(R.string.commits), RepoCommitsFragment.newInstance(repoId, login, defaultBranch)), - new FragmentPagerAdapterModel(context.getString(R.string.releases), RepoReleasesFragment.newInstance(repoId, login)), - new FragmentPagerAdapterModel(context.getString(R.string.contributors), RepoContributorsFragment.newInstance(repoId, login))) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForSearch(@NonNull Context context) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.repos), SearchReposFragment.newInstance()), - new FragmentPagerAdapterModel(context.getString(R.string.users), SearchUsersFragment.newInstance()), - new FragmentPagerAdapterModel(context.getString(R.string.issues), SearchIssuesFragment.newInstance()), - new FragmentPagerAdapterModel(context.getString(R.string.code), SearchCodeFragment.newInstance())) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForIssues(@NonNull Context context, long commentId) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.details), IssueTimelineFragment.newInstance(commentId))) - .collect(Collectors.toList()); - } - - - @NonNull public static List buildForPullRequest(@NonNull Context context, @NonNull PullRequest pullRequest) { - String login = pullRequest.getLogin(); - String repoId = pullRequest.getRepoId(); - int number = pullRequest.getNumber(); - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.details), PullRequestTimelineFragment.newInstance()), - new FragmentPagerAdapterModel(context.getString(R.string.commits), PullRequestCommitsFragment.newInstance(repoId, login, number)), - new FragmentPagerAdapterModel(context.getString(R.string.files), PullRequestFilesFragment.newInstance(repoId, login, number))) - .collect(Collectors.toList()); - } - - - @NonNull public static List buildForRepoIssue(@NonNull Context context, @NonNull String login, - @NonNull String repoId) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.opened), - RepoOpenedIssuesFragment.newInstance(repoId, login)), - new FragmentPagerAdapterModel(context.getString(R.string.closed), - RepoClosedIssuesFragment.newInstance(repoId, login))) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForRepoPullRequest(@NonNull Context context, @NonNull String login, - @NonNull String repoId) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.opened), - RepoPullRequestFragment.newInstance(repoId, login, IssueState.open)), - new FragmentPagerAdapterModel(context.getString(R.string.closed), - RepoPullRequestFragment.newInstance(repoId, login, IssueState.closed))) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForCommit(@NonNull Context context, @NonNull Commit commitModel) { - String login = commitModel.getLogin(); - String repoId = commitModel.getRepoId(); - String sha = commitModel.getSha(); - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.files), - CommitFilesFragment.newInstance(commitModel.getSha(), commitModel.getFiles())), - new FragmentPagerAdapterModel(context.getString(R.string.comments), - CommitCommentsFragment.newInstance(login, repoId, sha))) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForGist(@NonNull Context context, @NonNull Gist gistsModel) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.files), GistFilesListFragment.newInstance(gistsModel - .getFilesAsList(), false)), - new FragmentPagerAdapterModel(context.getString(R.string.comments), GistCommentsFragment.newInstance(gistsModel.getGistId()))) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForNotifications(@NonNull Context context) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.unread), new UnreadNotificationsFragment()), - new FragmentPagerAdapterModel(context.getString(R.string.all), AllNotificationsFragment.newInstance()), - new FragmentPagerAdapterModel(context.getString(R.string.app_name), new FastHubNotificationsFragment())) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForGists(@NonNull Context context) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.my_gists), ProfileGistsFragment - .newInstance(Login.getUser().getLogin())), - new FragmentPagerAdapterModel(context.getString(R.string.starred), StarredGistsFragment.newInstance()), - new FragmentPagerAdapterModel(context.getString(R.string.public_gists), GistsFragment.newInstance())) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForMyIssues(@NonNull Context context) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.created), - MyIssuesFragment.newInstance(IssueState.open, MyIssuesType.CREATED)), - new FragmentPagerAdapterModel(context.getString(R.string.assigned), - MyIssuesFragment.newInstance(IssueState.open, MyIssuesType.ASSIGNED)), - new FragmentPagerAdapterModel(context.getString(R.string.mentioned), - MyIssuesFragment.newInstance(IssueState.open, MyIssuesType.MENTIONED)), - new FragmentPagerAdapterModel(context.getString(R.string.participated), - MyIssuesFragment.newInstance(IssueState.open, MyIssuesType.PARTICIPATED))) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForMyPulls(@NonNull Context context) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.created), - MyPullRequestFragment.newInstance(IssueState.open, MyIssuesType.CREATED)), - new FragmentPagerAdapterModel(context.getString(R.string.assigned), - MyPullRequestFragment.newInstance(IssueState.open, MyIssuesType.ASSIGNED)), - new FragmentPagerAdapterModel(context.getString(R.string.mentioned), - MyPullRequestFragment.newInstance(IssueState.open, MyIssuesType.MENTIONED)), - new FragmentPagerAdapterModel(context.getString(R.string.review_requests), - MyPullRequestFragment.newInstance(IssueState.open, MyIssuesType.REVIEW))) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForOrg(@NonNull Context context, @NonNull String login, boolean isMember) { - return Stream.of( - new FragmentPagerAdapterModel(context.getString(R.string.feeds), - isMember ? FeedsFragment.newInstance(login, true) : null), - new FragmentPagerAdapterModel(context.getString(R.string.overview), OrgProfileOverviewFragment.newInstance(login)), - new FragmentPagerAdapterModel(context.getString(R.string.repos), OrgReposFragment.newInstance(login)), - new FragmentPagerAdapterModel(context.getString(R.string.people), OrgMembersFragment.newInstance(login)), - new FragmentPagerAdapterModel(context.getString(R.string.teams), isMember ? OrgTeamFragment.newInstance(login) : null)) - .filter(fragmentPagerAdapterModel -> fragmentPagerAdapterModel.getFragment() != null) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForTeam(@NonNull Context context, long id) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.members), TeamMembersFragment.newInstance(id)), - new FragmentPagerAdapterModel(context.getString(R.string.repos), TeamReposFragment.newInstance(id))) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForTheme() { - return Stream.of(new FragmentPagerAdapterModel("", ThemeFragment.Companion.newInstance(R.style.ThemeLight)), - new FragmentPagerAdapterModel("", ThemeFragment.Companion.newInstance(R.style.ThemeDark)), - new FragmentPagerAdapterModel("", ThemeFragment.Companion.newInstance(R.style.ThemeAmlod)), - new FragmentPagerAdapterModel("", ThemeFragment.Companion.newInstance(R.style.ThemeBluish))) -// new FragmentPagerAdapterModel("", ThemeFragment.Companion.newInstance(R.style.ThemeMidnight))) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForBranches(@NonNull Context context, @NonNull String repoId, @NonNull String login) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.branches), - BranchesFragment.Companion.newInstance(login, repoId, true)), - new FragmentPagerAdapterModel(context.getString(R.string.tags), - BranchesFragment.Companion.newInstance(login, repoId, false))) - .toList(); - } - - @NonNull public static List buildForRepoProjects(@NonNull Context context, @Nullable String repoId, - @NonNull String login) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.open), - RepoProjectFragment.Companion.newInstance(login, repoId, IssueState.open)), - new FragmentPagerAdapterModel(context.getString(R.string.closed), - RepoProjectFragment.Companion.newInstance(login, repoId, IssueState.closed))) - .toList(); - } - - @NonNull public static List buildForProjectColumns(@NonNull List models, boolean isCollaborator) { - return Stream.of(models) - .map(projectColumnModel -> new FragmentPagerAdapterModel("", ProjectColumnFragment.Companion - .newInstance(projectColumnModel, isCollaborator), String.valueOf(projectColumnModel.getId()))) - .toList(); - } - - @NonNull public static List buildForPinned(@NonNull Context context) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.repos), PinnedReposFragment.newInstance()), - new FragmentPagerAdapterModel(context.getString(R.string.issues), PinnedIssueFragment.newInstance()), - new FragmentPagerAdapterModel(context.getString(R.string.pull_requests), PinnedPullRequestFragment.newInstance()), - new FragmentPagerAdapterModel(context.getString(R.string.gists), PinnedGistFragment.newInstance())) - .collect(Collectors.toList()); - } - - @NonNull public static List buildForDrawer(@NonNull Context context) { - return Stream.of(new FragmentPagerAdapterModel(context.getString(R.string.menu_label), new MainDrawerFragment()), - new FragmentPagerAdapterModel(context.getString(R.string.profile), new AccountDrawerFragment())) - .toList(); - } - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - FragmentPagerAdapterModel that = (FragmentPagerAdapterModel) o; - - return key != null ? key.equals(that.key) : that.key == null; - } - - @Override public int hashCode() { - return key != null ? key.hashCode() : 0; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/GistHubErrorsModel.java b/app/src/main/java/com/fastaccess/data/dao/GistHubErrorsModel.java deleted file mode 100644 index 6111e8478..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/GistHubErrorsModel.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.fastaccess.data.dao; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 18 Feb 2017, 2:10 PM - */ - -@Getter @Setter @NoArgsConstructor class GistHubErrorsModel { - private String resource; - private String field; - private String code; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/GitCommitListModel.java b/app/src/main/java/com/fastaccess/data/dao/GitCommitListModel.java deleted file mode 100644 index 99827b7d3..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/GitCommitListModel.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.data.dao; - -import java.util.ArrayList; - -/** - * Created by Kosh on 12 Feb 2017, 12:14 AM - */ - -public class GitCommitListModel extends ArrayList {} diff --git a/app/src/main/java/com/fastaccess/data/dao/GitCommitModel.java b/app/src/main/java/com/fastaccess/data/dao/GitCommitModel.java deleted file mode 100644 index 61dd15767..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/GitCommitModel.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.User; -import com.google.gson.annotations.SerializedName; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 08 Dec 2016, 8:59 PM - */ - -@Getter @Setter @NoArgsConstructor -public class GitCommitModel implements Parcelable { - - public String sha; - public String url; - public String message; - public User author; - public User committer; - public User tree; - public @SerializedName("distinct") boolean distincted; - public GitCommitListModel parents; - public int commentCount; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.sha); - dest.writeString(this.url); - dest.writeString(this.message); - dest.writeParcelable(this.author, flags); - dest.writeParcelable(this.committer, flags); - dest.writeParcelable(this.tree, flags); - dest.writeByte(this.distincted ? (byte) 1 : (byte) 0); - dest.writeList(this.parents); - dest.writeInt(this.commentCount); - } - - protected GitCommitModel(Parcel in) { - this.sha = in.readString(); - this.url = in.readString(); - this.message = in.readString(); - this.author = in.readParcelable(User.class.getClassLoader()); - this.committer = in.readParcelable(User.class.getClassLoader()); - this.tree = in.readParcelable(User.class.getClassLoader()); - this.distincted = in.readByte() != 0; - this.parents = new GitCommitListModel(); - in.readList(this.parents, this.parents.getClass().getClassLoader()); - this.commentCount = in.readInt(); - } - - public static final Creator CREATOR = new Creator() { - @Override public GitCommitModel createFromParcel(Parcel source) {return new GitCommitModel(source);} - - @Override public GitCommitModel[] newArray(int size) {return new GitCommitModel[size];} - }; - - @Override public String toString() { - if (message != null) { - return (sha != null && sha.length() > 7 ? sha.substring(0, 7) + " - " : "") + message.split(System.lineSeparator())[0]; - } else if (sha != null && sha.length() > 10) { - return sha.substring(0, 10); - } - return "N/A"; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/GitHubErrorResponse.java b/app/src/main/java/com/fastaccess/data/dao/GitHubErrorResponse.java deleted file mode 100644 index cbe1c5b8e..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/GitHubErrorResponse.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.fastaccess.data.dao; - -import java.util.List; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 18 Feb 2017, 2:09 PM - */ - -@Getter @Setter @NoArgsConstructor -public class GitHubErrorResponse { - private String message; - private String documentation_url; - private List errors; - - @Override public String toString() { - return "GitHubErrorResponse{" + - "message='" + message + '\'' + - ", documentation_url='" + documentation_url + '\'' + - ", errors=" + errors + - '}'; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/GitHubStatusModel.java b/app/src/main/java/com/fastaccess/data/dao/GitHubStatusModel.java deleted file mode 100644 index e8eaed801..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/GitHubStatusModel.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Date; - -/** - * Created by Hashemsergani on 18.10.17. - */ - -public class GitHubStatusModel implements Parcelable { - - private String status; - private String body; - private Date createdOn; - - public String getStatus() { return status;} - - public void setStatus(String status) { this.status = status;} - - public String getBody() { return body;} - - public void setBody(String body) { this.body = body;} - - public Date getCreatedOn() { return createdOn;} - - public void setCreatedOn(Date createdOn) { this.createdOn = createdOn;} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.status); - dest.writeString(this.body); - dest.writeLong(this.createdOn != null ? this.createdOn.getTime() : -1); - } - - public GitHubStatusModel() {} - - protected GitHubStatusModel(Parcel in) { - this.status = in.readString(); - this.body = in.readString(); - long tmpCreatedOn = in.readLong(); - this.createdOn = tmpCreatedOn == -1 ? null : new Date(tmpCreatedOn); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public GitHubStatusModel createFromParcel(Parcel source) {return new GitHubStatusModel(source);} - - @Override public GitHubStatusModel[] newArray(int size) {return new GitHubStatusModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/GithubFileModel.java b/app/src/main/java/com/fastaccess/data/dao/GithubFileModel.java deleted file mode 100644 index b3d5a06fa..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/GithubFileModel.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.fastaccess.data.dao; - -import java.io.Serializable; -import java.util.HashMap; - -/** - * Created by Kosh on 10 Feb 2017, 9:46 PM - */ - - -public class GithubFileModel extends HashMap implements Serializable {} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/dao/GithubState.java b/app/src/main/java/com/fastaccess/data/dao/GithubState.java deleted file mode 100644 index 31020150f..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/GithubState.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 08 Dec 2016, 8:57 PM - */ - -@Getter @Setter @NoArgsConstructor -public class GithubState implements Parcelable { - private int additions; - private int deletions; - private int total; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.additions); - dest.writeInt(this.deletions); - dest.writeInt(this.total); - } - - protected GithubState(Parcel in) { - this.additions = in.readInt(); - this.deletions = in.readInt(); - this.total = in.readInt(); - } - - public static final Creator CREATOR = new Creator() { - @Override public GithubState createFromParcel(Parcel source) {return new GithubState(source);} - - @Override public GithubState[] newArray(int size) {return new GithubState[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/GroupedNotificationModel.java b/app/src/main/java/com/fastaccess/data/dao/GroupedNotificationModel.java deleted file mode 100644 index d52b86c0e..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/GroupedNotificationModel.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.fastaccess.data.dao; - -import android.support.annotation.Nullable; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.fastaccess.data.dao.model.Notification; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.InputHelper; - -import java.util.ArrayList; -import java.util.Date; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; - -import static com.annimon.stream.Collectors.toList; - -/** - * Created by Kosh on 18 Apr 2017, 8:07 PM - */ - -@Getter @Setter public class GroupedNotificationModel { - public static final int HEADER = 1; - public static final int ROW = 2; - - private int type; - private Repo repo; - private Notification notification; - private Date date; - - private GroupedNotificationModel(Repo repo) { - this.type = HEADER; - this.repo = repo; - } - - public GroupedNotificationModel(Notification notification) { - this.type = ROW; - this.notification = notification; - this.date = notification.getUpdatedAt(); - } - - @NonNull public static List construct(@Nullable List items) { - List models = new ArrayList<>(); - if (items == null || items.isEmpty()) return models; - Map> grouped = Stream.of(items) - .filter(value -> !value.isUnread()) - .collect(Collectors.groupingBy(Notification::getRepository, LinkedHashMap::new, - Collectors.mapping(o -> o, toList()))); - Stream.of(grouped) - .filter(repoListEntry -> repoListEntry.getValue() != null && !repoListEntry.getValue().isEmpty()) - .forEach(repoListEntry -> { - Repo repo = repoListEntry.getKey(); - List notifications = repoListEntry.getValue(); - models.add(new GroupedNotificationModel(repo)); - Stream.of(notifications) - .sorted((o1, o2) -> o2.getUpdatedAt().compareTo(o1.getUpdatedAt())) - .forEach(notification -> models.add(new GroupedNotificationModel(notification))); - }); - return models; - } - - @NonNull public static List onlyNotifications(@Nullable List items) { - if (items == null || items.isEmpty()) return new ArrayList<>(); - return Stream.of(items) - .map(GroupedNotificationModel::new) - .collect(Collectors.toList()); - } - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - GroupedNotificationModel model = (GroupedNotificationModel) o; - return notification != null && model.getNotification() != null && notification.getId() == (model.notification.getId()); - } - - @Override public int hashCode() { - return notification != null ? InputHelper.getSafeIntId(notification.getId()) : 0; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/GroupedReviewModel.java b/app/src/main/java/com/fastaccess/data/dao/GroupedReviewModel.java deleted file mode 100644 index 583c89a46..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/GroupedReviewModel.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Date; -import java.util.List; - -/** - * Created by Kosh on 07 May 2017, 5:08 PM - */ - -public class GroupedReviewModel implements Parcelable { - - private int position; //to group with! - private String diffText; - private Date date; - private String path; - private long id; - private List comments; - - public GroupedReviewModel() {} - - public int getPosition() { - return position; - } - - public void setPosition(int position) { - this.position = position; - } - - public String getDiffText() { - return diffText; - } - - public void setDiffText(String diffText) { - this.diffText = diffText; - } - - public Date getDate() { - return date; - } - - public void setDate(Date date) { - this.date = date; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public List getComments() { - return comments; - } - - public void setComments(List comments) { - this.comments = comments; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.position); - dest.writeString(this.diffText); - dest.writeLong(this.date != null ? this.date.getTime() : -1); - dest.writeString(this.path); - dest.writeLong(this.id); - dest.writeTypedList(this.comments); - } - - private GroupedReviewModel(Parcel in) { - this.position = in.readInt(); - this.diffText = in.readString(); - long tmpDate = in.readLong(); - this.date = tmpDate == -1 ? null : new Date(tmpDate); - this.path = in.readString(); - this.id = in.readLong(); - this.comments = in.createTypedArrayList(ReviewCommentModel.CREATOR); - } - - public static final Creator CREATOR = new Creator() { - @Override public GroupedReviewModel createFromParcel(Parcel source) {return new GroupedReviewModel(source);} - - @Override public GroupedReviewModel[] newArray(int size) {return new GroupedReviewModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/ImgurReponseModel.java b/app/src/main/java/com/fastaccess/data/dao/ImgurReponseModel.java deleted file mode 100644 index bd8d66e33..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/ImgurReponseModel.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 15 Apr 2017, 8:09 PM - */ - -@Getter @Setter public class ImgurReponseModel implements Parcelable { - private boolean success; - private int status; - private ImgurImage data; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeByte(this.success ? (byte) 1 : (byte) 0); - dest.writeInt(this.status); - dest.writeParcelable(this.data, flags); - } - - public ImgurReponseModel() {} - - private ImgurReponseModel(Parcel in) { - this.success = in.readByte() != 0; - this.status = in.readInt(); - this.data = in.readParcelable(ImgurImage.class.getClassLoader()); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public ImgurReponseModel createFromParcel(Parcel source) {return new ImgurReponseModel(source);} - - @Override public ImgurReponseModel[] newArray(int size) {return new ImgurReponseModel[size];} - }; - - @Getter @Setter public static class ImgurImage implements Parcelable { - private String title; - private String description; - private String link; - - public ImgurImage() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.title); - dest.writeString(this.description); - dest.writeString(this.link); - } - - private ImgurImage(Parcel in) { - this.title = in.readString(); - this.description = in.readString(); - this.link = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public ImgurImage createFromParcel(Parcel source) {return new ImgurImage(source);} - - @Override public ImgurImage[] newArray(int size) {return new ImgurImage[size];} - }; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/IssueEventAdapterModel.java b/app/src/main/java/com/fastaccess/data/dao/IssueEventAdapterModel.java deleted file mode 100644 index 915df44bc..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/IssueEventAdapterModel.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.Nullable; - -import com.annimon.stream.Stream; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.IssueEvent; - -import java.util.ArrayList; -import java.util.List; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 10 Dec 2016, 3:34 PM - */ - -@Getter @Setter -public class IssueEventAdapterModel implements Parcelable { - - public static final int HEADER = 1; - public static final int ROW = 2; - private int type; - - private IssueEvent issueEvent; - private Issue issueModel; - - private IssueEventAdapterModel(int type, IssueEvent model) { - this.type = type; - this.issueEvent = model; - } - - public IssueEventAdapterModel(int type, Issue issueModel) { - this.type = type; - this.issueModel = issueModel; - } - - public static ArrayList addEvents(@Nullable List modelList) { - ArrayList models = new ArrayList<>(); - if (modelList == null || modelList.isEmpty()) return models; - Stream.of(modelList).forEach(issueEventModel -> models.add(new IssueEventAdapterModel(ROW, issueEventModel))); - return models; - } - - public IssueEventAdapterModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.type); - dest.writeParcelable(this.issueEvent, flags); - dest.writeParcelable(this.issueModel, flags); - } - - private IssueEventAdapterModel(Parcel in) { - this.type = in.readInt(); - this.issueEvent = in.readParcelable(IssueEvent.class.getClassLoader()); - this.issueModel = in.readParcelable(Issue.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public IssueEventAdapterModel createFromParcel(Parcel source) {return new IssueEventAdapterModel(source);} - - @Override public IssueEventAdapterModel[] newArray(int size) {return new IssueEventAdapterModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/IssueRequestModel.java b/app/src/main/java/com/fastaccess/data/dao/IssueRequestModel.java deleted file mode 100644 index 73a7a805e..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/IssueRequestModel.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.types.IssueState; - -import java.util.List; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 10 Dec 2016, 8:53 AM - */ - -@Getter @Setter @NoArgsConstructor -public class IssueRequestModel implements Parcelable { - - private IssueState state; - private String title; - private String body; - private Integer milestone; - private String assignee; - private List labels; - private String base; - - public static IssueRequestModel clone(@NonNull Issue issue, boolean toClose) { - IssueRequestModel model = new IssueRequestModel(); - if (issue.getLabels() != null) { - model.setLabels(Stream.of(issue.getLabels()).filter(value -> value.getName() != null) - .map(LabelModel::getName).collect(Collectors.toList())); - } - model.setAssignee(issue.getAssignee() != null ? issue.getAssignee().getLogin() : null); - model.setBody(issue.getBody()); - model.setMilestone(issue.getMilestone() != null ? issue.getMilestone().getNumber() : null); - model.setState(toClose ? issue.getState() == IssueState.closed ? IssueState.open : IssueState.closed : issue.getState()); - model.setTitle(issue.getTitle()); - return model; - } - - public static IssueRequestModel clone(@NonNull PullRequest issue, boolean toClose) { - IssueRequestModel model = new IssueRequestModel(); - if (issue.getLabels() != null) { - model.setLabels(Stream.of(issue.getLabels()).filter(value -> value.getName() != null) - .map(LabelModel::getName).collect(Collectors.toList())); - } - model.setBase(issue.getBase() != null ? issue.getBase().getRef() : "master"); - model.setAssignee(issue.getAssignee() != null ? issue.getAssignee().getLogin() : null); - model.setBody(issue.getBody()); - model.setMilestone(issue.getMilestone() != null ? issue.getMilestone().getNumber() : null); - model.setState(toClose ? issue.getState() == IssueState.closed ? IssueState.open : IssueState.closed : issue.getState()); - model.setTitle(issue.getTitle()); - return model; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.state == null ? -1 : this.state.ordinal()); - dest.writeString(this.title); - dest.writeString(this.body); - dest.writeValue(this.milestone); - dest.writeString(this.assignee); - dest.writeStringList(this.labels); - } - - private IssueRequestModel(Parcel in) { - int tmpState = in.readInt(); - this.state = tmpState == -1 ? null : IssueState.values()[tmpState]; - this.title = in.readString(); - this.body = in.readString(); - this.milestone = (Integer) in.readValue(Integer.class.getClassLoader()); - this.assignee = in.readString(); - this.labels = in.createStringArrayList(); - } - - public static final Creator CREATOR = new Creator() { - @Override public IssueRequestModel createFromParcel(Parcel source) {return new IssueRequestModel(source);} - - @Override public IssueRequestModel[] newArray(int size) {return new IssueRequestModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/IssuesPageable.java b/app/src/main/java/com/fastaccess/data/dao/IssuesPageable.java deleted file mode 100644 index 99e8b3652..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/IssuesPageable.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.List; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 15 Nov 2016, 7:04 PM - */ - - -@Getter @Setter @NoArgsConstructor -public class IssuesPageable implements Parcelable { - - public int first; - public int next; - public int prev; - public int last; - public int totalCount; - public boolean incompleteResults; - public List items; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.first); - dest.writeInt(this.next); - dest.writeInt(this.prev); - dest.writeInt(this.last); - dest.writeInt(this.totalCount); - dest.writeByte(this.incompleteResults ? (byte) 1 : (byte) 0); - } - - @SuppressWarnings("WeakerAccess") protected IssuesPageable(Parcel in) { - this.first = in.readInt(); - this.next = in.readInt(); - this.prev = in.readInt(); - this.last = in.readInt(); - this.totalCount = in.readInt(); - this.incompleteResults = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override public IssuesPageable createFromParcel(Parcel source) {return new IssuesPageable(source);} - - @Override public IssuesPageable[] newArray(int size) {return new IssuesPageable[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/LabelListModel.java b/app/src/main/java/com/fastaccess/data/dao/LabelListModel.java deleted file mode 100644 index 77ee5a82a..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/LabelListModel.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.data.dao; - -import java.util.ArrayList; - -/** - * Created by Kosh on 12 Feb 2017, 1:32 PM - */ - -public class LabelListModel extends ArrayList {} diff --git a/app/src/main/java/com/fastaccess/data/dao/LabelModel.java b/app/src/main/java/com/fastaccess/data/dao/LabelModel.java deleted file mode 100644 index 68c4068f3..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/LabelModel.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 08 Dec 2016, 9:05 PM - */ - -@Getter @Setter @NoArgsConstructor -public class LabelModel implements Parcelable { - String url; - String name; - String color; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.url); - dest.writeString(this.name); - dest.writeString(this.color); - } - - protected LabelModel(Parcel in) { - this.url = in.readString(); - this.name = in.readString(); - this.color = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public LabelModel createFromParcel(Parcel source) {return new LabelModel(source);} - - @Override public LabelModel[] newArray(int size) {return new LabelModel[size];} - }; - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - LabelModel that = (LabelModel) o; - - return name != null ? name.equals(that.name) : that.name == null; - } - - @Override public int hashCode() { - return name != null ? name.hashCode() : 0; - } - - @Override public String toString() { - return "LabelModel{" + - "url='" + url + '\'' + - ", name='" + name + '\'' + - ", color='" + color + '\'' + - '}'; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/LanguageColorModel.java b/app/src/main/java/com/fastaccess/data/dao/LanguageColorModel.java deleted file mode 100644 index 2f40fc9a6..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/LanguageColorModel.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; - -/** - * Created by Kosh on 27 May 2017, 9:47 PM - */ - -@Getter @Setter @ToString public class LanguageColorModel implements Parcelable { - public String color; - public String url; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.color); - dest.writeString(this.url); - } - - public LanguageColorModel() {} - - private LanguageColorModel(Parcel in) { - this.color = in.readString(); - this.url = in.readString(); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public LanguageColorModel createFromParcel(Parcel source) {return new LanguageColorModel(source);} - - @Override public LanguageColorModel[] newArray(int size) {return new LanguageColorModel[size];} - }; -} - diff --git a/app/src/main/java/com/fastaccess/data/dao/LicenseModel.java b/app/src/main/java/com/fastaccess/data/dao/LicenseModel.java deleted file mode 100644 index c6a555186..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/LicenseModel.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 01 Jan 2017, 1:15 PM - */ - -@Getter @Setter @NoArgsConstructor -public class LicenseModel implements Parcelable { - String key; - String name; - String spdxId; - String url; - boolean featured; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.key); - dest.writeString(this.name); - dest.writeString(this.spdxId); - dest.writeString(this.url); - dest.writeByte(this.featured ? (byte) 1 : (byte) 0); - } - - protected LicenseModel(Parcel in) { - this.key = in.readString(); - this.name = in.readString(); - this.spdxId = in.readString(); - this.url = in.readString(); - this.featured = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override public LicenseModel createFromParcel(Parcel source) {return new LicenseModel(source);} - - @Override public LicenseModel[] newArray(int size) {return new LicenseModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/LockIssuePrModel.java b/app/src/main/java/com/fastaccess/data/dao/LockIssuePrModel.java deleted file mode 100644 index 481788b3c..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/LockIssuePrModel.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.data.dao; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 10.02.18. - */ -@NoArgsConstructor @AllArgsConstructor @Getter @Setter public class LockIssuePrModel { - private boolean locked; - private String activeLockReason; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/MarkdownModel.java b/app/src/main/java/com/fastaccess/data/dao/MarkdownModel.java deleted file mode 100644 index b4c972814..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/MarkdownModel.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 18 Feb 2017, 7:20 PM - */ - -@Getter @Setter @NoArgsConstructor -public class MarkdownModel implements Parcelable { - private String text; - private String mode = "gfm"; - private String context; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.text); - dest.writeString(this.mode); - dest.writeString(this.context); - } - - @SuppressWarnings("WeakerAccess") protected MarkdownModel(Parcel in) { - this.text = in.readString(); - this.mode = in.readString(); - this.context = in.readString(); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public MarkdownModel createFromParcel(Parcel source) {return new MarkdownModel(source);} - - @Override public MarkdownModel[] newArray(int size) {return new MarkdownModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/MergeRequestModel.java b/app/src/main/java/com/fastaccess/data/dao/MergeRequestModel.java deleted file mode 100644 index 70120d55e..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/MergeRequestModel.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 16 Dec 2016, 11:42 PM - */ - -@Getter @Setter @NoArgsConstructor -public class MergeRequestModel implements Parcelable { - - private String commitMessage; - private String sha; - private String base; - private String head; - private String mergeMethod = "merge"; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.commitMessage); - dest.writeString(this.sha); - dest.writeString(this.base); - dest.writeString(this.head); - } - - @SuppressWarnings("WeakerAccess") protected MergeRequestModel(Parcel in) { - this.commitMessage = in.readString(); - this.sha = in.readString(); - this.base = in.readString(); - this.head = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public MergeRequestModel createFromParcel(Parcel source) {return new MergeRequestModel(source);} - - @Override public MergeRequestModel[] newArray(int size) {return new MergeRequestModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/MergeResponseModel.java b/app/src/main/java/com/fastaccess/data/dao/MergeResponseModel.java deleted file mode 100644 index 2c20c7b5c..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/MergeResponseModel.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 16 Dec 2016, 11:40 PM - */ - -@Getter @Setter @NoArgsConstructor -public class MergeResponseModel implements Parcelable { - - private String sha; - private boolean merged; - private String message; - private String documentationUrl; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.sha); - dest.writeByte(this.merged ? (byte) 1 : (byte) 0); - dest.writeString(this.message); - dest.writeString(this.documentationUrl); - } - - @SuppressWarnings("WeakerAccess") protected MergeResponseModel(Parcel in) { - this.sha = in.readString(); - this.merged = in.readByte() != 0; - this.message = in.readString(); - this.documentationUrl = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public MergeResponseModel createFromParcel(Parcel source) {return new MergeResponseModel(source);} - - @Override public MergeResponseModel[] newArray(int size) {return new MergeResponseModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/MilestoneModel.java b/app/src/main/java/com/fastaccess/data/dao/MilestoneModel.java deleted file mode 100644 index a774dbdea..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/MilestoneModel.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.User; - -import java.util.Date; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 08 Dec 2016, 8:47 PM - */ - -@Getter @Setter @NoArgsConstructor -public class MilestoneModel implements Parcelable { - - long id; - String url; - String title; - String state; - String description; - int number; - User creator; - String htmlUr; - int openIssues; - int closedIssues; - Date createdAt; - Date updatedAt; - Date closedAt; - Date dueOn; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.url); - dest.writeString(this.title); - dest.writeString(this.state); - dest.writeString(this.description); - dest.writeInt(this.number); - dest.writeParcelable(this.creator, flags); - dest.writeString(this.htmlUr); - dest.writeInt(this.openIssues); - dest.writeInt(this.closedIssues); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeLong(this.closedAt != null ? this.closedAt.getTime() : -1); - dest.writeLong(this.dueOn != null ? this.dueOn.getTime() : -1); - } - - protected MilestoneModel(Parcel in) { - this.id = in.readLong(); - this.url = in.readString(); - this.title = in.readString(); - this.state = in.readString(); - this.description = in.readString(); - this.number = in.readInt(); - this.creator = in.readParcelable(User.class.getClassLoader()); - this.htmlUr = in.readString(); - this.openIssues = in.readInt(); - this.closedIssues = in.readInt(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - long tmpClosedAt = in.readLong(); - this.closedAt = tmpClosedAt == -1 ? null : new Date(tmpClosedAt); - long tmpDueOn = in.readLong(); - this.dueOn = tmpDueOn == -1 ? null : new Date(tmpDueOn); - } - - public static final Creator CREATOR = new Creator() { - @Override public MilestoneModel createFromParcel(Parcel source) {return new MilestoneModel(source);} - - @Override public MilestoneModel[] newArray(int size) {return new MilestoneModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/NameParser.java b/app/src/main/java/com/fastaccess/data/dao/NameParser.java deleted file mode 100644 index 11f0ffd51..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/NameParser.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fastaccess.data.dao; - -import android.net.Uri; -import android.support.annotation.Nullable; - -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.scheme.LinkParserHelper; - -import java.util.List; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 11 Feb 2017, 11:03 PM - */ - -@Getter @Setter -public class NameParser { - - public String name; - public String username; - public boolean isEnterprise; - - public NameParser(@Nullable String url) { - if (!InputHelper.isEmpty(url)) { - boolean isEnterprise = LinkParserHelper.isEnterprise(url); - if (isEnterprise) { - url = url.replace("api/v3/", ""); - } - Uri uri = Uri.parse(url); - List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 2) { - return; - } - boolean isFirstPathIsRepo = (segments.get(0).equalsIgnoreCase("repos") || segments.get(0).equalsIgnoreCase("repo")); - this.username = isFirstPathIsRepo ? segments.get(1) : segments.get(0); - this.name = isFirstPathIsRepo ? segments.get(2) : segments.get(1); - this.isEnterprise = isEnterprise; - } - } - - @Override public String toString() { - return "NameParser{" + - "name='" + name + '\'' + - ", username='" + username + '\'' + - '}'; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/NotificationSoundModel.kt b/app/src/main/java/com/fastaccess/data/dao/NotificationSoundModel.kt deleted file mode 100644 index fcb5b279e..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/NotificationSoundModel.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.fastaccess.data.dao - -import android.net.Uri - -/** - * Created by kosh on 23/07/2017. - */ -class NotificationSoundModel(val name: String? = null, val uri: Uri? = null, val isSelected: Boolean = false) \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/dao/NotificationSubjectModel.java b/app/src/main/java/com/fastaccess/data/dao/NotificationSubjectModel.java deleted file mode 100644 index e17e9eb7b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/NotificationSubjectModel.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.types.NotificationType; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 19 Feb 2017, 6:11 PM - */ - -@Getter @Setter @NoArgsConstructor -public class NotificationSubjectModel implements Parcelable { - String title; - String url; - NotificationType type; - String latestCommentUrl; - - @Override public String toString() { - return "NotificationSubjectModel{" + - ", title='" + title + '\'' + - ", url='" + url + '\'' + - ", type='" + type + '\'' + - ", latestCommentUrl='" + latestCommentUrl + '\'' + - '}'; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.title); - dest.writeString(this.url); - dest.writeInt(this.type == null ? -1 : this.type.ordinal()); - dest.writeString(this.latestCommentUrl); - } - - protected NotificationSubjectModel(Parcel in) { - this.title = in.readString(); - this.url = in.readString(); - int tmpType = in.readInt(); - this.type = tmpType == -1 ? null : NotificationType.values()[tmpType]; - this.latestCommentUrl = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public NotificationSubjectModel createFromParcel(Parcel source) {return new NotificationSubjectModel(source);} - - @Override public NotificationSubjectModel[] newArray(int size) {return new NotificationSubjectModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/NotificationSubscriptionBodyModel.java b/app/src/main/java/com/fastaccess/data/dao/NotificationSubscriptionBodyModel.java deleted file mode 100644 index a0f174763..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/NotificationSubscriptionBodyModel.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.data.dao; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Hashemsergani on 14.10.17. - */ - -@AllArgsConstructor @Getter @Setter public class NotificationSubscriptionBodyModel { - private Boolean subscribed; - private Boolean ignored; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/Pageable.java b/app/src/main/java/com/fastaccess/data/dao/Pageable.java deleted file mode 100644 index cbfafe6c6..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/Pageable.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.List; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 15 Nov 2016, 7:04 PM - */ - - -@Getter @Setter @NoArgsConstructor -public class Pageable implements Parcelable { - - public int first; - public int next; - public int prev; - public int last; - public int totalCount; - public boolean incompleteResults; - public List items; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.first); - dest.writeInt(this.next); - dest.writeInt(this.prev); - dest.writeInt(this.last); - dest.writeInt(this.totalCount); - dest.writeByte(this.incompleteResults ? (byte) 1 : (byte) 0); - dest.writeTypedList(this.items); - } - - @SuppressWarnings("WeakerAccess") protected Pageable(Parcel in) { - this.first = in.readInt(); - this.next = in.readInt(); - this.prev = in.readInt(); - this.last = in.readInt(); - this.totalCount = in.readInt(); - this.incompleteResults = in.readByte() != 0; - in.readList(this.items, this.items.getClass().getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public Pageable createFromParcel(Parcel source) {return new Pageable(source);} - - @Override public Pageable[] newArray(int size) {return new Pageable[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/PayloadModel.java b/app/src/main/java/com/fastaccess/data/dao/PayloadModel.java deleted file mode 100644 index e430ebe45..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/PayloadModel.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.Release; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.data.dao.model.User; - -import java.util.List; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - - -/** - * Created by Kosh on 08 Feb 2017, 10:03 PM - */ - - -@Getter @Setter @NoArgsConstructor -public class PayloadModel implements Parcelable { - - public String action; - public Repo forkee; - public Issue issue; - public PullRequest pullRequest; - public String refType; - public Comment comment; - public User target; - public User member; - public TeamsModel team; - public Comment commitComment; - public String description; - public ReleasesAssetsModel download; - public Gist gist; - public List pages; - public String before; - public String head; - public String ref; - public int size; - public List commits; - public User user; - public Release release; - public User blockedUser; - public User organization; - public User invitation; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.action); - dest.writeParcelable(this.forkee, flags); - dest.writeParcelable(this.issue, flags); - dest.writeParcelable(this.pullRequest, flags); - dest.writeString(this.refType); - dest.writeParcelable(this.comment, flags); - dest.writeParcelable(this.target, flags); - dest.writeParcelable(this.member, flags); - dest.writeParcelable(this.team, flags); - dest.writeParcelable(this.commitComment, flags); - dest.writeString(this.description); - dest.writeParcelable(this.download, flags); - dest.writeParcelable(this.gist, flags); - dest.writeTypedList(this.pages); - dest.writeString(this.before); - dest.writeString(this.head); - dest.writeString(this.ref); - dest.writeInt(this.size); - dest.writeTypedList(this.commits); - dest.writeParcelable(this.user, flags); - dest.writeParcelable(this.release, flags); - dest.writeParcelable(this.blockedUser, flags); - dest.writeParcelable(this.organization, flags); - dest.writeParcelable(this.invitation, flags); - } - - protected PayloadModel(Parcel in) { - this.action = in.readString(); - this.forkee = in.readParcelable(Repo.class.getClassLoader()); - this.issue = in.readParcelable(Issue.class.getClassLoader()); - this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader()); - this.refType = in.readString(); - this.comment = in.readParcelable(Comment.class.getClassLoader()); - this.target = in.readParcelable(User.class.getClassLoader()); - this.member = in.readParcelable(User.class.getClassLoader()); - this.team = in.readParcelable(TeamsModel.class.getClassLoader()); - this.commitComment = in.readParcelable(Comment.class.getClassLoader()); - this.description = in.readString(); - this.download = in.readParcelable(ReleasesAssetsModel.class.getClassLoader()); - this.gist = in.readParcelable(Gist.class.getClassLoader()); - this.pages = in.createTypedArrayList(WikiModel.CREATOR); - this.before = in.readString(); - this.head = in.readString(); - this.ref = in.readString(); - this.size = in.readInt(); - this.commits = in.createTypedArrayList(GitCommitModel.CREATOR); - this.user = in.readParcelable(User.class.getClassLoader()); - this.release = in.readParcelable(Release.class.getClassLoader()); - this.blockedUser = in.readParcelable(User.class.getClassLoader()); - this.organization = in.readParcelable(User.class.getClassLoader()); - this.invitation = in.readParcelable(User.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public PayloadModel createFromParcel(Parcel source) {return new PayloadModel(source);} - - @Override public PayloadModel[] newArray(int size) {return new PayloadModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/PostReactionModel.java b/app/src/main/java/com/fastaccess/data/dao/PostReactionModel.java deleted file mode 100644 index 46f428e80..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/PostReactionModel.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 29 Mar 2017, 9:50 PM - */ - -@Getter @Setter @NoArgsConstructor @AllArgsConstructor public class PostReactionModel implements Parcelable { - - private String content; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) {dest.writeString(this.content);} - - private PostReactionModel(Parcel in) {this.content = in.readString();} - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public PostReactionModel createFromParcel(Parcel source) {return new PostReactionModel(source);} - - @Override public PostReactionModel[] newArray(int size) {return new PostReactionModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/ProUsersModel.java b/app/src/main/java/com/fastaccess/data/dao/ProUsersModel.java deleted file mode 100644 index f39a58c1c..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/ProUsersModel.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Created by Hashemsergani on 03.10.17. - */ - -public class ProUsersModel implements Parcelable { - private int count; - private boolean allowed; - private int type; - private boolean isBlocked; - - public int getCount() { return count;} - - public void setCount(int count) { this.count = count;} - - public boolean isAllowed() { return allowed;} - - public void setAllowed(boolean allowed) { this.allowed = allowed;} - - public int getType() { return type;} - - public void setType(int type) { this.type = type;} - - public boolean isBlocked() { - return isBlocked; - } - - public void setBlocked(boolean blocked) { - isBlocked = blocked; - } - - @Override public String toString() { - return "ProUsersModel{" + - ", count=" + count + - ", allowed=" + allowed + - ", type=" + type + - '}'; - } - - public ProUsersModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.count); - dest.writeByte(this.allowed ? (byte) 1 : (byte) 0); - dest.writeInt(this.type); - dest.writeByte(this.isBlocked ? (byte) 1 : (byte) 0); - } - - protected ProUsersModel(Parcel in) { - this.count = in.readInt(); - this.allowed = in.readByte() != 0; - this.type = in.readInt(); - this.isBlocked = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override public ProUsersModel createFromParcel(Parcel source) {return new ProUsersModel(source);} - - @Override public ProUsersModel[] newArray(int size) {return new ProUsersModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/ProjectCardModel.java b/app/src/main/java/com/fastaccess/data/dao/ProjectCardModel.java deleted file mode 100644 index 0a5ec2fdc..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/ProjectCardModel.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.User; - -import java.util.Date; - -/** - * Created by Hashemsergani on 11.09.17. - */ - -public class ProjectCardModel implements Parcelable { - private String url; - private String columnUrl; - private String contentUrl; - private Integer id; - private String note; - private User creator; - private Date createdAt; - private Date updatedAt; - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getColumnUrl() { - return columnUrl; - } - - public void setColumnUrl(String columnUrl) { - this.columnUrl = columnUrl; - } - - public String getContentUrl() { - return contentUrl; - } - - public void setContentUrl(String contentUrl) { - this.contentUrl = contentUrl; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getNote() { - return note; - } - - public void setNote(String note) { - this.note = note; - } - - public User getCreator() { - return creator; - } - - public void setCreator(User creator) { - this.creator = creator; - } - - public Date getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(Date createdAt) { - this.createdAt = createdAt; - } - - public Date getUpdatedAt() { - return updatedAt; - } - - public void setUpdatedAt(Date updatedAt) { - this.updatedAt = updatedAt; - } - - public ProjectCardModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.url); - dest.writeString(this.columnUrl); - dest.writeString(this.contentUrl); - dest.writeValue(this.id); - dest.writeString(this.note); - dest.writeParcelable(this.creator, flags); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - } - - protected ProjectCardModel(Parcel in) { - this.url = in.readString(); - this.columnUrl = in.readString(); - this.contentUrl = in.readString(); - this.id = (Integer) in.readValue(Integer.class.getClassLoader()); - this.note = in.readString(); - this.creator = in.readParcelable(User.class.getClassLoader()); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - } - - public static final Creator CREATOR = new Creator() { - @Override public ProjectCardModel createFromParcel(Parcel source) {return new ProjectCardModel(source);} - - @Override public ProjectCardModel[] newArray(int size) {return new ProjectCardModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/ProjectColumnModel.java b/app/src/main/java/com/fastaccess/data/dao/ProjectColumnModel.java deleted file mode 100644 index c7f3515b3..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/ProjectColumnModel.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Date; - -/** - * Created by Hashemsergani on 11.09.17. - */ - -public class ProjectColumnModel implements Parcelable { - - private Long id; - private String name; - private String url; - private String projectUrl; - private String cardsUrl; - private Date createdAt; - private Date updatedAt; - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getProjectUrl() { - return projectUrl; - } - - public void setProjectUrl(String projectUrl) { - this.projectUrl = projectUrl; - } - - public String getCardsUrl() { - return cardsUrl; - } - - public void setCardsUrl(String cardsUrl) { - this.cardsUrl = cardsUrl; - } - - public Date getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(Date createdAt) { - this.createdAt = createdAt; - } - - public Date getUpdatedAt() { - return updatedAt; - } - - public void setUpdatedAt(Date updatedAt) { - this.updatedAt = updatedAt; - } - - public ProjectColumnModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeValue(this.id); - dest.writeString(this.name); - dest.writeString(this.url); - dest.writeString(this.projectUrl); - dest.writeString(this.cardsUrl); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - } - - protected ProjectColumnModel(Parcel in) { - this.id = (Long) in.readValue(Long.class.getClassLoader()); - this.name = in.readString(); - this.url = in.readString(); - this.projectUrl = in.readString(); - this.cardsUrl = in.readString(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - } - - public static final Creator CREATOR = new Creator() { - @Override public ProjectColumnModel createFromParcel(Parcel source) {return new ProjectColumnModel(source);} - - @Override public ProjectColumnModel[] newArray(int size) {return new ProjectColumnModel[size];} - }; - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ProjectColumnModel that = (ProjectColumnModel) o; - - return id != null ? id.equals(that.id) : that.id == null; - } - - @Override public int hashCode() { - return id != null ? id.hashCode() : 0; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/ProjectsModel.java b/app/src/main/java/com/fastaccess/data/dao/ProjectsModel.java deleted file mode 100644 index 92244fb61..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/ProjectsModel.java +++ /dev/null @@ -1,165 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.User; - -import java.util.Date; - -/** - * Created by kosh on 09/09/2017. - */ - -public class ProjectsModel implements Parcelable { - private String ownerUrl; - private String url; - private String htmlUrl; - private String columnsUrl; - private long id; - private String name; - private String body; - private int number; - private String state; - private User creator; - private Date createdAt; - private Date updatedAt; - - public String getOwnerUrl() { - return ownerUrl; - } - - public void setOwnerUrl(String ownerUrl) { - this.ownerUrl = ownerUrl; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getHtmlUrl() { - return htmlUrl; - } - - public void setHtmlUrl(String htmlUrl) { - this.htmlUrl = htmlUrl; - } - - public String getColumnsUrl() { - return columnsUrl; - } - - public void setColumnsUrl(String columnsUrl) { - this.columnsUrl = columnsUrl; - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getBody() { - return body; - } - - public void setBody(String body) { - this.body = body; - } - - public int getNumber() { - return number; - } - - public void setNumber(int number) { - this.number = number; - } - - public String getState() { - return state; - } - - public void setState(String state) { - this.state = state; - } - - public User getCreator() { - return creator; - } - - public void setCreator(User creator) { - this.creator = creator; - } - - public Date getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(Date createdAt) { - this.createdAt = createdAt; - } - - public Date getUpdatedAt() { - return updatedAt; - } - - public void setUpdatedAt(Date updatedAt) { - this.updatedAt = updatedAt; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.ownerUrl); - dest.writeString(this.url); - dest.writeString(this.htmlUrl); - dest.writeString(this.columnsUrl); - dest.writeLong(this.id); - dest.writeString(this.name); - dest.writeString(this.body); - dest.writeInt(this.number); - dest.writeString(this.state); - dest.writeParcelable(this.creator, flags); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - } - - public ProjectsModel() {} - - protected ProjectsModel(Parcel in) { - this.ownerUrl = in.readString(); - this.url = in.readString(); - this.htmlUrl = in.readString(); - this.columnsUrl = in.readString(); - this.id = in.readLong(); - this.name = in.readString(); - this.body = in.readString(); - this.number = in.readInt(); - this.state = in.readString(); - this.creator = in.readParcelable(User.class.getClassLoader()); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - } - - public static final Creator CREATOR = new Creator() { - @Override public ProjectsModel createFromParcel(Parcel source) {return new ProjectsModel(source);} - - @Override public ProjectsModel[] newArray(int size) {return new ProjectsModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/PullRequestAdapterModel.java b/app/src/main/java/com/fastaccess/data/dao/PullRequestAdapterModel.java deleted file mode 100644 index 92d2451fe..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/PullRequestAdapterModel.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.Nullable; - -import com.annimon.stream.Stream; -import com.fastaccess.data.dao.model.IssueEvent; -import com.fastaccess.data.dao.model.PullRequest; - -import java.util.ArrayList; -import java.util.List; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 10 Dec 2016, 3:34 PM - */ - -@Getter @Setter -public class PullRequestAdapterModel implements Parcelable { - - public static final int HEADER = 1; - public static final int ROW = 2; - private int type; - - private IssueEvent issueEvent; - private PullRequest pullRequest; - - private PullRequestAdapterModel(int type, IssueEvent model) { - this.type = type; - this.issueEvent = model; - } - - public PullRequestAdapterModel(int type, PullRequest pullRequest) { - this.type = type; - this.pullRequest = pullRequest; - } - - public static ArrayList addEvents(@Nullable List modelList) { - ArrayList models = new ArrayList<>(); - if (modelList == null || modelList.isEmpty()) return models; - Stream.of(modelList).forEach(issueEventModel -> models.add(new PullRequestAdapterModel(ROW, issueEventModel))); - return models; - } - - public PullRequestAdapterModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.type); - dest.writeParcelable(this.issueEvent, flags); - dest.writeParcelable(this.pullRequest, flags); - } - - private PullRequestAdapterModel(Parcel in) { - this.type = in.readInt(); - this.issueEvent = in.readParcelable(IssueEvent.class.getClassLoader()); - this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public PullRequestAdapterModel createFromParcel(Parcel source) {return new PullRequestAdapterModel(source);} - - @Override public PullRequestAdapterModel[] newArray(int size) {return new PullRequestAdapterModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/PullRequestStatusModel.java b/app/src/main/java/com/fastaccess/data/dao/PullRequestStatusModel.java deleted file mode 100644 index f292280ae..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/PullRequestStatusModel.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.types.StatusStateType; - -import java.util.Date; -import java.util.List; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 10 Apr 2017, 3:15 AM - */ - -@Getter @Setter public class PullRequestStatusModel implements Parcelable { - - private StatusStateType state; - private String sha; - private int totalCount; - private List statuses; - private String commitUrl; - private String url; - private boolean mergable; - private Date createdAt; - private String mergeableState; - - public PullRequestStatusModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.state == null ? -1 : this.state.ordinal()); - dest.writeString(this.sha); - dest.writeInt(this.totalCount); - dest.writeTypedList(this.statuses); - dest.writeString(this.commitUrl); - dest.writeString(this.url); - dest.writeByte(this.mergable ? (byte) 1 : (byte) 0); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeString(this.mergeableState); - } - - protected PullRequestStatusModel(Parcel in) { - int tmpState = in.readInt(); - this.state = tmpState == -1 ? null : StatusStateType.values()[tmpState]; - this.sha = in.readString(); - this.totalCount = in.readInt(); - this.statuses = in.createTypedArrayList(StatusesModel.CREATOR); - this.commitUrl = in.readString(); - this.url = in.readString(); - this.mergable = in.readByte() != 0; - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - this.mergeableState = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public PullRequestStatusModel createFromParcel(Parcel source) {return new PullRequestStatusModel(source);} - - @Override public PullRequestStatusModel[] newArray(int size) {return new PullRequestStatusModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/PullsIssuesParser.java b/app/src/main/java/com/fastaccess/data/dao/PullsIssuesParser.java deleted file mode 100644 index 59333a99b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/PullsIssuesParser.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.fastaccess.data.dao; - -import android.net.Uri; -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.fastaccess.helper.InputHelper; - -import java.util.List; - -/** - * Created by Kosh on 17 Dec 2016, 12:17 AM - */ - -public class PullsIssuesParser implements Parcelable { - - private String login; - private String repoId; - private int number; - - public static PullsIssuesParser getForPullRequest(@NonNull String url) { - Uri uri = Uri.parse(url); - List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 3) return null; - String owner = null; - String repo = null; - String number = null; - if (segments.size() > 3) { - if (("pull".equals(segments.get(2)) || "pulls".equals(segments.get(2)))) { - owner = segments.get(0); - repo = segments.get(1); - number = segments.get(3); - } else if (("pull".equals(segments.get(3)) || "pulls".equals(segments.get(3))) && segments.size() > 4) { - owner = segments.get(1); - repo = segments.get(2); - number = segments.get(4); - } else { - return null; - } - } - if (InputHelper.isEmpty(number)) return null; - int issueNumber; - try { - issueNumber = Integer.parseInt(number); - } catch (NumberFormatException nfe) { - return null; - } - if (issueNumber < 1) return null; - PullsIssuesParser model = new PullsIssuesParser(); - model.setLogin(owner); - model.setRepoId(repo); - model.setNumber(issueNumber); - return model; - } - - public static PullsIssuesParser getForIssue(@NonNull String url) { - Uri uri = Uri.parse(url); - List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 3) return null; - String owner = null; - String repo = null; - String number = null; - if (segments.size() > 3) { - if (segments.get(2).equalsIgnoreCase("issues")) { - owner = segments.get(0); - repo = segments.get(1); - number = segments.get(3); - } else if (segments.get(3).equalsIgnoreCase("issues") && segments.size() > 4) { - owner = segments.get(1); - repo = segments.get(2); - number = segments.get(4); - } else { - return null; - } - } - if (InputHelper.isEmpty(number)) - return null; - int issueNumber; - try { - issueNumber = Integer.parseInt(number); - } catch (NumberFormatException nfe) { - return null; - } - if (issueNumber < 1) return null; - PullsIssuesParser model = new PullsIssuesParser(); - model.setLogin(owner); - model.setRepoId(repo); - model.setNumber(issueNumber); - return model; - } - - @Override public String toString() { - return "PullsIssuesParser{" + - "login='" + login + '\'' + - ", repoId='" + repoId + '\'' + - ", number=" + number + - '}'; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.login); - dest.writeString(this.repoId); - dest.writeInt(this.number); - } - - public String getLogin() { - return login; - } - - public void setLogin(String login) { - this.login = login; - } - - public String getRepoId() { - return repoId; - } - - public void setRepoId(String repoId) { - this.repoId = repoId; - } - - public int getNumber() { - return number; - } - - public void setNumber(int number) { - this.number = number; - } - - public PullsIssuesParser() {} - - protected PullsIssuesParser(Parcel in) { - this.login = in.readString(); - this.repoId = in.readString(); - this.number = in.readInt(); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public PullsIssuesParser createFromParcel(Parcel source) {return new PullsIssuesParser(source);} - - @Override public PullsIssuesParser[] newArray(int size) {return new PullsIssuesParser[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/ReactionsModel.java b/app/src/main/java/com/fastaccess/data/dao/ReactionsModel.java deleted file mode 100644 index ee84a9074..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/ReactionsModel.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.User; -import com.google.gson.annotations.SerializedName; - -import java.util.ArrayList; -import java.util.List; - -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; -import github.PullRequestTimelineQuery; - -/** - * Created by Kosh on 28 Mar 2017, 9:15 PM - */ - -@Getter @Setter public class ReactionsModel implements Parcelable { - - public long id; - public String url; - public int total_count; - @SerializedName("+1") public int plusOne; - @SerializedName("-1") public int minusOne; - public int laugh; - public int hooray; - public int confused; - public int heart; - public String content; - public User user; - public boolean viewerHasReacted; - public boolean isCallingApi; - - public ReactionsModel() {} - - @Override public String toString() { - return "ReactionsModel{" + - "id=" + id + - ", url='" + url + '\'' + - ", total_count=" + total_count + - ", plusOne=" + plusOne + - ", minusOne=" + minusOne + - ", laugh=" + laugh + - ", hooray=" + hooray + - ", confused=" + confused + - ", heart=" + heart + - '}'; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.url); - dest.writeInt(this.total_count); - dest.writeInt(this.plusOne); - dest.writeInt(this.minusOne); - dest.writeInt(this.laugh); - dest.writeInt(this.hooray); - dest.writeInt(this.confused); - dest.writeInt(this.heart); - dest.writeString(this.content); - dest.writeParcelable(this.user, flags); - dest.writeByte(this.isCallingApi ? (byte) 1 : (byte) 0); - } - - protected ReactionsModel(Parcel in) { - this.id = in.readLong(); - this.url = in.readString(); - this.total_count = in.readInt(); - this.plusOne = in.readInt(); - this.minusOne = in.readInt(); - this.laugh = in.readInt(); - this.hooray = in.readInt(); - this.confused = in.readInt(); - this.heart = in.readInt(); - this.content = in.readString(); - this.user = in.readParcelable(User.class.getClassLoader()); - this.isCallingApi = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override public ReactionsModel createFromParcel(Parcel source) {return new ReactionsModel(source);} - - @Override public ReactionsModel[] newArray(int size) {return new ReactionsModel[size];} - }; - - @NonNull public static List getReactionGroup(@Nullable List reactions) { - List models = new ArrayList<>(); - if (reactions != null && !reactions.isEmpty()) { - for (PullRequestTimelineQuery.ReactionGroup reaction : reactions) { - ReactionsModel model = new ReactionsModel(); - model.setContent(reaction.content().name()); - model.setViewerHasReacted(reaction.viewerHasReacted()); - model.setTotal_count(reaction.users().totalCount()); - models.add(model); - } - } - return models; - } - - @NonNull public static List getReaction(@Nullable List reactions) { - List models = new ArrayList<>(); - if (reactions != null && !reactions.isEmpty()) { - for (PullRequestTimelineQuery.ReactionGroup1 reaction : reactions) { - ReactionsModel model = new ReactionsModel(); - model.setContent(reaction.content().name()); - model.setViewerHasReacted(reaction.viewerHasReacted()); - model.setTotal_count(reaction.users().totalCount()); - models.add(model); - } - } - return models; - } - - @NonNull public static List getReaction2(@Nullable List reactions) { - List models = new ArrayList<>(); - if (reactions != null && !reactions.isEmpty()) { - for (PullRequestTimelineQuery.ReactionGroup2 reaction : reactions) { - ReactionsModel model = new ReactionsModel(); - model.setContent(reaction.content().name()); - model.setViewerHasReacted(reaction.viewerHasReacted()); - model.setTotal_count(reaction.users().totalCount()); - models.add(model); - } - } - return models; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/ReleasesAssetsListModel.java b/app/src/main/java/com/fastaccess/data/dao/ReleasesAssetsListModel.java deleted file mode 100644 index 439b1d0f7..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/ReleasesAssetsListModel.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.data.dao; - -import java.util.ArrayList; - -/** - * Created by Kosh on 31 Dec 2016, 1:28 PM - */ - -public class ReleasesAssetsListModel extends ArrayList {} diff --git a/app/src/main/java/com/fastaccess/data/dao/ReleasesAssetsModel.java b/app/src/main/java/com/fastaccess/data/dao/ReleasesAssetsModel.java deleted file mode 100644 index 51beeabf8..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/ReleasesAssetsModel.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.User; - -import java.util.Date; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 31 Dec 2016, 1:28 PM - */ - -@Getter @Setter public class ReleasesAssetsModel implements Parcelable { - private String url; - private String browserDownloadUrl; - private long id; - private String name; - private String label; - private String state; - private String contentType; - private int size; - private int downloadCount; - private Date createdAt; - private Date updatedAt; - private User uploader; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.url); - dest.writeString(this.browserDownloadUrl); - dest.writeLong(this.id); - dest.writeString(this.name); - dest.writeString(this.label); - dest.writeString(this.state); - dest.writeString(this.contentType); - dest.writeInt(this.size); - dest.writeInt(this.downloadCount); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeParcelable(this.uploader, flags); - } - - public ReleasesAssetsModel() {} - - @SuppressWarnings("WeakerAccess") protected ReleasesAssetsModel(Parcel in) { - this.url = in.readString(); - this.browserDownloadUrl = in.readString(); - this.id = in.readLong(); - this.name = in.readString(); - this.label = in.readString(); - this.state = in.readString(); - this.contentType = in.readString(); - this.size = in.readInt(); - this.downloadCount = in.readInt(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - this.uploader = in.readParcelable(User.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public ReleasesAssetsModel createFromParcel(Parcel source) {return new ReleasesAssetsModel(source);} - - @Override public ReleasesAssetsModel[] newArray(int size) {return new ReleasesAssetsModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/RenameModel.java b/app/src/main/java/com/fastaccess/data/dao/RenameModel.java deleted file mode 100644 index 4ef99e22a..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/RenameModel.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.google.gson.annotations.SerializedName; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 13 Dec 2016, 12:33 AM - */ - -@Getter @Setter @NoArgsConstructor -public class RenameModel implements Parcelable { - @SerializedName("from") String fromValue; - @SerializedName("to") String toValue; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.fromValue); - dest.writeString(this.toValue); - } - - protected RenameModel(Parcel in) { - this.fromValue = in.readString(); - this.toValue = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public RenameModel createFromParcel(Parcel source) {return new RenameModel(source);} - - @Override public RenameModel[] newArray(int size) {return new RenameModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/RepoPathsManager.java b/app/src/main/java/com/fastaccess/data/dao/RepoPathsManager.java deleted file mode 100644 index 2e1bbd0a4..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/RepoPathsManager.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.fastaccess.data.dao; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.RepoFile; - -import java.util.HashMap; -import java.util.List; - -import lombok.NoArgsConstructor; - -/** - * Created by Kosh on 03 Mar 2017, 10:43 PM - */ - -@NoArgsConstructor -public class RepoPathsManager { - private HashMap> files = new HashMap<>(); - - @Nullable public List getPaths(@NonNull String url, @NonNull String ref) { - return files.get(ref + "/" + url); - } - - public void setFiles(@NonNull String ref, @NonNull String path, @NonNull List paths) { - files.put(ref + "/" + path, paths); - } - - public void clear() { - files.clear(); - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/RepoPermissionsModel.java b/app/src/main/java/com/fastaccess/data/dao/RepoPermissionsModel.java deleted file mode 100644 index 1ae4679d8..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/RepoPermissionsModel.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 03 Dec 2016, 11:12 AM - */ - -@Getter @Setter @NoArgsConstructor -public class RepoPermissionsModel implements Parcelable { - - boolean admin; - boolean push; - boolean pull; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeByte(this.admin ? (byte) 1 : (byte) 0); - dest.writeByte(this.push ? (byte) 1 : (byte) 0); - dest.writeByte(this.pull ? (byte) 1 : (byte) 0); - } - - protected RepoPermissionsModel(Parcel in) { - this.admin = in.readByte() != 0; - this.push = in.readByte() != 0; - this.pull = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override public RepoPermissionsModel createFromParcel(Parcel source) {return new RepoPermissionsModel(source);} - - @Override public RepoPermissionsModel[] newArray(int size) {return new RepoPermissionsModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/RepoSubscriptionModel.java b/app/src/main/java/com/fastaccess/data/dao/RepoSubscriptionModel.java deleted file mode 100644 index 4774d1c86..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/RepoSubscriptionModel.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.fastaccess.data.dao; - -import java.util.Date; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 14 Mar 2017, 9:10 PM - */ - -@Getter @Setter @NoArgsConstructor -public class RepoSubscriptionModel { - private boolean subscribed; - private boolean ignored; - private Date createdAt; - private String url; - private String repositoryUrl; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/ReviewCommentModel.java b/app/src/main/java/com/fastaccess/data/dao/ReviewCommentModel.java deleted file mode 100644 index eaf66c5db..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/ReviewCommentModel.java +++ /dev/null @@ -1,245 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.User; - -import java.util.Date; - -/** - * Created by Kosh on 04 May 2017, 7:10 PM - */ - - public class ReviewCommentModel implements Parcelable { - - private long id; - private String url; - private long pullRequestReviewId; - private String diffHunk; - private String path; - private int position; - private int originalPosition; - private String commitId; - private String originalCommitId; - private User user; - private String bodyHtml; - private String body; - private Date createdAt; - private Date updatedAt; - private String htmlUrl; - private String pullRequestUrl; - private ReactionsModel reactions; - private String authorAssociation; - - public ReviewCommentModel() {} - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public long getPullRequestReviewId() { - return pullRequestReviewId; - } - - public void setPullRequestReviewId(long pullRequestReviewId) { - this.pullRequestReviewId = pullRequestReviewId; - } - - public String getDiffHunk() { - return diffHunk; - } - - public void setDiffHunk(String diffHunk) { - this.diffHunk = diffHunk; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public int getPosition() { - return position; - } - - public void setPosition(int position) { - this.position = position; - } - - public int getOriginalPosition() { - return originalPosition; - } - - public void setOriginalPosition(int originalPosition) { - this.originalPosition = originalPosition; - } - - public String getCommitId() { - return commitId; - } - - public void setCommitId(String commitId) { - this.commitId = commitId; - } - - public String getOriginalCommitId() { - return originalCommitId; - } - - public void setOriginalCommitId(String originalCommitId) { - this.originalCommitId = originalCommitId; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public String getBodyHtml() { - return bodyHtml; - } - - public void setBodyHtml(String bodyHtml) { - this.bodyHtml = bodyHtml; - } - - public String getBody() { - return body; - } - - public void setBody(String body) { - this.body = body; - } - - public Date getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(Date createdAt) { - this.createdAt = createdAt; - } - - public Date getUpdatedAt() { - return updatedAt; - } - - public void setUpdatedAt(Date updatedAt) { - this.updatedAt = updatedAt; - } - - public String getHtmlUrl() { - return htmlUrl; - } - - public void setHtmlUrl(String htmlUrl) { - this.htmlUrl = htmlUrl; - } - - public String getPullRequestUrl() { - return pullRequestUrl; - } - - public void setPullRequestUrl(String pullRequestUrl) { - this.pullRequestUrl = pullRequestUrl; - } - - public ReactionsModel getReactions() { - return reactions; - } - - public void setReactions(ReactionsModel reactions) { - this.reactions = reactions; - } - - public String getAuthorAssociation() { - return authorAssociation; - } - - public void setAuthorAssociation(String authorAssociation) { - this.authorAssociation = authorAssociation; - } - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ReviewCommentModel that = (ReviewCommentModel) o; - - return id == that.id; - } - - @Override public int hashCode() { - return (int) (id ^ (id >>> 32)); - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.url); - dest.writeLong(this.pullRequestReviewId); - dest.writeString(this.diffHunk); - dest.writeString(this.path); - dest.writeInt(this.position); - dest.writeInt(this.originalPosition); - dest.writeString(this.commitId); - dest.writeString(this.originalCommitId); - dest.writeParcelable(this.user, flags); - dest.writeString(this.bodyHtml); - dest.writeString(this.body); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeString(this.htmlUrl); - dest.writeString(this.pullRequestUrl); - dest.writeParcelable(this.reactions, flags); - dest.writeString(this.authorAssociation); - } - - protected ReviewCommentModel(Parcel in) { - this.id = in.readLong(); - this.url = in.readString(); - this.pullRequestReviewId = in.readLong(); - this.diffHunk = in.readString(); - this.path = in.readString(); - this.position = in.readInt(); - this.originalPosition = in.readInt(); - this.commitId = in.readString(); - this.originalCommitId = in.readString(); - this.user = in.readParcelable(User.class.getClassLoader()); - this.bodyHtml = in.readString(); - this.body = in.readString(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - this.htmlUrl = in.readString(); - this.pullRequestUrl = in.readString(); - this.reactions = in.readParcelable(ReactionsModel.class.getClassLoader()); - this.authorAssociation = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public ReviewCommentModel createFromParcel(Parcel source) {return new ReviewCommentModel(source);} - - @Override public ReviewCommentModel[] newArray(int size) {return new ReviewCommentModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/ReviewModel.java b/app/src/main/java/com/fastaccess/data/dao/ReviewModel.java deleted file mode 100644 index 9e6d94216..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/ReviewModel.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.User; - -import java.util.Date; -import java.util.List; - -/** - * Created by Kosh on 10 Apr 2017, 4:26 PM - */ - -public class ReviewModel implements Parcelable { - - private long id; - private User user; - private String bodyHtml; - private String state; - private Date submittedAt; - private String commitId; - private String diffText; - private List comments; - private ReactionsModel reactions; - private String bodyText; - - public ReviewModel() {} - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ReviewModel that = (ReviewModel) o; - return id == that.id; - } - - @Override public int hashCode() { - return (int) (id ^ (id >>> 32)); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeParcelable(this.user, flags); - dest.writeString(this.bodyHtml); - dest.writeString(this.state); - dest.writeLong(this.submittedAt != null ? this.submittedAt.getTime() : -1); - dest.writeString(this.commitId); - dest.writeString(this.diffText); - dest.writeTypedList(this.comments); - dest.writeParcelable(this.reactions, flags); - dest.writeString(this.bodyText); - } - - protected ReviewModel(Parcel in) { - this.id = in.readLong(); - this.user = in.readParcelable(User.class.getClassLoader()); - this.bodyHtml = in.readString(); - this.state = in.readString(); - long tmpSubmittedAt = in.readLong(); - this.submittedAt = tmpSubmittedAt == -1 ? null : new Date(tmpSubmittedAt); - this.commitId = in.readString(); - this.diffText = in.readString(); - this.comments = in.createTypedArrayList(ReviewCommentModel.CREATOR); - this.reactions = in.readParcelable(ReactionsModel.class.getClassLoader()); - this.bodyText = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public ReviewModel createFromParcel(Parcel source) {return new ReviewModel(source);} - - @Override public ReviewModel[] newArray(int size) {return new ReviewModel[size];} - }; - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public String getBodyHtml() { - return bodyHtml; - } - - public void setBodyHtml(String bodyHtml) { - this.bodyHtml = bodyHtml; - } - - public String getState() { - return state; - } - - public void setState(String state) { - this.state = state; - } - - public Date getSubmittedAt() { - return submittedAt; - } - - public void setSubmittedAt(Date submittedAt) { - this.submittedAt = submittedAt; - } - - public String getCommitId() { - return commitId; - } - - public void setCommitId(String commitId) { - this.commitId = commitId; - } - - public String getDiffText() { - return diffText; - } - - public void setDiffText(String diffText) { - this.diffText = diffText; - } - - public List getComments() { - return comments; - } - - public void setComments(List comments) { - this.comments = comments; - } - - public ReactionsModel getReactions() { - return reactions; - } - - public void setReactions(ReactionsModel reactions) { - this.reactions = reactions; - } - - public String getBodyText() { - return bodyText; - } - - public void setBodyText(String bodyText) { - this.bodyText = bodyText; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/ReviewRequestModel.java b/app/src/main/java/com/fastaccess/data/dao/ReviewRequestModel.java deleted file mode 100644 index df40f83cb..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/ReviewRequestModel.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.List; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 24 Jun 2017, 4:15 PM - */ - -@Getter @Setter public class ReviewRequestModel implements Parcelable { - public String commitId; - public String body; - public String event; - public List comments; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.commitId); - dest.writeString(this.body); - dest.writeString(this.event); - dest.writeTypedList(this.comments); - } - - private ReviewRequestModel(Parcel in) { - this.commitId = in.readString(); - this.body = in.readString(); - this.event = in.readString(); - this.comments = in.createTypedArrayList(CommentRequestModel.CREATOR); - } - - public ReviewRequestModel() { - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public ReviewRequestModel createFromParcel(Parcel source) {return new ReviewRequestModel(source);} - - @Override public ReviewRequestModel[] newArray(int size) {return new ReviewRequestModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/SearchCodeModel.java b/app/src/main/java/com/fastaccess/data/dao/SearchCodeModel.java deleted file mode 100644 index f6e872219..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/SearchCodeModel.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.Repo; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 19 Feb 2017, 1:17 AM - */ - -@Getter @Setter -public class SearchCodeModel implements Parcelable { - private String name; - private String path; - private String sha; - private String url; - private String gitUrl; - private Repo repository; - private double score; - private String htmlUrl; - - - public SearchCodeModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.name); - dest.writeString(this.path); - dest.writeString(this.sha); - dest.writeString(this.url); - dest.writeString(this.gitUrl); - dest.writeParcelable(this.repository, flags); - dest.writeDouble(this.score); - } - - protected SearchCodeModel(Parcel in) { - this.name = in.readString(); - this.path = in.readString(); - this.sha = in.readString(); - this.url = in.readString(); - this.gitUrl = in.readString(); - this.repository = in.readParcelable(Repo.class.getClassLoader()); - this.score = in.readDouble(); - } - - public static final Creator CREATOR = new Creator() { - @Override public SearchCodeModel createFromParcel(Parcel source) {return new SearchCodeModel(source);} - - @Override public SearchCodeModel[] newArray(int size) {return new SearchCodeModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/SettingsModel.java b/app/src/main/java/com/fastaccess/data/dao/SettingsModel.java deleted file mode 100644 index f95ea515a..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/SettingsModel.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.fastaccess.data.dao; - -import android.support.annotation.IntDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -/** - * Created by JediB on 5/12/2017. - */ - -@Getter @Setter @AllArgsConstructor public class SettingsModel { - - - public static final int THEME = 0; - public static final int NOTIFICATION = 1; - public static final int BEHAVIOR = 2; - public static final int CUSTOMIZATION = 3; - public static final int BACKUP = 4; - public static final int LANGUAGE = 5; - public static final int CODE_THEME = 6; - - @IntDef({ - THEME, - NOTIFICATION, - CUSTOMIZATION, - BEHAVIOR, - BACKUP, - LANGUAGE, - CODE_THEME - }) - @Retention(RetentionPolicy.SOURCE) public @interface SettingsType {} - - private int image; - private String title; - @SettingsType private int settingsType; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/SimpleUrlsModel.java b/app/src/main/java/com/fastaccess/data/dao/SimpleUrlsModel.java deleted file mode 100644 index ddff012b5..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/SimpleUrlsModel.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 31 Dec 2016, 3:32 PM - */ - - -@Getter @Setter -public class SimpleUrlsModel implements Parcelable { - - public String item; - public String url; - - public SimpleUrlsModel(String item, String url) { - this.item = item; - this.url = url; - } - - @Override public String toString() { - return item; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.item); - dest.writeString(this.url); - } - - @SuppressWarnings("WeakerAccess") protected SimpleUrlsModel(Parcel in) { - this.item = in.readString(); - this.url = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public SimpleUrlsModel createFromParcel(Parcel source) {return new SimpleUrlsModel(source);} - - @Override public SimpleUrlsModel[] newArray(int size) {return new SimpleUrlsModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/SlackInvitePostModel.java b/app/src/main/java/com/fastaccess/data/dao/SlackInvitePostModel.java deleted file mode 100644 index ee147436a..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/SlackInvitePostModel.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 01 May 2017, 1:06 AM - */ - -@Getter @Setter public class SlackInvitePostModel implements Parcelable { - private String email; - private String first_name; - private String last_name; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.email); - dest.writeString(this.first_name); - dest.writeString(this.last_name); - } - - public SlackInvitePostModel() {} - - private SlackInvitePostModel(Parcel in) { - this.email = in.readString(); - this.first_name = in.readString(); - this.last_name = in.readString(); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public SlackInvitePostModel createFromParcel(Parcel source) {return new SlackInvitePostModel(source);} - - @Override public SlackInvitePostModel[] newArray(int size) {return new SlackInvitePostModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/SlackResponseModel.java b/app/src/main/java/com/fastaccess/data/dao/SlackResponseModel.java deleted file mode 100644 index d30da669e..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/SlackResponseModel.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 01 May 2017, 1:05 AM - */ - -@Getter @Setter public class SlackResponseModel implements Parcelable { - private boolean ok; - private String error; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeByte(this.ok ? (byte) 1 : (byte) 0); - dest.writeString(this.error); - } - - public SlackResponseModel() {} - - private SlackResponseModel(Parcel in) { - this.ok = in.readByte() != 0; - this.error = in.readString(); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public SlackResponseModel createFromParcel(Parcel source) {return new SlackResponseModel(source);} - - @Override public SlackResponseModel[] newArray(int size) {return new SlackResponseModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/SparseBooleanArrayParcelable.java b/app/src/main/java/com/fastaccess/data/dao/SparseBooleanArrayParcelable.java deleted file mode 100644 index 912eb792b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/SparseBooleanArrayParcelable.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; -import android.util.SparseBooleanArray; - - -/** - * Class from http://stackoverflow.com/a/16711258/1627904 - */ -public class SparseBooleanArrayParcelable extends SparseBooleanArray implements Parcelable { - public static Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public SparseBooleanArrayParcelable createFromParcel(Parcel source) { - SparseBooleanArrayParcelable read = new SparseBooleanArrayParcelable(); - int size = source.readInt(); - - int[] keys = new int[size]; - boolean[] values = new boolean[size]; - - source.readIntArray(keys); - source.readBooleanArray(values); - - for (int i = 0; i < size; i++) { - read.put(keys[i], values[i]); - } - - return read; - } - - @Override - public SparseBooleanArrayParcelable[] newArray(int size) { - return new SparseBooleanArrayParcelable[size]; - } - }; - - public SparseBooleanArrayParcelable() { - - } - - public SparseBooleanArrayParcelable(SparseBooleanArray sparseBooleanArray) { - for (int i = 0; i < sparseBooleanArray.size(); i++) { - this.put(sparseBooleanArray.keyAt(i), sparseBooleanArray.valueAt(i)); - } - } - - @Override public int describeContents() { - return 0; - } - - @Override public void writeToParcel(Parcel dest, int flags) { - int[] keys = new int[size()]; - boolean[] values = new boolean[size()]; - - for (int i = 0; i < size(); i++) { - keys[i] = keyAt(i); - values[i] = valueAt(i); - } - - dest.writeInt(size()); - dest.writeIntArray(keys); - dest.writeBooleanArray(values); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/dao/StatusesModel.java b/app/src/main/java/com/fastaccess/data/dao/StatusesModel.java deleted file mode 100644 index ca7cb0e9b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/StatusesModel.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.types.StatusStateType; - -import java.util.Date; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 10 Apr 2017, 3:16 AM - */ - -@Getter @Setter public class StatusesModel implements Parcelable { - private String url; - private StatusStateType state; - private String description; - private String targetUrl; - private String context; - private Date createdAt; - private Date updatedAt; - - public StatusesModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.url); - dest.writeInt(this.state == null ? -1 : this.state.ordinal()); - dest.writeString(this.description); - dest.writeString(this.targetUrl); - dest.writeString(this.context); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - } - - private StatusesModel(Parcel in) { - this.url = in.readString(); - int tmpState = in.readInt(); - this.state = tmpState == -1 ? null : StatusStateType.values()[tmpState]; - this.description = in.readString(); - this.targetUrl = in.readString(); - this.context = in.readString(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - } - - public static final Creator CREATOR = new Creator() { - @Override public StatusesModel createFromParcel(Parcel source) {return new StatusesModel(source);} - - @Override public StatusesModel[] newArray(int size) {return new StatusesModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/TabsCountStateModel.java b/app/src/main/java/com/fastaccess/data/dao/TabsCountStateModel.java deleted file mode 100644 index dcb45ede0..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/TabsCountStateModel.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.DrawableRes; - -import java.io.Serializable; - -/** - * Created by Kosh on 27 Apr 2017, 6:10 PM - */ - -public class TabsCountStateModel implements Parcelable, Serializable { - private int count; - private int tabIndex; - @DrawableRes private int drawableId; - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } - - public int getTabIndex() { - return tabIndex; - } - - public void setTabIndex(int tabIndex) { - this.tabIndex = tabIndex; - } - - public int getDrawableId() { - return drawableId; - } - - public void setDrawableId(int drawableId) { - this.drawableId = drawableId; - } - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - TabsCountStateModel model = (TabsCountStateModel) o; - - return tabIndex == model.tabIndex; - } - - @Override public int hashCode() { - return tabIndex; - } - - public TabsCountStateModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.count); - dest.writeInt(this.tabIndex); - dest.writeInt(this.drawableId); - } - - protected TabsCountStateModel(Parcel in) { - this.count = in.readInt(); - this.tabIndex = in.readInt(); - this.drawableId = in.readInt(); - } - - public static final Creator CREATOR = new Creator() { - @Override public TabsCountStateModel createFromParcel(Parcel source) {return new TabsCountStateModel(source);} - - @Override public TabsCountStateModel[] newArray(int size) {return new TabsCountStateModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/TeamsModel.java b/app/src/main/java/com/fastaccess/data/dao/TeamsModel.java deleted file mode 100644 index 984268d8b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/TeamsModel.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 03 Apr 2017, 7:40 PM - */ - -@Getter @Setter @NoArgsConstructor public class TeamsModel implements Parcelable { - private long id; - private String url; - private String name; - private String slug; - private String description; - private String privacy; - private String permission; - private String membersUrl; - private String repositoriesUrl; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.url); - dest.writeString(this.name); - dest.writeString(this.slug); - dest.writeString(this.description); - dest.writeString(this.privacy); - dest.writeString(this.permission); - dest.writeString(this.membersUrl); - dest.writeString(this.repositoriesUrl); - } - - protected TeamsModel(Parcel in) { - this.id = in.readLong(); - this.url = in.readString(); - this.name = in.readString(); - this.slug = in.readString(); - this.description = in.readString(); - this.privacy = in.readString(); - this.permission = in.readString(); - this.membersUrl = in.readString(); - this.repositoriesUrl = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public TeamsModel createFromParcel(Parcel source) {return new TeamsModel(source);} - - @Override public TeamsModel[] newArray(int size) {return new TeamsModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/TimelineModel.java b/app/src/main/java/com/fastaccess/data/dao/TimelineModel.java deleted file mode 100644 index 9fe29ba7a..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/TimelineModel.java +++ /dev/null @@ -1,223 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.timeline.GenericEvent; -import com.fastaccess.data.dao.timeline.PullRequestCommitModel; -import com.fastaccess.data.dao.types.IssueEventType; - -import java.util.List; - -import io.reactivex.Observable; -import lombok.Getter; -import lombok.NonNull; -import lombok.Setter; - -/** - * Created by Kosh on 30 Mar 2017, 9:03 PM - */ - -@Getter @Setter public class TimelineModel implements Parcelable { - public static final int HEADER = 1; - public static final int EVENT = 2; - public static final int COMMENT = 3; - public static final int REVIEW = 4; - public static final int GROUP = 5; - public static final int COMMIT_COMMENTS = 6; - public static final int STATUS = 7; - - private IssueEventType event; - private Comment comment; - private GenericEvent genericEvent; - private PullRequestStatusModel status; - private Issue issue; - private PullRequest pullRequest; - private ReviewModel review; - private GroupedReviewModel groupedReviewModel; - private PullRequestCommitModel commit; - private int position; - - public TimelineModel(Issue issue) { - this.issue = issue; - } - - public TimelineModel(PullRequest pullRequest) { - this.pullRequest = pullRequest; - } - - public TimelineModel(Comment comment) { - this.comment = comment; - this.event = IssueEventType.commented; - } - - public TimelineModel(PullRequestStatusModel statusModel) { - this.status = statusModel; - } - - public TimelineModel() {} - - public int getType() { - if (getEvent() != null) { - switch (getEvent()) { - case commented: - return COMMENT; - case reviewed: - case changes_requested: - return REVIEW; - case GROUPED: - return GROUP; - case commit_commented: - return COMMIT_COMMENTS; - default: - return EVENT; - } - } else { - if (issue != null || pullRequest != null) return HEADER; - else if (status != null) return STATUS; - return 0; - } - } - - public static TimelineModel constructHeader(Issue issue) { - return new TimelineModel(issue); - } - - public static TimelineModel constructHeader(PullRequest pullRequest) { - return new TimelineModel(pullRequest); - } - - public static TimelineModel constructComment(Comment comment) { - return new TimelineModel(comment); - } - - @NonNull public static Observable> construct(@Nullable List comments) { - if (comments == null || comments.isEmpty()) return Observable.empty(); - return Observable.fromIterable(comments) - .map(TimelineModel::new) - .toList() - .toObservable(); - } - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TimelineModel model = (TimelineModel) o; - return (comment != null && model.getComment() != null) && (comment.getId() == model.comment.getId()); - } - - @Override public int hashCode() { - return comment != null ? (int) comment.getId() : 0; - } - - public IssueEventType getEvent() { - return event; - } - - public void setEvent(IssueEventType event) { - this.event = event; - } - - public Comment getComment() { - return comment; - } - - public void setComment(Comment comment) { - this.comment = comment; - } - - public GenericEvent getGenericEvent() { - return genericEvent; - } - - public void setGenericEvent(GenericEvent genericEvent) { - this.genericEvent = genericEvent; - } - - public PullRequestStatusModel getStatus() { - return status; - } - - public void setStatus(PullRequestStatusModel status) { - this.status = status; - } - - public Issue getIssue() { - return issue; - } - - public void setIssue(Issue issue) { - this.issue = issue; - } - - public PullRequest getPullRequest() { - return pullRequest; - } - - public void setPullRequest(PullRequest pullRequest) { - this.pullRequest = pullRequest; - } - - public ReviewModel getReview() { - return review; - } - - public void setReview(ReviewModel review) { - this.review = review; - } - - public GroupedReviewModel getGroupedReviewModel() { - return groupedReviewModel; - } - - public void setGroupedReviewModel(GroupedReviewModel groupedReviewModel) { - this.groupedReviewModel = groupedReviewModel; - } - - public PullRequestCommitModel getCommit() { - return commit; - } - - public void setCommit(PullRequestCommitModel commit) { - this.commit = commit; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(this.event == null ? -1 : this.event.ordinal()); - dest.writeParcelable(this.comment, flags); - dest.writeParcelable(this.genericEvent, flags); - dest.writeParcelable(this.status, flags); - dest.writeParcelable(this.issue, flags); - dest.writeParcelable(this.pullRequest, flags); - dest.writeParcelable(this.review, flags); - dest.writeParcelable(this.groupedReviewModel, flags); - dest.writeParcelable(this.commit, flags); - dest.writeInt(this.position); - } - - protected TimelineModel(Parcel in) { - int tmpEvent = in.readInt(); - this.event = tmpEvent == -1 ? null : IssueEventType.values()[tmpEvent]; - this.comment = in.readParcelable(Comment.class.getClassLoader()); - this.genericEvent = in.readParcelable(GenericEvent.class.getClassLoader()); - this.status = in.readParcelable(PullRequestStatusModel.class.getClassLoader()); - this.issue = in.readParcelable(Issue.class.getClassLoader()); - this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader()); - this.review = in.readParcelable(ReviewModel.class.getClassLoader()); - this.groupedReviewModel = in.readParcelable(GroupedReviewModel.class.getClassLoader()); - this.commit = in.readParcelable(PullRequestCommitModel.class.getClassLoader()); - this.position = in.readInt(); - } - - public static final Creator CREATOR = new Creator() { - @Override public TimelineModel createFromParcel(Parcel source) {return new TimelineModel(source);} - - @Override public TimelineModel[] newArray(int size) {return new TimelineModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/TopicsModel.java b/app/src/main/java/com/fastaccess/data/dao/TopicsModel.java deleted file mode 100644 index 948dcbacc..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/TopicsModel.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.data.dao; - -import java.util.ArrayList; - -/** - * Created by Kosh on 09 May 2017, 7:52 PM - */ - -public class TopicsModel extends ArrayList {} diff --git a/app/src/main/java/com/fastaccess/data/dao/TreeResponseModel.java b/app/src/main/java/com/fastaccess/data/dao/TreeResponseModel.java deleted file mode 100644 index 53b9808f9..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/TreeResponseModel.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.fastaccess.data.dao; - -import com.fastaccess.data.dao.model.RepoFile; - -import java.util.List; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by Kosh on 12 Apr 2017, 1:12 PM - */ - -@NoArgsConstructor @Getter @Setter public class TreeResponseModel { - private String sha; - private String url; - boolean truncated; - List tree; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/TrendingModel.kt b/app/src/main/java/com/fastaccess/data/dao/TrendingModel.kt deleted file mode 100644 index 7fa396168..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/TrendingModel.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.fastaccess.data.dao - -import android.os.Parcel -import com.fastaccess.helper.KotlinParcelable -import com.fastaccess.helper.parcelableCreator - -data class TrendingModel( - val title: String? = null, - val description: String? = null, - val language: String? = null, - val stars: String? = null, - val forks: String? = null, - val todayStars: String? = null) : KotlinParcelable { - companion object { - @JvmField val CREATOR = parcelableCreator(::TrendingModel) - } - - constructor(source: Parcel) : this( - source.readString(), - source.readString(), - source.readString(), - source.readString(), - source.readString(), - source.readString() - ) - - override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) { - writeString(title) - writeString(description) - writeString(language) - writeString(stars) - writeString(forks) - writeString(todayStars) - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/UsersListModel.java b/app/src/main/java/com/fastaccess/data/dao/UsersListModel.java deleted file mode 100644 index fbaa38aaf..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/UsersListModel.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.fastaccess.data.dao; - -import com.fastaccess.data.dao.model.User; - -import java.util.ArrayList; - -/** - * Created by Kosh on 12 Feb 2017, 1:33 PM - */ - -public class UsersListModel extends ArrayList {} diff --git a/app/src/main/java/com/fastaccess/data/dao/WikiModel.java b/app/src/main/java/com/fastaccess/data/dao/WikiModel.java deleted file mode 100644 index 02c85eade..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/WikiModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fastaccess.data.dao; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 11 Jun 2017, 7:13 PM - */ - -@Getter @Setter public class WikiModel implements Parcelable { - public String pageName; - public String title; - public String summary; - public String action; - public String sha; - - public String htmlUrl; - - public WikiModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.pageName); - dest.writeString(this.title); - dest.writeString(this.summary); - dest.writeString(this.action); - dest.writeString(this.sha); - dest.writeString(this.htmlUrl); - } - - private WikiModel(Parcel in) { - this.pageName = in.readString(); - this.title = in.readString(); - this.summary = in.readString(); - this.action = in.readString(); - this.sha = in.readString(); - this.htmlUrl = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public WikiModel createFromParcel(Parcel source) {return new WikiModel(source);} - - @Override public WikiModel[] newArray(int size) {return new WikiModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/BaseConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/BaseConverter.java deleted file mode 100644 index aea04fb24..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/BaseConverter.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.provider.rest.RestProvider; - -import io.requery.Converter; - -/** - * Created by Kosh on 15 Mar 2017, 8:02 PM - */ - -public abstract class BaseConverter implements Converter { - - protected abstract Class getTypeClass(); - - @SuppressWarnings("unchecked") @Override public Class getMappedType() { - return (Class) getTypeClass(); - } - - @Override public Class getPersistedType() { - return String.class; - } - - @Override public Integer getPersistedSize() { - return null; - } - - @Override public String convertToPersisted(C value) { - return RestProvider.gson.toJson(value); - } - - @Override public C convertToMapped(Class type, String value) { - return RestProvider.gson.fromJson(value, type); - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/CommitConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/CommitConverter.java deleted file mode 100644 index b9fb30821..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/CommitConverter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.model.Commit; - -/** - * Created by Kosh on 15 Mar 2017, 7:58 PM - */ - -public class CommitConverter extends BaseConverter { - - @Override protected Class getTypeClass() { - return Commit.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/CommitFilesConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/CommitFilesConverter.java deleted file mode 100644 index bdb48e72b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/CommitFilesConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.CommitFileListModel; - -/** - * Created by Kosh on 15 Mar 2017, 8:37 PM - */ - -public class CommitFilesConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return CommitFileListModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/CommitsConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/CommitsConverter.java deleted file mode 100644 index e01b55110..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/CommitsConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.CommitListModel; - -/** - * Created by Kosh on 15 Mar 2017, 8:37 PM - */ - -public class CommitsConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return CommitListModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/GistConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/GistConverter.java deleted file mode 100644 index 067ff8f4e..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/GistConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.model.Gist; - -/** - * Created by Kosh on 15 Mar 2017, 8:30 PM - */ - -public class GistConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return Gist.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/GitCommitConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/GitCommitConverter.java deleted file mode 100644 index cf16b8d10..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/GitCommitConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.GitCommitModel; - -/** - * Created by Kosh on 15 Mar 2017, 8:42 PM - */ - -public class GitCommitConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return GitCommitModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/GitHubFilesConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/GitHubFilesConverter.java deleted file mode 100644 index 2c1a3c1e1..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/GitHubFilesConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.GithubFileModel; - -/** - * Created by Kosh on 15 Mar 2017, 8:21 PM - */ - -public class GitHubFilesConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return GithubFileModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/GitHubStateConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/GitHubStateConverter.java deleted file mode 100644 index bf506b34b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/GitHubStateConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.GithubState; - -/** - * Created by Kosh on 15 Mar 2017, 8:41 PM - */ - -public class GitHubStateConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return GithubState.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/IssueConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/IssueConverter.java deleted file mode 100644 index 9326c2172..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/IssueConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.model.Issue; - -/** - * Created by Kosh on 15 Mar 2017, 8:30 PM - */ - -public class IssueConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return Issue.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/LabelConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/LabelConverter.java deleted file mode 100644 index 0109c054f..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/LabelConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.LabelModel; - -/** - * Created by Kosh on 15 Mar 2017, 8:30 PM - */ - -public class LabelConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return LabelModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/LabelsListConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/LabelsListConverter.java deleted file mode 100644 index f1a605d7b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/LabelsListConverter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.LabelListModel; - -/** - * Created by Kosh on 11 Feb 2017, 11:43 PM - */ - -public class LabelsListConverter extends BaseConverter { - - @Override protected Class getTypeClass() { - return LabelListModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/LicenseConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/LicenseConverter.java deleted file mode 100644 index cd0b977f5..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/LicenseConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.LicenseModel; - -/** - * Created by Kosh on 15 Mar 2017, 8:33 PM - */ - -public class LicenseConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return LicenseModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/MilestoneConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/MilestoneConverter.java deleted file mode 100644 index 118b9cbfc..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/MilestoneConverter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.MilestoneModel; - -/** - * Created by Kosh on 11 Feb 2017, 11:43 PM - */ - -public class MilestoneConverter extends BaseConverter { - - @Override protected Class getTypeClass() { - return MilestoneModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/NotificationSubjectConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/NotificationSubjectConverter.java deleted file mode 100644 index dccbb1dec..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/NotificationSubjectConverter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.NotificationSubjectModel; - -/** - * Created by Kosh on 15 Mar 2017, 7:58 PM - */ - -public class NotificationSubjectConverter extends BaseConverter { - - @Override protected Class getTypeClass() { - return NotificationSubjectModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/PayloadConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/PayloadConverter.java deleted file mode 100644 index 3be077ec5..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/PayloadConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.PayloadModel; - -/** - * Created by Kosh on 15 Mar 2017, 8:39 PM - */ - -public class PayloadConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return PayloadModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/PullRequestConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/PullRequestConverter.java deleted file mode 100644 index 06a372c7e..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/PullRequestConverter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.model.PullRequest; - -/** - * Created by Kosh on 15 Mar 2017, 7:58 PM - */ - -public class PullRequestConverter extends BaseConverter { - - @Override protected Class getTypeClass() { - return PullRequest.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/ReactionsConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/ReactionsConverter.java deleted file mode 100644 index 8897a7608..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/ReactionsConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.ReactionsModel; - -/** - * Created by Kosh on 06 May 2017, 4:53 PM - */ - -public class ReactionsConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return ReactionsModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/ReleasesAssetsConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/ReleasesAssetsConverter.java deleted file mode 100644 index 88ecc3d68..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/ReleasesAssetsConverter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.ReleasesAssetsListModel; - -/** - * Created by Kosh on 11 Feb 2017, 11:43 PM - */ - -public class ReleasesAssetsConverter extends BaseConverter { - - @Override protected Class getTypeClass() { - return ReleasesAssetsListModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/RenameConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/RenameConverter.java deleted file mode 100644 index ebe0a5f78..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/RenameConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.RenameModel; - -/** - * Created by Kosh on 15 Mar 2017, 8:29 PM - */ - -public class RenameConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return RenameModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/RepoConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/RepoConverter.java deleted file mode 100644 index a92e6bb47..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/RepoConverter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.model.Repo; - -/** - * Created by Kosh on 15 Mar 2017, 7:58 PM - */ - -public class RepoConverter extends BaseConverter { - - @Override protected Class getTypeClass() { - return Repo.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/RepoPermissionConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/RepoPermissionConverter.java deleted file mode 100644 index e28979f24..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/RepoPermissionConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.RepoPermissionsModel; - -/** - * Created by Kosh on 15 Mar 2017, 8:33 PM - */ - -public class RepoPermissionConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return RepoPermissionsModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/TeamConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/TeamConverter.java deleted file mode 100644 index df637b03a..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/TeamConverter.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.TeamsModel; -import com.fastaccess.data.dao.model.User; - -/** - * Created by Kosh on 15 Mar 2017, 7:58 PM - */ - -public class TeamConverter extends BaseConverter { - - @Override protected Class getTypeClass() { - return TeamsModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/TopicsConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/TopicsConverter.java deleted file mode 100644 index adac4bfb1..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/TopicsConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.TopicsModel; - -/** - * Created by Kosh on 09 May 2017, 7:54 PM - */ - -public class TopicsConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return TopicsModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/UserConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/UserConverter.java deleted file mode 100644 index 90c02b75d..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/UserConverter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.model.User; - -/** - * Created by Kosh on 15 Mar 2017, 7:58 PM - */ - -public class UserConverter extends BaseConverter { - - @Override protected Class getTypeClass() { - return User.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/converters/UsersConverter.java b/app/src/main/java/com/fastaccess/data/dao/converters/UsersConverter.java deleted file mode 100644 index 10215295d..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/converters/UsersConverter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.converters; - -import com.fastaccess.data.dao.UsersListModel; - -/** - * Created by Kosh on 15 Mar 2017, 8:26 PM - */ - -public class UsersConverter extends BaseConverter { - @Override protected Class getTypeClass() { - return UsersListModel.class; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractComment.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractComment.java deleted file mode 100644 index ffcb09919..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractComment.java +++ /dev/null @@ -1,224 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.fastaccess.App; -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.data.dao.converters.ReactionsConverter; -import com.fastaccess.data.dao.converters.UserConverter; -import com.fastaccess.helper.RxHelper; - -import java.util.Date; -import java.util.List; - -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Column; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Persistable; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.Comment.COMMIT_ID; -import static com.fastaccess.data.dao.model.Comment.GIST_ID; -import static com.fastaccess.data.dao.model.Comment.ID; -import static com.fastaccess.data.dao.model.Comment.ISSUE_ID; -import static com.fastaccess.data.dao.model.Comment.LOGIN; -import static com.fastaccess.data.dao.model.Comment.PULL_REQUEST_ID; -import static com.fastaccess.data.dao.model.Comment.REPO_ID; -import static com.fastaccess.data.dao.model.Comment.UPDATED_AT; - -/** - * Created by Kosh on 16 Mar 2017, 7:24 PM - */ -@Entity @NoArgsConstructor public abstract class AbstractComment implements Parcelable { - @Key long id; - @Column(name = "user_column") @Convert(UserConverter.class) User user; - String url; - String body; - String bodyHtml; - String htmlUrl; - Date createdAt; - Date updatedAt; - int position; - int line; - String path; - String commitId; - String repoId; - String login; - String gistId; - String issueId; - String pullRequestId; - @Convert(ReactionsConverter.class) ReactionsModel reactions; - String authorAssociation; - - public static Disposable saveForGist(@NonNull List models, @NonNull String gistId) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - dataSource.delete(Comment.class) - .where(GIST_ID.equal(gistId)) - .get() - .value(); - if (!models.isEmpty()) { - for (Comment model : models) { - dataSource.delete(Comment.class).where(ID.eq(model.getId())).get().value(); - model.setGistId(gistId); - dataSource.insert(model); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - public static Disposable saveForCommits(@NonNull List models, @NonNull String repoId, - @NonNull String login, @NonNull String commitId) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - dataSource.delete(Comment.class) - .where(COMMIT_ID.equal(commitId) - .and(REPO_ID.equal(repoId)) - .and(LOGIN.equal(login))) - .get() - .value(); - if (!models.isEmpty()) { - for (Comment model : models) { - dataSource.delete(Comment.class).where(ID.eq(model.getId())).get().value(); - model.setLogin(login); - model.setRepoId(repoId); - model.setCommitId(commitId); - dataSource.insert(model); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - public static Single> getGistComments(@NonNull String gistId) { - return App.getInstance().getDataStore() - .select(Comment.class) - .where(GIST_ID.equal(gistId)) - .orderBy(UPDATED_AT.desc()) - .get() - .observable() - .toList(); - } - - public static Single> getCommitComments(@NonNull String repoId, @NonNull String login, - @NonNull String commitId) { - return App.getInstance().getDataStore() - .select(Comment.class) - .where(REPO_ID.equal(repoId) - .and(LOGIN.equal(login)) - .and(COMMIT_ID.equal(commitId))) - .orderBy(UPDATED_AT.desc()) - .get() - .observable() - .toList(); - } - - public static Single> getIssueComments(@NonNull String repoId, @NonNull String login, @NonNull String issueId) { - return App.getInstance().getDataStore() - .select(Comment.class) - .where(REPO_ID.equal(repoId) - .and(LOGIN.equal(login)) - .and(ISSUE_ID.equal(issueId))) - .orderBy(UPDATED_AT.desc()) - .get() - .observable() - .toList(); - } - - public static Single> getPullRequestComments(@NonNull String repoId, @NonNull String login, - @NonNull String pullRequestId) { - return App.getInstance().getDataStore() - .select(Comment.class) - .where(REPO_ID.equal(repoId) - .and(LOGIN.equal(login)) - .and(PULL_REQUEST_ID.equal(pullRequestId))) - .orderBy(UPDATED_AT.desc()) - .get() - .observable() - .toList(); - } - - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Comment that = (Comment) o; - return id == that.id; - - } - - @Override public int hashCode() { - return (int) (id ^ (id >>> 32)); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeParcelable(this.user, flags); - dest.writeString(this.url); - dest.writeString(this.body); - dest.writeString(this.bodyHtml); - dest.writeString(this.htmlUrl); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeInt(this.position); - dest.writeInt(this.line); - dest.writeString(this.path); - dest.writeString(this.commitId); - dest.writeString(this.repoId); - dest.writeString(this.login); - dest.writeString(this.gistId); - dest.writeString(this.issueId); - dest.writeString(this.pullRequestId); - dest.writeParcelable(this.reactions, flags); - dest.writeString(this.authorAssociation); - } - - protected AbstractComment(Parcel in) { - this.id = in.readLong(); - this.user = in.readParcelable(User.class.getClassLoader()); - this.url = in.readString(); - this.body = in.readString(); - this.bodyHtml = in.readString(); - this.htmlUrl = in.readString(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - this.position = in.readInt(); - this.line = in.readInt(); - this.path = in.readString(); - this.commitId = in.readString(); - this.repoId = in.readString(); - this.login = in.readString(); - this.gistId = in.readString(); - this.issueId = in.readString(); - this.pullRequestId = in.readString(); - this.reactions = in.readParcelable(ReactionsModel.class.getClassLoader()); - this.authorAssociation = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public Comment createFromParcel(Parcel source) {return new Comment(source);} - - @Override public Comment[] newArray(int size) {return new Comment[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractCommit.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractCommit.java deleted file mode 100644 index 0bdea8ddb..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractCommit.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.fastaccess.App; -import com.fastaccess.data.dao.CommitFileListModel; -import com.fastaccess.data.dao.CommitListModel; -import com.fastaccess.data.dao.GitCommitModel; -import com.fastaccess.data.dao.GithubState; -import com.fastaccess.data.dao.converters.CommitFilesConverter; -import com.fastaccess.data.dao.converters.CommitsConverter; -import com.fastaccess.data.dao.converters.GitCommitConverter; -import com.fastaccess.data.dao.converters.GitHubStateConverter; -import com.fastaccess.data.dao.converters.RepoConverter; -import com.fastaccess.data.dao.converters.UserConverter; -import com.fastaccess.helper.RxHelper; -import com.google.gson.annotations.SerializedName; - -import java.util.List; - -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Column; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Generated; -import io.requery.Key; -import io.requery.Nullable; -import io.requery.Persistable; -import io.requery.Table; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.Commit.ID; -import static com.fastaccess.data.dao.model.Commit.LOGIN; -import static com.fastaccess.data.dao.model.Commit.PULL_REQUEST_NUMBER; -import static com.fastaccess.data.dao.model.Commit.REPO_ID; -import static com.fastaccess.data.dao.model.Commit.SHA; - -@Entity @NoArgsConstructor @Table(name = "commit_table") -public abstract class AbstractCommit implements Parcelable { - @Key @Generated long id; - String url; - String sha; - String htmlUrl; - String login; - String repoId; - long pullRequestNumber; - @Convert(GitHubStateConverter.class) GithubState stats; - @Convert(CommitFilesConverter.class) CommitFileListModel files; - @Convert(CommitsConverter.class) CommitListModel parents; - @Column(name = "ref_column") String ref; - @SerializedName("distincted") boolean distincted; - @SerializedName("commit") @Convert(GitCommitConverter.class) GitCommitModel gitCommit; - @Convert(UserConverter.class) User author; - @Convert(UserConverter.class) User committer; - @Convert(RepoConverter.class) Repo repo; - @Column(name = "user_column") @Convert(UserConverter.class) User user; - @Nullable int commentCount; - - public Single save(Commit entity) { - return RxHelper.getSingle(App.getInstance().getDataStore().upsert(entity)); - } - - public static Disposable save(@NonNull List models, @NonNull String repoId, @NonNull String login) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - dataSource.delete(Commit.class) - .where(REPO_ID.eq(repoId).and(LOGIN.eq(login))) - .get() - .value(); - if (!models.isEmpty()) { - for (Commit commitModel : models) { - dataSource.delete(Commit.class).where(ID.eq(commitModel.getId())).get().value(); - commitModel.setRepoId(repoId); - commitModel.setLogin(login); - dataSource.insert(commitModel); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - public static Disposable save(@NonNull List models, @NonNull String repoId, @NonNull String login, long number) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - dataSource.delete(Commit.class) - .where(REPO_ID.eq(repoId) - .and(LOGIN.eq(login)) - .and(PULL_REQUEST_NUMBER.eq(number))) - .get() - .value(); - if (!models.isEmpty()) { - for (Commit commitModel : models) { - dataSource.delete(Commit.class).where(ID.eq(commitModel.getId())).get().value(); - commitModel.setRepoId(repoId); - commitModel.setLogin(login); - commitModel.setPullRequestNumber(number); - dataSource.insert(commitModel); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - public static Single> getCommits(@NonNull String repoId, @NonNull String login) { - return App.getInstance().getDataStore() - .select(Commit.class) - .where(REPO_ID.eq(repoId) - .and(LOGIN.eq(login)) - .and(PULL_REQUEST_NUMBER.eq(0L))) - .get() - .observable() - .toList(); - } - - public static Single> getCommits(@NonNull String repoId, @NonNull String login, long pullRequestNumber) { - return App.getInstance().getDataStore() - .select(Commit.class) - .where(REPO_ID.eq(repoId) - .and(LOGIN.eq(login)) - .and(PULL_REQUEST_NUMBER.eq(pullRequestNumber))) - .get() - .observable() - .toList(); - } - - public static Observable getCommit(@NonNull String sha, @NonNull String repoId, @NonNull String login) { - return App.getInstance().getDataStore() - .select(Commit.class) - .where(REPO_ID.eq(repoId) - .and(LOGIN.eq(login)) - .and(SHA.eq(sha))) - .limit(1) - .get() - .observable(); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.url); - dest.writeString(this.sha); - dest.writeString(this.htmlUrl); - dest.writeString(this.login); - dest.writeString(this.repoId); - dest.writeLong(this.pullRequestNumber); - dest.writeParcelable(this.stats, flags); - dest.writeList(this.files); - dest.writeList(this.parents); - dest.writeString(this.ref); - dest.writeByte(this.distincted ? (byte) 1 : (byte) 0); - dest.writeParcelable(this.gitCommit, flags); - dest.writeParcelable(this.author, flags); - dest.writeParcelable(this.committer, flags); - dest.writeParcelable(this.repo, flags); - dest.writeParcelable(this.user, flags); - dest.writeInt(this.commentCount); - } - - protected AbstractCommit(Parcel in) { - this.id = in.readLong(); - this.url = in.readString(); - this.sha = in.readString(); - this.htmlUrl = in.readString(); - this.login = in.readString(); - this.repoId = in.readString(); - this.pullRequestNumber = in.readLong(); - this.stats = in.readParcelable(GithubState.class.getClassLoader()); - this.files = new CommitFileListModel(); - in.readList(this.files, this.files.getClass().getClassLoader()); - this.parents = new CommitListModel(); - in.readList(this.parents, this.parents.getClass().getClassLoader()); - this.ref = in.readString(); - this.distincted = in.readByte() != 0; - this.gitCommit = in.readParcelable(GitCommitModel.class.getClassLoader()); - this.author = in.readParcelable(User.class.getClassLoader()); - this.committer = in.readParcelable(User.class.getClassLoader()); - this.repo = in.readParcelable(Repo.class.getClassLoader()); - this.user = in.readParcelable(User.class.getClassLoader()); - this.commentCount = in.readInt(); - } - - public static final Creator CREATOR = new Creator() { - @Override public Commit createFromParcel(Parcel source) {return new Commit(source);} - - @Override public Commit[] newArray(int size) {return new Commit[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractEvent.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractEvent.java deleted file mode 100644 index 32f974595..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractEvent.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.text.TextUtils; - -import com.fastaccess.App; -import com.fastaccess.data.dao.PayloadModel; -import com.fastaccess.data.dao.converters.PayloadConverter; -import com.fastaccess.data.dao.converters.RepoConverter; -import com.fastaccess.data.dao.converters.UserConverter; -import com.fastaccess.data.dao.types.EventsType; -import com.fastaccess.helper.RxHelper; -import com.google.gson.annotations.SerializedName; - -import java.util.Date; -import java.util.List; - -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Nullable; -import io.requery.Persistable; -import lombok.NoArgsConstructor; - -/** - * Created by Kosh on 16 Mar 2017, 7:29 PM - */ - -@Entity @NoArgsConstructor public abstract class AbstractEvent implements Parcelable { - @Key long id; - EventsType type; - Date createdAt; - @Convert(UserConverter.class) User actor; - @Convert(RepoConverter.class) Repo repo; - @Convert(PayloadConverter.class) PayloadModel payload; - @SerializedName("public") boolean publicEvent; - @Nullable String login; - - @NonNull - public static Disposable save(@android.support.annotation.Nullable List events, @android.support.annotation.Nullable String user) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - Login login = Login.getUser(); - if (login == null) { - s.onNext(""); - s.onComplete(); - return; - } - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - dataSource.delete(Event.class) - .where(Event.LOGIN.isNull() - .or(Event.LOGIN.eq(login.getLogin()))) - .get() - .value(); - if (events != null && !events.isEmpty() && TextUtils.equals(login.getLogin(), user)) { - for (Event event : events) { - dataSource.delete(Event.class).where(Event.ID.eq(event.getId())).get().value(); - event.setLogin(login.getLogin()); - dataSource.insert(event); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - @NonNull public static Single> getEvents(@NonNull String login) { - return RxHelper.getSingle( - App.getInstance().getDataStore() - .select(Event.class) - .where(Event.LOGIN.eq(login)) - .orderBy(Event.CREATED_AT.desc()) - .get() - .observable() - .toList()); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeInt(this.type == null ? -1 : this.type.ordinal()); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeParcelable(this.actor, flags); - dest.writeParcelable(this.repo, flags); - dest.writeParcelable(this.payload, flags); - dest.writeByte(this.publicEvent ? (byte) 1 : (byte) 0); - } - - protected AbstractEvent(Parcel in) { - this.id = in.readLong(); - int tmpType = in.readInt(); - this.type = tmpType == -1 ? null : EventsType.values()[tmpType]; - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - this.actor = in.readParcelable(User.class.getClassLoader()); - this.repo = in.readParcelable(Repo.class.getClassLoader()); - this.payload = in.readParcelable(PayloadModel.class.getClassLoader()); - this.publicEvent = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override public Event createFromParcel(Parcel source) {return new Event(source);} - - @Override public Event[] newArray(int size) {return new Event[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractFastHubNotification.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractFastHubNotification.java deleted file mode 100644 index 08de87aa7..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractFastHubNotification.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.App; - -import java.util.Date; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import io.reactivex.Observable; -import io.requery.Column; -import io.requery.Entity; -import io.requery.Generated; -import io.requery.Key; -import lombok.NoArgsConstructor; - -/** - * Created by Kosh on 11.11.17. - */ -@Entity @NoArgsConstructor public class AbstractFastHubNotification implements Parcelable { - - public enum NotificationType { - UPDATE, GUIDE, PURCHASE, REPORT_ISSUE, PROMOTION, STAR_REPO - } - - @Generated @Key long id; - @io.requery.Nullable @Column(name = "notification_date") Date date; - @io.requery.Nullable boolean read; - @io.requery.Nullable String body; - @io.requery.Nullable String title; - @io.requery.Nullable NotificationType type; - - public static void update(@Nonnull FastHubNotification notification) { - App.getInstance().getDataStore().toBlocking().update(notification); - } - - public static void save(@Nonnull FastHubNotification notification) { - App.getInstance().getDataStore().toBlocking().insert(notification); - } - - @Nullable public static FastHubNotification getLatest() { - return App.getInstance().getDataStore().toBlocking() - .select(FastHubNotification.class) - .where(FastHubNotification.READ.eq(false)) - .orderBy(FastHubNotification.DATE.desc()) - .limit(1) - .get() - .firstOrNull(); - } - - @Nonnull public static Observable getNotifications() { - return App.getInstance().getDataStore() - .select(FastHubNotification.class) - .orderBy(FastHubNotification.DATE.desc()) - .get() - .observable(); - } - - public static boolean hasNotifications() { - return App.getInstance().getDataStore() - .count(FastHubNotification.class) - .get() - .value() > 0; - } - - @Override public String toString() { - return "AbstractFastHubNotification{" + - "date=" + date + - ", isRead=" + read + - ", body='" + body + '\'' + - ", title='" + title + '\'' + - ", type=" + type + - '}'; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeLong(this.date != null ? this.date.getTime() : -1); - dest.writeByte(this.read ? (byte) 1 : (byte) 0); - dest.writeString(this.body); - dest.writeString(this.title); - dest.writeInt(this.type == null ? -1 : this.type.ordinal()); - } - - protected AbstractFastHubNotification(Parcel in) { - this.id = in.readLong(); - long tmpDate = in.readLong(); - this.date = tmpDate == -1 ? null : new Date(tmpDate); - this.read = in.readByte() != 0; - this.body = in.readString(); - this.title = in.readString(); - int tmpType = in.readInt(); - this.type = tmpType == -1 ? null : NotificationType.values()[tmpType]; - } - - public static final Creator CREATOR = new Creator() { - @Override public FastHubNotification createFromParcel(Parcel source) {return new FastHubNotification(source);} - - @Override public FastHubNotification[] newArray(int size) {return new FastHubNotification[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractGist.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractGist.java deleted file mode 100644 index 6177812a4..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractGist.java +++ /dev/null @@ -1,257 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.annimon.stream.Collectors; -import com.annimon.stream.LongStream; -import com.annimon.stream.Stream; -import com.fastaccess.App; -import com.fastaccess.data.dao.FilesListModel; -import com.fastaccess.data.dao.GithubFileModel; -import com.fastaccess.data.dao.converters.GitHubFilesConverter; -import com.fastaccess.data.dao.converters.UserConverter; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.google.gson.annotations.SerializedName; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Column; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Persistable; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.Gist.ID; -import static com.fastaccess.data.dao.model.Gist.OWNER_NAME; - -/** - * Created by Kosh on 16 Mar 2017, 7:32 PM - */ - -@Entity() @NoArgsConstructor public abstract class AbstractGist implements Parcelable { - @SerializedName("nooope") @Key long id; - String url; - String forksUrl; - String commitsUrl; - String gitPullUrl; - String gitPushUrl; - String htmlUrl; - boolean publicX; - Date createdAt; - Date updatedAt; - String description; - int comments; - String commentsUrl; - boolean truncated; - String ownerName; - @SerializedName("id") String gistId; - @Convert(GitHubFilesConverter.class) GithubFileModel files; - @Column(name = "user_column") @Convert(UserConverter.class) User user; - @Convert(UserConverter.class) User owner; - - public static Disposable save(@NonNull List models, @NonNull String ownerName) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - Login login = Login.getUser(); - if (login != null) { - if (login.getLogin().equalsIgnoreCase(ownerName)) { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - dataSource.delete(Gist.class) - .where(Gist.OWNER_NAME.equal(ownerName)) - .get() - .value(); - if (!models.isEmpty()) { - for (Gist gistModel : models) { - dataSource.delete(Gist.class).where(ID.eq(gistModel.getId())).get().value(); - gistModel.setOwnerName(ownerName); - dataSource.insert(gistModel); - } - } - } else { - App.getInstance().getDataStore().toBlocking() - .delete(Gist.class) - .where(Gist.OWNER_NAME.notEqual(ownerName) - .or(OWNER_NAME.isNull())) - .get() - .value(); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - @NonNull public static Single> getMyGists(@NonNull String ownerName) { - return App.getInstance() - .getDataStore() - .select(Gist.class) - .where(Gist.OWNER_NAME.equal(ownerName)) - .get() - .observable() - .toList(); - } - - @NonNull public static Single> getGists() { - return App.getInstance() - .getDataStore() - .select(Gist.class) - .where(Gist.OWNER_NAME.isNull()) - .get() - .observable() - .toList(); - } - - public static Observable getGist(@NonNull String gistId) { - return App.getInstance() - .getDataStore() - .select(Gist.class) - .where(Gist.GIST_ID.eq(gistId)) - .get() - .observable(); - } - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AbstractGist that = (AbstractGist) o; - return url != null ? url.equals(that.url) : that.url == null; - } - - @Override public int hashCode() { - return url != null ? url.hashCode() : 0; - } - - @NonNull public ArrayList getFilesAsList() { - if (files != null) { - return Stream.of(files) - .map(Map.Entry::getValue) - .collect(Collectors.toCollection(ArrayList::new)); - } - return new ArrayList<>(); - } - - @NonNull public SpannableBuilder getDisplayTitle(boolean isFromProfile) { - return getDisplayTitle(isFromProfile, false); - } - - @NonNull public SpannableBuilder getDisplayTitle(boolean isFromProfile, boolean gistView) { - SpannableBuilder spannableBuilder = SpannableBuilder.builder(); - boolean addDescription = true; - if (!isFromProfile) { - if (owner != null) { - spannableBuilder.bold(owner.getLogin()); - } else if (user != null) { - spannableBuilder.bold(user.getLogin()); - } else { - spannableBuilder.bold("Anonymous"); - } - if (!gistView) { - List files = getFilesAsList(); - if (!files.isEmpty()) { - FilesListModel filesListModel = files.get(0); - if (!InputHelper.isEmpty(filesListModel.getFilename()) && filesListModel.getFilename().trim().length() > 2) { - spannableBuilder.append(" ").append("/").append(" ") - .append(filesListModel.getFilename()); - addDescription = false; - } - } - } - } - if (!InputHelper.isEmpty(description) && addDescription) { - if (!InputHelper.isEmpty(spannableBuilder.toString())) { - spannableBuilder.append(" ").append("/").append(" "); - } - spannableBuilder.append(description); - } - if (InputHelper.isEmpty(spannableBuilder.toString())) { - if (isFromProfile) { - List files = getFilesAsList(); - if (!files.isEmpty()) { - FilesListModel filesListModel = files.get(0); - if (!InputHelper.isEmpty(filesListModel.getFilename()) && filesListModel.getFilename().trim().length() > 2) { - spannableBuilder.append(" ") - .append(filesListModel.getFilename()); - } - } - } - } - return spannableBuilder; - } - - public long getSize() { - List models = getFilesAsList(); - if (!models.isEmpty()) { - return Stream.of(models).flatMapToLong(filesListModel -> LongStream.of(filesListModel.getSize())).sum(); - } - return 0; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.url); - dest.writeString(this.forksUrl); - dest.writeString(this.commitsUrl); - dest.writeString(this.gitPullUrl); - dest.writeString(this.gitPushUrl); - dest.writeString(this.htmlUrl); - dest.writeByte(this.publicX ? (byte) 1 : (byte) 0); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeString(this.description); - dest.writeInt(this.comments); - dest.writeString(this.commentsUrl); - dest.writeByte(this.truncated ? (byte) 1 : (byte) 0); - dest.writeString(this.ownerName); - dest.writeString(this.gistId); - dest.writeSerializable(this.files); - dest.writeParcelable(this.user, flags); - dest.writeParcelable(this.owner, flags); - } - - protected AbstractGist(Parcel in) { - this.id = in.readLong(); - this.url = in.readString(); - this.forksUrl = in.readString(); - this.commitsUrl = in.readString(); - this.gitPullUrl = in.readString(); - this.gitPushUrl = in.readString(); - this.htmlUrl = in.readString(); - this.publicX = in.readByte() != 0; - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - this.description = in.readString(); - this.comments = in.readInt(); - this.commentsUrl = in.readString(); - this.truncated = in.readByte() != 0; - this.ownerName = in.readString(); - this.gistId = in.readString(); - this.files = (GithubFileModel) in.readSerializable(); - this.user = in.readParcelable(User.class.getClassLoader()); - this.owner = in.readParcelable(User.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public Gist createFromParcel(Parcel source) {return new Gist(source);} - - @Override public Gist[] newArray(int size) {return new Gist[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractIssue.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractIssue.java deleted file mode 100644 index 86c886f3b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractIssue.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.fastaccess.App; -import com.fastaccess.data.dao.LabelListModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.data.dao.UsersListModel; -import com.fastaccess.data.dao.converters.LabelsListConverter; -import com.fastaccess.data.dao.converters.MilestoneConverter; -import com.fastaccess.data.dao.converters.PullRequestConverter; -import com.fastaccess.data.dao.converters.ReactionsConverter; -import com.fastaccess.data.dao.converters.RepoConverter; -import com.fastaccess.data.dao.converters.UserConverter; -import com.fastaccess.data.dao.converters.UsersConverter; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.RxHelper; - -import java.util.Date; -import java.util.List; - -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Column; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Persistable; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.Issue.ID; -import static com.fastaccess.data.dao.model.Issue.LOGIN; -import static com.fastaccess.data.dao.model.Issue.NUMBER; -import static com.fastaccess.data.dao.model.Issue.REPO_ID; -import static com.fastaccess.data.dao.model.Issue.STATE; -import static com.fastaccess.data.dao.model.Issue.UPDATED_AT; - -/** - * Created by Kosh on 16 Mar 2017, 7:34 PM - */ -@Entity @NoArgsConstructor public abstract class AbstractIssue implements Parcelable { - @Key long id; - String url; - String body; - String title; - int comments; - int number; - boolean locked; - IssueState state; - String repoUrl; - String bodyHtml; - String htmlUrl; - Date closedAt; - Date createdAt; - Date updatedAt; - String repoId; - String login; - @Column(name = "user_column") @Convert(UserConverter.class) User user; - @Convert(UserConverter.class) User assignee; - @Convert(UsersConverter.class) UsersListModel assignees; - @Convert(LabelsListConverter.class) LabelListModel labels; - @Convert(MilestoneConverter.class) MilestoneModel milestone; - @Convert(RepoConverter.class) Repo repository; - @Convert(PullRequestConverter.class) PullRequest pullRequest; - @Convert(UserConverter.class) User closedBy; - @Convert(ReactionsConverter.class) ReactionsModel reactions; - - public Single save(Issue entity) { - return RxHelper.getSingle(App.getInstance().getDataStore() - .delete(Issue.class) - .where(Issue.ID.eq(entity.getId())) - .get() - .single() - .flatMap(observer -> App.getInstance().getDataStore().insert(entity))); - } - - public static Disposable save(@NonNull List models, @NonNull String repoId, @NonNull String login) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - dataSource.delete(Issue.class) - .where(REPO_ID.equal(repoId).and(LOGIN.equal(login))) - .get() - .value(); - if (!models.isEmpty()) { - for (Issue issueModel : models) { - dataSource.delete(Issue.class).where(Issue.ID.eq(issueModel.getId())).get().value(); - issueModel.setRepoId(repoId); - issueModel.setLogin(login); - dataSource.insert(issueModel); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - public static Single> getIssues(@NonNull String repoId, @NonNull String login, @NonNull IssueState issueState) { - return App.getInstance().getDataStore().select(Issue.class) - .where(REPO_ID.equal(repoId) - .and(LOGIN.equal(login)) - .and(STATE.equal(issueState))) - .orderBy(UPDATED_AT.desc()) - .get() - .observable() - .toList(); - } - - public static Observable getIssue(long id) { - return App.getInstance().getDataStore() - .select(Issue.class) - .where(ID.equal(id)) - .get() - .observable(); - } - - public static Observable getIssueByNumber(int number, String repoId, String login) { - return App.getInstance().getDataStore() - .select(Issue.class) - .where(NUMBER.equal(number) - .and(REPO_ID.eq(repoId)) - .and(LOGIN.eq(login))) - .get() - .observable(); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.url); - dest.writeString(this.body); - dest.writeString(this.title); - dest.writeInt(this.comments); - dest.writeInt(this.number); - dest.writeByte(this.locked ? (byte) 1 : (byte) 0); - dest.writeInt(this.state == null ? -1 : this.state.ordinal()); - dest.writeString(this.repoUrl); - dest.writeString(this.bodyHtml); - dest.writeString(this.htmlUrl); - dest.writeLong(this.closedAt != null ? this.closedAt.getTime() : -1); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeString(this.repoId); - dest.writeString(this.login); - dest.writeParcelable(this.user, flags); - dest.writeParcelable(this.assignee, flags); - dest.writeList(this.assignees); - dest.writeList(this.labels); - dest.writeParcelable(this.milestone, flags); - dest.writeParcelable(this.repository, flags); - dest.writeParcelable(this.pullRequest, flags); - dest.writeParcelable(this.closedBy, flags); - dest.writeParcelable(this.reactions, flags); - } - - protected AbstractIssue(Parcel in) { - this.id = in.readLong(); - this.url = in.readString(); - this.body = in.readString(); - this.title = in.readString(); - this.comments = in.readInt(); - this.number = in.readInt(); - this.locked = in.readByte() != 0; - int tmpState = in.readInt(); - this.state = tmpState == -1 ? null : IssueState.values()[tmpState]; - this.repoUrl = in.readString(); - this.bodyHtml = in.readString(); - this.htmlUrl = in.readString(); - long tmpClosedAt = in.readLong(); - this.closedAt = tmpClosedAt == -1 ? null : new Date(tmpClosedAt); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - this.repoId = in.readString(); - this.login = in.readString(); - this.user = in.readParcelable(User.class.getClassLoader()); - this.assignee = in.readParcelable(User.class.getClassLoader()); - this.assignees = new UsersListModel(); - in.readList(this.assignees, this.assignees.getClass().getClassLoader()); - this.labels = new LabelListModel(); - in.readList(this.labels, this.labels.getClass().getClassLoader()); - this.milestone = in.readParcelable(MilestoneModel.class.getClassLoader()); - this.repository = in.readParcelable(Repo.class.getClassLoader()); - this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader()); - this.closedBy = in.readParcelable(User.class.getClassLoader()); - this.reactions = in.readParcelable(ReactionsModel.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public Issue createFromParcel(Parcel source) {return new Issue(source);} - - @Override public Issue[] newArray(int size) {return new Issue[size];} - }; - -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractIssueEvent.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractIssueEvent.java deleted file mode 100644 index 74f1176ca..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractIssueEvent.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.fastaccess.App; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.RenameModel; -import com.fastaccess.data.dao.TeamsModel; -import com.fastaccess.data.dao.converters.IssueConverter; -import com.fastaccess.data.dao.converters.LabelConverter; -import com.fastaccess.data.dao.converters.MilestoneConverter; -import com.fastaccess.data.dao.converters.RenameConverter; -import com.fastaccess.data.dao.converters.TeamConverter; -import com.fastaccess.data.dao.converters.UserConverter; -import com.fastaccess.data.dao.types.IssueEventType; -import com.fastaccess.helper.RxHelper; - -import java.util.Date; -import java.util.List; - -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Persistable; -import io.requery.Transient; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.IssueEvent.CREATED_AT; -import static com.fastaccess.data.dao.model.IssueEvent.ISSUE_ID; -import static com.fastaccess.data.dao.model.IssueEvent.LOGIN; -import static com.fastaccess.data.dao.model.IssueEvent.REPO_ID; - -/** - * Created by Kosh on 16 Mar 2017, 7:33 PM - */ - -@Entity @NoArgsConstructor public abstract class AbstractIssueEvent implements Parcelable { - - @Key long id; - String url; - IssueEventType event; - @Convert(UserConverter.class) User actor; - @Convert(UserConverter.class) User assigner; - @Convert(UserConverter.class) User assignee; - @Convert(UserConverter.class) User requestedReviewer; - @Convert(TeamConverter.class) TeamsModel requestedTeam; - @Convert(MilestoneConverter.class) MilestoneModel milestone; - @Convert(RenameConverter.class) RenameModel rename; - @Convert(IssueConverter.class) Issue source; - @Convert(LabelConverter.class) LabelModel label; - String commitId; - String commitUrl; - Date createdAt; - String issueId; - String repoId; - String login; - @Transient List labels; - @Transient Issue issue; - - public static Disposable save(@NonNull List models, @NonNull String repoId, - @NonNull String login, @NonNull String issueId) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - dataSource.delete(IssueEvent.class) - .where(LOGIN.equal(login) - .and(REPO_ID.equal(repoId)) - .and(ISSUE_ID.equal(issueId))) - .get() - .value(); - if (!models.isEmpty()) { - for (IssueEvent issueEventModel : models) { - dataSource.delete(IssueEvent.class).where(IssueEvent.ID.eq(issueEventModel.getId())).get().value(); - issueEventModel.setIssueId(issueId); - issueEventModel.setLogin(login); - issueEventModel.setRepoId(repoId); - dataSource.insert(issueEventModel); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - public static Single> get(@NonNull String repoId, @NonNull String login, - @NonNull String issueId) { - return App.getInstance().getDataStore() - .select(IssueEvent.class) - .where(LOGIN.equal(login) - .and(REPO_ID.equal(repoId)) - .and(ISSUE_ID.equal(issueId))) - .orderBy(CREATED_AT.desc()) - .get() - .observable() - .toList(); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.url); - dest.writeInt(this.event == null ? -1 : this.event.ordinal()); - dest.writeParcelable(this.actor, flags); - dest.writeParcelable(this.assigner, flags); - dest.writeParcelable(this.assignee, flags); - dest.writeParcelable(this.requestedReviewer, flags); - dest.writeParcelable(this.requestedTeam, flags); - dest.writeParcelable(this.milestone, flags); - dest.writeParcelable(this.rename, flags); - dest.writeParcelable(this.source, flags); - dest.writeParcelable(this.label, flags); - dest.writeString(this.commitId); - dest.writeString(this.commitUrl); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeString(this.issueId); - dest.writeString(this.repoId); - dest.writeString(this.login); - dest.writeTypedList(this.labels); - dest.writeParcelable(this.issue, flags); - } - - protected AbstractIssueEvent(Parcel in) { - this.id = in.readLong(); - this.url = in.readString(); - int tmpEvent = in.readInt(); - this.event = tmpEvent == -1 ? null : IssueEventType.values()[tmpEvent]; - this.actor = in.readParcelable(User.class.getClassLoader()); - this.assigner = in.readParcelable(User.class.getClassLoader()); - this.assignee = in.readParcelable(User.class.getClassLoader()); - this.requestedReviewer = in.readParcelable(User.class.getClassLoader()); - this.requestedTeam = in.readParcelable(TeamsModel.class.getClassLoader()); - this.milestone = in.readParcelable(MilestoneModel.class.getClassLoader()); - this.rename = in.readParcelable(RenameModel.class.getClassLoader()); - this.source = in.readParcelable(Issue.class.getClassLoader()); - this.label = in.readParcelable(LabelModel.class.getClassLoader()); - this.commitId = in.readString(); - this.commitUrl = in.readString(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - this.issueId = in.readString(); - this.repoId = in.readString(); - this.login = in.readString(); - this.labels = in.createTypedArrayList(LabelModel.CREATOR); - this.issue = in.readParcelable(Issue.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public IssueEvent createFromParcel(Parcel source) {return new IssueEvent(source);} - - @Override public IssueEvent[] newArray(int size) {return new IssueEvent[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractLogin.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractLogin.java deleted file mode 100644 index 86a6c09c4..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractLogin.java +++ /dev/null @@ -1,263 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.fastaccess.App; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.RxHelper; - -import java.util.Date; - -import io.reactivex.Observable; -import io.requery.Column; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Nullable; -import lombok.NoArgsConstructor; - -/** - * Created by Kosh on 16 Mar 2017, 7:36 PM - */ - -@Entity @NoArgsConstructor public abstract class AbstractLogin implements Parcelable { - @Key long id; - @Column String login; - String avatarUrl; - String gravatarId; - String url; - String htmlUrl; - String followersUrl; - String followingUrl; - String gistsUrl; - String starredUrl; - String subscriptionsUrl; - String organizationsUrl; - String reposUrl; - String eventsUrl; - String receivedEventsUrl; - String type; - boolean siteAdmin; - String name; - String company; - String blog; - String location; - String email; - boolean hireable; - String bio; - long publicRepos; - long publicGists; - long followers; - long following; - Date createdAt; - Date updatedAt; - String token; - int contributions; - @Nullable boolean isLoggedIn; - @Nullable boolean isEnterprise; - @Nullable String otpCode; - @Nullable String enterpriseUrl; - - public Observable update(Login login) { - return RxHelper.safeObservable(App.getInstance().getDataStore().update(login) - .toObservable()); - } - - public void save(Login entity) { - App.getInstance().getDataStore() - .delete(Login.class) - .where(Login.LOGIN.eq(entity.getLogin())) - .get() - .single() - .flatMap(integer -> App.getInstance().getDataStore().insert(entity)) - .blockingGet(); - } - - public static Login getUser() { - return App.getInstance().getDataStore() - .select(Login.class) - .where(Login.LOGIN.notNull() - .and(Login.TOKEN.notNull()) - .and(Login.IS_LOGGED_IN.eq(true))) - .get() - .firstOrNull(); - } - - public static Login getUser(@NonNull String login) { - return App.getInstance().getDataStore() - .select(Login.class) - .where(Login.LOGIN.eq(login) - .and(Login.TOKEN.notNull())) - .get() - .firstOrNull(); - } - - public static Observable getAccounts() { - return App.getInstance().getDataStore() - .select(Login.class) - .where(Login.IS_LOGGED_IN.eq(false)) - .orderBy(Login.LOGIN.desc()) - .get() - .observable(); - } - - public static void logout() { - Login login = getUser(); - if (login == null) return; - App.getInstance().getDataStore().toBlocking().delete(PinnedRepos.class) - .where(PinnedRepos.LOGIN.eq(login.getLogin())).get().value(); - App.getInstance().getDataStore().toBlocking().delete(login); - } - - public static boolean hasNormalLogin() { - return App.getInstance().getDataStore() - .count(Login.class) - .where(Login.IS_ENTERPRISE.eq(false) - .or(Login.IS_ENTERPRISE.isNull())) - .get() - .value() > 0; - } - - public static Observable onMultipleLogin(@NonNull Login userModel, boolean isEnterprise, boolean isNew) { - return Observable.fromPublisher(s -> { - Login currentUser = Login.getUser(); - if (currentUser != null) { - currentUser.setIsLoggedIn(false); - App.getInstance().getDataStore() - .toBlocking() - .update(currentUser); - } - if (!isEnterprise) { - PrefGetter.resetEnterprise(); - } - userModel.setIsLoggedIn(true); - if (isNew) { - userModel.setIsEnterprise(isEnterprise); - userModel.setToken(isEnterprise ? PrefGetter.getEnterpriseToken() : PrefGetter.getToken()); - userModel.setOtpCode(isEnterprise ? PrefGetter.getEnterpriseOtpCode() : PrefGetter.getOtpCode()); - userModel.setEnterpriseUrl(isEnterprise ? PrefGetter.getEnterpriseUrl() : null); - App.getInstance().getDataStore() - .toBlocking() - .delete(Login.class) - .where(Login.ID.eq(userModel.getId())) - .get() - .value(); - App.getInstance().getDataStore() - .toBlocking() - .insert(userModel); - } else { - if (isEnterprise) { - PrefGetter.setTokenEnterprise(userModel.token); - PrefGetter.setEnterpriseOtpCode(userModel.otpCode); - PrefGetter.setEnterpriseUrl(userModel.enterpriseUrl); - } else { - PrefGetter.resetEnterprise(); - PrefGetter.setToken(userModel.token); - PrefGetter.setOtpCode(userModel.otpCode); - } - App.getInstance().getDataStore() - .toBlocking() - .update(userModel); - } - s.onNext(true); - s.onComplete(); - }); - } - - @Override public int describeContents() { - return 0; - } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.login); - dest.writeString(this.avatarUrl); - dest.writeString(this.gravatarId); - dest.writeString(this.url); - dest.writeString(this.htmlUrl); - dest.writeString(this.followersUrl); - dest.writeString(this.followingUrl); - dest.writeString(this.gistsUrl); - dest.writeString(this.starredUrl); - dest.writeString(this.subscriptionsUrl); - dest.writeString(this.organizationsUrl); - dest.writeString(this.reposUrl); - dest.writeString(this.eventsUrl); - dest.writeString(this.receivedEventsUrl); - dest.writeString(this.type); - dest.writeByte(this.siteAdmin ? (byte) 1 : (byte) 0); - dest.writeString(this.name); - dest.writeString(this.company); - dest.writeString(this.blog); - dest.writeString(this.location); - dest.writeString(this.email); - dest.writeByte(this.hireable ? (byte) 1 : (byte) 0); - dest.writeString(this.bio); - dest.writeLong(this.publicRepos); - dest.writeLong(this.publicGists); - dest.writeLong(this.followers); - dest.writeLong(this.following); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeString(this.token); - dest.writeInt(this.contributions); - dest.writeByte(this.isLoggedIn ? (byte) 1 : (byte) 0); - dest.writeByte(this.isEnterprise ? (byte) 1 : (byte) 0); - dest.writeString(this.otpCode); - dest.writeString(this.enterpriseUrl); - } - - protected AbstractLogin(Parcel in) { - this.id = in.readLong(); - this.login = in.readString(); - this.avatarUrl = in.readString(); - this.gravatarId = in.readString(); - this.url = in.readString(); - this.htmlUrl = in.readString(); - this.followersUrl = in.readString(); - this.followingUrl = in.readString(); - this.gistsUrl = in.readString(); - this.starredUrl = in.readString(); - this.subscriptionsUrl = in.readString(); - this.organizationsUrl = in.readString(); - this.reposUrl = in.readString(); - this.eventsUrl = in.readString(); - this.receivedEventsUrl = in.readString(); - this.type = in.readString(); - this.siteAdmin = in.readByte() != 0; - this.name = in.readString(); - this.company = in.readString(); - this.blog = in.readString(); - this.location = in.readString(); - this.email = in.readString(); - this.hireable = in.readByte() != 0; - this.bio = in.readString(); - this.publicRepos = in.readLong(); - this.publicGists = in.readLong(); - this.followers = in.readLong(); - this.following = in.readLong(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - this.token = in.readString(); - this.contributions = in.readInt(); - this.isLoggedIn = in.readByte() != 0; - this.isEnterprise = in.readByte() != 0; - this.otpCode = in.readString(); - this.enterpriseUrl = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override - public Login createFromParcel(Parcel source) { - return new Login(source); - } - - @Override - public Login[] newArray(int size) { - return new Login[size]; - } - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractNotification.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractNotification.java deleted file mode 100644 index 573f44dd0..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractNotification.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.App; -import com.fastaccess.data.dao.NotificationSubjectModel; -import com.fastaccess.data.dao.converters.NotificationSubjectConverter; -import com.fastaccess.data.dao.converters.RepoConverter; -import com.fastaccess.data.dao.types.NotificationReason; -import com.fastaccess.helper.RxHelper; - -import java.util.Date; -import java.util.List; - -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Nullable; -import io.requery.Persistable; -import lombok.NoArgsConstructor; - -/** - * Created by Kosh on 16 Mar 2017, 7:37 PM - */ - -@Entity @NoArgsConstructor public abstract class AbstractNotification implements Parcelable { - @Key long id; - @Convert(RepoConverter.class) Repo repository; - @Convert(NotificationSubjectConverter.class) NotificationSubjectModel subject; - NotificationReason reason; - String url; - boolean unread; - Date updatedAt; - Date lastReadAt; - @Nullable boolean isSubscribed; - - public Disposable save(Notification entity) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataStore = App.getInstance().getDataStore().toBlocking(); - dataStore.delete(Notification.class).where(Notification.ID.eq(entity.getId())).get().value(); - dataStore.insert(entity); - s.onNext(true); - } catch (Exception e) { - e.printStackTrace(); - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*do nothing*/}, Throwable::printStackTrace); - } - - public static Disposable markAsRead(long id) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataStore = App.getInstance().getDataStore().toBlocking(); - Notification current = dataStore.select(Notification.class).where(Notification.ID.eq(id)).get().firstOrNull(); - if (current != null) { - current.setUnread(false); - dataStore.update(current); - } - s.onNext(true); - } catch (Exception e) { - e.printStackTrace(); - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*do nothing*/}, Throwable::printStackTrace); - } - - public static Disposable save(@android.support.annotation.Nullable List models) { - if (models == null || models.isEmpty()) { - return Observable.empty().subscribe(); - } - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataStore = App.getInstance().getDataStore().toBlocking(); - for (Notification entity : models) { - dataStore.delete(Notification.class).where(Notification.ID.eq(entity.getId())).get().value(); - } - dataStore.insert(models); - s.onNext(true); - } catch (Exception e) { - e.printStackTrace(); - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*do nothing*/}, Throwable::printStackTrace); - } - - public static Single saveAsSingle(@android.support.annotation.Nullable List models) { - if (models == null || models.isEmpty()) { - return Single.just(true); - } - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataStore = App.getInstance().getDataStore().toBlocking(); - for (Notification entity : models) { - dataStore.delete(Notification.class).where(Notification.ID.eq(entity.getId())).get().value(); - } - dataStore.insert(models); - s.onNext(true); - } catch (Exception e) { - e.printStackTrace(); - s.onError(e); - } - s.onComplete(); - })); - } - - public static Single> getUnreadNotifications() { - return App.getInstance() - .getDataStore() - .select(Notification.class) - .where(Notification.UNREAD.eq(true)) - .orderBy(Notification.UPDATED_AT.desc()) - .get() - .observable() - .toList(); - } - - public static Single> getAllNotifications() { - return App.getInstance() - .getDataStore() - .select(Notification.class) - .orderBy(Notification.UPDATED_AT.desc(), Notification.UNREAD.eq(false).getLeftOperand()) - .get() - .observable() - .toList(); - } - - public static boolean hasUnreadNotifications() { - return App.getInstance() - .getDataStore() - .toBlocking() - .count(Notification.class) - .where(Notification.UNREAD.equal(true)) - .get() - .value() > 0; - } - - public static void deleteAll() { - App.getInstance().getDataStore().toBlocking().delete(Notification.class).get().value(); - } - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Notification that = (Notification) o; - return repository != null && that.repository != null && repository.getId() == that.repository.getId(); - } - - @Override public int hashCode() { - return repository != null ? (int) repository.getId() : 0; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeParcelable(this.repository, flags); - dest.writeParcelable(this.subject, flags); - dest.writeInt(this.reason == null ? -1 : this.reason.ordinal()); - dest.writeString(this.url); - dest.writeByte(this.unread ? (byte) 1 : (byte) 0); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeLong(this.lastReadAt != null ? this.lastReadAt.getTime() : -1); - dest.writeByte(this.isSubscribed ? (byte) 1 : (byte) 0); - } - - protected AbstractNotification(Parcel in) { - this.id = in.readLong(); - this.repository = in.readParcelable(Repo.class.getClassLoader()); - this.subject = in.readParcelable(NotificationSubjectModel.class.getClassLoader()); - int tmpReason = in.readInt(); - this.reason = tmpReason == -1 ? null : NotificationReason.values()[tmpReason]; - this.url = in.readString(); - this.unread = in.readByte() != 0; - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - long tmpLastReadAt = in.readLong(); - this.lastReadAt = tmpLastReadAt == -1 ? null : new Date(tmpLastReadAt); - this.isSubscribed = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override public Notification createFromParcel(Parcel source) {return new Notification(source);} - - @Override public Notification[] newArray(int size) {return new Notification[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractNotificationQueue.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractNotificationQueue.java deleted file mode 100644 index 4a24acdab..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractNotificationQueue.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.App; -import com.fastaccess.helper.RxHelper; - -import java.util.Date; -import java.util.List; - -import javax.annotation.Nullable; - -import io.reactivex.Observable; -import io.requery.BlockingEntityStore; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Persistable; -import lombok.NoArgsConstructor; - -/** - * Created by Kosh on 03.11.17. - */ - -@Entity @NoArgsConstructor public abstract class AbstractNotificationQueue implements Parcelable { - @Key long notificationId; - Date date; - - public static boolean exists(long notificationId) { - return App.getInstance().getDataStore().toBlocking().select(NotificationQueue.class) - .where(NotificationQueue.NOTIFICATION_ID.eq(notificationId)) - .get().firstOrNull() != null; - } - - public static Observable put(@Nullable List models) { - if (models == null || models.isEmpty()) { - return Observable.empty(); - } - return RxHelper.getObservable(Observable.fromPublisher(s -> { - try { - BlockingEntityStore dataStore = App.getInstance().getDataStore().toBlocking(); - dataStore.delete(NotificationQueue.class).get().value(); - for (Notification entity : models) { - NotificationQueue notificationQueue = new NotificationQueue(); - notificationQueue.setNotificationId(entity.getId()); - notificationQueue.setDate(entity.getUpdatedAt()); - dataStore.insert(notificationQueue); - } - s.onNext(true); - } catch (Exception e) { - e.printStackTrace(); - s.onError(e); - } - s.onComplete(); - })); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.notificationId); - dest.writeLong(this.date != null ? this.date.getTime() : -1); - } - - protected AbstractNotificationQueue(Parcel in) { - this.notificationId = in.readLong(); - long tmpDate = in.readLong(); - this.date = tmpDate == -1 ? null : new Date(tmpDate); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public NotificationQueue createFromParcel(Parcel source) {return new NotificationQueue(source);} - - @Override public NotificationQueue[] newArray(int size) {return new NotificationQueue[size];} - }; - -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedGists.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedGists.java deleted file mode 100644 index 66ce439d1..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedGists.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.App; -import com.fastaccess.data.dao.converters.GistConverter; - -import java.util.List; - -import io.reactivex.Single; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Generated; -import io.requery.Key; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.PinnedGists.ENTRY_COUNT; -import static com.fastaccess.data.dao.model.PinnedGists.ID; -import static com.fastaccess.data.dao.model.PinnedGists.LOGIN; - -/** - * Created by Hashemsergani on 14.10.17. - */ - -@Entity @NoArgsConstructor public class AbstractPinnedGists { - - @Key @Generated long id; - @io.requery.Nullable int entryCount; - @io.requery.Nullable String login; - @io.requery.Nullable @Convert(GistConverter.class) Gist gist; - @io.requery.Nullable long gistId; - - public static void pinUpin(@NonNull Gist gist) { - PinnedGists pinnedIssues = get(gist.getGistId().hashCode()); - if (pinnedIssues == null) { - PinnedGists pinned = new PinnedGists(); - pinned.setLogin(Login.getUser().getLogin()); - pinned.setGist(gist); - pinned.setGistId(gist.getGistId().hashCode()); - try { - App.getInstance().getDataStore().toBlocking().insert(pinned); - } catch (Exception ignored) {} - } else { - delete(gist.getGistId().hashCode()); - } - } - - @Nullable public static PinnedGists get(long gistId) { - return App.getInstance().getDataStore().select(PinnedGists.class) - .where(PinnedGists.GIST_ID.eq(gistId)) - .get() - .firstOrNull(); - } - - public static void delete(long gistId) { - App.getInstance().getDataStore().delete(PinnedGists.class) - .where(PinnedGists.GIST_ID.eq(gistId)) - .get() - .value(); - } - - @NonNull public static Single> getMyPinnedGists() { - return App.getInstance().getDataStore().select(PinnedGists.class) - .where(LOGIN.eq(Login.getUser().getLogin()).or(LOGIN.isNull())) - .orderBy(ENTRY_COUNT.desc(), ID.desc()) - .get() - .observable() - .map(PinnedGists::getGist) - .toList(); - } - - public static boolean isPinned(long gistId) { - return get(gistId) != null; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedIssues.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedIssues.java deleted file mode 100644 index 22cdc9adc..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedIssues.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.App; -import com.fastaccess.data.dao.converters.IssueConverter; -import com.fastaccess.helper.RxHelper; - -import java.util.List; - -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Generated; -import io.requery.Key; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.PinnedIssues.ENTRY_COUNT; -import static com.fastaccess.data.dao.model.PinnedIssues.ID; -import static com.fastaccess.data.dao.model.PinnedIssues.LOGIN; - -/** - * Created by Hashemsergani on 14.10.17. - */ - -@Entity @NoArgsConstructor public class AbstractPinnedIssues { - - @Key @Generated long id; - @io.requery.Nullable int entryCount; - @io.requery.Nullable String login; - @io.requery.Nullable @Convert(IssueConverter.class) Issue issue; - @io.requery.Nullable long issueId; - - public static void pinUpin(@NonNull Issue issue) { - PinnedIssues pinnedIssues = get(issue.getId()); - if (pinnedIssues == null) { - PinnedIssues pinned = new PinnedIssues(); - pinned.setLogin(Login.getUser().getLogin()); - pinned.setIssue(issue); - pinned.setIssueId(issue.getId()); - try { - App.getInstance().getDataStore().toBlocking().insert(pinned); - } catch (Exception ignored) {} - } else { - delete(issue.getId()); - } - } - - @Nullable public static PinnedIssues get(long issueId) { - return App.getInstance().getDataStore().select(PinnedIssues.class) - .where(PinnedIssues.ISSUE_ID.eq(issueId)) - .get() - .firstOrNull(); - } - - public static void delete(long issueId) { - App.getInstance().getDataStore().delete(PinnedIssues.class) - .where(PinnedIssues.ISSUE_ID.eq(issueId)) - .get() - .value(); - } - - @NonNull public static Disposable updateEntry(long issueId) { - return RxHelper.getObservable(Observable.fromPublisher(e -> { - PinnedIssues pinned = get(issueId); - if (pinned != null) { - pinned.setEntryCount(pinned.getEntryCount() + 1); - App.getInstance().getDataStore().toBlocking().update(pinned); - e.onNext(""); - } - e.onComplete(); - })).subscribe(o -> {/*do nothing*/}, Throwable::printStackTrace); - } - - @NonNull public static Single> getMyPinnedIssues() { - return App.getInstance().getDataStore().select(PinnedIssues.class) - .where(LOGIN.eq(Login.getUser().getLogin()).or(LOGIN.isNull())) - .orderBy(ENTRY_COUNT.desc(), ID.desc()) - .get() - .observable() - .map(PinnedIssues::getIssue) - .toList(); - } - - public static boolean isPinned(long issueId) { - return get(issueId) != null; - } - -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedPullRequests.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedPullRequests.java deleted file mode 100644 index 869d78f62..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedPullRequests.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.App; -import com.fastaccess.data.dao.converters.PullRequestConverter; -import com.fastaccess.helper.RxHelper; - -import java.util.List; - -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Generated; -import io.requery.Key; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.PinnedPullRequests.ENTRY_COUNT; -import static com.fastaccess.data.dao.model.PinnedPullRequests.ID; -import static com.fastaccess.data.dao.model.PinnedPullRequests.LOGIN; - -/** - * Created by Hashemsergani on 14.10.17. - */ - -@Entity @NoArgsConstructor public class AbstractPinnedPullRequests { - - @Key @Generated long id; - @io.requery.Nullable int entryCount; - @io.requery.Nullable String login; - @io.requery.Nullable @Convert(PullRequestConverter.class) PullRequest pullRequest; - @io.requery.Nullable long pullRequestId; - - public static void pinUpin(@NonNull PullRequest pullRequest) { - PinnedPullRequests pinnedPullRequests = get(pullRequest.getId()); - if (pinnedPullRequests == null) { - PinnedPullRequests pinned = new PinnedPullRequests(); - pinned.setLogin(Login.getUser().getLogin()); - pinned.setPullRequest(pullRequest); - pinned.setPullRequestId(pullRequest.getId()); - try { - App.getInstance().getDataStore().toBlocking().insert(pinned); - } catch (Exception ignored) {} - } else { - delete(pullRequest.getId()); - } - } - - @Nullable public static PinnedPullRequests get(long pullRequestId) { - return App.getInstance().getDataStore().select(PinnedPullRequests.class) - .where(PinnedPullRequests.PULL_REQUEST_ID.eq(pullRequestId)) - .get() - .firstOrNull(); - } - - public static void delete(long pullRequestId) { - App.getInstance().getDataStore().delete(PinnedPullRequests.class) - .where(PinnedPullRequests.PULL_REQUEST_ID.eq(pullRequestId)) - .get() - .value(); - } - - @NonNull public static Disposable updateEntry(@NonNull long pullRequestId) { - return RxHelper.getObservable(Observable.fromPublisher(e -> { - PinnedPullRequests pinned = get(pullRequestId); - if (pinned != null) { - pinned.setEntryCount(pinned.getEntryCount() + 1); - App.getInstance().getDataStore().toBlocking().update(pinned); - e.onNext(""); - } - e.onComplete(); - })).subscribe(o -> {/*do nothing*/}, Throwable::printStackTrace); - } - - @NonNull public static Single> getMyPinnedPullRequests() { - return App.getInstance().getDataStore().select(PinnedPullRequests.class) - .where(LOGIN.eq(Login.getUser().getLogin()).or(LOGIN.isNull())) - .orderBy(ENTRY_COUNT.desc(), ID.desc()) - .get() - .observable() - .map(PinnedPullRequests::getPullRequest) - .toList(); - } - - public static boolean isPinned(long pullRequestId) { - return get(pullRequestId) != null; - } - -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedRepos.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedRepos.java deleted file mode 100644 index e9bfde702..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractPinnedRepos.java +++ /dev/null @@ -1,150 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.App; -import com.fastaccess.data.dao.converters.RepoConverter; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.RxHelper; - -import java.util.List; - -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Column; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Generated; -import io.requery.Key; -import io.requery.Persistable; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.PinnedRepos.ENTRY_COUNT; -import static com.fastaccess.data.dao.model.PinnedRepos.ID; -import static com.fastaccess.data.dao.model.PinnedRepos.LOGIN; -import static com.fastaccess.data.dao.model.PinnedRepos.REPO_FULL_NAME; - -/** - * Created by Kosh on 25 Mar 2017, 7:29 PM - */ - -@Entity @NoArgsConstructor public abstract class AbstractPinnedRepos implements Parcelable { - @Key @Generated long id; - @Column(unique = false) String repoFullName; - @Convert(RepoConverter.class) Repo pinnedRepo; - @io.requery.Nullable int entryCount; - @io.requery.Nullable String login; - - public static Single update(@NonNull PinnedRepos entity) { - return RxHelper.getSingle(App.getInstance().getDataStore().update(entity)); - } - - public static boolean pinUpin(@NonNull Repo repo) { - PinnedRepos pinnedRepos = get(repo.getFullName()); - if (pinnedRepos == null) { - PinnedRepos pinned = new PinnedRepos(); - pinned.setRepoFullName(repo.getFullName()); - pinned.setLogin(Login.getUser().getLogin()); - pinned.setPinnedRepo(repo); - try { - App.getInstance().getDataStore().toBlocking().insert(pinned); - return true; - } catch (Exception ignored) {} - return false; - } else { - delete(pinnedRepos.getId()); - return false; - } - } - - @Nullable public static PinnedRepos get(long id) { - return App.getInstance().getDataStore().select(PinnedRepos.class) - .where(ID.eq(id)) - .get() - .firstOrNull(); - } - - @Nullable public static PinnedRepos get(@NonNull String repoFullName) { - return App.getInstance().getDataStore().toBlocking().select(PinnedRepos.class) - .where(REPO_FULL_NAME.eq(repoFullName).and(LOGIN.eq(Login.getUser().getLogin())) - .or(REPO_FULL_NAME.eq(repoFullName))) - .get() - .firstOrNull(); - } - - public static boolean isPinned(@NonNull String repoFullName) { - return get(repoFullName) != null; - } - - @NonNull public static Disposable updateEntry(@NonNull String repoFullName) { - return RxHelper.getObservable(Observable.fromPublisher(e -> { - PinnedRepos pinned = get(repoFullName); - if (pinned != null) { - pinned.setEntryCount(pinned.getEntryCount() + 1); - App.getInstance().getDataStore().toBlocking().update(pinned); - e.onNext(""); - } - e.onComplete(); - })).subscribe(o -> {/*do nothing*/}, Throwable::printStackTrace); - } - - @NonNull public static Single> getMyPinnedRepos() { - return App.getInstance().getDataStore().select(PinnedRepos.class) - .where(LOGIN.eq(Login.getUser().getLogin()) - .or(LOGIN.isNull())) - .orderBy(ENTRY_COUNT.desc(), ID.desc()) - .get() - .observable() - .toList(); - - } - - @NonNull public static Observable> getMenuRepos() { - return App.getInstance().getDataStore().select(PinnedRepos.class) - .where(LOGIN.eq(Login.getUser().getLogin())) - .orderBy(ENTRY_COUNT.desc(), ID.desc()) - .limit(5) - .get() - .observable() - .toList() - .toObservable(); - } - - public static void migrateToVersion4() { - RxHelper.getObservable(Observable.fromPublisher(e -> { - try { - Login login = Login.getUser(); - if (login == null) { - e.onComplete(); - return; - } - BlockingEntityStore reactiveEntityStore = App.getInstance().getDataStore().toBlocking(); - List pinnedRepos = reactiveEntityStore.select(PinnedRepos.class) - .where(LOGIN.isNull()) - .get() - .toList(); - if (pinnedRepos != null) { - for (PinnedRepos pinnedRepo : pinnedRepos) { - pinnedRepo.setRepoFullName(login.getLogin()); - reactiveEntityStore.update(pinnedRepo); - } - } - Logger.e("Hello"); - } catch (Exception ignored) { - e.onError(ignored); - } - e.onComplete(); - })).subscribe(o -> {/*do nothing*/}, Throwable::printStackTrace); - } - - public static void delete(long id) { - App.getInstance().getDataStore().delete(PinnedRepos.class) - .where(ID.eq(id)) - .get() - .value(); - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractPullRequest.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractPullRequest.java deleted file mode 100644 index 42925d45b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractPullRequest.java +++ /dev/null @@ -1,335 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.content.Context; -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.fastaccess.App; -import com.fastaccess.R; -import com.fastaccess.data.dao.LabelListModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.data.dao.UsersListModel; -import com.fastaccess.data.dao.converters.CommitConverter; -import com.fastaccess.data.dao.converters.LabelsListConverter; -import com.fastaccess.data.dao.converters.MilestoneConverter; -import com.fastaccess.data.dao.converters.PullRequestConverter; -import com.fastaccess.data.dao.converters.ReactionsConverter; -import com.fastaccess.data.dao.converters.UserConverter; -import com.fastaccess.data.dao.converters.UsersConverter; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.ui.widgets.SpannableBuilder; - -import java.util.Date; -import java.util.List; - -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Column; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Persistable; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.PullRequest.ID; -import static com.fastaccess.data.dao.model.PullRequest.LOGIN; -import static com.fastaccess.data.dao.model.PullRequest.NUMBER; -import static com.fastaccess.data.dao.model.PullRequest.REPO_ID; -import static com.fastaccess.data.dao.model.PullRequest.STATE; -import static com.fastaccess.data.dao.model.PullRequest.UPDATED_AT; - -/** - * Created by Kosh on 16 Mar 2017, 7:39 PM - */ - -@Entity @NoArgsConstructor public abstract class AbstractPullRequest implements Parcelable { - @Key long id; - String url; - String body; - String title; - int comments; - int number; - boolean locked; - boolean mergable; - boolean merged; - boolean mergeable; - int commits; - int additions; - int deletions; - IssueState state; - String bodyHtml; - String htmlUrl; - Date closedAt; - Date createdAt; - Date updatedAt; - int changedFiles; - String diffUrl; - String patchUrl; - String mergeCommitSha; - Date mergedAt; - String mergeState; - int reviewComments; - String repoId; - String login; - String mergeableState; - @Convert(UsersConverter.class) UsersListModel assignees; - @Convert(UserConverter.class) User mergedBy; - @Convert(UserConverter.class) User closedBy; - @Column(name = "user_column") @Convert(UserConverter.class) User user; - @Convert(UserConverter.class) User assignee; - @Convert(LabelsListConverter.class) LabelListModel labels; - @Convert(MilestoneConverter.class) MilestoneModel milestone; - @Convert(CommitConverter.class) Commit base; - @Convert(CommitConverter.class) Commit head; - @Convert(PullRequestConverter.class) PullRequest pullRequest; - @Convert(ReactionsConverter.class) ReactionsModel reactions; - - public Single save(PullRequest entity) { - return RxHelper.getSingle(App.getInstance().getDataStore() - .delete(PullRequest.class) - .where(PullRequest.ID.eq(entity.getId())) - .get() - .single() - .flatMap(observer -> App.getInstance().getDataStore().insert(entity))); - } - - public static Disposable save(@NonNull List models, @NonNull String repoId, @NonNull String login) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - dataSource.delete(PullRequest.class) - .where(REPO_ID.equal(repoId) - .and(LOGIN.equal(login))) - .get() - .value(); - if (!models.isEmpty()) { - for (PullRequest pullRequest : models) { - dataSource.delete(PullRequest.class).where(PullRequest.ID.eq(pullRequest.getId())).get().value(); - pullRequest.setRepoId(repoId); - pullRequest.setLogin(login); - dataSource.insert(pullRequest); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - public static Single> getPullRequests(@NonNull String repoId, @NonNull String login, - @NonNull IssueState issueState) { - return App.getInstance().getDataStore() - .select(PullRequest.class) - .where(REPO_ID.equal(repoId) - .and(LOGIN.equal(login)) - .and(STATE.equal(issueState))) - .orderBy(UPDATED_AT.desc()) - .get() - .observable() - .toList(); - } - - public static Observable getPullRequestById(long id) { - return App.getInstance().getDataStore() - .select(PullRequest.class) - .where(ID.eq(id)) - .get() - .observable(); - } - - public static Observable getPullRequestByNumber(int number, @NonNull String repoId, @NonNull String login) { - return App.getInstance().getDataStore() - .select(PullRequest.class) - .where(REPO_ID.equal(repoId) - .and(LOGIN.equal(login)) - .and(NUMBER.equal(number))) - .get() - .observable(); - } - - @NonNull public static SpannableBuilder getMergeBy(@NonNull PullRequest pullRequest, @NonNull Context context, boolean showRepoName) { - boolean isMerge = pullRequest.isMerged() || !InputHelper.isEmpty(pullRequest.mergedAt); - if (isMerge) { - User merger = pullRequest.getMergedBy(); - SpannableBuilder builder = SpannableBuilder.builder(); - if (showRepoName) { - PullsIssuesParser parser = PullsIssuesParser.getForPullRequest(pullRequest.getHtmlUrl()); - if (parser != null) - builder.bold(parser.getLogin()) - .append("/") - .bold(parser.getRepoId()) - .append(" ") - .bold("#").bold(String.valueOf(pullRequest.getNumber())) - .append(" "); - } else { - builder.bold("#" + pullRequest.getNumber()) - .append(" ") - .append(merger != null ? merger.getLogin() + " " : ""); - } - builder.append(context.getString(R.string.merged).toLowerCase()) - .append(" "); - if (pullRequest.getHead() != null) { - builder.bold(pullRequest.getHead().getRef()) - .append(" ") - .append(context.getString(R.string.to)) - .append(" ") - .bold(pullRequest.getBase().getRef()) - .append(" "); - } - builder.append(ParseDateFormat.getTimeAgo(pullRequest.getMergedAt())); - return builder; - } else { - User user = pullRequest.getUser(); - String status = context.getString(pullRequest.getState().getStatus()); - SpannableBuilder builder = SpannableBuilder.builder(); - if (showRepoName) { - PullsIssuesParser parser = PullsIssuesParser.getForPullRequest(pullRequest.getHtmlUrl()); - if (parser != null) { - builder.bold(parser.getLogin()) - .append("/") - .bold(parser.getRepoId()) - .append(" ") - .bold("#").bold(String.valueOf(pullRequest.getNumber())) - .append(" "); - } - } else { - builder.bold("#" + pullRequest.getNumber()) - .append(" ") - .append(user.getLogin()) - .append(" "); - } - if (pullRequest.getState() == IssueState.open && pullRequest.getHead() != null && pullRequest.getBase() != null) { - return builder - .append(context.getString(R.string.want_to_merge)) - .append(" ") - .bold(pullRequest.getHead().getRef()) - .append(" ") - .append(context.getString(R.string.to)) - .append(" ") - .bold(pullRequest.getBase().getRef()) - .append(" ") - .append(ParseDateFormat.getTimeAgo(pullRequest.getState() == IssueState.closed - ? pullRequest.getClosedAt() : pullRequest.getCreatedAt())); - } else { - return builder - .bold(status.toLowerCase()) - .append(" ") - .bold(pullRequest.getHead() != null ? pullRequest.getHead().getRef() : "") - .append(" ") - .append(ParseDateFormat.getTimeAgo(pullRequest.getState() == IssueState.closed - ? pullRequest.getClosedAt() : pullRequest.getCreatedAt())); - } - } - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.url); - dest.writeString(this.body); - dest.writeString(this.title); - dest.writeInt(this.comments); - dest.writeInt(this.number); - dest.writeByte(this.locked ? (byte) 1 : (byte) 0); - dest.writeByte(this.mergable ? (byte) 1 : (byte) 0); - dest.writeByte(this.merged ? (byte) 1 : (byte) 0); - dest.writeByte(this.mergeable ? (byte) 1 : (byte) 0); - dest.writeInt(this.commits); - dest.writeInt(this.additions); - dest.writeInt(this.deletions); - dest.writeInt(this.state == null ? -1 : this.state.ordinal()); - dest.writeString(this.bodyHtml); - dest.writeString(this.htmlUrl); - dest.writeLong(this.closedAt != null ? this.closedAt.getTime() : -1); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeInt(this.changedFiles); - dest.writeString(this.diffUrl); - dest.writeString(this.patchUrl); - dest.writeString(this.mergeCommitSha); - dest.writeLong(this.mergedAt != null ? this.mergedAt.getTime() : -1); - dest.writeString(this.mergeState); - dest.writeInt(this.reviewComments); - dest.writeString(this.repoId); - dest.writeString(this.login); - dest.writeString(this.mergeableState); - dest.writeList(this.assignees); - dest.writeParcelable(this.mergedBy, flags); - dest.writeParcelable(this.closedBy, flags); - dest.writeParcelable(this.user, flags); - dest.writeParcelable(this.assignee, flags); - dest.writeList(this.labels); - dest.writeParcelable(this.milestone, flags); - dest.writeParcelable(this.base, flags); - dest.writeParcelable(this.head, flags); - dest.writeParcelable(this.pullRequest, flags); - dest.writeParcelable(this.reactions, flags); - } - - protected AbstractPullRequest(Parcel in) { - this.id = in.readLong(); - this.url = in.readString(); - this.body = in.readString(); - this.title = in.readString(); - this.comments = in.readInt(); - this.number = in.readInt(); - this.locked = in.readByte() != 0; - this.mergable = in.readByte() != 0; - this.merged = in.readByte() != 0; - this.mergeable = in.readByte() != 0; - this.commits = in.readInt(); - this.additions = in.readInt(); - this.deletions = in.readInt(); - int tmpState = in.readInt(); - this.state = tmpState == -1 ? null : IssueState.values()[tmpState]; - this.bodyHtml = in.readString(); - this.htmlUrl = in.readString(); - long tmpClosedAt = in.readLong(); - this.closedAt = tmpClosedAt == -1 ? null : new Date(tmpClosedAt); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - this.changedFiles = in.readInt(); - this.diffUrl = in.readString(); - this.patchUrl = in.readString(); - this.mergeCommitSha = in.readString(); - long tmpMergedAt = in.readLong(); - this.mergedAt = tmpMergedAt == -1 ? null : new Date(tmpMergedAt); - this.mergeState = in.readString(); - this.reviewComments = in.readInt(); - this.repoId = in.readString(); - this.login = in.readString(); - this.mergeableState = in.readString(); - this.assignees = new UsersListModel(); - in.readList(this.assignees, this.assignees.getClass().getClassLoader()); - this.mergedBy = in.readParcelable(User.class.getClassLoader()); - this.closedBy = in.readParcelable(User.class.getClassLoader()); - this.user = in.readParcelable(User.class.getClassLoader()); - this.assignee = in.readParcelable(User.class.getClassLoader()); - this.labels = new LabelListModel(); - in.readList(this.labels, this.labels.getClass().getClassLoader()); - this.milestone = in.readParcelable(MilestoneModel.class.getClassLoader()); - this.base = in.readParcelable(Commit.class.getClassLoader()); - this.head = in.readParcelable(Commit.class.getClassLoader()); - this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader()); - this.reactions = in.readParcelable(ReactionsModel.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public PullRequest createFromParcel(Parcel source) {return new PullRequest(source);} - - @Override public PullRequest[] newArray(int size) {return new PullRequest[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractRelease.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractRelease.java deleted file mode 100644 index b7c7ac7ea..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractRelease.java +++ /dev/null @@ -1,168 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.fastaccess.App; -import com.fastaccess.data.dao.ReleasesAssetsListModel; -import com.fastaccess.data.dao.converters.ReleasesAssetsConverter; -import com.fastaccess.data.dao.converters.UserConverter; -import com.fastaccess.helper.RxHelper; -import com.google.gson.annotations.SerializedName; - -import java.util.Date; -import java.util.List; - -import io.reactivex.Completable; -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Persistable; -import io.requery.Table; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.Release.CREATED_AT; -import static com.fastaccess.data.dao.model.Release.ID; -import static com.fastaccess.data.dao.model.Release.LOGIN; -import static com.fastaccess.data.dao.model.Release.REPO_ID; - -/** - * Created by Kosh on 16 Mar 2017, 7:40 PM - */ - -@Entity @NoArgsConstructor @Table(name = "release_table") -public abstract class AbstractRelease implements Parcelable { - @Key long id; - String url; - String htmlUrl; - String assetsUrl; - String uploadUrl; - String tagName; - String targetCommitish; - String name; - boolean draft; - boolean preRelease; - Date createdAt; - Date publishedAt; - String repoId; - String login; - @SerializedName("tarball_url") String tarballUrl; - @SerializedName("body_html") String body; - @SerializedName("zipball_url") String zipBallUrl; - @Convert(UserConverter.class) User author; - @Convert(ReleasesAssetsConverter.class) ReleasesAssetsListModel assets; - - public static Disposable save(@NonNull List models, @NonNull String repoId, @NonNull String login) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - dataSource.delete(Release.class) - .where(Release.REPO_ID.equal(repoId) - .and(Release.LOGIN.equal(login))) - .get() - .value(); - if (!models.isEmpty()) { - for (Release releasesModel : models) { - dataSource.delete(Release.class).where(Release.ID.eq(releasesModel.getId())).get().value(); - releasesModel.setRepoId(repoId); - releasesModel.setLogin(login); - dataSource.insert(releasesModel); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - public static Completable delete(@NonNull String repoId, @NonNull String login) { - return App.getInstance().getDataStore() - .delete(Release.class) - .where(REPO_ID.eq(repoId) - .and(LOGIN.eq(login))) - .get() - .single() - .toCompletable(); - } - - public static Observable get(long id) { - return App.getInstance().getDataStore() - .select(Release.class) - .where(ID.eq(id)) - .get() - .observable(); - } - - public static Single> get(@NonNull String repoId, @NonNull String login) { - return App.getInstance().getDataStore() - .select(Release.class) - .where(REPO_ID.eq(repoId) - .and(LOGIN.eq(login))) - .orderBy(CREATED_AT.desc()) - .get() - .observable() - .toList(); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.url); - dest.writeString(this.htmlUrl); - dest.writeString(this.assetsUrl); - dest.writeString(this.uploadUrl); - dest.writeString(this.tagName); - dest.writeString(this.targetCommitish); - dest.writeString(this.name); - dest.writeByte(this.draft ? (byte) 1 : (byte) 0); - dest.writeByte(this.preRelease ? (byte) 1 : (byte) 0); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.publishedAt != null ? this.publishedAt.getTime() : -1); - dest.writeString(this.repoId); - dest.writeString(this.login); - dest.writeString(this.tarballUrl); - dest.writeString(this.body); - dest.writeString(this.zipBallUrl); - dest.writeParcelable(this.author, flags); - dest.writeList(this.assets); - } - - protected AbstractRelease(Parcel in) { - this.id = in.readLong(); - this.url = in.readString(); - this.htmlUrl = in.readString(); - this.assetsUrl = in.readString(); - this.uploadUrl = in.readString(); - this.tagName = in.readString(); - this.targetCommitish = in.readString(); - this.name = in.readString(); - this.draft = in.readByte() != 0; - this.preRelease = in.readByte() != 0; - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpPublishedAt = in.readLong(); - this.publishedAt = tmpPublishedAt == -1 ? null : new Date(tmpPublishedAt); - this.repoId = in.readString(); - this.login = in.readString(); - this.tarballUrl = in.readString(); - this.body = in.readString(); - this.zipBallUrl = in.readString(); - this.author = in.readParcelable(User.class.getClassLoader()); - this.assets = new ReleasesAssetsListModel(); - in.readList(this.assets, this.assets.getClass().getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public Release createFromParcel(Parcel source) {return new Release(source);} - - @Override public Release[] newArray(int size) {return new Release[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractRepo.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractRepo.java deleted file mode 100644 index 8a8c63062..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractRepo.java +++ /dev/null @@ -1,419 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.fastaccess.App; -import com.fastaccess.data.dao.LicenseModel; -import com.fastaccess.data.dao.RepoPermissionsModel; -import com.fastaccess.data.dao.TopicsModel; -import com.fastaccess.data.dao.converters.LicenseConverter; -import com.fastaccess.data.dao.converters.RepoConverter; -import com.fastaccess.data.dao.converters.RepoPermissionConverter; -import com.fastaccess.data.dao.converters.TopicsConverter; -import com.fastaccess.data.dao.converters.UserConverter; -import com.fastaccess.helper.RxHelper; -import com.google.gson.annotations.SerializedName; - -import java.util.Date; -import java.util.List; - -import io.reactivex.Maybe; -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Column; -import io.requery.Convert; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Nullable; -import io.requery.Persistable; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.Repo.FULL_NAME; -import static com.fastaccess.data.dao.model.Repo.ID; -import static com.fastaccess.data.dao.model.Repo.REPOS_OWNER; -import static com.fastaccess.data.dao.model.Repo.STARRED_USER; -import static com.fastaccess.data.dao.model.Repo.STATUSES_URL; -import static com.fastaccess.data.dao.model.Repo.UPDATED_AT; - -/** - * Created by Kosh on 16 Mar 2017, 7:54 PM - */ - -@Entity @NoArgsConstructor public abstract class AbstractRepo implements Parcelable { - @Key long id; - String name; - String fullName; - @SerializedName("private") boolean privateX; - String htmlUrl; - String description; - boolean fork; - String url; - String forksUrl; - String keysUrl; - String collaboratorsUrl; - String teamsUrl; - String hooksUrl; - String issueEventsUrl; - String eventsUrl; - String assigneesUrl; - String branchesUrl; - String tagsUrl; - String blobsUrl; - String gitTagsUrl; - String gitRefsUrl; - String treesUrl; - String statusesUrl; - String languagesUrl; - String stargazersUrl; - String contributorsUrl; - String subscribersUrl; - String subscriptionUrl; - String commitsUrl; - String gitCommitsUrl; - String commentsUrl; - String issueCommentUrl; - String contentsUrl; - String compareUrl; - String mergesUrl; - String archiveUrl; - String downloadsUrl; - String issuesUrl; - String pullsUrl; - String milestonesUrl; - String notificationsUrl; - String labelsUrl; - String releasesUrl; - Date createdAt; - Date updatedAt; - Date pushedAt; - String gitUrl; - String sshUrl; - String cloneUrl; - String svnUrl; - String homepage; - long size; - long stargazersCount; - long watchersCount; - @Column(name = "language_column") String language; - boolean hasIssues; - boolean hasDownloads; - boolean hasWiki; - boolean hasPages; - long forksCount; - String mirrorUrl; - long openIssuesCount; - long forks; - long openIssues; - long watchers; - String defaultBranch; - @Nullable @Convert(TopicsConverter.class) TopicsModel topics; - @Convert(UserConverter.class) User owner; - @Convert(RepoPermissionConverter.class) RepoPermissionsModel permissions; - @Convert(UserConverter.class) User organization; - @Convert(RepoConverter.class) Repo parent; - @Convert(RepoConverter.class) Repo source; - @Convert(LicenseConverter.class) LicenseModel license; - @SerializedName("subscribers_count") int subsCount; - int networkCount; - String starredUser; - String reposOwner; - @Nullable boolean hasProjects; - - public Disposable save(Repo entity) { - return Single.create(e -> { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - dataSource.delete(Repo.class).where(Repo.ID.eq(entity.getId())).get().value(); - dataSource.insert(entity); - }).subscribe(o -> {/**/}, Throwable::printStackTrace); - } - - public static Maybe getRepo(@NonNull String name, @NonNull String login) { - return App.getInstance().getDataStore() - .select(Repo.class) - .where(FULL_NAME.eq(login + "/" + name)) - .get() - .maybe(); - } - - public static Repo getRepo(long id) { - return App.getInstance().getDataStore() - .select(Repo.class) - .where(ID.eq(id)) - .get() - .firstOrNull(); - } - - public static Disposable saveStarred(@NonNull List models, @NonNull String starredUser) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - Login login = Login.getUser(); - if (login != null) { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - if (login.getLogin().equalsIgnoreCase(starredUser)) { - dataSource.delete(Repo.class) - .where(STARRED_USER.eq(starredUser)) - .get() - .value(); - if (!models.isEmpty()) { - for (Repo repo : models) { - dataSource.delete(Repo.class).where(Repo.ID.eq(repo.getId())).get().value(); - repo.setStarredUser(starredUser); - dataSource.insert(repo); - } - } - } else { - dataSource.delete(Repo.class) - .where(STARRED_USER.notEqual(login.getLogin()) - .or(STATUSES_URL.isNull())) - .get() - .value(); - } - } - s.onNext(""); - } catch (Exception ignored) {} - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - public static Disposable saveMyRepos(@NonNull List models, @NonNull String reposOwner) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - Login login = Login.getUser(); - if (login != null) { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - if (login.getLogin().equalsIgnoreCase(reposOwner)) { - dataSource.delete(Repo.class) - .where(REPOS_OWNER.eq(reposOwner)) - .get() - .value(); - if (!models.isEmpty()) { - for (Repo repo : models) { - dataSource.delete(Repo.class).where(Repo.ID.eq(repo.getId())).get().value(); - repo.setReposOwner(reposOwner); - dataSource.insert(repo); - } - } - } else { - dataSource.delete(Repo.class) - .where(REPOS_OWNER.notEqual(login.getLogin()) - .or(REPOS_OWNER.isNull())) - .get() - .value(); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - public static Single> getStarred(@NonNull String starredUser) { - return App.getInstance().getDataStore() - .select(Repo.class) - .where(STARRED_USER.eq(starredUser)) - .orderBy(UPDATED_AT.desc()) - .get() - .observable() - .toList(); - } - - public static Single> getMyRepos(@NonNull String reposOwner) { - return App.getInstance().getDataStore() - .select(Repo.class) - .where(REPOS_OWNER.eq(reposOwner)) - .orderBy(UPDATED_AT.desc()) - .get() - .observable() - .toList(); - } - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AbstractRepo that = (AbstractRepo) o; - return id == that.id; - } - - @Override public int hashCode() { - return (int) (id ^ (id >>> 32)); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.name); - dest.writeString(this.fullName); - dest.writeByte(this.privateX ? (byte) 1 : (byte) 0); - dest.writeString(this.htmlUrl); - dest.writeString(this.description); - dest.writeByte(this.fork ? (byte) 1 : (byte) 0); - dest.writeString(this.url); - dest.writeString(this.forksUrl); - dest.writeString(this.keysUrl); - dest.writeString(this.collaboratorsUrl); - dest.writeString(this.teamsUrl); - dest.writeString(this.hooksUrl); - dest.writeString(this.issueEventsUrl); - dest.writeString(this.eventsUrl); - dest.writeString(this.assigneesUrl); - dest.writeString(this.branchesUrl); - dest.writeString(this.tagsUrl); - dest.writeString(this.blobsUrl); - dest.writeString(this.gitTagsUrl); - dest.writeString(this.gitRefsUrl); - dest.writeString(this.treesUrl); - dest.writeString(this.statusesUrl); - dest.writeString(this.languagesUrl); - dest.writeString(this.stargazersUrl); - dest.writeString(this.contributorsUrl); - dest.writeString(this.subscribersUrl); - dest.writeString(this.subscriptionUrl); - dest.writeString(this.commitsUrl); - dest.writeString(this.gitCommitsUrl); - dest.writeString(this.commentsUrl); - dest.writeString(this.issueCommentUrl); - dest.writeString(this.contentsUrl); - dest.writeString(this.compareUrl); - dest.writeString(this.mergesUrl); - dest.writeString(this.archiveUrl); - dest.writeString(this.downloadsUrl); - dest.writeString(this.issuesUrl); - dest.writeString(this.pullsUrl); - dest.writeString(this.milestonesUrl); - dest.writeString(this.notificationsUrl); - dest.writeString(this.labelsUrl); - dest.writeString(this.releasesUrl); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeLong(this.pushedAt != null ? this.pushedAt.getTime() : -1); - dest.writeString(this.gitUrl); - dest.writeString(this.sshUrl); - dest.writeString(this.cloneUrl); - dest.writeString(this.svnUrl); - dest.writeString(this.homepage); - dest.writeLong(this.size); - dest.writeLong(this.stargazersCount); - dest.writeLong(this.watchersCount); - dest.writeString(this.language); - dest.writeByte(this.hasIssues ? (byte) 1 : (byte) 0); - dest.writeByte(this.hasDownloads ? (byte) 1 : (byte) 0); - dest.writeByte(this.hasWiki ? (byte) 1 : (byte) 0); - dest.writeByte(this.hasPages ? (byte) 1 : (byte) 0); - dest.writeLong(this.forksCount); - dest.writeString(this.mirrorUrl); - dest.writeLong(this.openIssuesCount); - dest.writeLong(this.forks); - dest.writeLong(this.openIssues); - dest.writeLong(this.watchers); - dest.writeString(this.defaultBranch); - dest.writeList(this.topics); - dest.writeParcelable(this.owner, flags); - dest.writeParcelable(this.permissions, flags); - dest.writeParcelable(this.organization, flags); - dest.writeParcelable(this.parent, flags); - dest.writeParcelable(this.source, flags); - dest.writeParcelable(this.license, flags); - dest.writeInt(this.subsCount); - dest.writeInt(this.networkCount); - dest.writeString(this.starredUser); - dest.writeString(this.reposOwner); - dest.writeByte(this.hasProjects ? (byte) 1 : (byte) 0); - } - - protected AbstractRepo(Parcel in) { - this.id = in.readLong(); - this.name = in.readString(); - this.fullName = in.readString(); - this.privateX = in.readByte() != 0; - this.htmlUrl = in.readString(); - this.description = in.readString(); - this.fork = in.readByte() != 0; - this.url = in.readString(); - this.forksUrl = in.readString(); - this.keysUrl = in.readString(); - this.collaboratorsUrl = in.readString(); - this.teamsUrl = in.readString(); - this.hooksUrl = in.readString(); - this.issueEventsUrl = in.readString(); - this.eventsUrl = in.readString(); - this.assigneesUrl = in.readString(); - this.branchesUrl = in.readString(); - this.tagsUrl = in.readString(); - this.blobsUrl = in.readString(); - this.gitTagsUrl = in.readString(); - this.gitRefsUrl = in.readString(); - this.treesUrl = in.readString(); - this.statusesUrl = in.readString(); - this.languagesUrl = in.readString(); - this.stargazersUrl = in.readString(); - this.contributorsUrl = in.readString(); - this.subscribersUrl = in.readString(); - this.subscriptionUrl = in.readString(); - this.commitsUrl = in.readString(); - this.gitCommitsUrl = in.readString(); - this.commentsUrl = in.readString(); - this.issueCommentUrl = in.readString(); - this.contentsUrl = in.readString(); - this.compareUrl = in.readString(); - this.mergesUrl = in.readString(); - this.archiveUrl = in.readString(); - this.downloadsUrl = in.readString(); - this.issuesUrl = in.readString(); - this.pullsUrl = in.readString(); - this.milestonesUrl = in.readString(); - this.notificationsUrl = in.readString(); - this.labelsUrl = in.readString(); - this.releasesUrl = in.readString(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - long tmpPushedAt = in.readLong(); - this.pushedAt = tmpPushedAt == -1 ? null : new Date(tmpPushedAt); - this.gitUrl = in.readString(); - this.sshUrl = in.readString(); - this.cloneUrl = in.readString(); - this.svnUrl = in.readString(); - this.homepage = in.readString(); - this.size = in.readLong(); - this.stargazersCount = in.readLong(); - this.watchersCount = in.readLong(); - this.language = in.readString(); - this.hasIssues = in.readByte() != 0; - this.hasDownloads = in.readByte() != 0; - this.hasWiki = in.readByte() != 0; - this.hasPages = in.readByte() != 0; - this.forksCount = in.readLong(); - this.mirrorUrl = in.readString(); - this.openIssuesCount = in.readLong(); - this.forks = in.readLong(); - this.openIssues = in.readLong(); - this.watchers = in.readLong(); - this.defaultBranch = in.readString(); - this.topics = new TopicsModel(); - in.readList(this.topics, this.topics.getClass().getClassLoader()); - this.owner = in.readParcelable(User.class.getClassLoader()); - this.permissions = in.readParcelable(RepoPermissionsModel.class.getClassLoader()); - this.organization = in.readParcelable(User.class.getClassLoader()); - this.parent = in.readParcelable(Repo.class.getClassLoader()); - this.source = in.readParcelable(Repo.class.getClassLoader()); - this.license = in.readParcelable(LicenseModel.class.getClassLoader()); - this.subsCount = in.readInt(); - this.networkCount = in.readInt(); - this.starredUser = in.readString(); - this.reposOwner = in.readString(); - this.hasProjects = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override public Repo createFromParcel(Parcel source) {return new Repo(source);} - - @Override public Repo[] newArray(int size) {return new Repo[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractRepoFile.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractRepoFile.java deleted file mode 100644 index 474af92cc..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractRepoFile.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.fastaccess.App; -import com.fastaccess.data.dao.types.FilesType; -import com.fastaccess.helper.RxHelper; - -import java.util.List; - -import io.reactivex.Observable; -import io.reactivex.Single; -import io.requery.Entity; -import io.requery.Generated; -import io.requery.Key; -import io.requery.Persistable; -import io.requery.reactivex.ReactiveEntityStore; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.RepoFile.LOGIN; -import static com.fastaccess.data.dao.model.RepoFile.REPO_ID; -import static com.fastaccess.data.dao.model.RepoFile.SHA; -import static com.fastaccess.data.dao.model.RepoFile.TYPE; - -/** - * Created by Kosh on 16 Mar 2017, 7:53 PM - */ - -@Entity @NoArgsConstructor public abstract class AbstractRepoFile implements Parcelable { - @Key @Generated long id; - String name; - String path; - String sha; - long size; - String url; - String htmlUrl; - String gitUrl; - String downloadUrl; - FilesType type; - String repoId; - String login; - - - public Single save(RepoFile entity) { - return RxHelper.getSingle(App.getInstance().getDataStore().insert(entity)); - } - - public static Observable save(@NonNull List models, @NonNull String login, @NonNull String repoId) { - ReactiveEntityStore singleEntityStore = App.getInstance().getDataStore(); - return RxHelper.safeObservable(singleEntityStore.delete(RepoFile.class) - .where(REPO_ID.eq(repoId) - .and(LOGIN.eq(login))) - .get() - .single() - .toObservable() - .flatMap(integer -> Observable.fromIterable(models)) - .flatMap(filesModel -> { - filesModel.setRepoId(repoId); - filesModel.setLogin(login); - return filesModel.save(filesModel).toObservable(); - })); - } - - public static Single> getFiles(@NonNull String login, @NonNull String repoId) { - return App.getInstance().getDataStore() - .select(RepoFile.class) - .where(REPO_ID.eq(repoId) - .and(LOGIN.eq(login))) - .orderBy(TYPE.asc()) - .get() - .observable() - .toList(); - } - - public static Observable getFile(@NonNull String login, @NonNull String repoId, @NonNull String sha) { - return App.getInstance().getDataStore() - .select(RepoFile.class) - .where(REPO_ID.eq(repoId) - .and(LOGIN.eq(login)) - .and(SHA.eq(sha))) - .orderBy(TYPE.asc()) - .get() - .observable(); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.name); - dest.writeString(this.path); - dest.writeString(this.sha); - dest.writeLong(this.size); - dest.writeString(this.url); - dest.writeString(this.htmlUrl); - dest.writeString(this.gitUrl); - dest.writeString(this.downloadUrl); - dest.writeInt(this.type == null ? -1 : this.type.ordinal()); - dest.writeString(this.repoId); - dest.writeString(this.login); - } - - protected AbstractRepoFile(Parcel in) { - this.id = in.readLong(); - this.name = in.readString(); - this.path = in.readString(); - this.sha = in.readString(); - this.size = in.readLong(); - this.url = in.readString(); - this.htmlUrl = in.readString(); - this.gitUrl = in.readString(); - this.downloadUrl = in.readString(); - int tmpType = in.readInt(); - this.type = tmpType == -1 ? null : FilesType.values()[tmpType]; - this.repoId = in.readString(); - this.login = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public RepoFile createFromParcel(Parcel source) {return new RepoFile(source);} - - @Override public RepoFile[] newArray(int size) {return new RepoFile[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractSearchHistory.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractSearchHistory.java deleted file mode 100644 index 6953ddf30..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractSearchHistory.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.App; -import com.fastaccess.helper.RxHelper; - -import java.util.List; - -import io.reactivex.Single; -import io.requery.Column; -import io.requery.Entity; - -/** - * Created by Kosh on 01 Jan 2017, 11:20 PM - */ - - -@Entity -public abstract class AbstractSearchHistory implements Parcelable { - @Column(unique = true) String text; - - public Single save(SearchHistory entity) { - return RxHelper.getSingle( - App.getInstance().getDataStore() - .delete(SearchHistory.class) - .where(SearchHistory.TEXT.eq(entity.getText())) - .get() - .single() - .flatMap(integer -> App.getInstance().getDataStore().insert(entity))); - } - - public static Single> getHistory() { - return App.getInstance().getDataStore() - .select(SearchHistory.class) - .groupBy(SearchHistory.TEXT.asc()) - .get() - .observable() - .toList(); - } - - @Override public String toString() { - return text; - } - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - AbstractSearchHistory that = (AbstractSearchHistory) o; - - return text != null ? text.equals(that.text) : that.text == null; - - } - - @Override public int hashCode() { - return text != null ? text.hashCode() : 0; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) {dest.writeString(this.text);} - - public AbstractSearchHistory() {} - - public AbstractSearchHistory(String text) { - this.text = text; - } - - protected AbstractSearchHistory(Parcel in) {this.text = in.readString();} - - public static final Creator CREATOR = new Creator() { - @Override public SearchHistory createFromParcel(Parcel source) {return new SearchHistory(source);} - - @Override public SearchHistory[] newArray(int size) {return new SearchHistory[size];} - }; - - public static void deleteAll() { - App.getInstance().getDataStore() - .delete(SearchHistory.class) - .get() - .value(); - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractUser.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractUser.java deleted file mode 100644 index 06c44fd7a..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractUser.java +++ /dev/null @@ -1,274 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.App; -import com.fastaccess.helper.RxHelper; - -import java.util.Date; -import java.util.List; - -import io.reactivex.Single; -import io.reactivex.disposables.Disposable; -import io.requery.BlockingEntityStore; -import io.requery.Column; -import io.requery.Entity; -import io.requery.Key; -import io.requery.Persistable; -import io.requery.Table; -import io.requery.Transient; -import lombok.NoArgsConstructor; - -import static com.fastaccess.data.dao.model.User.FOLLOWER_NAME; -import static com.fastaccess.data.dao.model.User.FOLLOWING_NAME; -import static com.fastaccess.data.dao.model.User.ID; -import static com.fastaccess.data.dao.model.User.LOGIN; - -/** - * Created by Kosh on 16 Mar 2017, 7:55 PM - */ - -@Entity @NoArgsConstructor @Table(name = "user_table") -public abstract class AbstractUser implements Parcelable { - @Key long id; - String login; - String avatarUrl; - String gravatarId; - String url; - String htmlUrl; - String followersUrl; - String followingUrl; - String gistsUrl; - String starredUrl; - String subscriptionsUrl; - String organizationsUrl; - String reposUrl; - String eventsUrl; - String receivedEventsUrl; - String type; - boolean siteAdmin; - String name; - String company; - String blog; - String location; - String email; - boolean hireable; - String bio; - long publicRepos; - long publicGists; - long followers; - long following; - Date createdAt; - Date updatedAt; - int contributions; - String followingName; - String followerName; - @Column(name = "date_column") Date date; - String repoId; - String description; - @Transient boolean hasOrganizationProjects; - - public void save(User entity) { - if (getUser(entity.getId()) != null) { - App.getInstance().getDataStore().toBlocking().update(entity); - } else { - App.getInstance().getDataStore().toBlocking().insert(entity); - } - } - - @Nullable public static User getUser(String login) { - return App.getInstance().getDataStore() - .select(User.class) - .where(LOGIN.eq(login)) - .get() - .firstOrNull(); - } - - @Nullable public static User getUser(long id) { - return App.getInstance().getDataStore() - .select(User.class) - .where(ID.eq(id)) - .get() - .firstOrNull(); - } - - public static Disposable saveUserFollowerList(@NonNull List models, @NonNull String followingName) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - Login login = Login.getUser(); - if (login != null) { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - if (login.getLogin().equalsIgnoreCase(followingName)) { - dataSource.delete(User.class) - .where(FOLLOWING_NAME.eq(followingName)) - .get() - .value(); - if (!models.isEmpty()) { - for (User user : models) { - dataSource.delete(User.class).where(User.ID.eq(user.getId())).get().value(); - user.setFollowingName(followingName); - dataSource.insert(user); - } - } - } else { - dataSource.delete(User.class) - .where(User.FOLLOWING_NAME.notEqual(login.getLogin())) - .get() - .value(); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - public static Disposable saveUserFollowingList(@NonNull List models, @NonNull String followerName) { - return RxHelper.getSingle(Single.fromPublisher(s -> { - try { - Login login = Login.getUser(); - if (login != null) { - BlockingEntityStore dataSource = App.getInstance().getDataStore().toBlocking(); - if (login.getLogin().equalsIgnoreCase(followerName)) { - dataSource.delete(User.class) - .where(FOLLOWER_NAME.eq(followerName)) - .get() - .value(); - if (!models.isEmpty()) { - for (User user : models) { - dataSource.delete(User.class).where(User.ID.eq(user.getId())).get().value(); - user.setFollowerName(followerName); - dataSource.insert(user); - } - } - } else { - dataSource.delete(User.class) - .where(User.FOLLOWER_NAME.notEqual(login.getLogin())) - .get() - .value(); - } - } - s.onNext(""); - } catch (Exception e) { - s.onError(e); - } - s.onComplete(); - })).subscribe(o -> {/*donothing*/}, Throwable::printStackTrace); - } - - @NonNull public static Single> getUserFollowerList(@NonNull String following) { - return App.getInstance().getDataStore() - .select(User.class) - .where(FOLLOWING_NAME.eq(following)) - .get() - .observable() - .toList(); - } - - @NonNull public static Single> getUserFollowingList(@NonNull String follower) { - return App.getInstance().getDataStore() - .select(User.class) - .where(FOLLOWER_NAME.eq(follower)) - .get() - .observable() - .toList(); - } - - public boolean isOrganizationType() { - return type != null && type.equalsIgnoreCase("Organization"); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.login); - dest.writeString(this.avatarUrl); - dest.writeString(this.gravatarId); - dest.writeString(this.url); - dest.writeString(this.htmlUrl); - dest.writeString(this.followersUrl); - dest.writeString(this.followingUrl); - dest.writeString(this.gistsUrl); - dest.writeString(this.starredUrl); - dest.writeString(this.subscriptionsUrl); - dest.writeString(this.organizationsUrl); - dest.writeString(this.reposUrl); - dest.writeString(this.eventsUrl); - dest.writeString(this.receivedEventsUrl); - dest.writeString(this.type); - dest.writeByte(this.siteAdmin ? (byte) 1 : (byte) 0); - dest.writeString(this.name); - dest.writeString(this.company); - dest.writeString(this.blog); - dest.writeString(this.location); - dest.writeString(this.email); - dest.writeByte(this.hireable ? (byte) 1 : (byte) 0); - dest.writeString(this.bio); - dest.writeLong(this.publicRepos); - dest.writeLong(this.publicGists); - dest.writeLong(this.followers); - dest.writeLong(this.following); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeInt(this.contributions); - dest.writeString(this.followingName); - dest.writeString(this.followerName); - dest.writeLong(this.date != null ? this.date.getTime() : -1); - dest.writeString(this.repoId); - dest.writeString(this.description); - } - - protected AbstractUser(Parcel in) { - this.id = in.readLong(); - this.login = in.readString(); - this.avatarUrl = in.readString(); - this.gravatarId = in.readString(); - this.url = in.readString(); - this.htmlUrl = in.readString(); - this.followersUrl = in.readString(); - this.followingUrl = in.readString(); - this.gistsUrl = in.readString(); - this.starredUrl = in.readString(); - this.subscriptionsUrl = in.readString(); - this.organizationsUrl = in.readString(); - this.reposUrl = in.readString(); - this.eventsUrl = in.readString(); - this.receivedEventsUrl = in.readString(); - this.type = in.readString(); - this.siteAdmin = in.readByte() != 0; - this.name = in.readString(); - this.company = in.readString(); - this.blog = in.readString(); - this.location = in.readString(); - this.email = in.readString(); - this.hireable = in.readByte() != 0; - this.bio = in.readString(); - this.publicRepos = in.readLong(); - this.publicGists = in.readLong(); - this.followers = in.readLong(); - this.following = in.readLong(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - this.contributions = in.readInt(); - this.followingName = in.readString(); - this.followerName = in.readString(); - long tmpDate = in.readLong(); - this.date = tmpDate == -1 ? null : new Date(tmpDate); - this.repoId = in.readString(); - this.description = in.readString(); - } - - public static final Creator CREATOR = new Creator() { - @Override public User createFromParcel(Parcel source) {return new User(source);} - - @Override public User[] newArray(int size) {return new User[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/model/AbstractViewerFile.java b/app/src/main/java/com/fastaccess/data/dao/model/AbstractViewerFile.java deleted file mode 100644 index cc0bd4ac2..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/model/AbstractViewerFile.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.fastaccess.data.dao.model; - -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; - -import com.fastaccess.App; -import com.fastaccess.helper.RxHelper; - -import io.requery.Column; -import io.requery.Entity; -import io.requery.Generated; -import io.requery.Key; -import lombok.NoArgsConstructor; -import io.reactivex.Observable;import io.reactivex.Single; - -/** - * Created by Kosh on 06 Dec 2016, 10:42 PM - */ - -@Entity @NoArgsConstructor public abstract class AbstractViewerFile implements Parcelable { - @Key @Generated long id; - boolean markdown; - String content; - @Column(unique = true) String fullUrl; - boolean repo; - - public Single save(ViewerFile modelEntity) { - return RxHelper.getSingle(App.getInstance().getDataStore() - .delete(ViewerFile.class) - .where(ViewerFile.FULL_URL.eq(modelEntity.getFullUrl())) - .get() - .single() - .flatMap(i -> App.getInstance().getDataStore().insert(modelEntity))); - } - - public static Observable get(@NonNull String url) { - return App.getInstance() - .getDataStore() - .select(ViewerFile.class) - .where(ViewerFile.FULL_URL.equal(url)) - .get() - .observable(); - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeByte(this.markdown ? (byte) 1 : (byte) 0); - dest.writeString(this.content); - dest.writeString(this.fullUrl); - dest.writeByte(this.repo ? (byte) 1 : (byte) 0); - } - - protected AbstractViewerFile(Parcel in) { - this.id = in.readLong(); - this.markdown = in.readByte() != 0; - this.content = in.readString(); - this.fullUrl = in.readString(); - this.repo = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override public ViewerFile createFromParcel(Parcel source) {return new ViewerFile(source);} - - @Override public ViewerFile[] newArray(int size) {return new ViewerFile[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/timeline/AuthorModel.java b/app/src/main/java/com/fastaccess/data/dao/timeline/AuthorModel.java deleted file mode 100644 index fc89b57b3..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/timeline/AuthorModel.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.fastaccess.data.dao.timeline; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Date; - -import lombok.Getter; -import lombok.Setter; - -@Getter @Setter public class AuthorModel implements Parcelable { - private String name; - private String email; - private Date date; - - public AuthorModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.name); - dest.writeString(this.email); - dest.writeLong(this.date != null ? this.date.getTime() : -1); - } - - private AuthorModel(Parcel in) { - this.name = in.readString(); - this.email = in.readString(); - long tmpDate = in.readLong(); - this.date = tmpDate == -1 ? null : new Date(tmpDate); - } - - public static final Creator CREATOR = new Creator() { - @Override public AuthorModel createFromParcel(Parcel source) {return new AuthorModel(source);} - - @Override public AuthorModel[] newArray(int size) {return new AuthorModel[size];} - }; -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/dao/timeline/CommentEvent.java b/app/src/main/java/com/fastaccess/data/dao/timeline/CommentEvent.java deleted file mode 100644 index 4086a5775..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/timeline/CommentEvent.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.fastaccess.data.dao.timeline; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.User; - -import java.util.Date; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by Kosh on 16 Mar 2017, 7:24 PM - */ -@Getter @Setter public class CommentEvent implements Parcelable { - private long id; - private User user; - private String url; - private String body; - private String bodyHtml; - private String htmlUrl; - private Date createdAt; - private Date updatedAt; - private int position; - private int line; - private String path; - private String commitId; - private String repoId; - private String login; - private String gistId; - private String issueId; - private String pullRequestId; - private ReactionsModel reactions; - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Comment that = (Comment) o; - return id == that.getId(); - - } - - @Override public int hashCode() { - return (int) (id ^ (id >>> 32)); - } - - public CommentEvent() {} - - @Override public String toString() { - return "CommentEvent{" + - "id=" + id + - ", user=" + user + - ", url='" + url + '\'' + - ", body='" + body + '\'' + - ", bodyHtml='" + bodyHtml + '\'' + - ", htmlUrl='" + htmlUrl + '\'' + - ", createdAt=" + createdAt + - ", updatedAt=" + updatedAt + - ", position=" + position + - ", line=" + line + - ", path='" + path + '\'' + - ", commitId='" + commitId + '\'' + - ", repoId='" + repoId + '\'' + - ", login='" + login + '\'' + - ", gistId='" + gistId + '\'' + - ", issueId='" + issueId + '\'' + - ", pullRequestId='" + pullRequestId + '\'' + - ", reactions=" + reactions + - '}'; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeParcelable(this.user, flags); - dest.writeString(this.url); - dest.writeString(this.body); - dest.writeString(this.bodyHtml); - dest.writeString(this.htmlUrl); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeLong(this.updatedAt != null ? this.updatedAt.getTime() : -1); - dest.writeInt(this.position); - dest.writeInt(this.line); - dest.writeString(this.path); - dest.writeString(this.commitId); - dest.writeString(this.repoId); - dest.writeString(this.login); - dest.writeString(this.gistId); - dest.writeString(this.issueId); - dest.writeString(this.pullRequestId); - dest.writeParcelable(this.reactions, flags); - } - - private CommentEvent(Parcel in) { - this.id = in.readLong(); - this.user = in.readParcelable(User.class.getClassLoader()); - this.url = in.readString(); - this.body = in.readString(); - this.bodyHtml = in.readString(); - this.htmlUrl = in.readString(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - long tmpUpdatedAt = in.readLong(); - this.updatedAt = tmpUpdatedAt == -1 ? null : new Date(tmpUpdatedAt); - this.position = in.readInt(); - this.line = in.readInt(); - this.path = in.readString(); - this.commitId = in.readString(); - this.repoId = in.readString(); - this.login = in.readString(); - this.gistId = in.readString(); - this.issueId = in.readString(); - this.pullRequestId = in.readString(); - this.reactions = in.readParcelable(ReactionsModel.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public CommentEvent createFromParcel(Parcel source) {return new CommentEvent(source);} - - @Override public CommentEvent[] newArray(int size) {return new CommentEvent[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/timeline/GenericEvent.java b/app/src/main/java/com/fastaccess/data/dao/timeline/GenericEvent.java deleted file mode 100644 index a5d4c86b5..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/timeline/GenericEvent.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.fastaccess.data.dao.timeline; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.RenameModel; -import com.fastaccess.data.dao.TeamsModel; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.IssueEventType; - -import java.util.Date; -import java.util.List; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -/** - * Created by kosh on 25/07/2017. - */ - -@NoArgsConstructor @Getter @Setter public class GenericEvent implements Parcelable { - - private long id; - private String url; - private String commitId; - private String commitUrl; - private String message; - private String sha; - private String htmlUrl; - private Date createdAt; - private User actor; - private User requestedReviewer; - private User reviewRequester; - private User assigner; - private User assignee; - private User author; - private User committer; - private LabelModel label; - private TeamsModel requestedTeam; - private MilestoneModel milestone; - private RenameModel rename; - private SourceModel source; - private Issue issue; - private PullRequest pullRequest; - private ParentsModel tree; - private List parents; - private IssueEventType event; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(this.id); - dest.writeString(this.url); - dest.writeString(this.commitId); - dest.writeString(this.commitUrl); - dest.writeString(this.message); - dest.writeString(this.sha); - dest.writeString(this.htmlUrl); - dest.writeLong(this.createdAt != null ? this.createdAt.getTime() : -1); - dest.writeParcelable(this.actor, flags); - dest.writeParcelable(this.requestedReviewer, flags); - dest.writeParcelable(this.reviewRequester, flags); - dest.writeParcelable(this.assigner, flags); - dest.writeParcelable(this.assignee, flags); - dest.writeParcelable(this.author, flags); - dest.writeParcelable(this.committer, flags); - dest.writeParcelable(this.label, flags); - dest.writeParcelable(this.requestedTeam, flags); - dest.writeParcelable(this.milestone, flags); - dest.writeParcelable(this.rename, flags); - dest.writeParcelable(this.source, flags); - dest.writeParcelable(this.issue, flags); - dest.writeParcelable(this.pullRequest, flags); - dest.writeParcelable(this.tree, flags); - dest.writeTypedList(this.parents); - dest.writeInt(this.event == null ? -1 : this.event.ordinal()); - } - - private GenericEvent(Parcel in) { - this.id = in.readLong(); - this.url = in.readString(); - this.commitId = in.readString(); - this.commitUrl = in.readString(); - this.message = in.readString(); - this.sha = in.readString(); - this.htmlUrl = in.readString(); - long tmpCreatedAt = in.readLong(); - this.createdAt = tmpCreatedAt == -1 ? null : new Date(tmpCreatedAt); - this.actor = in.readParcelable(User.class.getClassLoader()); - this.requestedReviewer = in.readParcelable(User.class.getClassLoader()); - this.reviewRequester = in.readParcelable(User.class.getClassLoader()); - this.assigner = in.readParcelable(User.class.getClassLoader()); - this.assignee = in.readParcelable(User.class.getClassLoader()); - this.author = in.readParcelable(User.class.getClassLoader()); - this.committer = in.readParcelable(User.class.getClassLoader()); - this.label = in.readParcelable(LabelModel.class.getClassLoader()); - this.requestedTeam = in.readParcelable(TeamsModel.class.getClassLoader()); - this.milestone = in.readParcelable(MilestoneModel.class.getClassLoader()); - this.rename = in.readParcelable(RenameModel.class.getClassLoader()); - this.source = in.readParcelable(SourceModel.class.getClassLoader()); - this.issue = in.readParcelable(Issue.class.getClassLoader()); - this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader()); - this.tree = in.readParcelable(ParentsModel.class.getClassLoader()); - this.parents = in.createTypedArrayList(ParentsModel.CREATOR); - int tmpEvent = in.readInt(); - this.event = tmpEvent == -1 ? null : IssueEventType.values()[tmpEvent]; - } - - public static final Creator CREATOR = new Creator() { - @Override public GenericEvent createFromParcel(Parcel source) {return new GenericEvent(source);} - - @Override public GenericEvent[] newArray(int size) {return new GenericEvent[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/timeline/ParentsModel.java b/app/src/main/java/com/fastaccess/data/dao/timeline/ParentsModel.java deleted file mode 100644 index 9c091d984..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/timeline/ParentsModel.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.fastaccess.data.dao.timeline; - -import android.os.Parcel; -import android.os.Parcelable; - -import lombok.Getter; -import lombok.Setter; - -@Getter @Setter public class ParentsModel implements Parcelable { - private String sha; - private String url; - private String htmlUrl; - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.sha); - dest.writeString(this.url); - dest.writeString(this.htmlUrl); - } - - public ParentsModel() {} - - private ParentsModel(Parcel in) { - this.sha = in.readString(); - this.url = in.readString(); - this.htmlUrl = in.readString(); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override public ParentsModel createFromParcel(Parcel source) {return new ParentsModel(source);} - - @Override public ParentsModel[] newArray(int size) {return new ParentsModel[size];} - }; -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestCommitModel.java b/app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestCommitModel.java deleted file mode 100644 index d17c6bb2b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestCommitModel.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.fastaccess.data.dao.timeline; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.Comment; - -import java.util.List; - -/** - * Created by kosh on 15/08/2017. - */ - -public class PullRequestCommitModel implements Parcelable { - private String login; - private String path; - private int position; - private String commitId; - private List comments; - private int line; - - - public int getLine() { - return line; - } - - public void setLine(int line) { - this.line = line; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - - public int getPosition() { - return position; - } - - public void setPosition(int position) { - this.position = position; - } - - public String getCommitId() { - return commitId; - } - - public void setCommitId(String commitId) { - this.commitId = commitId; - } - - public List getComments() { - return comments; - } - - public void setComments(List comments) { - this.comments = comments; - } - - public PullRequestCommitModel() {} - - public String getLogin() { - return login; - } - - public void setLogin(String login) { - this.login = login; - } - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.login); - dest.writeString(this.path); - dest.writeInt(this.position); - dest.writeString(this.commitId); - dest.writeTypedList(this.comments); - dest.writeInt(this.line); - } - - protected PullRequestCommitModel(Parcel in) { - this.login = in.readString(); - this.path = in.readString(); - this.position = in.readInt(); - this.commitId = in.readString(); - this.comments = in.createTypedArrayList(Comment.CREATOR); - this.line = in.readInt(); - } - - public static final Creator CREATOR = new Creator() { - @Override public PullRequestCommitModel createFromParcel(Parcel source) {return new PullRequestCommitModel(source);} - - @Override public PullRequestCommitModel[] newArray(int size) {return new PullRequestCommitModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestReviewModel.java b/app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestReviewModel.java deleted file mode 100644 index f260ea429..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestReviewModel.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.fastaccess.data.dao.timeline; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.ParseDateFormat; - -import java.util.ArrayList; -import java.util.List; - -import github.PullRequestTimelineQuery; -import github.type.PullRequestReviewState; - -/** - * Created by kosh on 20/08/2017. - */ - -public class PullRequestReviewModel { - private PullRequestTimelineQuery.AsReviewDismissedEvent reviewDismissedEvent; - private PullRequestTimelineQuery.AsReviewRequestedEvent reviewRequestedEvent; - private PullRequestTimelineQuery.AsReviewRequestRemovedEvent reviewRequestRemovedEvent; - private PullRequestTimelineQuery.Node2 node; - private List reaction; - private List comments; - private String id; - private String url; - private PullRequestTimelineQuery.Author2 author; - private String bodyHTML; - private String createdAt; - private PullRequestReviewState state; - - @Nullable public static PullRequestReviewModel build(@NonNull PullRequestTimelineQuery.Node node) { - PullRequestReviewModel model = new PullRequestReviewModel(); - if (node.asReviewRequestRemovedEvent() != null) { - model.reviewRequestRemovedEvent = node.asReviewRequestRemovedEvent(); - } else if (node.asReviewDismissedEvent() != null) { - model.reviewDismissedEvent = node.asReviewDismissedEvent(); - } else if (node.asReviewRequestedEvent() != null) { - model.reviewRequestedEvent = node.asReviewRequestedEvent(); - } else { - PullRequestTimelineQuery.AsPullRequestReview pullRequestReview = node.asPullRequestReview(); - if (pullRequestReview != null) { - model.state = pullRequestReview.state(); - model.url = pullRequestReview.url().toString(); - model.author = pullRequestReview.author(); - model.bodyHTML = pullRequestReview.bodyHTML().toString(); - model.createdAt = ParseDateFormat.getTimeAgo(pullRequestReview.createdAt().toString()).toString(); - model.id = pullRequestReview.id(); - model.url = pullRequestReview.url().toString(); - List edges = pullRequestReview.comments().edges(); - if (edges != null && !edges.isEmpty()) { - List comments = new ArrayList<>(); - for (PullRequestTimelineQuery.Edge2 edge : edges) { - PullRequestTimelineQuery.Node2 node2 = edge.node(); - if (node2 != null) { - PullRequestReviewModel comment = new PullRequestReviewModel(); - comment.node = node2; - comment.reaction = ReactionsModel.getReaction(node2.reactionGroups()); - comments.add(comment); - } - } - Logger.e(comments.size()); - model.comments = comments; - } - } else { - return null; - } - } - return model; - } - - public PullRequestTimelineQuery.AsReviewDismissedEvent getReviewDismissedEvent() { - return reviewDismissedEvent; - } - - public void setReviewDismissedEvent(PullRequestTimelineQuery.AsReviewDismissedEvent reviewDismissedEvent) { - this.reviewDismissedEvent = reviewDismissedEvent; - } - - public PullRequestTimelineQuery.AsReviewRequestedEvent getReviewRequestedEvent() { - return reviewRequestedEvent; - } - - public void setReviewRequestedEvent(PullRequestTimelineQuery.AsReviewRequestedEvent reviewRequestedEvent) { - this.reviewRequestedEvent = reviewRequestedEvent; - } - - public PullRequestTimelineQuery.AsReviewRequestRemovedEvent getReviewRequestRemovedEvent() { - return reviewRequestRemovedEvent; - } - - public void setReviewRequestRemovedEvent(PullRequestTimelineQuery.AsReviewRequestRemovedEvent reviewRequestRemovedEvent) { - this.reviewRequestRemovedEvent = reviewRequestRemovedEvent; - } - - public PullRequestTimelineQuery.Node2 getNode() { - return node; - } - - public void setNode(PullRequestTimelineQuery.Node2 node) { - this.node = node; - } - - public List getReaction() { - return reaction; - } - - public void setReaction(List reaction) { - this.reaction = reaction; - } - - public List getComments() { - return comments; - } - - public void setComments(List comments) { - this.comments = comments; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public PullRequestTimelineQuery.Author2 getAuthor() { - return author; - } - - public void setAuthor(PullRequestTimelineQuery.Author2 author) { - this.author = author; - } - - public String getBodyHTML() { - return bodyHTML; - } - - public void setBodyHTML(String bodyHTML) { - this.bodyHTML = bodyHTML; - } - - public String getCreatedAt() { - return createdAt; - } - - public void setCreatedAt(String createdAt) { - this.createdAt = createdAt; - } - - public PullRequestReviewState getState() { - return state; - } - - public void setState(PullRequestReviewState state) { - this.state = state; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestTimelineModel.java b/app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestTimelineModel.java deleted file mode 100644 index 0cd8bd06b..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/timeline/PullRequestTimelineModel.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.fastaccess.data.dao.timeline; - -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.data.dao.model.PullRequest; - -import java.util.List; - -import lombok.Getter; -import lombok.Setter; -import github.PullRequestTimelineQuery; - -/** - * Created by kosh on 02/08/2017. - */ - -@Getter @Setter public class PullRequestTimelineModel { - - public static final int HEADER = 1; - public static final int EVENT = 2; - public static final int COMMENT = 3; - public static final int STATUS = 4; - public static final int REVIEW = 5; - public static final int COMMIT_COMMENTS = 6; - public PullRequestTimelineQuery.Node node; - public PullRequest pullRequest; - public PullRequestTimelineQuery.Status status; - public List reactions; - public boolean isMergeable; - public PullRequestCommitModel commitThread; - public PullRequestReviewModel reviewModel; - - public PullRequestTimelineModel(PullRequest pullRequest) { - this.pullRequest = pullRequest; - } - - public PullRequestTimelineModel(PullRequestTimelineQuery.Node node) { - this.node = node; - if (this.node.asCommitCommentThread() != null) { - - } else { - if (node.asPullRequestReview() != null || node.asReviewDismissedEvent() != null - || node.asReviewRequestedEvent() != null || node.asReviewRequestRemovedEvent() != null) { - reviewModel = PullRequestReviewModel.build(node); - } - } - } - - public PullRequestTimelineModel(PullRequestTimelineQuery.Status status, boolean isMergeable) { - this.status = status; - this.isMergeable = isMergeable; - } - - public int getType() { - if (pullRequest != null) return HEADER; - if (node != null) { - if (node.asAssignedEvent() != null || node.asClosedEvent() != null - || node.asDemilestonedEvent() != null || node.asHeadRefDeletedEvent() != null - || node.asLabeledEvent() != null || node.asLockedEvent() != null - || node.asMergedEvent() != null || node.asMilestonedEvent() != null - || node.asReferencedEvent() != null || node.asRenamedTitleEvent() != null - || node.asReopenedEvent() != null || node.asUnassignedEvent() != null - || node.asUnlabeledEvent() != null || node.asUnlockedEvent() != null - || node.asCommit() != null || node.asHeadRefRestoredEvent() != null) { - return EVENT; - } else if (node.asIssueComment() != null) { - if (reactions == null) { - //noinspection ConstantConditions - setReactions(ReactionsModel.getReaction2(node.asIssueComment().reactionGroups())); - } - return COMMENT; - } else if (reviewModel != null) { - return REVIEW; - } else if (commitThread != null) { - return COMMIT_COMMENTS; - } - } else if (status != null) { - return STATUS; - } - return 0; - } - - @Override public String toString() { - return String.valueOf(getType()); - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/timeline/SourceModel.java b/app/src/main/java/com/fastaccess/data/dao/timeline/SourceModel.java deleted file mode 100644 index 3efcfe06d..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/timeline/SourceModel.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.fastaccess.data.dao.timeline; - -import android.os.Parcel; -import android.os.Parcelable; - -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.Repo; - -import lombok.Getter; -import lombok.Setter; - -/** - * Created by kosh on 26/07/2017. - */ - -@Getter @Setter public class SourceModel implements Parcelable { - - private String type; - private Issue issue; - private PullRequest pullRequest; - private Commit commit; - private Repo repository; - - public SourceModel() {} - - @Override public int describeContents() { return 0; } - - @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeString(this.type); - dest.writeParcelable(this.issue, flags); - dest.writeParcelable(this.pullRequest, flags); - dest.writeParcelable(this.commit, flags); - dest.writeParcelable(this.repository, flags); - } - - private SourceModel(Parcel in) { - this.type = in.readString(); - this.issue = in.readParcelable(Issue.class.getClassLoader()); - this.pullRequest = in.readParcelable(PullRequest.class.getClassLoader()); - this.commit = in.readParcelable(Commit.class.getClassLoader()); - this.repository = in.readParcelable(Repo.class.getClassLoader()); - } - - public static final Creator CREATOR = new Creator() { - @Override public SourceModel createFromParcel(Parcel source) {return new SourceModel(source);} - - @Override public SourceModel[] newArray(int size) {return new SourceModel[size];} - }; -} diff --git a/app/src/main/java/com/fastaccess/data/dao/types/EventsType.java b/app/src/main/java/com/fastaccess/data/dao/types/EventsType.java deleted file mode 100644 index fdcf64df0..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/types/EventsType.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.fastaccess.data.dao.types; - - -import android.support.annotation.DrawableRes; -import android.support.annotation.StringRes; - -import com.fastaccess.R; - -public enum EventsType { - WatchEvent(R.string.starred, R.drawable.ic_star_filled), - CreateEvent(R.string.created_repo, R.drawable.ic_repo), - CommitCommentEvent(R.string.commented_on_commit, R.drawable.ic_comment), - DownloadEvent(R.string.downloaded, R.drawable.ic_download), - FollowEvent(R.string.followed, R.drawable.ic_add), - ForkEvent(R.string.forked, R.drawable.ic_fork), - GistEvent(R.string.created_gist, R.drawable.ic_gists), - GollumEvent(R.string.gollum, R.drawable.ic_info_outline), - IssueCommentEvent(R.string.commented_on_issue, R.drawable.ic_comment), - IssuesEvent(R.string.created_issue, R.drawable.ic_issues), - MemberEvent(R.string.member, R.drawable.ic_add), - PublicEvent(R.string.public_event, R.drawable.ic_repo), - PullRequestEvent(R.string.pull_request, R.drawable.ic_pull_requests), - PullRequestReviewCommentEvent(R.string.pr_comment_review, R.drawable.ic_comment), - PullRequestReviewEvent(R.string.pr_review_event, R.drawable.ic_eye), - RepositoryEvent(R.string.repo_event, R.drawable.ic_repo), - PushEvent(R.string.pushed, R.drawable.ic_push), - TeamAddEvent(R.string.team_event, R.drawable.ic_profile), - DeleteEvent(R.string.deleted, R.drawable.ic_trash), - ReleaseEvent(R.string.released, R.drawable.ic_download), - ForkApplyEvent(R.string.forked, R.drawable.ic_fork), - OrgBlockEvent(R.string.organization_event, R.drawable.ic_profile), - ProjectCardEvent(R.string.card_event, R.drawable.ic_info_outline), - ProjectColumnEvent(R.string.project_event, R.drawable.ic_info_outline), - OrganizationEvent(R.string.organization_event, R.drawable.ic_profile), - ProjectEvent(R.string.project_event, R.drawable.ic_info_outline); - - @StringRes int type; - @DrawableRes int drawableRes; - - EventsType(@StringRes int type, @DrawableRes int drawableRes) { - this.type = type; - this.drawableRes = drawableRes; - } - - @DrawableRes public int getDrawableRes() { - return drawableRes > 0 ? drawableRes : R.drawable.ic_info_outline; - } - - @StringRes public int getType() { - return type > 0 ? type : R.string.unknown; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/dao/types/FilesType.java b/app/src/main/java/com/fastaccess/data/dao/types/FilesType.java deleted file mode 100644 index 00431f1b4..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/types/FilesType.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.fastaccess.data.dao.types; - -import android.support.annotation.DrawableRes; - -import com.fastaccess.R; - -/** - * Created by Kosh on 17 Feb 2017, 7:45 PM - */ - -public enum FilesType { - file(R.drawable.ic_file_document), - dir(R.drawable.ic_folder), - blob(R.drawable.ic_file_document), - tree(R.drawable.ic_folder), - symlink(R.drawable.ic_submodule); - - int icon; - - FilesType(int icon) { - this.icon = icon; - } - - @DrawableRes public int getIcon() { - return icon > 0 ? icon : R.drawable.ic_file_document; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/types/GitEntryType.java b/app/src/main/java/com/fastaccess/data/dao/types/GitEntryType.java deleted file mode 100644 index ac7457a6f..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/types/GitEntryType.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.fastaccess.data.dao.types; - -public enum GitEntryType { - commit, - tree, - blob -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/dao/types/IssueEventType.java b/app/src/main/java/com/fastaccess/data/dao/types/IssueEventType.java deleted file mode 100644 index d29060b46..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/types/IssueEventType.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.fastaccess.data.dao.types; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.annimon.stream.Stream; -import com.fastaccess.R; -import com.google.gson.annotations.SerializedName; - -public enum IssueEventType { - assigned(R.drawable.ic_profile), - closed(R.drawable.ic_issue_closed), - commented(R.drawable.ic_comment), - committed(R.drawable.ic_push), - demilestoned(R.drawable.ic_milestone), - head_ref_deleted(R.drawable.ic_trash), - head_ref_restored(R.drawable.ic_redo), - labeled(R.drawable.ic_label), - locked(R.drawable.ic_lock), - mentioned(R.drawable.ic_at), - merged(R.drawable.ic_fork), - milestoned(R.drawable.ic_milestone), - referenced(R.drawable.ic_format_quote), - renamed(R.drawable.ic_edit), - reopened(R.drawable.ic_issue_opened), - subscribed(R.drawable.ic_subscribe), - unassigned(R.drawable.ic_profile), - unlabeled(R.drawable.ic_label), - unlocked(R.drawable.ic_unlock), - unsubscribed(R.drawable.ic_eye_off), - review_requested(R.drawable.ic_eye), - review_dismissed(R.drawable.ic_eye_off), - review_request_removed(R.drawable.ic_eye_off), - @SerializedName("cross-referenced")cross_referenced(R.drawable.ic_format_quote), - @SerializedName("line-commented")line_commented(R.drawable.ic_comment), - @SerializedName("commit-commented")commit_commented(R.drawable.ic_comment), - reviewed(R.drawable.ic_eye), - changes_requested(R.drawable.ic_eye), - added_to_project(R.drawable.ic_add), - GROUPED(R.drawable.ic_eye), - deployed(R.drawable.ic_rocket); - - int iconResId; - - IssueEventType(int iconResId) {this.iconResId = iconResId;} - - public int getIconResId() { - return iconResId == 0 ? R.drawable.ic_label : iconResId; - } - - @Nullable public static IssueEventType getType(@NonNull String type) { - return Stream.of(values()) - .filter(value -> value.name().toLowerCase().equalsIgnoreCase(type.toLowerCase() - .replaceAll("-", "_"))) - .findFirst() - .orElse(null); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/dao/types/IssueState.java b/app/src/main/java/com/fastaccess/data/dao/types/IssueState.java deleted file mode 100644 index 6155871e0..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/types/IssueState.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.data.dao.types; - -import android.support.annotation.StringRes; - -import com.fastaccess.R; - -public enum IssueState { - open(R.string.opened), - closed(R.string.closed), - all(R.string.all); - - int status; - - IssueState(@StringRes int status) { - this.status = status; - } - - @StringRes public int getStatus() { - return status; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/dao/types/MyIssuesType.java b/app/src/main/java/com/fastaccess/data/dao/types/MyIssuesType.java deleted file mode 100644 index ba93a0ad3..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/types/MyIssuesType.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.data.dao.types; - -/** - * Created by Kosh on 30 Apr 2017, 1:03 PM - */ - -public enum MyIssuesType { - CREATED, - ASSIGNED, - MENTIONED, - REVIEW, - PARTICIPATED -} diff --git a/app/src/main/java/com/fastaccess/data/dao/types/NotificationReason.java b/app/src/main/java/com/fastaccess/data/dao/types/NotificationReason.java deleted file mode 100644 index 7600a115f..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/types/NotificationReason.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.fastaccess.data.dao.types; - -public enum NotificationReason { - subscribed, - manual, - author, - comment, - mention, - team_mention, - state_change, - assign, -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/dao/types/NotificationType.java b/app/src/main/java/com/fastaccess/data/dao/types/NotificationType.java deleted file mode 100644 index 7f681b286..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/types/NotificationType.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.fastaccess.data.dao.types; - -import com.fastaccess.R; - -/** - * Created by Kosh on 19 Apr 2017, 7:57 PM - */ - -public enum NotificationType { - PullRequest(R.drawable.ic_pull_requests), - Issue(R.drawable.ic_issues), - Commit(R.drawable.ic_push); - - int drawableRes; - - NotificationType(int drawableRes) { - this.drawableRes = drawableRes; - } - - public int getDrawableRes() { - return drawableRes > 0 ? drawableRes : R.drawable.ic_issues; - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/types/ReactionTypes.java b/app/src/main/java/com/fastaccess/data/dao/types/ReactionTypes.java deleted file mode 100644 index a8a132705..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/types/ReactionTypes.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.fastaccess.data.dao.types; - -import android.support.annotation.IdRes; -import android.support.annotation.Nullable; - -import com.annimon.stream.Stream; -import com.fastaccess.R; - -/** - * Created by Kosh on 29 Mar 2017, 10:11 PM - */ - -public enum ReactionTypes { - - HEART("heart", R.id.heart, R.id.heartReaction), - HOORAY("hooray", R.id.hurray, R.id.hurrayReaction), - PLUS_ONE("+1", R.id.thumbsUp, R.id.thumbsUpReaction), - MINUS_ONE("-1", R.id.thumbsDown, R.id.thumbsDownReaction), - CONFUSED("confused", R.id.sad, R.id.sadReaction), - LAUGH("laugh", R.id.laugh, R.id.laughReaction); - - private String content; - private int vId; - private int secondaryViewId; - - ReactionTypes(String content, int vId, int secondaryViewId) { - this.content = content; - this.vId = vId; - this.secondaryViewId = secondaryViewId; - } - - public String getContent() { - return content; - } - - @IdRes public int getvId() { - return vId; - } - - @Nullable public static ReactionTypes get(@IdRes int vId) { - return Stream.of(values()) - .filter(value -> value.getvId() == vId || value.secondaryViewId == vId) - .findFirst() - .orElse(null); - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/types/ReviewStateType.java b/app/src/main/java/com/fastaccess/data/dao/types/ReviewStateType.java deleted file mode 100644 index da91a5904..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/types/ReviewStateType.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.fastaccess.data.dao.types; - -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; - -import com.annimon.stream.Stream; -import com.fastaccess.R; - -/** - * Created by Kosh on 10 Apr 2017, 4:27 PM - */ - -public enum ReviewStateType { - COMMENTED(R.string.reviewed, R.drawable.ic_eye), - CHANGES_REQUESTED(R.string.request_changes, R.drawable.ic_clear), - REQUEST_CHANGES(R.string.reviewed, R.drawable.ic_eye), - DISMISSED(R.string.dismissed_review, R.drawable.ic_clear), - APPROVED(R.string.approved_these_changes, R.drawable.ic_done), - APPROVE(R.string.approved_these_changes, R.drawable.ic_done); - - private int stringRes; - private int drawableRes; - - ReviewStateType(@StringRes int stringRes, @DrawableRes int drawableRes) { - this.stringRes = stringRes; - this.drawableRes = drawableRes; - } - - @StringRes public int getStringRes() { - return stringRes > 0 ? stringRes : R.string.reviewed; - } - - @DrawableRes public int getDrawableRes() { - return drawableRes > 0 ? drawableRes : R.drawable.ic_eye; - } - - @Nullable public static ReviewStateType getType(@NonNull String state) { - return Stream.of(values()) - .filter(value -> value.name().toLowerCase().equalsIgnoreCase(state.toLowerCase())) - .findFirst() - .orElse(null); - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/types/StatusStateType.java b/app/src/main/java/com/fastaccess/data/dao/types/StatusStateType.java deleted file mode 100644 index ae02006bd..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/types/StatusStateType.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.fastaccess.data.dao.types; - -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.annimon.stream.Stream; -import com.fastaccess.R; - -/** - * Created by Kosh on 10 Apr 2017, 3:41 AM - */ - -public enum StatusStateType { - failure(R.drawable.ic_issues_small), - pending(R.drawable.ic_time_small), - success(R.drawable.ic_check_small), - error(R.drawable.ic_issues_small); - - @DrawableRes private int drawableRes; - - StatusStateType(@DrawableRes int drawableRes) { - this.drawableRes = drawableRes; - } - - @DrawableRes public int getDrawableRes() { - return drawableRes; - } - - @NonNull public static StatusStateType getState(@Nullable String status) { - return Stream.of(values()) - .filter(value -> value.name().toLowerCase().equalsIgnoreCase(status)) - .findFirst() - .orElse(pending); - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/wiki/WikiContentModel.kt b/app/src/main/java/com/fastaccess/data/dao/wiki/WikiContentModel.kt deleted file mode 100644 index d37c14789..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/wiki/WikiContentModel.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.fastaccess.data.dao.wiki - -import android.os.Parcel -import com.fastaccess.helper.KotlinParcelable -import com.fastaccess.helper.parcelableCreator - -/** - * Created by Kosh on 13 Jun 2017, 8:06 PM - */ -data class WikiContentModel(val content: String? = null, private val footer: String? = null, - val sidebar: ArrayList) : KotlinParcelable { - companion object { - @JvmField val CREATOR = parcelableCreator(::WikiContentModel) - } - - constructor(source: Parcel) : this( - source.readString(), - source.readString(), - source.createTypedArrayList(WikiSideBarModel.CREATOR) - ) - - override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) { - writeString(content) - writeString(footer) - writeTypedList(sidebar) - } -} diff --git a/app/src/main/java/com/fastaccess/data/dao/wiki/WikiSideBarModel.kt b/app/src/main/java/com/fastaccess/data/dao/wiki/WikiSideBarModel.kt deleted file mode 100644 index e064d1417..000000000 --- a/app/src/main/java/com/fastaccess/data/dao/wiki/WikiSideBarModel.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.fastaccess.data.dao.wiki - -import android.os.Parcel -import com.fastaccess.helper.KotlinParcelable -import com.fastaccess.helper.parcelableCreator - -/** - * Created by Kosh on 13 Jun 2017, 8:03 PM - */ -data class WikiSideBarModel(val title: String? = null, val link: String? = null) : KotlinParcelable { - companion object { - @JvmField val CREATOR = parcelableCreator(::WikiSideBarModel) - } - - constructor(source: Parcel) : this( - source.readString(), - source.readString() - ) - - override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) { - writeString(title) - writeString(link) - } -} diff --git a/app/src/main/java/com/fastaccess/data/service/ContentService.kt b/app/src/main/java/com/fastaccess/data/service/ContentService.kt deleted file mode 100644 index 5f686406b..000000000 --- a/app/src/main/java/com/fastaccess/data/service/ContentService.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.data.service - -import com.fastaccess.data.dao.CommitRequestModel -import com.fastaccess.data.dao.GitCommitModel -import com.fastaccess.data.dao.GitHubStatusModel -import io.reactivex.Observable -import retrofit2.http.* - -/** - * Created by kosh on 29/08/2017. - */ -interface ContentService { - - @PUT("repos/{owner}/{repoId}/contents/{path}") - fun updateCreateFile(@Path("owner") owner: String, - @Path("repoId") repoId: String, - @Path("path") path: String, - @Query("branch") branch: String, - @Body body: CommitRequestModel): Observable - - @HTTP(method = "DELETE", path = "repos/{owner}/{repoId}/contents/{path}", hasBody = true) - fun deleteFile(@Path("owner") owner: String, - @Path("repoId") repoId: String, - @Path("path") path: String, - @Query("branch") branch: String, - @Body body: CommitRequestModel): Observable - - @GET("api/last-message.json") - fun checkStatus(): Observable -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/service/GistService.java b/app/src/main/java/com/fastaccess/data/service/GistService.java deleted file mode 100644 index a0e70ecdc..000000000 --- a/app/src/main/java/com/fastaccess/data/service/GistService.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.fastaccess.data.service; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.CreateGistModel; -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Gist; - -import io.reactivex.Observable; -import retrofit2.Response; -import retrofit2.http.Body; -import retrofit2.http.DELETE; -import retrofit2.http.GET; -import retrofit2.http.Headers; -import retrofit2.http.PATCH; -import retrofit2.http.POST; -import retrofit2.http.PUT; -import retrofit2.http.Path; -import retrofit2.http.Query; -import retrofit2.http.Url; - -/** - * Created by Kosh on 20 Nov 2016, 10:28 AM - */ - -public interface GistService { - - @NonNull @GET @Headers("Accept: application/vnd.github.VERSION.raw") - Observable getGistFile(@Url String url); - - @POST("gists") Observable createGist(@Body CreateGistModel gistBody); - - @PATCH("gists/{id}") Observable editGist(@Body CreateGistModel gistBody, @Path("id") String id); - - @DELETE("gists/{id}") Observable> deleteGist(@Path("id") String id); - - @GET("gists/public") Observable> getPublicGists(@Query("per_page") int perPage, @Query("page") int page); - - @GET("gists") Observable> getMyGists(@Query("page") int page); - - @GET("users/{username}/gists") - Observable> getUserGists(@NonNull @Path("username") String username, @Query("page") int page); - - @GET("gists/{id}") - Observable getGist(@Path("id") String id); - - @GET("gists/{id}/comments") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable> getGistComments(@NonNull @Path("id") String id, @Query("page") int page); - - @POST("gists/{gist_id}/comments") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable createGistComment(@Path("gist_id") String gistId, @Body CommentRequestModel body); - - @PATCH("gists/{gist_id}/comments/{id}") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable editGistComment(@Path("gist_id") String gistId, @Path("id") long id, @Body CommentRequestModel body); - - @DELETE("gists/{gist_id}/comments/{id}") - Observable> deleteGistComment(@Path("gist_id") String gistId, @Path("id") long id); - - @GET("gists/{gist_id}/star") - Observable> checkGistStar(@Path("gist_id") @NonNull String gistId); - - @PUT("gists/{gist_id}/star") - Observable> starGist(@Path("gist_id") @NonNull String gistId); - - @DELETE("gists/{gist_id}/star") - Observable> unStarGist(@Path("gist_id") @NonNull String gistId); - - @POST("gists/{gist_id}/forks") - Observable> forkGist(@Path("gist_id") @NonNull String gistId); - - @GET("/gists/starred") Observable> getStarredGists(@Query("page") int page); - -} diff --git a/app/src/main/java/com/fastaccess/data/service/ImgurService.java b/app/src/main/java/com/fastaccess/data/service/ImgurService.java deleted file mode 100644 index 746876988..000000000 --- a/app/src/main/java/com/fastaccess/data/service/ImgurService.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.fastaccess.data.service; - -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.ImgurReponseModel; - -import okhttp3.RequestBody; -import retrofit2.http.Body; -import retrofit2.http.POST; -import retrofit2.http.Query; -import io.reactivex.Observable; - -/** - * Created by Kosh on 15 Apr 2017, 8:06 PM - */ - -public interface ImgurService { - @POST("image") - Observable postImage(@Nullable @Query("title") String title, @Body RequestBody body); -} diff --git a/app/src/main/java/com/fastaccess/data/service/IssueService.java b/app/src/main/java/com/fastaccess/data/service/IssueService.java deleted file mode 100644 index d63d7c4b2..000000000 --- a/app/src/main/java/com/fastaccess/data/service/IssueService.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.fastaccess.data.service; - - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.AssigneesRequestModel; -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.CreateIssueModel; -import com.fastaccess.data.dao.IssueRequestModel; -import com.fastaccess.data.dao.IssuesPageable; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.LockIssuePrModel; -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.IssueEvent; -import com.google.gson.JsonObject; - -import java.util.List; - -import io.reactivex.Observable; -import retrofit2.Response; -import retrofit2.http.Body; -import retrofit2.http.DELETE; -import retrofit2.http.GET; -import retrofit2.http.HTTP; -import retrofit2.http.Headers; -import retrofit2.http.PATCH; -import retrofit2.http.POST; -import retrofit2.http.PUT; -import retrofit2.http.Path; -import retrofit2.http.Query; - -public interface IssueService { - - @GET("repos/{owner}/{repo}/issues") - Observable> getRepositoryIssues(@Path("owner") String owner, @Path("repo") String repo, - @Query("state") String state, @Query("sort") String sortBy, - @Query("page") int page); - - @GET("search/issues") Observable> getIssuesWithCount(@NonNull @Query(value = "q", encoded = true) String query, - @Query("page") int page); - - @GET("user/issues") - Observable> getUserIssues(@Query("page") int page, @Query("state") @NonNull String state); - - @GET("repos/{owner}/{repo}/issues/{number}") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable getIssue(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") int number); - - @GET("repos/{owner}/{repo}/issues/{issue_number}/events?per_page=100") - Observable> getTimeline(@Path("owner") String owner, @Path("repo") String repo, - @Path("issue_number") int issue_number); - - @GET("repos/{owner}/{repo}/issues/{issue_number}/timeline?per_page=100") - @Headers("Accept: application/vnd.github.mockingbird-preview,application/vnd.github.VERSION.full+json," + - " application/vnd.github.squirrel-girl-preview") - Observable> getTimeline(@Path("owner") String owner, @Path("repo") String repo, - @Path("issue_number") int issue_number, @Query("page") int page); - - @POST("repos/{owner}/{repo}/issues") - Observable createIssue(@Path("owner") String owner, @Path("repo") String repo, - @Body IssueRequestModel issue); - - @PATCH("repos/{owner}/{repo}/issues/{number}") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable editIssue(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") int number, - @Body IssueRequestModel issue); - - @Headers("Accept: application/vnd.github.sailor-v-preview+json") - @PUT("repos/{owner}/{repo}/issues/{number}/lock") - Observable> lockIssue(@Body LockIssuePrModel body, @Path("owner") String owner, - @Path("repo") String repo, @Path("number") int number); - - @DELETE("repos/{owner}/{repo}/issues/{number}/lock") - Observable> unlockIssue(@Path("owner") String owner, @Path("repo") String repo, @Path("number") int number); - - - @GET("repos/{owner}/{repo}/issues/{number}/comments?per_page=100") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable> getIssueComments(@Path("owner") String owner, - @Path("repo") String repo, - @Path("number") int number, - @Query("page") int page); - - @GET("repos/{owner}/{repo}/issues/{number}/comments/{id}") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable getIssueComment(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") int number, @Path("id") long id); - - @POST("repos/{owner}/{repo}/issues/{number}/comments") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable createIssueComment(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") int number, @Body CommentRequestModel body); - - @PATCH("repos/{owner}/{repo}/issues/comments/{id}") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable editIssueComment(@Path("owner") String owner, @Path("repo") String repo, @Path("id") long id, - @Body CommentRequestModel body); - - @DELETE("repos/{owner}/{repo}/issues/comments/{id}") - Observable> deleteIssueComment(@Path("owner") String owner, @Path("repo") String repo, @Path("id") long id); - - @POST("repos/{owner}/{repo}/issues") - Observable createIssue(@Path("owner") String owner, @Path("repo") String repo, @NonNull @Body CreateIssueModel body); - - @PUT("repos/{owner}/{repo}/issues/{number}/labels") - Observable> putLabels(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") int number, @Body @NonNull List labels); - - - @POST("repos/{owner}/{repo}/issues/{number}/assignees") - Observable putAssignees(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") int number, @Body AssigneesRequestModel body); - - @HTTP(method = "DELETE", path = "repos/{owner}/{repo}/issues/{number}/assignees", hasBody = true) - Observable deleteAssignees(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") int number, @Body AssigneesRequestModel body); - - @GET("/repos/{owner}/{repo}/issues/comments/{id}") - @Headers("Accept: application/vnd.github.mockingbird-preview,application/vnd.github.VERSION.full+json," + - " application/vnd.github.squirrel-girl-preview") - Observable getComment(@Path("owner") String owner, @Path("repo") String repo, @Path("id") long id); - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/service/LoginRestService.java b/app/src/main/java/com/fastaccess/data/service/LoginRestService.java deleted file mode 100644 index e9049bdd6..000000000 --- a/app/src/main/java/com/fastaccess/data/service/LoginRestService.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.data.service; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.AccessTokenModel; -import com.fastaccess.data.dao.AuthModel; -import com.fastaccess.data.dao.model.Login; - -import io.reactivex.Observable; -import retrofit2.http.Body; -import retrofit2.http.Field; -import retrofit2.http.FormUrlEncoded; -import retrofit2.http.GET; -import retrofit2.http.Headers; -import retrofit2.http.POST; - -public interface LoginRestService { - - @GET("user") Observable loginAccessToken(); - - @POST("authorizations") Observable login(@NonNull @Body AuthModel authModel); - - @FormUrlEncoded @POST("access_token") - @Headers("Accept: application/json") - Observable getAccessToken(@NonNull @Field("code") String code, - @NonNull @Field("client_id") String clientId, - @NonNull @Field("client_secret") String clientSecret, - @NonNull @Field("state") String state, - @NonNull @Field("redirect_uri") String redirectUrl); -} diff --git a/app/src/main/java/com/fastaccess/data/service/NotificationService.java b/app/src/main/java/com/fastaccess/data/service/NotificationService.java deleted file mode 100644 index f32ed1a01..000000000 --- a/app/src/main/java/com/fastaccess/data/service/NotificationService.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.fastaccess.data.service; - - -import android.support.annotation.NonNull; -import android.support.annotation.StringDef; - -import com.fastaccess.data.dao.NotificationSubscriptionBodyModel; -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.RepoSubscriptionModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Notification; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import io.reactivex.Observable; -import retrofit2.Response; -import retrofit2.http.Body; -import retrofit2.http.DELETE; -import retrofit2.http.GET; -import retrofit2.http.PATCH; -import retrofit2.http.PUT; -import retrofit2.http.Path; -import retrofit2.http.Query; -import retrofit2.http.Url; - -/** - * Created by Kosh on 19 Feb 2017, 6:34 PM - */ - -public interface NotificationService { - String SUBSCRIPTION_URL = "https://github.com/notifications/thread"; - - String ISSUE_THREAD_CLASS = "Issue"; - String PULL_REQUEST_THREAD_CLASS = "PullRequest"; - String SUBSCRIBE = "subscribe"; - String MUTE = "mute"; - String UTF8 = "✓"; - - @StringDef({ - ISSUE_THREAD_CLASS, - PULL_REQUEST_THREAD_CLASS - }) - @Retention(RetentionPolicy.SOURCE) @interface ThreadClass {} - - @StringDef({ - SUBSCRIBE, - MUTE - }) - @Retention(RetentionPolicy.SOURCE) @interface ThreadId {} - - @GET("notifications") Observable> getNotifications(@Query("since") String date); - - @GET("notifications?all=true&per_page=200") Observable> getAllNotifications(); - - @PATCH("notifications/threads/{id}") Observable> markAsRead(@Path("id") String id); - - @GET() Observable getComment(@Url @NonNull String commentUrl); - - @GET("notifications/threads/{id}/subscription") Observable isSubscribed(@Path("id") long id); - - @DELETE("notifications/threads/{id}/subscription") Observable> unSubscribe(@Path("id") long id); - - @PUT("notifications/threads/{id}/subscription") - Observable> subscribe(@Path("id") long id, @Body NotificationSubscriptionBodyModel body); -} diff --git a/app/src/main/java/com/fastaccess/data/service/OrganizationService.java b/app/src/main/java/com/fastaccess/data/service/OrganizationService.java deleted file mode 100644 index f4b64f101..000000000 --- a/app/src/main/java/com/fastaccess/data/service/OrganizationService.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.fastaccess.data.service; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.TeamsModel; -import com.fastaccess.data.dao.model.Event; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.data.dao.model.User; - -import java.util.Map; - -import io.reactivex.Observable; -import retrofit2.Response; -import retrofit2.http.GET; -import retrofit2.http.Path; -import retrofit2.http.Query; -import retrofit2.http.QueryMap; - -/** - * Created by Kosh on 22 Mar 2017, 6:44 PM - */ -public interface OrganizationService { - - @GET("orgs/{org}/members/{username}") - Observable> isMember(@NonNull @Path("org") String org, @NonNull @Path("username") String username); - - @GET("orgs/{org}") Observable getOrganization(@NonNull @Path("org") String org); - - @GET("user/orgs?per_page=200") Observable> getMyOrganizations(); - - @GET("users/{user}/orgs") Observable> getMyOrganizations(@NonNull @Path("user") String user); - - @GET("orgs/{org}/teams") Observable> getOrgTeams(@NonNull @Path("org") String org, @Query("page") int page); - - @GET("orgs/{org}/members") Observable> getOrgMembers(@NonNull @Path("org") String org, @Query("page") int page); - - @GET("teams/{id}/members") Observable> getTeamMembers(@Path("id") long id, @Query("page") int page); - - @GET("teams/{id}/repos") Observable> getTeamRepos(@Path("id") long id, @Query("page") int page); - - @GET("users/{username}/events/orgs/{org}") - Observable> getReceivedEvents(@NonNull @Path("username") String userName, - @NonNull @Path("org") String org, @Query("page") int page); - - @GET("orgs/{org}/repos") - Observable> getOrgRepos(@NonNull @Path("org") String org, - @QueryMap(encoded = true) Map filterParams, - @Query("page") int page); - -} diff --git a/app/src/main/java/com/fastaccess/data/service/ProjectsService.kt b/app/src/main/java/com/fastaccess/data/service/ProjectsService.kt deleted file mode 100644 index 61eb11685..000000000 --- a/app/src/main/java/com/fastaccess/data/service/ProjectsService.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.fastaccess.data.service - -import com.fastaccess.data.dao.Pageable -import com.fastaccess.data.dao.ProjectCardModel -import com.fastaccess.data.dao.ProjectColumnModel -import com.fastaccess.data.dao.ProjectsModel -import io.reactivex.Observable -import retrofit2.Response -import retrofit2.http.* - -/** - * Created by kosh on 09/09/2017. - */ - -interface ProjectsService { - - @GET("repos/{owner}/{repo}/projects") - @Headers("Accept: application/vnd.github.inertia-preview+json") - fun getRepoProjects(@Path("owner") owner: String, @Path("repo") repo: String, - @Query("state") state: String?, @Query("page") page: Int): Observable> - - @GET("orgs/{org}/projects") - @Headers("Accept: application/vnd.github.inertia-preview+json") - fun getOrgsProjects(@Path("org") org: String, - @Query("page") page: Int): Observable> - - @GET("projects/{projectId}/columns?per_page=100") - @Headers("Accept: application/vnd.github.inertia-preview+json") - fun getProjectColumns(@Path("projectId") projectId: Long): Observable> - - @GET("projects/columns/{columnId}/cards") - @Headers("Accept: application/vnd.github.inertia-preview+json") - fun getProjectCards(@Path("columnId") columnId: Long, @Query("page") page: Int): Observable> - - @POST("projects/columns/{projectId}") - @Headers("Accept: application/vnd.github.inertia-preview+json") - fun createColumn(@Path("projectId") projectId: Long, @Body card: ProjectColumnModel): Observable - - @PATCH("projects/columns/{projectId}") - @Headers("Accept: application/vnd.github.inertia-preview+json") - fun updateColumn(@Path("projectId") projectId: Long, @Body card: ProjectColumnModel): Observable - - @DELETE("projects/columns/{projectId}") - @Headers("Accept: application/vnd.github.inertia-preview+json") - fun deleteColumn(@Path("projectId") projectId: Long): Observable> - - @POST("/projects/columns/{columnId}/cards") - @Headers("Accept: application/vnd.github.inertia-preview+json") - fun createCard(@Path("columnId") columnId: Long, @Body card: ProjectCardModel): Observable - - @PATCH("projects/columns/cards/{cardId}") - @Headers("Accept: application/vnd.github.inertia-preview+json") - fun updateCard(@Path("cardId") cardId: Long, @Body card: ProjectCardModel): Observable - - @DELETE("projects/columns/cards/{cardId}") - @Headers("Accept: application/vnd.github.inertia-preview+json") - fun deleteCard(@Path("cardId") cardId: Long): Observable> -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/data/service/PullRequestService.java b/app/src/main/java/com/fastaccess/data/service/PullRequestService.java deleted file mode 100644 index 999c82b89..000000000 --- a/app/src/main/java/com/fastaccess/data/service/PullRequestService.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.fastaccess.data.service; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.AssigneesRequestModel; -import com.fastaccess.data.dao.CommitFileModel; -import com.fastaccess.data.dao.IssueRequestModel; -import com.fastaccess.data.dao.MergeRequestModel; -import com.fastaccess.data.dao.MergeResponseModel; -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.PullRequestStatusModel; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.data.dao.model.PullRequest; - -import retrofit2.Response; -import retrofit2.http.Body; -import retrofit2.http.GET; -import retrofit2.http.Headers; -import retrofit2.http.PATCH; -import retrofit2.http.POST; -import retrofit2.http.PUT; -import retrofit2.http.Path; -import retrofit2.http.Query; -import io.reactivex.Observable; - -/** - * Created by Kosh on 15 Dec 2016, 10:21 PM - */ - -public interface PullRequestService { - - @GET("repos/{owner}/{repo}/pulls") - Observable> getPullRequests(@Path("owner") String owner, @Path("repo") String repo, - @Query("state") String state, @Query("page") int page); - - @GET("search/issues") - Observable> getPullsWithCount(@NonNull @Query(value = "q", encoded = true) String query, - @Query("page") int page); - - @GET("repos/{owner}/{repo}/pulls/{number}") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable getPullRequest(@Path("owner") String owner, @Path("repo") String repo, @Path("number") long number); - - @PUT("repos/{owner}/{repo}/pulls/{number}/merge") - Observable mergePullRequest(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") long number, @Body MergeRequestModel body); - - - @GET("repos/{owner}/{repo}/pulls/{number}/commits") - Observable> getPullRequestCommits(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") long number, - @Query("page") int page); - - @GET("repos/{owner}/{repo}/pulls/{number}/files") - Observable> getPullRequestFiles(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") long number, - @Query("page") int page); - - @GET("repos/{owner}/{repo}/pulls/{number}/merge") - Observable> hasPullRequestBeenMerged(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") long number); - - @PATCH("repos/{owner}/{repo}/pulls/{number}") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable editPullRequest(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") int number, - @Body IssueRequestModel issue); - - @PATCH("repos/{owner}/{repo}/issues/{number}") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable editIssue(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") int number, - @Body IssueRequestModel issue); - - @POST("repos/{owner}/{repo}/issues/{number}/assignees") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable putAssignees(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") int number, @Body AssigneesRequestModel body); - - @GET("repos/{owner}/{repo}/commits/{ref}/status") - Observable getPullStatus(@Path("owner") String owner, @Path("repo") String repo, @Path("ref") String ref); - - @POST("repos/{owner}/{repo}/pulls/{number}/requested_reviewers") - @Headers("Accept: application/vnd.github.black-cat-preview+json") - Observable putReviewers(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") int number, @Body AssigneesRequestModel body); -} diff --git a/app/src/main/java/com/fastaccess/data/service/ReactionsService.java b/app/src/main/java/com/fastaccess/data/service/ReactionsService.java deleted file mode 100644 index 06a4a6ead..000000000 --- a/app/src/main/java/com/fastaccess/data/service/ReactionsService.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.fastaccess.data.service; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.PostReactionModel; -import com.fastaccess.data.dao.ReactionsModel; - -import retrofit2.Response; -import retrofit2.http.Body; -import retrofit2.http.DELETE; -import retrofit2.http.GET; -import retrofit2.http.Headers; -import retrofit2.http.POST; -import retrofit2.http.Path; -import retrofit2.http.Query; -import io.reactivex.Observable; - -/** - * Created by Kosh on 29 Mar 2017, 9:48 PM - */ -public interface ReactionsService { - - @POST("repos/{owner}/{repo}/issues/comments/{id}/reactions") - @Headers("Accept: application/vnd.github.squirrel-girl-preview") - Observable postIssueCommentReaction(@NonNull @Body PostReactionModel body, - @NonNull @Path("owner") String owner, - @Path("repo") @NonNull String repo, - @Path("id") long id); - - @POST("repos/{owner}/{repo}/issues/{number}/reactions") - @Headers("Accept: application/vnd.github.squirrel-girl-preview") - Observable postIssueReaction(@NonNull @Body PostReactionModel body, - @NonNull @Path("owner") String owner, - @Path("repo") @NonNull String repo, - @Path("number") long number); - - @POST("repos/{owner}/{repo}/comments/{id}/reactions") - @Headers("Accept: application/vnd.github.squirrel-girl-preview") - Observable postCommitReaction(@NonNull @Body PostReactionModel body, - @NonNull @Path("owner") String owner, - @Path("repo") @NonNull String repo, - @Path("id") long id); - - @DELETE("reactions/{id}") - @Headers("Accept: application/vnd.github.squirrel-girl-preview") - Observable> delete(@Path("id") long id); - - @GET("repos/{owner}/{repo}/issues/comments/{id}/reactions") - @Headers("Accept: application/vnd.github.squirrel-girl-preview") - Observable> getIssueCommentReaction(@NonNull @Path("owner") String owner, - @Path("repo") @NonNull String repo, - @Path("id") long id, - @Query("content") @NonNull String content, - @Query("page") int page); - - @GET("repos/{owner}/{repo}/issues/{number}/reactions") - @Headers("Accept: application/vnd.github.squirrel-girl-preview") - Observable> getIssueReaction(@NonNull @Path("owner") String owner, - @Path("repo") @NonNull String repo, - @Path("number") long id, - @Query("content") @NonNull String content, - @Query("page") int page); - - @GET("repos/{owner}/{repo}/comments/{id}/reactions") - @Headers("Accept: application/vnd.github.squirrel-girl-preview") - Observable> getCommitReaction(@NonNull @Path("owner") String owner, - @Path("repo") @NonNull String repo, - @Path("id") long id, - @Query("content") @NonNull String content, - @Query("page") int page); - - @GET("repos/{owner}/{repo}/pulls/comments/{id}/reactions") - @Headers("Accept: application/vnd.github.squirrel-girl-preview, application/vnd.github.black-cat-preview") - Observable> getPullRequestReactions(@NonNull @Path("owner") String owner, - @Path("repo") @NonNull String repo, - @Path("id") long id, - @Query("content") @NonNull String content, - @Query("page") int page); - - @POST("repos/{owner}/{repo}/pulls/comments/{id}/reactions") - @Headers("Accept: application/vnd.github.squirrel-girl-preview, application/vnd.github.black-cat-preview") - Observable postCommentReviewReaction(@NonNull @Body PostReactionModel body, - @NonNull @Path("owner") String owner, - @Path("repo") @NonNull String repo, - @Path("id") long id); -} - diff --git a/app/src/main/java/com/fastaccess/data/service/RepoService.java b/app/src/main/java/com/fastaccess/data/service/RepoService.java deleted file mode 100644 index 92c0054b3..000000000 --- a/app/src/main/java/com/fastaccess/data/service/RepoService.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.fastaccess.data.service; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.BranchesModel; -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.CreateMilestoneModel; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MarkdownModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.RepoSubscriptionModel; -import com.fastaccess.data.dao.TreeResponseModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.data.dao.model.Release; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.data.dao.model.RepoFile; -import com.fastaccess.data.dao.model.User; - -import io.reactivex.Observable; -import retrofit2.Response; -import retrofit2.http.Body; -import retrofit2.http.DELETE; -import retrofit2.http.GET; -import retrofit2.http.Headers; -import retrofit2.http.PATCH; -import retrofit2.http.POST; -import retrofit2.http.PUT; -import retrofit2.http.Path; -import retrofit2.http.Query; -import retrofit2.http.Url; - -/** - * Created by Kosh on 10 Dec 2016, 3:16 PM - */ -public interface RepoService { - - - @NonNull @GET @Headers("Accept: application/vnd.github.VERSION.raw") - Observable getFileAsStream(@Url String url); - - @NonNull @GET @Headers("Accept: application/vnd.github.html") - Observable getFileAsHtmlStream(@Url String url); - - @NonNull @POST("markdown") - Observable convertReadmeToHtml(@Body MarkdownModel model); - - @NonNull @GET("repos/{login}/{repoId}") - @Headers({"Accept: application/vnd.github.drax-preview+json, application/vnd.github.mercy-preview+json"}) - Observable getRepo(@Path("login") String login, @Path("repoId") String repoId); - - @NonNull @DELETE("repos/{login}/{repoId}") - Observable> deleteRepo(@Path("login") String login, @Path("repoId") String repoId); - - @NonNull @GET @Headers("Accept: application/vnd.github.html") - Observable getReadmeHtml(@NonNull @Url String url); - - @NonNull @GET("user/starred/{owner}/{repo}") - Observable> checkStarring(@NonNull @Path("owner") String login, @NonNull @Path("repo") String repoId); - - @NonNull @PUT("user/starred/{owner}/{repo}") - Observable> starRepo(@NonNull @Path("owner") String login, @NonNull @Path("repo") String repoId); - - @NonNull @DELETE("user/starred/{owner}/{repo}") - Observable> unstarRepo(@NonNull @Path("owner") String login, @NonNull @Path("repo") String repoId); - - @NonNull @POST("/repos/{owner}/{repo}/forks") - Observable forkRepo(@NonNull @Path("owner") String login, @NonNull @Path("repo") String repoId); - - @NonNull @GET("repos/{owner}/{repo}/subscription") - Observable isWatchingRepo(@Path("owner") String owner, @Path("repo") String repo); - - @NonNull @PUT("user/subscriptions/{owner}/{repo}") - Observable> watchRepo(@Path("owner") String owner, @Path("repo") String repo); - - @NonNull @DELETE("user/subscriptions/{owner}/{repo}") - Observable> unwatchRepo(@Path("owner") String owner, @Path("repo") String repo); - - @NonNull @GET("repos/{owner}/{repo}/commits") - Observable> getCommits(@Path("owner") String owner, @Path("repo") String repo, - @NonNull @Query("sha") String branch, @Query("page") int page); - - @NonNull @GET("repos/{owner}/{repo}/commits") - Observable> getCommits(@Path("owner") String owner, @Path("repo") String repo, - @NonNull @Query("sha") String branch, - @NonNull @Query("path") String path, - @Query("page") int page); - - @NonNull @GET("repos/{owner}/{repo}/releases") - @Headers("Accept: application/vnd.github.VERSION.full+json") - Observable> getReleases(@Path("owner") String owner, @Path("repo") String repo, @Query("page") int page); - - @NonNull @GET("repos/{owner}/{repo}/releases/{id}") - @Headers("Accept: application/vnd.github.VERSION.full+json") - Observable getRelease(@Path("owner") String owner, @Path("repo") String repo, @Path("id") long id); - - @NonNull @GET("repos/{owner}/{repo}/releases/latest") - Observable getLatestRelease(@Path("owner") String owner, @Path("repo") String repo); - - @NonNull @GET("repos/{owner}/{repo}/tags") - @Headers("Accept: application/vnd.github.VERSION.full+json") - Observable> getTagReleases(@Path("owner") String owner, @Path("repo") String repo, @Query("page") int page); - - @NonNull @GET("repos/{owner}/{repo}/tags/{tag}") - @Headers("Accept: application/vnd.github.VERSION.full+json") - Observable getTagRelease(@Path("owner") String owner, @Path("repo") String repo, @Path("tag") String tag); - - @NonNull @GET("repos/{owner}/{repo}/contributors") - Observable> getContributors(@Path("owner") String owner, @Path("repo") String repo, @Query("page") int page); - - @NonNull @GET("repos/{owner}/{repo}/commits/{sha}") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable getCommit(@Path("owner") String owner, @Path("repo") String repo, @Path("sha") String sha); - - @NonNull @GET("repos/{owner}/{repo}/commits/{sha}/comments") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable> getCommitComments(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo, - @NonNull @Path("sha") String ref, @Query("page") int page); - - @NonNull @POST("repos/{owner}/{repo}/commits/{sha}/comments") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable postCommitComment(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo, - @NonNull @Path("sha") String ref, @Body CommentRequestModel model); - - - @NonNull @PATCH("repos/{owner}/{repo}/comments/{id}") - @Headers("Accept: application/vnd.github.VERSION.full+json, application/vnd.github.squirrel-girl-preview") - Observable editCommitComment(@Path("owner") String owner, @Path("repo") String repo, @Path("id") long id, - @Body CommentRequestModel body); - - @NonNull @DELETE("repos/{owner}/{repo}/comments/{id}") - Observable> deleteComment(@Path("owner") String owner, @Path("repo") String repo, @Path("id") long id); - - @NonNull @GET("repos/{owner}/{repo}/contents/{path}") - Observable> getRepoFiles(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo, - @NonNull @Path(value = "path", encoded = true) String path, - @NonNull @Query("ref") String ref); - - @NonNull @GET("repos/{owner}/{repo}/git/trees/{sha}?recursive=1") - Observable getRepoTree(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo, - @NonNull @Path("sha") String sha); - - @NonNull @GET("repos/{owner}/{repo}/labels?per_page=100") - Observable> getLabels(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo); - - @NonNull @GET("repos/{owner}/{repo}/labels?per_page=100") - Observable> getLabels(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo, @Query("page") int page); - - @NonNull @POST("repos/{owner}/{repo}/labels") - Observable addLabel(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo, @Body LabelModel body); - - @NonNull @GET("repos/{owner}/{repo}/collaborators/{username}") - Observable> isCollaborator(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo, - @NonNull @Path("username") String username); - - @NonNull @GET("repos/{owner}/{repo}/collaborators?per_page=100") - Observable> getCollaborator(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo); - - - @NonNull @GET("repos/{owner}/{repo}/branches") - Observable> getBranches(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo, - @Query("page") int page); - - @NonNull @GET("repos/{owner}/{repo}/tags") - Observable> getTags(@NonNull @Path("owner") String owner, @NonNull @Path("repo") String repo, - @Query("page") int page); - - @NonNull @GET("repos/{owner}/{repo}/milestones") - Observable> getMilestones(@Path("owner") String owner, @Path("repo") String repo); - - @NonNull @POST("repos/{owner}/{repo}/milestones") - Observable createMilestone(@Path("owner") String owner, @Path("repo") String repo, - @Body CreateMilestoneModel create); - - @NonNull @GET("repos/{owner}/{repo}/assignees") - Observable> getAssignees(@Path("owner") String owner, @Path("repo") String repo); - - @NonNull @GET("repos/{owner}/{repo}/commits?per_page=1") - Observable> getCommitCounts(@Path("owner") String owner, @Path("repo") String repo, @Query("sha") String ref); - - @NonNull @GET("/repos/{owner}/{repo}/stargazers") - Observable> getStargazers(@Path("owner") String owner, @Path("repo") String repo, @Query("page") int page); - - @NonNull @GET("/repos/{owner}/{repo}/subscribers") - Observable> getWatchers(@Path("owner") String owner, @Path("repo") String repo, @Query("page") int page); - - @NonNull @GET("/repos/{owner}/{repo}/forks") - Observable> getForks(@Path("owner") String owner, @Path("repo") String repo, @Query("page") int page); - - @NonNull @GET("repos/{owner}/{repo}/license") @Headers("Accept: application/vnd.github.html") - Observable getLicense(@Path("owner") String owner, @Path("repo") String repo); -} diff --git a/app/src/main/java/com/fastaccess/data/service/ReviewService.java b/app/src/main/java/com/fastaccess/data/service/ReviewService.java deleted file mode 100644 index 8d947c36e..000000000 --- a/app/src/main/java/com/fastaccess/data/service/ReviewService.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.fastaccess.data.service; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.ReviewCommentModel; -import com.fastaccess.data.dao.ReviewModel; -import com.fastaccess.data.dao.ReviewRequestModel; - -import io.reactivex.Observable; -import retrofit2.Response; -import retrofit2.http.Body; -import retrofit2.http.DELETE; -import retrofit2.http.GET; -import retrofit2.http.Headers; -import retrofit2.http.PATCH; -import retrofit2.http.POST; -import retrofit2.http.Path; - -/** - * Created by Kosh on 07 May 2017, 1:01 PM - */ - -public interface ReviewService { - - @GET("repos/{owner}/{repo}/pulls/{number}/reviews/{id}") - @Headers("Accept: application/vnd.github.black-cat-preview+json, application/vnd.github.VERSION.html") - @NonNull - Observable getReview(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") long number, @Path("id") long id); - - @GET("repos/{owner}/{repo}/pulls/{number}/reviews?per_page=100") - @Headers("Accept: application/vnd.github.black-cat-preview+json, application/vnd.github.VERSION.html") - @NonNull - Observable> getReviews(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") long number); - - @GET("repos/{owner}/{repo}/pulls/{number}/reviews/{id}/comments") - @Headers("Accept: application/vnd.github.black-cat-preview+json, application/vnd.github.VERSION.html") - @NonNull - Observable> getReviewComments(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") long number, @Path("id") long reviewId); - - @GET("repos/{owner}/{repo}/pulls/{number}/comments?per_page=100") - @Headers("Accept: application/vnd.github.black-cat-preview+json, application/vnd.github.VERSION.html, " - + "application/vnd.github.squirrel-girl-preview") - @NonNull - Observable> getPrReviewComments(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") long number); - - @POST("/repos/{owner}/{repo}/pulls/{number}/comments") - @Headers("Accept: application/vnd.github.black-cat-preview+json, application/vnd.github.VERSION.html, " - + "application/vnd.github.squirrel-girl-preview") - Observable submitComment(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") long number, @Body CommentRequestModel body); - - @PATCH("/repos/{owner}/{repo}/pulls/comments/{id}") - @Headers("Accept: application/vnd.github.black-cat-preview+json, application/vnd.github.VERSION.html, " - + "application/vnd.github.squirrel-girl-preview") - Observable editComment(@Path("owner") String owner, @Path("repo") String repo, - @Path("id") long id, @Body CommentRequestModel body); - - @DELETE("repos/{owner}/{repo}/pulls/comments/{id}") - @Headers("Accept: application/vnd.github.black-cat-preview") - Observable> deleteComment(@Path("owner") String owner, @Path("repo") String repo, @Path("id") long id); - - @POST("repos/{owner}/{repo}/pulls/{number}/reviews") - @Headers("Accept: application/vnd.github.black-cat-preview") - Observable> submitPrReview(@Path("owner") String owner, @Path("repo") String repo, - @Path("number") long number, @NonNull @Body ReviewRequestModel body); -} diff --git a/app/src/main/java/com/fastaccess/data/service/SearchService.java b/app/src/main/java/com/fastaccess/data/service/SearchService.java deleted file mode 100644 index 60ca75fbc..000000000 --- a/app/src/main/java/com/fastaccess/data/service/SearchService.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.data.service; - -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.SearchCodeModel; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.data.dao.model.User; - -import retrofit2.http.GET; -import retrofit2.http.Query; -import io.reactivex.Observable; - -/** - * Created by Kosh on 08 Dec 2016, 9:07 PM - */ - -public interface SearchService { - - @GET("search/repositories") - Observable> searchRepositories(@Query(value = "q", encoded = true) String query, @Query("page") long page); - - @GET("search/code") - Observable> searchCode(@Query(value = "q", encoded = true) String query, @Query("page") long page); - - @GET("search/issues") - Observable> searchIssues(@Query(value = "q", encoded = true) String query, @Query("page") long page); - - @GET("search/users") - Observable> searchUsers(@Query(value = "q", encoded = true) String query, @Query("page") long page); -} diff --git a/app/src/main/java/com/fastaccess/data/service/SlackService.java b/app/src/main/java/com/fastaccess/data/service/SlackService.java deleted file mode 100644 index 7aca9e4a5..000000000 --- a/app/src/main/java/com/fastaccess/data/service/SlackService.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.fastaccess.data.service; - -import com.fastaccess.data.dao.SlackInvitePostModel; -import com.fastaccess.data.dao.SlackResponseModel; - -import retrofit2.http.Body; -import retrofit2.http.Headers; -import retrofit2.http.POST; -import io.reactivex.Observable; - -/** - * Created by Kosh on 01 May 2017, 1:04 AM - */ - -public interface SlackService { - - @POST("FastHubSlackInvite") - @Headers("X-API-Key: MvFQyrJ9703DYmKHvk13I3agw3AdH8vh1lKbKGx4") - Observable invite(@Body SlackInvitePostModel body); -} diff --git a/app/src/main/java/com/fastaccess/data/service/UserRestService.java b/app/src/main/java/com/fastaccess/data/service/UserRestService.java deleted file mode 100644 index a3d2289d9..000000000 --- a/app/src/main/java/com/fastaccess/data/service/UserRestService.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.fastaccess.data.service; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.model.Event; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.data.dao.model.User; - -import java.util.Map; - -import io.reactivex.Observable; -import retrofit2.Response; -import retrofit2.http.DELETE; -import retrofit2.http.GET; -import retrofit2.http.Headers; -import retrofit2.http.PUT; -import retrofit2.http.Path; -import retrofit2.http.Query; -import retrofit2.http.QueryMap; -import retrofit2.http.Url; - - -/** - * Created by Kosh on 08 Feb 2017, 8:54 PM - */ - -public interface UserRestService { - - @GET("user") Observable getUser(); - - @GET("users/{username}") Observable getUser(@Path("username") @NonNull String username); - - @GET("users/{username}/received_events") - Observable> getReceivedEvents(@NonNull @Path("username") String userName, @Query("page") int page); - - @GET("users/{username}/events") - Observable> getUserEvents(@NonNull @Path("username") String userName, @Query("page") int page); - - @GET("users/{username}/repos") - Observable> getRepos(@Path("username") @NonNull String username, @QueryMap(encoded = true) Map filterParams, - @Query("page") int page); - - @GET("user/repos") - Observable> getRepos(@QueryMap(encoded = true) Map filterParams, @Query(value = "page") int page); - - @GET("users/{username}/starred") Observable> - getStarred(@Path("username") @NonNull String username, @Query("page") int page); - - @GET("users/{username}/starred?per_page=1") Observable> - getStarredCount(@Path("username") @NonNull String username); - - @GET("users/{username}/following") - Observable> getFollowing(@Path("username") @NonNull String username, @Query("page") int page); - - @GET("users/{username}/followers") - Observable> getFollowers(@Path("username") @NonNull String username, @Query("page") int page); - - @GET("user/following/{username}") - Observable> getFollowStatus(@Path("username") @NonNull String username); - - @PUT("user/following/{username}") - Observable> followUser(@Path("username") @NonNull String username); - - @DELETE("user/following/{username}") - Observable> unfollowUser(@Path("username") @NonNull String username); - - @GET Observable getContributions(@Url String url); - - @GET("user/blocks/{username}") - @Headers("Accept: application/vnd.github.giant-sentry-fist-preview+json") - Observable> isUserBlocked(@Path("username") @NonNull String username); - - @PUT("user/blocks/{username}") - @Headers("Accept: application/vnd.github.giant-sentry-fist-preview+json") - Observable> blockUser(@Path("username") @NonNull String username); - - @DELETE("user/blocks/{username}") - @Headers("Accept: application/vnd.github.giant-sentry-fist-preview+json") - Observable> unBlockUser(@Path("username") @NonNull String username); -} diff --git a/app/src/main/java/com/fastaccess/github/App.kt b/app/src/main/java/com/fastaccess/github/App.kt new file mode 100644 index 000000000..a5357b3df --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/App.kt @@ -0,0 +1,42 @@ +package com.fastaccess.github + +import androidx.work.Configuration +import androidx.work.WorkManager +import com.evernote.android.state.StateSaver +import com.fastaccess.github.di.components.AppComponent +import com.fastaccess.github.platform.fabric.FabricProvider +import com.fastaccess.github.platform.timber.FabricTree +import com.fastaccess.github.platform.timber.FastHubTree +import com.fastaccess.markdown.emoji.EmojiManager +import dagger.android.AndroidInjector +import dagger.android.support.DaggerApplication +import timber.log.Timber + +/** + * Created by Kosh on 12.05.18. + */ +class App : DaggerApplication() { + + private val appComponent by lazy { AppComponent.getComponent(this) } + + override fun applicationInjector(): AndroidInjector = appComponent + + override fun onCreate() { + super.onCreate() + initConfigs() + } + + private fun initConfigs() { + WorkManager.initialize(this, Configuration.Builder() + .setWorkerFactory(appComponent.daggerWorkerFactory()) + .build()) + FabricProvider.initFabric(this) + StateSaver.setEnabledForAllActivitiesAndSupportFragments(this, true) + if (BuildConfig.DEBUG) { + Timber.plant(FastHubTree()) + } else { + Timber.plant(FabricTree()) + } + EmojiManager.load(this) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/base/BaseActivity.kt b/app/src/main/java/com/fastaccess/github/base/BaseActivity.kt new file mode 100644 index 000000000..77ea303a7 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/base/BaseActivity.kt @@ -0,0 +1,72 @@ +package com.fastaccess.github.base + +import android.os.Bundle +import android.view.View +import androidx.annotation.LayoutRes +import com.fastaccess.data.storage.FastHubSharedPreference +import com.fastaccess.github.R +import com.fastaccess.github.base.engine.ThemeEngine +import com.fastaccess.github.di.modules.AuthenticationInterceptor +import com.fastaccess.github.ui.modules.auth.LoginChooserActivity +import com.fastaccess.github.utils.IS_ENTERPRISE +import com.fastaccess.github.utils.extensions.materialize +import com.fastaccess.github.utils.extensions.otpCode +import com.fastaccess.github.utils.extensions.theme +import com.fastaccess.github.utils.extensions.token +import com.google.android.material.snackbar.Snackbar +import dagger.android.AndroidInjection +import dagger.android.support.DaggerAppCompatActivity +import javax.inject.Inject + +/** + * Created by Kosh on 12.05.18. + */ +abstract class BaseActivity : DaggerAppCompatActivity(), ActivityCallback { + + @Inject lateinit var preference: FastHubSharedPreference + @Inject lateinit var interceptor: AuthenticationInterceptor + + @LayoutRes abstract fun layoutRes(): Int + + abstract fun onActivityCreatedWithUser(savedInstanceState: Bundle?) + override fun isLoggedIn() = !preference.token.isNullOrEmpty() + override fun isEnterprise(): Boolean = intent?.extras?.getBoolean(IS_ENTERPRISE) ?: false + + override fun onCreate(savedInstanceState: Bundle?) { + AndroidInjection.inject(this) // for the sake of theme engine + ThemeEngine.setTheme(this, preference.theme) + super.onCreate(savedInstanceState) + val layoutRes = layoutRes() + if (layoutRes > 0) setContentView(layoutRes) + + if (!isLoggedIn() && this is LoginChooserActivity) { + onActivityCreated(savedInstanceState) + return + } + + if (isLoggedIn()) { + interceptor.token = preference.token + interceptor.otp = preference.otpCode + onActivityCreatedWithUser(savedInstanceState) + } else { + LoginChooserActivity.startActivity(this) + onActivityCreated(savedInstanceState) + } + + } + + override fun showSnackBar(root: View, resId: Int?, message: String?, duration: Int) { + if ((resId == null && message == null) || isFinishing) return + Snackbar.make(root, message ?: getString(resId ?: R.string.unknown), duration) + .materialize() + .show() + } + + protected open fun onActivityCreated(savedInstanceState: Bundle?) = Unit +} + +interface ActivityCallback { + fun isLoggedIn(): Boolean + fun isEnterprise(): Boolean + fun showSnackBar(root: View, resId: Int? = null, message: String? = null, duration: Int = Snackbar.LENGTH_LONG) +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/base/BaseBottomSheetDialogFragment.kt b/app/src/main/java/com/fastaccess/github/base/BaseBottomSheetDialogFragment.kt new file mode 100644 index 000000000..fb49e5690 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/base/BaseBottomSheetDialogFragment.kt @@ -0,0 +1,164 @@ +package com.fastaccess.github.base + +import android.content.Context +import android.graphics.Color +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.ViewTreeObserver +import android.widget.TextView +import androidx.annotation.LayoutRes +import androidx.appcompat.view.ContextThemeWrapper +import androidx.appcompat.widget.Toolbar +import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import com.fastaccess.github.R +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.utils.extensions.setBottomSheetCallback +import com.github.zagum.expandicon.ExpandIconView +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import dagger.android.AndroidInjector +import dagger.android.DispatchingAndroidInjector +import dagger.android.support.AndroidSupportInjection +import dagger.android.support.HasSupportFragmentInjector +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.disposables.Disposable +import javax.inject.Inject + +/** + * Created by Kosh on 2018-11-25. + */ +abstract class BaseBottomSheetDialogFragment : BottomSheetDialogFragment(), HasSupportFragmentInjector { + + @Inject lateinit var childFragmentInjector: DispatchingAndroidInjector + + private var disposal = CompositeDisposable() + private var activityCallback: ActivityCallback? = null + private var bottomSheetBehavior: BottomSheetBehavior? = null + + @LayoutRes abstract fun layoutRes(): Int + abstract fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) + abstract fun viewModel(): BaseViewModel? + protected open fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {} + + override fun onAttach(context: Context) { + AndroidSupportInjection.inject(this) + super.onAttach(context) + activityCallback = when { + parentFragment is ActivityCallback -> parentFragment as ActivityCallback + context is ActivityCallback -> context + else -> null + } + } + + override fun onCreate(savedInstanceState: Bundle?) { // expose so its easier to find + super.onCreate(savedInstanceState) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + super.onCreateView(inflater, container, savedInstanceState) + val contextThemeWrapper = ContextThemeWrapper(context, context?.theme) + val themeAwareInflater = inflater.cloneInContext(contextThemeWrapper) + val view = themeAwareInflater.inflate(layoutRes(), container, false) + view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { + override fun onGlobalLayout() { + view.viewTreeObserver.removeOnGlobalLayoutListener(this) + onGlobalLayoutChanged(view) + } + }) + return view + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + if (activityCallback?.isLoggedIn() == true) { + onFragmentCreatedWithUser(view, savedInstanceState) + } else { + onFragmentCreated(view, savedInstanceState) + } + + viewModel()?.progress?.observe(this, Observer { + val refresh = this@BaseBottomSheetDialogFragment.view?.findViewById(R.id.swipeRefresh) + refresh?.isRefreshing = it == true + }) + + viewModel()?.error?.observeNotNull(this) { + this@BaseBottomSheetDialogFragment.view?.let { view -> activityCallback?.showSnackBar(view, resId = it.resId, message = it.message) } + } + + val toggleArrow = view.findViewById(R.id.toggleArrow) + toggleArrow?.setOnClickListener { + bottomSheetBehavior?.let { behaviour -> + if (behaviour.state != BottomSheetBehavior.STATE_EXPANDED) { + behaviour.state = BottomSheetBehavior.STATE_EXPANDED + } else { + behaviour.state = BottomSheetBehavior.STATE_COLLAPSED + } + } + } + } + + override fun onDestroyView() { + disposal.clear() + super.onDestroyView() + } + + fun dismissDialog() = dialog?.dismiss() + + protected fun addDisposal(disposable: Disposable) { + disposal.add(disposable) + } + + protected fun removeAndAddDisposal(disposable: Disposable) { + disposal.remove(disposable) + disposal.add(disposable) + } + + protected fun setupToolbar(resId: Int, menuId: Int? = null) { + view?.findViewById(R.id.toolbar)?.apply { + val titleText = findViewById(R.id.toolbarTitle) + if (titleText != null) { + titleText.setText(resId) + } else { + setTitle(resId) + } + setNavigationOnClickListener { dismiss() } + menuId?.let { inflateMenu(it) } + } + } + + private fun onGlobalLayoutChanged(view: View) { + val parent = dialog?.findViewById(R.id.design_bottom_sheet); + if (parent != null) { + val toggleArrow = view.findViewById(R.id.toggleArrow) + toggleArrow?.setState(ExpandIconView.LESS, true) + parent.setBackgroundColor(Color.TRANSPARENT) + bottomSheetBehavior = BottomSheetBehavior.from(parent) + bottomSheetBehavior?.setBottomSheetCallback({ newState -> + if (newState == BottomSheetBehavior.STATE_HIDDEN) dialog?.cancel() + when (newState) { + BottomSheetBehavior.STATE_EXPANDED -> toggleArrow?.setState(ExpandIconView.MORE, true) + BottomSheetBehavior.STATE_COLLAPSED -> toggleArrow?.setState(ExpandIconView.LESS, true) + else -> toggleArrow?.setFraction(0.5f, false) + } + }) + bottomSheetBehavior?.let { behaviour -> + toggleArrow?.setOnClickListener { + toggleArrow.setOnClickListener { + if (behaviour.state != BottomSheetBehavior.STATE_EXPANDED) { + behaviour.state = BottomSheetBehavior.STATE_EXPANDED + } else { + behaviour.state = BottomSheetBehavior.STATE_COLLAPSED + } + } + } + } + } + } + + + override fun supportFragmentInjector(): AndroidInjector? = this.childFragmentInjector +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/base/BaseDialogFragment.kt b/app/src/main/java/com/fastaccess/github/base/BaseDialogFragment.kt new file mode 100644 index 000000000..5a9c40e1e --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/base/BaseDialogFragment.kt @@ -0,0 +1,72 @@ +package com.fastaccess.github.base + +import android.app.Dialog +import android.graphics.Color +import android.graphics.drawable.ColorDrawable +import android.os.Bundle +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.annotation.LayoutRes +import androidx.appcompat.view.ContextThemeWrapper +import androidx.appcompat.widget.Toolbar +import androidx.fragment.app.DialogFragment +import com.fastaccess.github.R +import com.fastaccess.github.extensions.getDrawable +import dagger.android.support.DaggerDialogFragment + +/** + * Created by Kosh on 07.03.19. + */ +abstract class BaseDialogFragment : DaggerDialogFragment() { + + @LayoutRes abstract fun layoutRes(): Int + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setStyle(DialogFragment.STYLE_NO_TITLE, R.style.ThemeOverlay_AppCompat_Dialog_Alert) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + super.onCreateView(inflater, container, savedInstanceState) + val contextThemeWrapper = ContextThemeWrapper(requireContext(), requireContext().theme) + val themeAwareInflater = inflater.cloneInContext(contextThemeWrapper) + return themeAwareInflater.inflate(layoutRes(), container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + val dialog = super.onCreateDialog(savedInstanceState) + dialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) + return dialog + } + + fun dismissDialog() = dialog?.dismiss() + + fun setupToolbar(title: String, menuId: Int? = null, onMenuItemClick: ((item: MenuItem) -> Unit)? = null) { + view?.findViewById(R.id.toolbar)?.apply { + navigationIcon = getDrawable(R.drawable.ic_clear) + val titleText = findViewById(R.id.toolbarTitle) + if (titleText != null) { + titleText.text = title + } else { + setTitle(title) + } + setNavigationOnClickListener { dismissDialog() } + menuId?.let { menuResId -> + inflateMenu(menuResId) + onMenuItemClick?.let { onClick -> + setOnMenuItemClickListener { + onClick.invoke(it) + return@setOnMenuItemClickListener true + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/base/BaseFragment.kt b/app/src/main/java/com/fastaccess/github/base/BaseFragment.kt new file mode 100644 index 000000000..f2bbc4d65 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/base/BaseFragment.kt @@ -0,0 +1,172 @@ +package com.fastaccess.github.base + +import android.content.Context +import android.graphics.Color +import android.os.Bundle +import android.view.LayoutInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.annotation.LayoutRes +import androidx.appcompat.widget.Toolbar +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.RecyclerView +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import androidx.transition.TransitionManager +import androidx.viewpager.widget.ViewPager +import com.fastaccess.data.model.FragmentType +import com.fastaccess.github.R +import com.fastaccess.github.base.callback.UpdateTabCount +import com.fastaccess.github.extensions.getColorAttr +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.ui.adapter.PagerAdapter +import com.fastaccess.markdown.spans.LabelSpan +import com.fastaccess.markdown.widget.SpannableBuilder +import com.google.android.material.tabs.TabLayout +import dagger.android.support.DaggerFragment +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.disposables.Disposable + +/** + * Created by Kosh on 13.05.18. + */ +abstract class BaseFragment : DaggerFragment(), ActivityCallback, UpdateTabCount { + + protected var updateCountCallback: UpdateTabCount? = null + private var activityCallback: ActivityCallback? = null + private var disposal = CompositeDisposable() + + @LayoutRes abstract fun layoutRes(): Int + + abstract fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) + protected open fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {} + abstract fun viewModel(): BaseViewModel? + + override fun onAttach(context: Context) { + super.onAttach(context) + activityCallback = context as? ActivityCallback + updateCountCallback = when { + parentFragment is UpdateTabCount -> parentFragment as UpdateTabCount + context is UpdateTabCount -> context + else -> null + } + } + + override fun onDetach() { + activityCallback = null + updateCountCallback = null + super.onDetach() + } + + override fun onCreate(savedInstanceState: Bundle?) { // expose so its easier to find + super.onCreate(savedInstanceState) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + super.onCreateView(inflater, container, savedInstanceState) + return inflater.inflate(layoutRes(), container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + if (isLoggedIn()) { + onFragmentCreatedWithUser(view, savedInstanceState) + } else { + onFragmentCreated(view, savedInstanceState) + } + + viewModel()?.progress?.observe(this, Observer { + val refresh = this@BaseFragment.view?.findViewById(R.id.swipeRefresh) + refresh?.isRefreshing = it == true + }) + + viewModel()?.error?.observeNotNull(this) { + this@BaseFragment.view?.let { view -> showSnackBar(view, resId = it.resId, message = it.message) } + } + } + + override fun onDestroyView() { + disposal.clear() + super.onDestroyView() + } + + override fun isLoggedIn(): Boolean = activityCallback?.isLoggedIn() ?: false + + override fun isEnterprise(): Boolean = activityCallback?.isEnterprise() ?: false + + override fun showSnackBar(root: View, resId: Int?, message: String?, duration: Int) { + activityCallback?.showSnackBar(root, resId, message, duration) + } + + override fun updateCount(type: FragmentType, count: Int) { + val pager = view?.findViewById(R.id.pager) ?: return + val tabs = view?.findViewById(R.id.tabs) ?: return + val adapter = pager.adapter as? PagerAdapter ?: return + val index = adapter.getIndex(type) + if (index == -1) return + val model = adapter.getModel(index) + tabs.getTabAt(index)?.let { + it.text = SpannableBuilder.builder() + .append(model?.text ?: "", LabelSpan(Color.TRANSPARENT)) + .space() + .append(" $count ", LabelSpan(requireContext().getColorAttr(R.attr.colorAccent))) + } + } + + protected fun postCount(type: FragmentType, count: Int) { + updateCountCallback?.updateCount(type, count) + } + + protected fun startTransactionDelay(view: View?) { + view?.let { TransitionManager.beginDelayedTransition(it as ViewGroup) } + } + + open fun onScrollToTop() { + view?.findViewById(R.id.recyclerView)?.scrollToPosition(0) + } + + open fun onBackPressed(): Boolean = true + + fun addDisposal(disposable: Disposable) { + disposal.add(disposable) + } + + fun removeAndAddDisposal(disposable: Disposable) { + disposal.remove(disposable) + disposal.add(disposable) + } + + fun dismiss() { + when (parentFragment) { + is BaseBottomSheetDialogFragment -> (parentFragment as? BaseBottomSheetDialogFragment)?.dismissDialog() + is BaseDialogFragment -> (parentFragment as? BaseDialogFragment)?.dismissDialog() + else -> activity?.onBackPressed() + } + } + + fun setupToolbar(title: String, menuId: Int? = null, onMenuItemClick: ((item: MenuItem) -> Unit)? = null) { + view?.findViewById(R.id.toolbar)?.apply { + val titleText = findViewById(R.id.toolbarTitle) + if (titleText != null) { + titleText.text = title + } else { + setTitle(title) + } + setNavigationOnClickListener { dismiss() } + menuId?.let { menuResId -> + inflateMenu(menuResId) + onMenuItemClick?.let { onClick -> + setOnMenuItemClickListener { + onClick.invoke(it) + return@setOnMenuItemClickListener true + } + } + } + } + } + + fun setupToolbar(resId: Int, menuId: Int? = null, onMenuItemClick: ((item: MenuItem) -> Unit)? = null) { + setupToolbar(getString(resId), menuId, onMenuItemClick) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/base/BasePagerFragment.kt b/app/src/main/java/com/fastaccess/github/base/BasePagerFragment.kt new file mode 100644 index 000000000..9248ad3c4 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/base/BasePagerFragment.kt @@ -0,0 +1,24 @@ +package com.fastaccess.github.base + +import android.os.Bundle +import android.view.View +import com.fastaccess.github.R +import com.fastaccess.github.base.callback.UpdateTabCount +import com.google.android.material.tabs.TabLayout + +/** + * Created by Kosh on 07.10.18. + */ + +abstract class BasePagerFragment : BaseFragment(), UpdateTabCount { + abstract fun onPageSelected(page: Int) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val tab = view.findViewById(R.id.tabs) as? TabLayout + tab?.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { + override fun onTabReselected(p0: TabLayout.Tab?) = this@BasePagerFragment.onPageSelected(p0?.position ?: 0) + override fun onTabUnselected(p0: TabLayout.Tab?) = Unit + override fun onTabSelected(p0: TabLayout.Tab?) = Unit + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/base/BaseViewModel.kt b/app/src/main/java/com/fastaccess/github/base/BaseViewModel.kt new file mode 100644 index 000000000..15252175d --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/base/BaseViewModel.kt @@ -0,0 +1,95 @@ +package com.fastaccess.github.base + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.fastaccess.data.model.FastHubErrors +import com.fastaccess.extension.uiThread +import com.fastaccess.github.R +import com.google.gson.Gson +import io.reactivex.Completable +import io.reactivex.Observable +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.disposables.Disposable +import org.json.JSONObject +import retrofit2.HttpException +import java.io.IOException +import java.util.concurrent.TimeoutException +import javax.inject.Inject + +/** + * Created by Kosh on 12.05.18. + */ +abstract class BaseViewModel : ViewModel() { + @Inject lateinit var gson: Gson + val error = MutableLiveData() + val progress = MutableLiveData() + val logoutProcess = MutableLiveData() + val counter = MutableLiveData() + private val disposable = CompositeDisposable() + + protected fun add(disposable: Disposable) = this.disposable.add(disposable) + + protected fun disposeAll() = disposable.clear() + + private fun handleError(throwable: Throwable) { + hideProgress() + if (throwable is HttpException) { + val response = throwable.response() + val message: String? = JSONObject(response?.errorBody()?.string() ?: "").getString("message") + val code = response?.code() + if (code == 401) { // OTP + val twoFactor = response.headers()["X-GitHub-OTP"] + if (twoFactor != null) { + error.postValue(FastHubErrors(FastHubErrors.ErrorType.TWO_FACTOR, message = message + ?: response.message())) + } else { + error.postValue(FastHubErrors(FastHubErrors.ErrorType.OTHER, resId = R.string.failed_login, message = message)) + } + } else { + error.postValue(FastHubErrors(FastHubErrors.ErrorType.OTHER, resId = R.string.network_error, message = message)) + } + return + } + error.postValue(FastHubErrors(FastHubErrors.ErrorType.OTHER, resId = getErrorResId(throwable))) + } + + protected fun showProgress() { + progress.postValue(true) + } + + protected fun hideProgress() { + progress.postValue(false) + } + + protected fun postCounter(count: Int) { + counter.postValue(count) + } + + protected fun callApi(observable: Observable): Observable = observable + .uiThread() + .doOnSubscribe { showProgress() } + .doOnNext { hideProgress() } + .doOnError { handleError(it) } + .doOnComplete { hideProgress() } + + protected fun callApi(completable: Completable): Completable = completable + .uiThread() + .doOnSubscribe { showProgress() } + .doOnComplete { hideProgress() } + .doOnError { handleError(it) } + .doOnComplete { hideProgress() } + + protected fun justSubscribe(observable: Observable) = add(callApi(observable).subscribe({}, { it.printStackTrace() })) + protected fun justSubscribe(completable: Completable) = add(callApi(completable).subscribe({}, { it.printStackTrace() })) + + override fun onCleared() { + super.onCleared() + disposeAll() + } + + private fun getErrorResId(throwable: Throwable): Int = when (throwable) { + is IOException -> R.string.request_error + is TimeoutException -> R.string.unexpected_error + else -> R.string.network_error + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/base/callback/UpdateTabCount.kt b/app/src/main/java/com/fastaccess/github/base/callback/UpdateTabCount.kt new file mode 100644 index 000000000..650c74e69 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/base/callback/UpdateTabCount.kt @@ -0,0 +1,10 @@ +package com.fastaccess.github.base.callback + +import com.fastaccess.data.model.FragmentType + +/** + * Created by Kosh on 16.10.18. + */ +interface UpdateTabCount { + fun updateCount(type: FragmentType, count: Int) +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/base/engine/ThemeEngine.kt b/app/src/main/java/com/fastaccess/github/base/engine/ThemeEngine.kt new file mode 100644 index 000000000..b45ab6629 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/base/engine/ThemeEngine.kt @@ -0,0 +1,39 @@ +package com.fastaccess.github.base.engine + +import android.graphics.Color +import androidx.annotation.ColorInt +import com.fastaccess.github.base.BaseActivity +import com.fastaccess.github.ui.modules.auth.LoginChooserActivity +import com.fastaccess.resources.R + +/** + * Created by Kosh on 18.05.18. + */ +object ThemeEngine { + + fun setTheme(activity: BaseActivity, theme: Int) { + if (!hasTheme(activity)) { + activity.setTheme(when (theme) { + 1 -> R.style.ThemeLight + 2 -> R.style.ThemeDark + 3 -> R.style.ThemeAmlod + 4 -> R.style.ThemeBluish + else -> R.style.ThemeLight + }) + } + } + + + fun isLightTheme(theme: Int) = theme == R.style.ThemeLight + + @ColorInt fun getCodeBackground(theme: Int): Int { + return when (theme) { + 2 -> Color.parseColor("#22252A") + 3 -> Color.parseColor("#0B162A") + 4 -> Color.parseColor("#111C2C") + else -> Color.parseColor("#EEEEEE") + } + } + + private fun hasTheme(activity: BaseActivity) = activity is LoginChooserActivity +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/annotations/ForActivity.kt b/app/src/main/java/com/fastaccess/github/di/annotations/ForActivity.kt new file mode 100644 index 000000000..1b2dc87eb --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/annotations/ForActivity.kt @@ -0,0 +1,11 @@ +package com.fastaccess.github.di.annotations + +/** + * Created by Kosh on 12.05.18. + */ + +import javax.inject.Qualifier + +@Qualifier +@Retention(AnnotationRetention.RUNTIME) +annotation class ForActivity \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/annotations/ForApplication.kt b/app/src/main/java/com/fastaccess/github/di/annotations/ForApplication.kt new file mode 100644 index 000000000..593fcd3fa --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/annotations/ForApplication.kt @@ -0,0 +1,10 @@ +package com.fastaccess.github.di.annotations + +/** + * Created by Kosh on 12.05.18. + */ +import javax.inject.Qualifier + +@Qualifier +@Retention(AnnotationRetention.RUNTIME) +annotation class ForApplication \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/annotations/ForAuth.kt b/app/src/main/java/com/fastaccess/github/di/annotations/ForAuth.kt new file mode 100644 index 000000000..fe9f2c057 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/annotations/ForAuth.kt @@ -0,0 +1,11 @@ +package com.fastaccess.github.di.annotations + +import javax.inject.Qualifier + +/** + * Created by Kosh on 11.05.18. + */ + +@Qualifier +@Retention(AnnotationRetention.RUNTIME) +annotation class ForAuth \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/annotations/ForDB.kt b/app/src/main/java/com/fastaccess/github/di/annotations/ForDB.kt new file mode 100644 index 000000000..d2b09927c --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/annotations/ForDB.kt @@ -0,0 +1,11 @@ +package com.fastaccess.github.di.annotations + +import javax.inject.Qualifier + +/** + * Created by Kosh on 11.05.18. + */ + +@Qualifier +@Retention(AnnotationRetention.RUNTIME) +annotation class ForDB \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/annotations/ViewModelKey.kt b/app/src/main/java/com/fastaccess/github/di/annotations/ViewModelKey.kt new file mode 100644 index 000000000..414f7c694 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/annotations/ViewModelKey.kt @@ -0,0 +1,15 @@ +package com.fastaccess.github.di.annotations + +import androidx.lifecycle.ViewModel +import dagger.MapKey +import kotlin.reflect.KClass + +/** + * Created by Kosh on 12.05.18. + */ + +@MustBeDocumented +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) +@Retention(AnnotationRetention.RUNTIME) +@MapKey +internal annotation class ViewModelKey(val value: KClass) \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/annotations/WorkerKey.kt b/app/src/main/java/com/fastaccess/github/di/annotations/WorkerKey.kt new file mode 100644 index 000000000..37df16781 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/annotations/WorkerKey.kt @@ -0,0 +1,10 @@ +package com.fastaccess.github.di.annotations + +import androidx.work.RxWorker +import dagger.MapKey +import kotlin.reflect.KClass + +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) +@Retention(AnnotationRetention.RUNTIME) +@MapKey +annotation class WorkerKey(val value: KClass) \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/components/AppComponent.kt b/app/src/main/java/com/fastaccess/github/di/components/AppComponent.kt new file mode 100644 index 000000000..45b13c518 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/components/AppComponent.kt @@ -0,0 +1,71 @@ +package com.fastaccess.github.di.components + +import android.app.Application +import com.fastaccess.data.persistence.db.FastHubDatabase +import com.fastaccess.data.persistence.db.FastHubLoginDatabase +import com.fastaccess.github.App +import com.fastaccess.github.di.modules.* +import com.fastaccess.github.platform.workmanager.DaggerWorkerFactory +import dagger.BindsInstance +import dagger.Component +import dagger.android.AndroidInjector +import dagger.android.support.AndroidSupportInjectionModule +import dagger.android.support.DaggerApplication +import javax.inject.Singleton + +/** + * Created by Kosh on 12.05.18. + */ +@Singleton +@Component(modules = [ + ApplicationModule::class, + FastHubDatabaseModule::class, + NetworkModule::class, + RepositoryModule::class, + ActivityBindingModule::class, + FragmentBindingModule::class, + DialogFragmentBindingModule::class, + ActivityModule::class, + RepositoryModule::class, + AndroidSupportInjectionModule::class]) +interface AppComponent : AndroidInjector { + + @Component.Builder + interface Builder { + @BindsInstance fun application(application: Application): Builder + + @BindsInstance fun fastHubDatabaseModule(fastHubDatabaseModule: FastHubDatabaseModule): Builder + + @BindsInstance fun networkModule(networkModule: NetworkModule): Builder + + @BindsInstance fun activityModule(activityModule: ActivityModule): Builder + + @BindsInstance fun repoModule(repositoryModule: RepositoryModule): Builder + + @BindsInstance fun repositoryModule(repositoryModule: RepositoryModule): Builder + + fun build(): AppComponent + } + + fun daggerWorkerFactory(): DaggerWorkerFactory + + fun workerSubComponentBuilder(): WorkerSubComponent.Builder + + fun fastHubDatabase() : FastHubDatabase + fun fasthubLoginDatabase() : FastHubLoginDatabase + + fun inject(app: App) + + override fun inject(instance: DaggerApplication) + + companion object { + fun getComponent(app: App): AppComponent = DaggerAppComponent.builder() + .application(app) + .fastHubDatabaseModule(FastHubDatabaseModule()) + .networkModule(NetworkModule()) + .activityModule(ActivityModule()) + .repoModule(RepositoryModule()) + .repositoryModule(RepositoryModule()) + .build() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/components/WorkerSubComponent.kt b/app/src/main/java/com/fastaccess/github/di/components/WorkerSubComponent.kt new file mode 100644 index 000000000..6196f002f --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/components/WorkerSubComponent.kt @@ -0,0 +1,22 @@ +package com.fastaccess.github.di.components + +import androidx.work.RxWorker +import androidx.work.WorkerParameters +import com.fastaccess.github.di.modules.WorkersModule +import dagger.BindsInstance +import dagger.Subcomponent +import javax.inject.Provider + +@Subcomponent(modules = [WorkersModule::class]) +interface WorkerSubComponent { + + fun workers(): Map, Provider> + + @Subcomponent.Builder + interface Builder { + @BindsInstance + fun workerParameters(param: WorkerParameters): Builder + + fun build(): WorkerSubComponent + } +} diff --git a/app/src/main/java/com/fastaccess/github/di/modules/ActivityBindingModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/ActivityBindingModule.kt new file mode 100644 index 000000000..95411ca91 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/ActivityBindingModule.kt @@ -0,0 +1,27 @@ +package com.fastaccess.github.di.modules + +import com.fastaccess.github.di.scopes.PerActivity +import com.fastaccess.github.ui.modules.auth.LoginChooserActivity +import com.fastaccess.github.ui.modules.editor.EditorWebViewActivity +import com.fastaccess.github.ui.modules.issue.IssueActivity +import com.fastaccess.github.ui.modules.main.MainActivity +import com.fastaccess.github.ui.modules.multipurpose.MultiPurposeActivity +import com.fastaccess.github.ui.modules.profile.ProfileActivity +import com.fastaccess.github.ui.modules.trending.TrendingActivity +import dagger.Module +import dagger.android.ContributesAndroidInjector + +/** + * Created by Kosh on 12.05.18. + */ +@Suppress("unused") +@Module +abstract class ActivityBindingModule { + @PerActivity @ContributesAndroidInjector abstract fun mainActivity(): MainActivity + @PerActivity @ContributesAndroidInjector abstract fun loginChooser(): LoginChooserActivity + @PerActivity @ContributesAndroidInjector abstract fun profileActivity(): ProfileActivity + @PerActivity @ContributesAndroidInjector abstract fun multiPurposeActivity(): MultiPurposeActivity + @PerActivity @ContributesAndroidInjector abstract fun trendingActivity(): TrendingActivity + @PerActivity @ContributesAndroidInjector abstract fun issueActivity(): IssueActivity + @PerActivity @ContributesAndroidInjector abstract fun editorActivity(): EditorWebViewActivity +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/modules/ActivityModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/ActivityModule.kt new file mode 100644 index 000000000..b1725154b --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/ActivityModule.kt @@ -0,0 +1,9 @@ +package com.fastaccess.github.di.modules + +import dagger.Module + +/** + * Created by Kosh on 18.05.18. + */ +@Module +class ActivityModule \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/modules/ApplicationModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/ApplicationModule.kt new file mode 100644 index 000000000..e77177e88 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/ApplicationModule.kt @@ -0,0 +1,23 @@ +package com.fastaccess.github.di.modules + +import android.app.Application +import android.content.Context +import com.fastaccess.github.di.annotations.ForApplication +import com.google.firebase.database.DatabaseReference +import com.google.firebase.database.FirebaseDatabase +import dagger.Module +import dagger.Provides + +/** + * Created by Kosh on 12.05.18. + */ + +@Module(includes = [ViewModelModule::class]) +class ApplicationModule { + + @Provides @ForApplication fun providesApplicationContext(application: Application): Context { + return application + } + +// @Provides fun provideGlide(@ForApplication context: Context): GlideRequests = GlideApp.with(context) +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/modules/DialogFragmentBindingModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/DialogFragmentBindingModule.kt new file mode 100644 index 000000000..18d97d9a8 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/DialogFragmentBindingModule.kt @@ -0,0 +1,19 @@ +package com.fastaccess.github.di.modules + +import com.fastaccess.github.di.scopes.PerFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.labels.create.CreateLabelFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.milestone.CreateMilestoneDialogFragment +import com.fastaccess.github.ui.widget.dialog.IconDialogFragment +import dagger.Module +import dagger.android.ContributesAndroidInjector + +/** + * Created by Kosh on 19.05.18. + */ +@Suppress("unused") +@Module +abstract class DialogFragmentBindingModule { + @PerFragment @ContributesAndroidInjector abstract fun provideIconDialog(): IconDialogFragment + @PerFragment @ContributesAndroidInjector abstract fun provideCreateLabel(): CreateLabelFragment + @PerFragment @ContributesAndroidInjector abstract fun provideCreateMilestone(): CreateMilestoneDialogFragment +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/modules/FastHubDatabaseModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/FastHubDatabaseModule.kt new file mode 100644 index 000000000..a1f40e991 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/FastHubDatabaseModule.kt @@ -0,0 +1,52 @@ +package com.fastaccess.github.di.modules + +import android.app.Application +import android.content.Context +import androidx.room.Room +import com.fastaccess.data.persistence.db.DATABASE_NAME +import com.fastaccess.data.persistence.db.FastHubDatabase +import com.fastaccess.data.persistence.db.FastHubLoginDatabase +import com.fastaccess.data.persistence.db.LOGIN_DATABASE_NAME +import com.fastaccess.data.storage.FastHubSharedPreference +import com.fastaccess.github.di.annotations.ForApplication +import com.fastaccess.github.di.annotations.ForDB +import com.google.firebase.database.DatabaseReference +import com.google.firebase.database.FirebaseDatabase +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import dagger.Module +import dagger.Provides +import java.lang.reflect.Modifier +import javax.inject.Named +import javax.inject.Singleton + +/** + * Created by Kosh on 11.05.18. + */ +@Module +class FastHubDatabaseModule { + + @Singleton @Provides fun provideDatabase(@ForApplication context: Context): FastHubDatabase = Room.databaseBuilder(context, + FastHubDatabase::class.java, DATABASE_NAME) + .allowMainThreadQueries() // allow querying on MainThread (this useful in some cases) + .fallbackToDestructiveMigration() // this mean that it will delete all tables and recreate them after version is changed + .build() + + @Singleton @Provides fun provideLoginDatabase(@ForApplication context: Context): FastHubLoginDatabase = Room.databaseBuilder(context, + FastHubLoginDatabase::class.java, LOGIN_DATABASE_NAME) + .allowMainThreadQueries() // allow querying on MainThread + .build() + + @Singleton @Provides fun providePreference(app: Application): FastHubSharedPreference = FastHubSharedPreference(app) + + @ForDB @Singleton @Provides fun provideGson(): Gson = GsonBuilder() + .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC) + .disableHtmlEscaping() + .setPrettyPrinting() + .create() + + @Singleton @Provides @Named(value = "github_trending") fun provideFastHubTrendingDataReference(): DatabaseReference { + return FirebaseDatabase.getInstance().reference.child("github_trending") + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/modules/FragmentBindingModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/FragmentBindingModule.kt new file mode 100644 index 000000000..a4b9f6b7c --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/FragmentBindingModule.kt @@ -0,0 +1,65 @@ +package com.fastaccess.github.di.modules + +import com.fastaccess.github.di.scopes.PerFragment +import com.fastaccess.github.ui.modules.auth.chooser.LoginChooserFragment +import com.fastaccess.github.ui.modules.auth.login.AuthLoginFragment +import com.fastaccess.github.ui.modules.feed.fragment.FeedsFragment +import com.fastaccess.github.ui.modules.issue.fragment.IssueFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.LockUnlockFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.assignees.AssigneesFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.labels.LabelsFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.milestone.MilestoneFragment +import com.fastaccess.github.ui.modules.issuesprs.filter.FilterIssuesPrsBottomSheet +import com.fastaccess.github.ui.modules.issuesprs.fragment.FilterIssuePullRequestsFragment +import com.fastaccess.github.ui.modules.main.fragment.MainFragment +import com.fastaccess.github.ui.modules.multipurpose.MultiPurposeBottomSheetDialog +import com.fastaccess.github.ui.modules.notifications.NotificationPagerFragment +import com.fastaccess.github.ui.modules.notifications.fragment.read.AllNotificationsFragment +import com.fastaccess.github.ui.modules.notifications.fragment.unread.UnreadNotificationsFragment +import com.fastaccess.github.ui.modules.profile.feeds.ProfileFeedFragment +import com.fastaccess.github.ui.modules.profile.followersandfollowings.ProfileFollowersFragment +import com.fastaccess.github.ui.modules.profile.fragment.ProfileFragment +import com.fastaccess.github.ui.modules.profile.gists.ProfileGistsFragment +import com.fastaccess.github.ui.modules.profile.orgs.userorgs.UserOrgsFragment +import com.fastaccess.github.ui.modules.profile.repos.ProfileReposFragment +import com.fastaccess.github.ui.modules.profile.starred.ProfileStarredReposFragment +import com.fastaccess.github.ui.modules.search.filter.FilterSearchBottomSheet +import com.fastaccess.github.ui.modules.search.fragment.SearchFragment +import com.fastaccess.github.ui.modules.trending.filter.FilterTrendingBottomSheet +import com.fastaccess.github.ui.modules.trending.fragment.TrendingFragment +import dagger.Module +import dagger.android.ContributesAndroidInjector + +/** + * Created by Kosh on 19.05.18. + */ +@Suppress("unused") +@Module +abstract class FragmentBindingModule { + @PerFragment @ContributesAndroidInjector abstract fun provideLoginChooseFragment(): LoginChooserFragment + @PerFragment @ContributesAndroidInjector abstract fun provideLoginFragment(): AuthLoginFragment + @PerFragment @ContributesAndroidInjector abstract fun provideMainFragment(): MainFragment + @PerFragment @ContributesAndroidInjector abstract fun provideProfileFragment(): ProfileFragment + @PerFragment @ContributesAndroidInjector abstract fun provideProfileReposFragment(): ProfileReposFragment + @PerFragment @ContributesAndroidInjector abstract fun provideProfileStarredReposFragment(): ProfileStarredReposFragment + @PerFragment @ContributesAndroidInjector abstract fun provideProfileGistsFragment(): ProfileGistsFragment + @PerFragment @ContributesAndroidInjector abstract fun provideProfileFollowersFragment(): ProfileFollowersFragment + @PerFragment @ContributesAndroidInjector abstract fun provideProfileFeedsFragment(): ProfileFeedFragment + @PerFragment @ContributesAndroidInjector abstract fun provideFeedsFragment(): FeedsFragment + @PerFragment @ContributesAndroidInjector abstract fun provideNotificationPagerFragment(): NotificationPagerFragment + @PerFragment @ContributesAndroidInjector abstract fun provideUnreadNotificationsFragment(): UnreadNotificationsFragment + @PerFragment @ContributesAndroidInjector abstract fun provideAllNotificationsFragment(): AllNotificationsFragment + @PerFragment @ContributesAndroidInjector abstract fun provideMultiPurposeBottomSheetDialog(): MultiPurposeBottomSheetDialog + @PerFragment @ContributesAndroidInjector abstract fun provideUserOrgsFragment(): UserOrgsFragment + @PerFragment @ContributesAndroidInjector abstract fun provideFilterIssuePullRequestsFragment(): FilterIssuePullRequestsFragment + @PerFragment @ContributesAndroidInjector abstract fun provideFilterIssuesPrsBottomSheet(): FilterIssuesPrsBottomSheet + @PerFragment @ContributesAndroidInjector abstract fun provideSearchFragment(): SearchFragment + @PerFragment @ContributesAndroidInjector abstract fun provideFilterSearchBottomSheet(): FilterSearchBottomSheet + @PerFragment @ContributesAndroidInjector abstract fun provideTrendingFragment(): TrendingFragment + @PerFragment @ContributesAndroidInjector abstract fun provideFilterTrendingBottomSheet(): FilterTrendingBottomSheet + @PerFragment @ContributesAndroidInjector(modules = [FragmentModule::class]) abstract fun provideIssueFragment(): IssueFragment + @PerFragment @ContributesAndroidInjector abstract fun provideLockUnlockFragment(): LockUnlockFragment + @PerFragment @ContributesAndroidInjector abstract fun provideLabelsFragment(): LabelsFragment + @PerFragment @ContributesAndroidInjector abstract fun provideAssigneesFragment(): AssigneesFragment + @PerFragment @ContributesAndroidInjector abstract fun provideMilestoneFragment(): MilestoneFragment +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/modules/FragmentModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/FragmentModule.kt new file mode 100644 index 000000000..1d8204c08 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/FragmentModule.kt @@ -0,0 +1,51 @@ +package com.fastaccess.github.di.modules + +import android.content.Context +import com.fastaccess.github.di.annotations.ForApplication +import com.fastaccess.github.di.scopes.PerFragment +import com.fastaccess.github.extensions.getDrawableCompat +import com.fastaccess.markdown.R +import com.fastaccess.markdown.spans.* +import dagger.Module +import dagger.Provides +import net.nightwhistler.htmlspanner.HtmlSpanner +import net.nightwhistler.htmlspanner.handlers.StyledTextHandler +import net.nightwhistler.htmlspanner.style.Style + +/** + * Created by Kosh on 02.02.19. + */ +@Module +class FragmentModule { + + @PerFragment @Provides fun provideHtmlSpanner(@ForApplication context: Context): HtmlSpanner { + val mySpanner = HtmlSpanner() + mySpanner.isStripExtraWhiteSpace = true + val checked = context.getDrawableCompat(R.drawable.ic_checkbox_small) + val unchecked = context.getDrawableCompat(R.drawable.ic_checkbox_empty_small) + mySpanner.registerHandler("li", ListsHandler(checked, unchecked)) + mySpanner.registerHandler("g-emoji", EmojiHandler()) + mySpanner.registerHandler("b", StyledTextHandler(Style().setFontWeight(Style.FontWeight.BOLD))) + mySpanner.registerHandler("strong", StyledTextHandler(Style().setFontWeight(Style.FontWeight.BOLD))) + mySpanner.registerHandler("i", ItalicHandler()) + mySpanner.registerHandler("em", ItalicHandler()) + mySpanner.registerHandler("ul", MarginHandler()) + mySpanner.registerHandler("ol", MarginHandler()) + mySpanner.registerHandler("u", UnderlineHandler()) + mySpanner.registerHandler("strike", StrikethroughHandler()) + mySpanner.registerHandler("ins", UnderlineHandler()) + mySpanner.registerHandler("del", StrikethroughHandler()) + mySpanner.registerHandler("sub", SubScriptHandler()) + mySpanner.registerHandler("sup", SuperScriptHandler()) + mySpanner.registerHandler("a", LinkHandler()) + mySpanner.registerHandler("emoji", EmojiHandler()) + mySpanner.registerHandler("mention", LinkHandler()) + mySpanner.registerHandler("h1", HeaderHandler(1.5f)) + mySpanner.registerHandler("h2", HeaderHandler(1.4f)) + mySpanner.registerHandler("h3", HeaderHandler(1.3f)) + mySpanner.registerHandler("h4", HeaderHandler(1.2f)) + mySpanner.registerHandler("h5", HeaderHandler(1.1f)) + mySpanner.registerHandler("h6", HeaderHandler(1.0f)) + return mySpanner + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/modules/NetworkModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/NetworkModule.kt new file mode 100644 index 000000000..4daca5e9e --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/NetworkModule.kt @@ -0,0 +1,233 @@ +package com.fastaccess.github.di.modules + +import android.net.Uri +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.response.CustomTypeAdapter +import com.apollographql.apollo.response.CustomTypeValue +import com.fastaccess.domain.repository.services.* +import com.fastaccess.github.BuildConfig +import com.google.gson.FieldNamingPolicy +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import dagger.Module +import dagger.Provides +import github.type.CustomType +import okhttp3.* +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Converter +import retrofit2.Retrofit +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory +import retrofit2.converter.gson.GsonConverterFactory +import tech.linjiang.pandora.Pandora +import java.io.IOException +import java.lang.reflect.Modifier +import java.lang.reflect.Type +import java.net.URI +import java.text.SimpleDateFormat +import java.util.* +import javax.inject.Singleton + +/** + * Created by Kosh on 11.05.18. + */ +@Module +class NetworkModule { + + @Singleton @Provides fun provideGson(): Gson = GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC) + .setDateFormat("yyyy-MM-dd HH:mm:ss") + .disableHtmlEscaping() + .setPrettyPrinting() + .create() + + @Singleton @Provides fun provideInterceptor() = AuthenticationInterceptor() + + @Singleton @Provides fun provideHttpClient(auth: AuthenticationInterceptor): OkHttpClient = OkHttpClient + .Builder() + .addInterceptor(ContentTypeInterceptor()) + .addInterceptor(auth) + .addInterceptor(PaginationInterceptor()) + .addInterceptor(Pandora.get().interceptor) + .addInterceptor(HttpLoggingInterceptor()) + .build() + + @Singleton @Provides fun provideRetrofit( + gson: Gson, + okHttpClient: OkHttpClient + ): Retrofit = Retrofit.Builder() + .baseUrl(BuildConfig.REST_URL) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .addConverterFactory(GithubResponseConverter(gson)) + .client(okHttpClient) + .build() + + @Singleton @Provides fun provideRetrofitBuilder( + gson: Gson, + okHttpClient: OkHttpClient + ): Retrofit.Builder = Retrofit.Builder() + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .addConverterFactory(GithubResponseConverter(gson)) + .client(okHttpClient) + + @Singleton @Provides fun provideApollo(okHttpClient: OkHttpClient): ApolloClient = ApolloClient.builder() + .serverUrl(BuildConfig.GRAPHQL_REST_URL) + .okHttpClient(okHttpClient) + .addCustomTypeAdapter(CustomType.URI, UriApolloAdapter()) + .addCustomTypeAdapter(CustomType.DATETIME, DateApolloAdapter()) + .addCustomTypeAdapter(CustomType.HTML, ObjectApolloAdapter()) + .build() + + @Singleton @Provides fun provideLoginService(retrofit: Retrofit): LoginService = retrofit.create(LoginService::class.java) + @Singleton @Provides fun provideUserService(retrofit: Retrofit): UserService = retrofit.create(UserService::class.java) + @Singleton @Provides fun provideNotificationService(retrofit: Retrofit): NotificationService = retrofit.create(NotificationService::class.java) + @Singleton @Provides fun provideOrganizationService(retrofit: Retrofit): OrganizationService = retrofit.create(OrganizationService::class.java) + @Singleton @Provides fun provideIssueService(retrofit: Retrofit): IssuePrService = retrofit.create(IssuePrService::class.java) + @Singleton @Provides fun provideRepoService(retrofit: Retrofit): RepoService = retrofit.create(RepoService::class.java) +} + +class AuthenticationInterceptor( + var otp: String? = null, + var token: String? = null, + var isScrapping: Boolean = false +) : Interceptor { + + override fun intercept(chain: Interceptor.Chain): Response { + val original = chain.request() + val builder = original.newBuilder() + token?.let { builder.header("Authorization", if (it.startsWith("Basic")) it else "token $it") } + otp?.let { + if (!it.isEmpty()) builder.addHeader("X-GitHub-OTP", it.trim()) + } + if (!isScrapping) builder.addHeader("User-Agent", "FastHub") + val request = builder.build() + return chain.proceed(request) + } +} + +private class ContentTypeInterceptor : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + return chain.proceed( + request.newBuilder() + .addHeader("Accept", "application/vnd.github.v3+json") + .addHeader("Content-type", "application/vnd.github.v3+json") + .method(request.method, request.body) + .build() + ) + } +} + +private class PaginationInterceptor : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + val response = chain.proceed(request) + val headers = chain.request().headers + headers.let { + if (it.values("Accept").contains("application/vnd.github.html") || + it.values("Accept").contains("application/vnd.github.VERSION" + ".raw") + ) { + return response//return them as they are. + } + } + if (response.isSuccessful) { + if (response.peekBody(1).string() == "[") { + var json = "{" + val link = response.header("link") + if (link != null) { + val links = link.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + for (link1 in links) { + val pageLink = link1.split(";".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + val page = Uri.parse(pageLink[0].replace("[<>]".toRegex(), "")).getQueryParameter("page") + val rel = pageLink[1].replace("\"".toRegex(), "").replace("rel=", "") + if (page != null) json += String.format("\"%s\":\"%s\",", rel.trim { it <= ' ' }, page) + } + } + json += String.format("\"items\":%s}", response.body?.string()) + return response.newBuilder().body(ResponseBody.create(response.body?.contentType(), json)).build() + } else if (response.header("link") != null) { + val link = response.header("link") + var pagination = "" + val links = link!!.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + for (link1 in links) { + val pageLink = link1.split(";".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + val page = Uri.parse(pageLink[0].replace("[<>]".toRegex(), "")).getQueryParameter("page") + val rel = pageLink[1].replace("\"".toRegex(), "").replace("rel=", "") + if (page != null) pagination += String.format("\"%s\":\"%s\",", rel.trim { it <= ' ' }, page) + } + if (pagination.isNotEmpty()) { + val body = response.body?.string() + return response.newBuilder().body( + ResponseBody.create( + response.body?.contentType(), + "{" + pagination + body?.substring(1, body.length) + ) + ).build() + } + } + } + return response + } +} + +private class GithubResponseConverter( + private val gson: Gson, + private val creator: GsonConverterFactory = GsonConverterFactory.create(gson) +) : Converter.Factory() { + + override fun responseBodyConverter( + type: Type, + annotations: Array, + retrofit: Retrofit + ): Converter? { + return try { + if (type === String::class.java) { + StringResponseConverter() + } else { + creator.responseBodyConverter(type, annotations, retrofit) + } + } catch (ignored: OutOfMemoryError) { + null + } as Converter? + + } + + override fun requestBodyConverter( + type: Type, + parameterAnnotations: Array, + methodAnnotations: Array, + retrofit: Retrofit + ): Converter<*, RequestBody>? { + return creator.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit) + } + + private class StringResponseConverter : Converter { + @Throws(IOException::class) + override fun convert(value: ResponseBody): String { + return value.string() + } + } +} + +private class UriApolloAdapter : CustomTypeAdapter { + override fun encode(value: URI): CustomTypeValue = CustomTypeValue.GraphQLString(value.toString()) + override fun decode(value: CustomTypeValue<*>): URI = URI.create(value.value.toString()) +} + +private class ObjectApolloAdapter : CustomTypeAdapter { + override fun encode(value: Any): CustomTypeValue = CustomTypeValue.GraphQLString(value.toString()) + override fun decode(value: CustomTypeValue<*>): Any = value.value +} + +private class DateApolloAdapter : CustomTypeAdapter { + override fun encode(value: Date): CustomTypeValue<*> = CustomTypeValue.fromRawValue(value) + override fun decode(value: CustomTypeValue<*>): Date { + return try { + val date = value.value as String + SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH).parse(date) // because Github API is the best of all. /shrug + } catch (e: Exception) { + e.printStackTrace() + Date() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/modules/RepositoryModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/RepositoryModule.kt new file mode 100644 index 000000000..b6a2ed430 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/RepositoryModule.kt @@ -0,0 +1,94 @@ +package com.fastaccess.github.di.modules + +import com.apollographql.apollo.ApolloClient +import com.fastaccess.data.persistence.db.FastHubDatabase +import com.fastaccess.data.persistence.db.FastHubLoginDatabase +import com.fastaccess.data.repository.* +import com.fastaccess.domain.repository.services.LoginService +import com.fastaccess.domain.repository.services.UserService +import com.google.gson.Gson +import dagger.Module +import dagger.Provides +import javax.inject.Singleton + +/** + * Created by Kosh on 11.05.18. + */ +@Module +class RepositoryModule { + @Singleton @Provides fun provideLoginRepository( + fastHubLoginDatabase: FastHubLoginDatabase, + loginService: LoginService + ): LoginRepositoryProvider { + return LoginRepositoryProvider(fastHubLoginDatabase.provideLoginDao(), loginService) + } + + @Singleton @Provides fun provideUserRepository( + fastHubDatabase: FastHubDatabase, + apolloClient: ApolloClient, + userService: UserService + ): UserRepositoryProvider { + return UserRepositoryProvider(fastHubDatabase.getUserDao(), apolloClient, userService) + } + + @Singleton @Provides fun provideMainIssuesPullsRepository(fastHubDatabase: FastHubDatabase): MyIssuesPullsRepositoryProvider { + return MyIssuesPullsRepositoryProvider(fastHubDatabase.getMainIssuesPullsDao()) + } + + @Singleton @Provides fun provideNotificationRepositoryProvider(fastHubDatabase: FastHubDatabase): NotificationRepositoryProvider { + return NotificationRepositoryProvider(fastHubDatabase.getNotifications()) + } + + @Singleton @Provides fun provideFeedsRepositoryProvider( + fastHubDatabase: FastHubDatabase, + userService: UserService, + loginRepositoryProvider: LoginRepositoryProvider, + gson: Gson + ): FeedsRepositoryProvider { + return FeedsRepositoryProvider(fastHubDatabase.getFeedsDao(), userService, loginRepositoryProvider, gson) + } + + @Singleton @Provides fun provideUserReposRepositoryProvider( + fastHubDatabase: FastHubDatabase, + apolloClient: ApolloClient + ): UserReposRepositoryProvider { + return UserReposRepositoryProvider(fastHubDatabase.getUserRepoDao(), apolloClient) + } + + @Singleton @Provides fun provideUserStarredReposRepositoryProvider( + fastHubDatabase: FastHubDatabase, + apolloClient: ApolloClient + ): UserStarredReposRepositoryProvider { + return UserStarredReposRepositoryProvider(fastHubDatabase.getUserStarredRepoDao(), apolloClient) + } + + @Singleton @Provides fun provideUserGistsRepositoryProvider( + fastHubDatabase: FastHubDatabase, + apolloClient: ApolloClient + ): UserGistsRepositoryProvider { + return UserGistsRepositoryProvider(fastHubDatabase.getGistsDao(), apolloClient) + } + + @Singleton @Provides fun provideUserFollowersFollowingRepositoryProvider( + fastHubDatabase: FastHubDatabase, + apolloClient: ApolloClient + ): UserFollowersFollowingRepositoryProvider { + return UserFollowersFollowingRepositoryProvider(fastHubDatabase.getFollowingFollowerDao(), apolloClient) + } + + @Singleton @Provides fun provideOrgRepositoryProvider( + fastHubDatabase: FastHubDatabase, + apolloClient: ApolloClient, + loginRepositoryProvider: LoginRepositoryProvider + ): OrgRepositoryProvider { + return OrgRepositoryProvider(fastHubDatabase.getOrganizationDao(), apolloClient, loginRepositoryProvider) + } + + @Singleton @Provides fun provideIssueRepository(fastHubDatabase: FastHubDatabase): IssueRepositoryProvider { + return IssueRepositoryProvider(fastHubDatabase.getIssueDao()) + } + + @Singleton @Provides fun provideSuggestionRepositoryProvider(fastHubDatabase: FastHubDatabase): SuggestionRepositoryProvider { + return SuggestionRepositoryProvider(fastHubDatabase.getSuggestionDao()) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/modules/UseCaseModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/UseCaseModule.kt new file mode 100644 index 000000000..15e85645d --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/UseCaseModule.kt @@ -0,0 +1,187 @@ +package com.fastaccess.github.di.modules + +import com.apollographql.apollo.ApolloClient +import com.fastaccess.data.repository.* +import com.fastaccess.domain.repository.services.IssuePrService +import com.fastaccess.domain.repository.services.NotificationService +import com.fastaccess.domain.repository.services.RepoService +import com.fastaccess.github.di.scopes.PerFragment +import com.fastaccess.github.usecase.auth.GetAccessTokenUseCase +import com.fastaccess.github.usecase.auth.LoginUseCase +import com.fastaccess.github.usecase.auth.LoginWithAccessTokenUseCase +import com.fastaccess.github.usecase.feed.FeedsUseCase +import com.fastaccess.github.usecase.issuesprs.* +import com.fastaccess.github.usecase.main.IssuesMainScreenUseCase +import com.fastaccess.github.usecase.main.PullRequestsMainScreenUseCase +import com.fastaccess.github.usecase.notification.NotificationUseCase +import com.fastaccess.github.usecase.search.FilterSearchReposUseCase +import com.fastaccess.github.usecase.search.FilterSearchUsersUseCase +import com.fastaccess.github.usecase.user.BlockUnblockUserUseCase +import com.fastaccess.github.usecase.user.IsUserBlockedUseCase +import com.fastaccess.github.usecase.user.UserUseCase +import com.google.gson.Gson +import dagger.Module +import dagger.Provides + +/** + * Created by Kosh on 12.05.18. + */ +@Module(includes = [FastHubDatabaseModule::class, NetworkModule::class]) +class UseCaseModule { + + @PerFragment @Provides fun provideLoginUseCase(loginRemoteRepository: LoginRepositoryProvider): LoginUseCase = LoginUseCase(loginRemoteRepository) + + @PerFragment @Provides fun provideLoginWithAccessTokenUseCase( + loginRemoteRepository: LoginRepositoryProvider, + gson: Gson + ): LoginWithAccessTokenUseCase { + return LoginWithAccessTokenUseCase(loginRemoteRepository, gson) + } + + @PerFragment @Provides fun provideGetAccessTokenUseCase(loginRemoteRepository: LoginRepositoryProvider): GetAccessTokenUseCase { + return GetAccessTokenUseCase(loginRemoteRepository) + } + + @PerFragment @Provides fun provideUserUseCase(userRepository: UserRepositoryProvider): UserUseCase = UserUseCase(userRepository) + + @PerFragment @Provides fun provideIssuesMainScreenUseCase( + loginRepository: LoginRepositoryProvider, + myIssuesPullsRepository: MyIssuesPullsRepositoryProvider, + apolloClient: ApolloClient + ): IssuesMainScreenUseCase { + return IssuesMainScreenUseCase(loginRepository, myIssuesPullsRepository, apolloClient) + } + + @PerFragment @Provides fun providePullRequestsMainScreenUseCase( + loginRepository: LoginRepositoryProvider, + myIssues: MyIssuesPullsRepositoryProvider, + apolloClient: ApolloClient + ): PullRequestsMainScreenUseCase { + return PullRequestsMainScreenUseCase(loginRepository, myIssues, apolloClient) + } + + @PerFragment @Provides fun provideNotificationUseCase( + notificationRepositoryProvider: NotificationRepositoryProvider, + notificationService: NotificationService, + gson: Gson + ): NotificationUseCase { + return NotificationUseCase(notificationRepositoryProvider, notificationService, gson) + } + + @PerFragment @Provides fun provideFeedsUseCase(provider: FeedsRepositoryProvider): FeedsUseCase = FeedsUseCase(provider) + + + @PerFragment @Provides fun provideBlockUnblockUserUseCase(userRepository: UserRepositoryProvider): BlockUnblockUserUseCase { + return BlockUnblockUserUseCase(userRepository) + } + + @PerFragment @Provides fun provideIsUserBlockedUseCase(userRepository: UserRepositoryProvider): IsUserBlockedUseCase { + return IsUserBlockedUseCase(userRepository) + } + + @PerFragment @Provides fun provideFilterIssuesUseCase( + loginRepository: LoginRepositoryProvider, + apolloClient: ApolloClient + ): FilterIssuesUseCase { + return FilterIssuesUseCase(loginRepository, apolloClient) + } + + @PerFragment @Provides fun provideFilterPullRequestsUseCase( + loginRepository: LoginRepositoryProvider, + apolloClient: ApolloClient + ): FilterPullRequestsUseCase { + return FilterPullRequestsUseCase(loginRepository, apolloClient) + } + + @PerFragment @Provides fun provideFilterSearchReposUseCase( + apolloClient: ApolloClient + ): FilterSearchReposUseCase { + return FilterSearchReposUseCase(apolloClient) + } + + @PerFragment @Provides fun provideFilterSearchUsersUseCase( + apolloClient: ApolloClient + ): FilterSearchUsersUseCase { + return FilterSearchUsersUseCase(apolloClient) + } + + @PerFragment @Provides fun provideGetIssueUseCase( + issueRepositoryProvider: IssueRepositoryProvider, + apolloClient: ApolloClient + ): GetIssueUseCase { + return GetIssueUseCase(issueRepositoryProvider, apolloClient) + } + + @PerFragment @Provides fun provideGetIssueTimelineUseCase( + issueRepositoryProvider: IssueRepositoryProvider, + apolloClient: ApolloClient + ): GetIssueTimelineUseCase { + return GetIssueTimelineUseCase(issueRepositoryProvider, apolloClient) + } + + @PerFragment @Provides fun provideEditIssuePrUseCase( + issueRepositoryProvider: IssueRepositoryProvider, + issuePrService: IssuePrService, + loginRepositoryProvider: LoginRepositoryProvider + ): CloseOpenIssuePrUseCase { + return CloseOpenIssuePrUseCase(issueRepositoryProvider, issuePrService, loginRepositoryProvider) + } + + @PerFragment @Provides fun provideLockUnlockIssuePrUseCase( + issueRepositoryProvider: IssueRepositoryProvider, + apolloClient: ApolloClient, + loginRepositoryProvider: LoginRepositoryProvider + ): LockUnlockIssuePrUseCase { + return LockUnlockIssuePrUseCase(issueRepositoryProvider, apolloClient, loginRepositoryProvider) + } + + @PerFragment @Provides fun provideGetLabelsUseCase( + apolloClient: ApolloClient + ): GetLabelsUseCase { + return GetLabelsUseCase(apolloClient) + } + + @PerFragment @Provides fun provideCreateLabelUseCase( + repoService: RepoService + ): CreateLabelUseCase { + return CreateLabelUseCase(repoService) + } + + @PerFragment @Provides fun providePutLabelsUseCase( + repoService: RepoService + ): PutLabelsUseCase { + return PutLabelsUseCase(repoService) + } + + @PerFragment @Provides fun provideGetAssigneesUseCase( + apolloClient: ApolloClient + ): GetAssigneesUseCase { + return GetAssigneesUseCase(apolloClient) + } + + @PerFragment @Provides fun provideAddAssigneesUseCase( + repoService: RepoService + ): AddAssigneesUseCase { + return AddAssigneesUseCase(repoService) + } + + @PerFragment @Provides fun provideGetMilestonesUseCase( + apolloClient: ApolloClient + ): GetMilestonesUseCase { + return GetMilestonesUseCase(apolloClient) + } + + @PerFragment @Provides fun provideCreateMilestoneUseCase( + repoService: RepoService + ): CreateMilestoneUseCase { + return CreateMilestoneUseCase(repoService) + } + + @PerFragment @Provides fun provideMilestoneIssuePrUseCase( + issueRepositoryProvider: IssueRepositoryProvider, + issuePrService: IssuePrService, + loginRepositoryProvider: LoginRepositoryProvider + ): MilestoneIssuePrUseCase { + return MilestoneIssuePrUseCase(issueRepositoryProvider, issuePrService, loginRepositoryProvider) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/modules/ViewModelModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/ViewModelModule.kt new file mode 100644 index 000000000..5e17b92f3 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/ViewModelModule.kt @@ -0,0 +1,99 @@ +package com.fastaccess.github.di.modules + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.fastaccess.github.di.annotations.ViewModelKey +import com.fastaccess.github.platform.viewmodel.FastHubViewModelFactory +import com.fastaccess.github.ui.modules.auth.LoginChooserViewModel +import com.fastaccess.github.ui.modules.auth.login.LoginViewModel +import com.fastaccess.github.ui.modules.feed.fragment.viewmodel.FeedsViewModel +import com.fastaccess.github.ui.modules.issue.fragment.viewmodel.IssueTimelineViewModel +import com.fastaccess.github.ui.modules.issuesprs.edit.assignees.viewmodel.AssigneesViewModel +import com.fastaccess.github.ui.modules.issuesprs.edit.labels.viewmodel.LabelsViewModel +import com.fastaccess.github.ui.modules.issuesprs.edit.milestone.viewmodel.MilestoneViewModel +import com.fastaccess.github.ui.modules.issuesprs.fragment.viewmodel.FilterIssuePullRequestsViewModel +import com.fastaccess.github.ui.modules.main.fragment.viewmodel.MainFragmentViewModel +import com.fastaccess.github.ui.modules.notifications.fragment.read.AllNotificationsViewModel +import com.fastaccess.github.ui.modules.notifications.fragment.unread.viewmodel.UnreadNotificationsViewModel +import com.fastaccess.github.ui.modules.profile.feeds.viewmodel.ProfileFeedsViewModel +import com.fastaccess.github.ui.modules.profile.followersandfollowings.viewmodel.FollowersFollowingViewModel +import com.fastaccess.github.ui.modules.profile.fragment.viewmodel.ProfileViewModel +import com.fastaccess.github.ui.modules.profile.gists.viewmodel.ProfileGistsViewModel +import com.fastaccess.github.ui.modules.profile.orgs.userorgs.viewmodel.UserOrgsViewModel +import com.fastaccess.github.ui.modules.profile.repos.viewmodel.ProfileReposViewModel +import com.fastaccess.github.ui.modules.profile.starred.viewmodel.ProfileStarredReposViewModel +import com.fastaccess.github.ui.modules.search.fragment.viewmodel.FilterSearchViewModel +import com.fastaccess.github.ui.modules.trending.fragment.viewmodel.TrendingViewModel +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap + +/** + * Created by Kosh on 21.05.18. + */ +@Suppress("unused") +@Module +abstract class ViewModelModule { + + @Binds abstract fun bindViewModelFactory(factoryFastHub: FastHubViewModelFactory): ViewModelProvider.Factory + + @Binds @IntoMap @ViewModelKey(LoginViewModel::class) + abstract fun bindLoginViewModel(viewModel: LoginViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(MainFragmentViewModel::class) + abstract fun bindMainFragmentViewModel(viewModel: MainFragmentViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(ProfileViewModel::class) + abstract fun bindProfileViewModel(viewModel: ProfileViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(ProfileReposViewModel::class) + abstract fun bindProfileReposViewModel(viewModel: ProfileReposViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(ProfileStarredReposViewModel::class) + abstract fun bindProfileStarredReposViewModel(viewModel: ProfileStarredReposViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(ProfileGistsViewModel::class) + abstract fun bindProfileGistsViewModel(viewModel: ProfileGistsViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(FollowersFollowingViewModel::class) + abstract fun bindFollowersFollowingViewModel(viewModel: FollowersFollowingViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(ProfileFeedsViewModel::class) + abstract fun bindProfileFeedsViewModel(viewModel: ProfileFeedsViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(FeedsViewModel::class) + abstract fun bindFeedsViewModel(viewModel: FeedsViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(UnreadNotificationsViewModel::class) + abstract fun bindUnreadNotificationsViewModel(viewModel: UnreadNotificationsViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(AllNotificationsViewModel::class) + abstract fun bindAllNotificationsViewModel(viewModel: AllNotificationsViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(LoginChooserViewModel::class) + abstract fun bindLoginChooserViewModel(viewModel: LoginChooserViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(UserOrgsViewModel::class) + abstract fun bindUserOrgsViewModel(viewModel: UserOrgsViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(FilterIssuePullRequestsViewModel::class) + abstract fun bindFilterIssuePullRequestsViewModel(viewModel: FilterIssuePullRequestsViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(FilterSearchViewModel::class) + abstract fun bindFilterSearchViewModel(viewModel: FilterSearchViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(TrendingViewModel::class) + abstract fun bindTrendingViewModel(viewModel: TrendingViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(IssueTimelineViewModel::class) + abstract fun bindIssueTimelineViewModel(viewModel: IssueTimelineViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(LabelsViewModel::class) + abstract fun bindLabelsViewModel(viewModel: LabelsViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(AssigneesViewModel::class) + abstract fun bindAssigneesViewModel(viewModel: AssigneesViewModel): ViewModel + + @Binds @IntoMap @ViewModelKey(MilestoneViewModel::class) + abstract fun bindMilestoneViewModel(viewModel: MilestoneViewModel): ViewModel +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/modules/WorkersModule.kt b/app/src/main/java/com/fastaccess/github/di/modules/WorkersModule.kt new file mode 100644 index 000000000..c0299a8ae --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/modules/WorkersModule.kt @@ -0,0 +1,24 @@ +package com.fastaccess.github.di.modules + +import androidx.work.RxWorker +import com.fastaccess.github.di.annotations.WorkerKey +import com.fastaccess.github.platform.works.MarkAsReadNotificationWorker +import com.fastaccess.github.platform.works.ReactionWorker +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap + +/** + * Created by Kosh on 12.01.19. + */ +@Module abstract class WorkersModule { + @Binds + @IntoMap + @WorkerKey(MarkAsReadNotificationWorker::class) + abstract fun bindMarkAsReadNotificationWorker(worker: MarkAsReadNotificationWorker): RxWorker + + @Binds + @IntoMap + @WorkerKey(ReactionWorker::class) + abstract fun bindReactionWorker(worker: ReactionWorker): RxWorker +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/scopes/PerActivity.kt b/app/src/main/java/com/fastaccess/github/di/scopes/PerActivity.kt new file mode 100644 index 000000000..8d236ca53 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/scopes/PerActivity.kt @@ -0,0 +1,10 @@ +package com.fastaccess.github.di.scopes + +/** + * Created by Kosh on 12.05.18. + */ +import javax.inject.Scope + +@Scope +@Retention(AnnotationRetention.RUNTIME) +annotation class PerActivity \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/di/scopes/PerFragment.kt b/app/src/main/java/com/fastaccess/github/di/scopes/PerFragment.kt new file mode 100644 index 000000000..082e46eb3 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/di/scopes/PerFragment.kt @@ -0,0 +1,10 @@ +package com.fastaccess.github.di.scopes + +/** + * Created by Kosh on 12.05.18. + */ +import javax.inject.Scope + +@Scope +@Retention(AnnotationRetention.RUNTIME) +annotation class PerFragment \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/platform/deeplink/AppDeepLink.kt b/app/src/main/java/com/fastaccess/github/platform/deeplink/AppDeepLink.kt new file mode 100644 index 000000000..6b979ad0b --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/platform/deeplink/AppDeepLink.kt @@ -0,0 +1,6 @@ +package com.fastaccess.github.platform.deeplink + +import com.airbnb.deeplinkdispatch.DeepLinkSpec + +@DeepLinkSpec(prefix = ["app://fasthub"]) +annotation class AppDeepLink(vararg val value: String) diff --git a/app/src/main/java/com/fastaccess/github/platform/deeplink/RawWebDeepLink.kt b/app/src/main/java/com/fastaccess/github/platform/deeplink/RawWebDeepLink.kt new file mode 100644 index 000000000..6855abcaa --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/platform/deeplink/RawWebDeepLink.kt @@ -0,0 +1,6 @@ +package com.fastaccess.github.platform.deeplink + +import com.airbnb.deeplinkdispatch.DeepLinkSpec + +@DeepLinkSpec(prefix = ["https://raw.githubusercontent.com"]) +annotation class RawWebDeepLink(vararg val value: String) \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/platform/deeplink/WebDeepLink.kt b/app/src/main/java/com/fastaccess/github/platform/deeplink/WebDeepLink.kt new file mode 100644 index 000000000..ad8e19ca9 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/platform/deeplink/WebDeepLink.kt @@ -0,0 +1,8 @@ +package com.fastaccess.github.platform.deeplink + +import com.airbnb.deeplinkdispatch.DeepLinkSpec + +@DeepLinkSpec(prefix = ["http://github.com", "https://github.com", + "https://api.github.com", "http://api.github.com", + "https://raw.githubusercontent.com"]) +annotation class WebDeepLink(vararg val value: String) \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/platform/extension/ClickExtenion.kt b/app/src/main/java/com/fastaccess/github/platform/extension/ClickExtenion.kt new file mode 100644 index 000000000..86ea8a9fc --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/platform/extension/ClickExtenion.kt @@ -0,0 +1,41 @@ +package com.fastaccess.github.platform.extension + +import androidx.fragment.app.Fragment +import com.fastaccess.data.model.MainScreenModel +import com.fastaccess.data.model.MainScreenModelRowType +import com.fastaccess.data.persistence.models.FeedModel +import com.fastaccess.domain.response.enums.EventsType +import com.fastaccess.github.utils.FEEDS_LINK +import com.fastaccess.github.utils.FILTER_ISSUE_LINK +import com.fastaccess.github.utils.FILTER_PR_LINK +import com.fastaccess.github.utils.NOTIFICATION_LINK +import com.fastaccess.github.utils.extensions.route +import timber.log.Timber + +/** + * Created by Kosh on 2019-01-29. + */ + + +fun MainScreenModel.onClick(fragment: Fragment) { + val model = this + when (model.mainScreenModelRowType) { + MainScreenModelRowType.FEED_TITLE -> fragment.route(FEEDS_LINK) + MainScreenModelRowType.FEED -> model.feed?.onClick(fragment) + MainScreenModelRowType.NOTIFICATION_TITLE -> fragment.route(NOTIFICATION_LINK) + MainScreenModelRowType.NOTIFICATION -> Timber.e("${model.notificationModel}") + MainScreenModelRowType.ISSUES_TITLE -> fragment.route(FILTER_ISSUE_LINK) + MainScreenModelRowType.ISSUES -> fragment.route("${model.issuesPullsModel?.url}") + MainScreenModelRowType.PRS_TITLE -> fragment.route(FILTER_PR_LINK) + MainScreenModelRowType.PRS -> Timber.e("${model.issuesPullsModel}") + } +} + +fun FeedModel.onClick(fragment: Fragment) { + Timber.e("$type") + when (type) { + EventsType.IssueCommentEvent -> fragment.route("${payload?.issue?.htmlUrl}") + EventsType.IssuesEvent -> fragment.route("${payload?.issue?.htmlUrl}") + else -> fragment.route(actor?.url) // TODO(handle click) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/fabric/FabricProvider.kt b/app/src/main/java/com/fastaccess/github/platform/fabric/FabricProvider.kt similarity index 75% rename from app/src/main/java/com/fastaccess/provider/fabric/FabricProvider.kt rename to app/src/main/java/com/fastaccess/github/platform/fabric/FabricProvider.kt index fc57ba4ba..7f842c243 100644 --- a/app/src/main/java/com/fastaccess/provider/fabric/FabricProvider.kt +++ b/app/src/main/java/com/fastaccess/github/platform/fabric/FabricProvider.kt @@ -1,19 +1,15 @@ -package com.fastaccess.provider.fabric +package com.fastaccess.github.platform.fabric import android.content.Context +import com.crashlytics.android.BuildConfig import com.crashlytics.android.Crashlytics import com.crashlytics.android.answers.Answers import com.crashlytics.android.answers.PurchaseEvent import com.crashlytics.android.core.CrashlyticsCore -import com.fastaccess.BuildConfig import io.fabric.sdk.android.Fabric import java.math.BigDecimal import java.math.RoundingMode -/** - * Created by kosh on 14/08/2017. - */ - object FabricProvider { fun initFabric(context: Context) { @@ -30,13 +26,8 @@ object FabricProvider { val purchaseEvent = PurchaseEvent() .putItemName(productKey) .putSuccess(true) - - priceText?.let { - purchaseEvent.putItemType(priceText) - } - price?.let { - purchaseEvent.putItemPrice(BigDecimal(price).setScale(2, RoundingMode.CEILING)) - } + priceText?.let { purchaseEvent.putItemType(it) } + price?.let { purchaseEvent.putItemPrice(BigDecimal(it).setScale(2, RoundingMode.CEILING)) } Answers.getInstance().logPurchase(purchaseEvent) } } diff --git a/app/src/main/java/com/fastaccess/github/platform/glide/GlideModule.kt b/app/src/main/java/com/fastaccess/github/platform/glide/GlideModule.kt new file mode 100644 index 000000000..709e27548 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/platform/glide/GlideModule.kt @@ -0,0 +1,8 @@ +package com.fastaccess.github.platform.glide + +import com.bumptech.glide.annotation.GlideModule +import com.bumptech.glide.module.AppGlideModule + + +@GlideModule +class GlideModule : AppGlideModule() \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/platform/timber/LogTree.kt b/app/src/main/java/com/fastaccess/github/platform/timber/LogTree.kt new file mode 100644 index 000000000..706a722a3 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/platform/timber/LogTree.kt @@ -0,0 +1,36 @@ +package com.fastaccess.github.platform.timber + +import android.util.Log +import com.crashlytics.android.Crashlytics +import timber.log.Timber + +class FabricTree : Timber.Tree() { + + override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { + if (priority == Log.VERBOSE || priority == Log.DEBUG || priority == Log.INFO) { + return + } + + Crashlytics.setInt(CRASHLYTICS_KEY_PRIORITY, priority) + Crashlytics.setString(CRASHLYTICS_KEY_TAG, tag) + Crashlytics.setString(CRASHLYTICS_KEY_MESSAGE, message) + if (t == null) { + Crashlytics.logException(Exception(message)) + } else { + Crashlytics.logException(t) + } + } + + companion object { + private const val CRASHLYTICS_KEY_PRIORITY = "priority" + private const val CRASHLYTICS_KEY_TAG = "tag" + private const val CRASHLYTICS_KEY_MESSAGE = "message" + } +} + +class FastHubTree : Timber.DebugTree() { + override fun createStackElementTag(element: StackTraceElement): String? { + val className = super.createStackElementTag(element)?.split("$")?.get(0) + return "($className.kt:${element.lineNumber})#${element.methodName}" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/platform/viewmodel/FastHubViewModelFactory.kt b/app/src/main/java/com/fastaccess/github/platform/viewmodel/FastHubViewModelFactory.kt new file mode 100644 index 000000000..aed68af80 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/platform/viewmodel/FastHubViewModelFactory.kt @@ -0,0 +1,26 @@ +package com.fastaccess.github.platform.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider + +import javax.inject.Inject +import javax.inject.Provider +import javax.inject.Singleton + +@Singleton +class FastHubViewModelFactory @Inject constructor( + private val creators: Map, @JvmSuppressWildcards Provider> +) : ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + val creator = creators[modelClass] ?: creators.entries.firstOrNull { + modelClass.isAssignableFrom(it.key) + }?.value ?: throw IllegalArgumentException("unknown model class $modelClass") + try { + @Suppress("UNCHECKED_CAST") + return creator.get() as T + } catch (e: Exception) { + throw RuntimeException(e) + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/platform/workmanager/DaggerWorkerFactory.kt b/app/src/main/java/com/fastaccess/github/platform/workmanager/DaggerWorkerFactory.kt new file mode 100644 index 000000000..62c605537 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/platform/workmanager/DaggerWorkerFactory.kt @@ -0,0 +1,51 @@ +package com.fastaccess.github.platform.workmanager + +import android.content.Context +import androidx.work.ListenableWorker +import androidx.work.RxWorker +import androidx.work.WorkerFactory +import androidx.work.WorkerParameters +import com.fastaccess.github.di.components.WorkerSubComponent +import javax.inject.Inject +import javax.inject.Provider +import javax.inject.Singleton + +@Singleton +class DaggerWorkerFactory @Inject constructor( + private val workerSubComponent: WorkerSubComponent.Builder +) : WorkerFactory() { + + override fun createWorker( + appContext: Context, + workerClassName: String, + workerParameters: WorkerParameters + ) = workerSubComponent + .workerParameters(workerParameters) + .build().run { + createWorker(workerClassName, workers()) + } + + private fun createWorker( + workerClassName: String, + workers: Map, Provider> + ): ListenableWorker? = try { + val workerClass = Class.forName(workerClassName).asSubclass(RxWorker::class.java) + + var provider = workers[workerClass] + if (provider == null) { + for ((key, value) in workers) { + if (workerClass.isAssignableFrom(key)) { + provider = value + break + } + } + } + if (provider == null) { + throw IllegalArgumentException("Missing binding for $workerClassName") + } + + provider.get() + } catch (e: Exception) { + throw RuntimeException(e) + } +} diff --git a/app/src/main/java/com/fastaccess/github/platform/works/MarkAsReadNotificationWorker.kt b/app/src/main/java/com/fastaccess/github/platform/works/MarkAsReadNotificationWorker.kt new file mode 100644 index 000000000..0d652d46d --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/platform/works/MarkAsReadNotificationWorker.kt @@ -0,0 +1,72 @@ +package com.fastaccess.github.platform.works + +import android.app.Application +import androidx.work.* +import com.fastaccess.data.repository.NotificationRepositoryProvider +import com.fastaccess.domain.repository.services.NotificationService +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.EXTRA_TWO +import io.reactivex.Single +import javax.inject.Inject + +/** + * Created by Kosh on 12.01.19. + */ +class MarkAsReadNotificationWorker @Inject constructor( + context: Application, + private val workerParams: WorkerParameters, + private val notificationService: NotificationService, + private val provider: NotificationRepositoryProvider +) : RxWorker(context, workerParams) { + override fun createWork(): Single { + val id = workerParams.inputData.getString(EXTRA) + val ids = workerParams.inputData.getStringArray(EXTRA_TWO) + if (id.isNullOrEmpty() && ids.isNullOrEmpty()) { + return Single.just(Result.failure()) + } + return if (!id.isNullOrEmpty()) markSingleAsRead(id) else if (!ids.isNullOrEmpty()) markMultiAsRead(ids) else Single.just(Result.failure()) + } + + private fun markSingleAsRead(id: String): Single { + return Single.fromObservable(notificationService.markAsRead(id)) + .doOnSuccess { + if (it.code() == 205) { + provider.markAsRead(id) + } + } + .map { if (it.code() == 205) Result.success() else Result.failure() } + .onErrorReturnItem(Result.failure()) + } + + private fun markMultiAsRead(ids: Array): Single { + return Single.fromPublisher { subscriber -> + provider.markAllAsRead() + kotlin.runCatching { + ids.forEach { + notificationService.markAsRead(it).blockingSingle() + } + } + subscriber.onNext(Result.success()) // always succeed + subscriber.onComplete() + } + } + + companion object { + fun enqueue(id: String? = null, ids: Array? = null) { + val workManager = WorkManager.getInstance() + workManager.enqueueUniqueWork(id ?: ids?.hashCode()?.toString() ?: "MarkAsReadNotificationWorker", + ExistingWorkPolicy.KEEP, OneTimeWorkRequest.Builder(MarkAsReadNotificationWorker::class.java) + .setInputData(Data.Builder() + .apply { + if (!id.isNullOrEmpty()) { + putString(EXTRA, id) + } + if (!ids.isNullOrEmpty()) { + putStringArray(EXTRA_TWO, ids) + } + } + .build()) + .build()) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/platform/works/ReactionWorker.kt b/app/src/main/java/com/fastaccess/github/platform/works/ReactionWorker.kt new file mode 100644 index 000000000..04adef4db --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/platform/works/ReactionWorker.kt @@ -0,0 +1,55 @@ +package com.fastaccess.github.platform.works + +import android.app.Application +import androidx.work.* +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.EXTRA_THREE +import com.fastaccess.github.utils.EXTRA_TWO +import github.AddReactionMutation +import github.RemoveReactionMutation +import github.type.ReactionContent +import io.reactivex.Single +import javax.inject.Inject + +/** + * Created by Kosh on 06.02.19. + */ +class ReactionWorker @Inject constructor( + context: Application, + private val workerParams: WorkerParameters, + private val apolloClient: ApolloClient +) : RxWorker(context, workerParams) { + + private val content: String by lazy { workerParams.inputData.keyValueMap[EXTRA_TWO] as String } + private val id: String by lazy { workerParams.inputData.keyValueMap[EXTRA] as String } + private val add: Boolean by lazy { workerParams.inputData.keyValueMap[EXTRA_THREE] as Boolean } + + override fun createWork(): Single = Single.fromCallable { + kotlin.runCatching { + if (add) { + Rx2Apollo.from(apolloClient.mutate(AddReactionMutation(id, ReactionContent.valueOf(content)))).blockingSingle() + } else { + Rx2Apollo.from(apolloClient.mutate(RemoveReactionMutation(id, ReactionContent.valueOf(content)))).blockingSingle() + } + }.getOrNull() + return@fromCallable Result.success() + } + + + companion object { + + fun enqueue(content: String, id: String, add: Boolean = true) { + val workManager = WorkManager.getInstance() + workManager.enqueueUniqueWork(id, + ExistingWorkPolicy.REPLACE, OneTimeWorkRequest.Builder(ReactionWorker::class.java) + .setInputData(Data.Builder() + .putString(EXTRA, id) + .putString(EXTRA_TWO, content) + .putBoolean(EXTRA_THREE, add) + .build()) + .build()) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/AllNotificationsAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/AllNotificationsAdapter.kt new file mode 100644 index 000000000..6993b25ae --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/AllNotificationsAdapter.kt @@ -0,0 +1,52 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.data.model.GroupedNotificationsModel +import com.fastaccess.github.ui.adapter.viewholder.NotificationsViewHolder +import com.fastaccess.github.ui.adapter.viewholder.TitleSectionViewHolder + +/** + * Created by Kosh on 04.11.18. + */ +class AllNotificationsAdapter : ListAdapter(DIFF_CALLBACK) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return when (viewType) { + GroupedNotificationsModel.HEADER -> TitleSectionViewHolder(parent) + else -> NotificationsViewHolder(parent) + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + val item = getItem(position) ?: return + when (holder) { + is NotificationsViewHolder -> { + val notification = item.notification + if (notification != null) { + holder.bind(notification) + } else { + holder.itemView.isVisible = false + } + } + is TitleSectionViewHolder -> holder.bind(item.repo?.fullName ?: item.repo?.name ?: "N/A") + } + } + + override fun getItemViewType(position: Int): Int { + return getItem(position).rowType + } + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: GroupedNotificationsModel, newItem: GroupedNotificationsModel): + Boolean = oldItem.rowType == newItem.rowType + + override fun areContentsTheSame(oldItem: GroupedNotificationsModel, newItem: GroupedNotificationsModel): + Boolean = oldItem == newItem + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/AssigneesAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/AssigneesAdapter.kt new file mode 100644 index 000000000..20d83ad26 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/AssigneesAdapter.kt @@ -0,0 +1,45 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import com.fastaccess.data.model.ShortUserModel +import com.fastaccess.github.ui.adapter.viewholder.AssigneeViewHolder + +/** + * Created by Kosh on 20.01.19. + */ +class AssigneesAdapter( + val selection: HashSet, + val deselection: HashSet +) : ListAdapter(DIFF_CALLBACK) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AssigneeViewHolder = AssigneeViewHolder(parent).apply { + itemView.let { view -> + view.setOnClickListener { + val position = adapterPosition + val item = getItem(position) + if (!selection.contains(item)) { + selection.add(item) + deselection.remove(item) + } else { + deselection.add(item) + selection.remove(item) + } + notifyItemChanged(position) + } + } + } + + override fun onBindViewHolder(holder: AssigneeViewHolder, position: Int) { + val item = getItem(position) + holder.bind(item, selection.contains(item)) + } + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: ShortUserModel, newItem: ShortUserModel): Boolean = oldItem.name == newItem.name + override fun areContentsTheSame(oldItem: ShortUserModel, newItem: ShortUserModel): Boolean = oldItem == newItem + } + } +} diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/IssueTimelineAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/IssueTimelineAdapter.kt new file mode 100644 index 000000000..e5beaa763 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/IssueTimelineAdapter.kt @@ -0,0 +1,75 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.data.model.TimelineModel +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.ui.adapter.viewholder.CommentViewHolder +import com.fastaccess.github.ui.adapter.viewholder.IssueContentViewHolder +import com.fastaccess.github.ui.adapter.viewholder.LoadingViewHolder +import net.nightwhistler.htmlspanner.HtmlSpanner + +/** + * Created by Kosh on 20.01.19. + */ +class IssueTimelineAdapter( + private val htmlSpanner: HtmlSpanner, + private val theme: Int +) : ListAdapter(DIFF_CALLBACK) { + + private val notifyCallback by lazy { + { position: Int -> + notifyItemChanged(position) + } + } + + override fun getItemViewType(position: Int): Int { + return getItem(position)?.let { + when { + it.issue != null -> HEADER + it.comment != null -> COMMENT + else -> CONTENT + } + } ?: super.getItemViewType(position) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return when (viewType) { + COMMENT -> CommentViewHolder(parent, htmlSpanner, theme, notifyCallback) + CONTENT -> IssueContentViewHolder(parent) + else -> LoadingViewHolder(parent).apply { itemView.isVisible = false } + } + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (holder) { + is CommentViewHolder -> holder.bind(getItem(position).comment) + is IssueContentViewHolder -> holder.bind(getItem(position)) + } + } + + override fun onViewRecycled(holder: RecyclerView.ViewHolder) { + if (holder is BaseViewHolder<*>) { + holder.onDetached() + } + super.onViewRecycled(holder) + } + + fun getItemByPosition(position: Int): TimelineModel? { + return kotlin.runCatching { getItem(position) }.getOrNull() + } + + companion object { + private const val HEADER = 1 + private const val COMMENT = 2 + private const val CONTENT = 3 + + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: TimelineModel, newItem: TimelineModel): Boolean = oldItem.hashCode() == newItem.hashCode() + override fun areContentsTheSame(oldItem: TimelineModel, newItem: TimelineModel): Boolean = oldItem == newItem + } + } +} diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/LabelColorAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/LabelColorAdapter.kt new file mode 100644 index 000000000..36265b460 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/LabelColorAdapter.kt @@ -0,0 +1,23 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.github.ui.adapter.viewholder.LabelColorViewHolder + +/** + * Created by Kosh on 07.03.19. + */ +class LabelColorAdapter( + private val list: List, + private val callback: (String) -> Unit +) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LabelColorViewHolder = LabelColorViewHolder(parent).apply { + itemView.setOnClickListener { + callback.invoke(list[adapterPosition]) + } + } + + override fun getItemCount(): Int = list.size + override fun onBindViewHolder(holder: LabelColorViewHolder, position: Int) = holder.bind(list[position]) +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/LabelsAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/LabelsAdapter.kt new file mode 100644 index 000000000..5daaae5d6 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/LabelsAdapter.kt @@ -0,0 +1,45 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import com.fastaccess.data.model.parcelable.LabelModel +import com.fastaccess.github.ui.adapter.viewholder.LabelViewHolder + +/** + * Created by Kosh on 20.01.19. + */ +class LabelsAdapter( + val selection: HashSet, + val deselection: HashSet +) : ListAdapter(DIFF_CALLBACK) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LabelViewHolder = LabelViewHolder(parent).apply { + itemView.let { view -> + view.setOnClickListener { + val position = adapterPosition + val item = getItem(position) + if (!selection.contains(item)) { + selection.add(item) + deselection.remove(item) + } else { + deselection.add(item) + selection.remove(item) + } + notifyItemChanged(position) + } + } + } + + override fun onBindViewHolder(holder: LabelViewHolder, position: Int) { + val item = getItem(position) + holder.bind(item, selection.contains(item)) + } + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: LabelModel, newItem: LabelModel): Boolean = oldItem.name == newItem.name + override fun areContentsTheSame(oldItem: LabelModel, newItem: LabelModel): Boolean = oldItem == newItem + } + } +} diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/LanguagesAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/LanguagesAdapter.kt new file mode 100644 index 000000000..56f6bbe41 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/LanguagesAdapter.kt @@ -0,0 +1,39 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import com.fastaccess.data.model.LanguageColorsModel +import com.fastaccess.github.ui.adapter.viewholder.LanguagesViewHolder +import kotlinx.android.synthetic.main.language_row_item.view.* + +/** + * Created by Kosh on 20.01.19. + */ +class LanguagesAdapter : ListAdapter(DIFF_CALLBACK) { + + var checkedLanguage = "All" + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LanguagesViewHolder = LanguagesViewHolder(this, parent).apply { + itemView.languageChip.let { chip -> + chip.setOnClickListener { + val isChecked = chip.isChecked + checkedLanguage = if (isChecked) { + chip.text?.toString() ?: "All" + } else { + "All" + } + notifyDataSetChanged() + } + } + } + + override fun onBindViewHolder(holder: LanguagesViewHolder, position: Int) = holder.bind(getItem(position)) + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: LanguageColorsModel, newItem: LanguageColorsModel): Boolean = oldItem.name == newItem.name + override fun areContentsTheSame(oldItem: LanguageColorsModel, newItem: LanguageColorsModel): Boolean = oldItem == newItem + } + } +} diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/LoggedInUsersAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/LoggedInUsersAdapter.kt new file mode 100644 index 000000000..431007fd1 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/LoggedInUsersAdapter.kt @@ -0,0 +1,30 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.data.persistence.models.LoginModel +import com.fastaccess.github.ui.adapter.viewholder.LoggedInUserViewHolder + +/** + * Created by Kosh on 12.10.18. + */ +class LoggedInUsersAdapter(private val onClick: (user: LoginModel) -> Unit) : ListAdapter(DIFF_CALLBACK) { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LoggedInUserViewHolder = LoggedInUserViewHolder(parent).apply { + itemView.setOnClickListener { + val position = adapterPosition + if (position == RecyclerView.NO_POSITION) return@setOnClickListener + getItem(position)?.let(onClick) + } + } + + override fun onBindViewHolder(holder: LoggedInUserViewHolder, position: Int) = holder.bind(getItem(position)) + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: LoginModel, newItem: LoginModel): Boolean = oldItem.login == newItem.login + override fun areContentsTheSame(oldItem: LoginModel, newItem: LoginModel): Boolean = oldItem == newItem + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/MainScreenAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/MainScreenAdapter.kt new file mode 100644 index 000000000..07e58fb0a --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/MainScreenAdapter.kt @@ -0,0 +1,96 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.data.model.MainScreenModel +import com.fastaccess.data.model.MainScreenModelRowType +import com.fastaccess.github.R +import com.fastaccess.github.extensions.getDrawableCompat +import com.fastaccess.github.ui.adapter.viewholder.FeedsViewHolder +import com.fastaccess.github.ui.adapter.viewholder.MyIssuesPrsViewHolder +import com.fastaccess.github.ui.adapter.viewholder.NotificationsViewHolder +import com.fastaccess.github.ui.adapter.viewholder.TitleSectionViewHolder +import com.fastaccess.markdown.widget.SpannableBuilder + +/** + * Created by Kosh on 04.11.18. + */ +class MainScreenAdapter( + private val clickListener: (model: MainScreenModel) -> Unit +) : ListAdapter(DIFF_CALLBACK) { + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): RecyclerView.ViewHolder { + return when (viewType) { + MainScreenModelRowType.FEED.rowType -> FeedsViewHolder(parent).apply { setOnClick(this) } + MainScreenModelRowType.NOTIFICATION.rowType -> NotificationsViewHolder(parent).apply { setOnClick(this) } + MainScreenModelRowType.ISSUES.rowType -> MyIssuesPrsViewHolder(parent).apply { setOnClick(this) } + MainScreenModelRowType.PRS.rowType -> MyIssuesPrsViewHolder(parent).apply { setOnClick(this) } + else -> TitleSectionViewHolder(parent).apply { setOnClick(this) } + } + } + + private fun setOnClick(viewHolder: RecyclerView.ViewHolder) { + viewHolder.itemView.setOnClickListener { + val position = viewHolder.adapterPosition + if (position > RecyclerView.NO_POSITION) { + clickListener.invoke(getItem(position)) + } + } + } + + override fun onBindViewHolder( + holder: RecyclerView.ViewHolder, + position: Int + ) { + val item = getItem(position) ?: return + when (holder) { + is FeedsViewHolder -> item.feed?.let { holder.bind(it) } + is NotificationsViewHolder -> item.notificationModel?.let { holder.bind(it) } + is MyIssuesPrsViewHolder -> item.issuesPullsModel?.let { holder.bind(it) } + is TitleSectionViewHolder -> { + when (item.mainScreenModelRowType) { + MainScreenModelRowType.FEED_TITLE -> holder.bind(holder.itemView.context.getString(R.string.feeds)) + MainScreenModelRowType.NOTIFICATION_TITLE -> holder.bind( + if (item.hasBubble) { + SpannableBuilder.builder() + .append(holder.itemView.context.getString(R.string.notifications)) + .space().space() + .append(holder.itemView.context.getDrawableCompat(R.drawable.circle_shape_red_small)) + } else { + holder.itemView.context.getString(R.string.notifications) + } + ) + MainScreenModelRowType.ISSUES_TITLE -> holder.bind(holder.itemView.context.getString(R.string.issues)) + MainScreenModelRowType.PRS_TITLE -> holder.bind(holder.itemView.context.getString(R.string.pull_requests)) + else -> holder.itemView.isVisible = false + } + } + } + } + + override fun getItemViewType(position: Int): Int { + return getItem(position).mainScreenModelRowType?.rowType ?: super.getItemViewType(position) + } + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame( + oldItem: MainScreenModel, + newItem: MainScreenModel + ): + Boolean = oldItem.mainScreenModelRowType == newItem.mainScreenModelRowType + + override fun areContentsTheSame( + oldItem: MainScreenModel, + newItem: MainScreenModel + ): + Boolean = oldItem == newItem + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/MilestonesAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/MilestonesAdapter.kt new file mode 100644 index 000000000..499b242cc --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/MilestonesAdapter.kt @@ -0,0 +1,35 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import com.fastaccess.data.model.parcelable.MilestoneModel +import com.fastaccess.github.ui.adapter.viewholder.MilestoneViewHolder + +/** + * Created by Kosh on 20.01.19. + */ +class MilestonesAdapter( + private val clickCallback: (MilestoneModel) -> Unit +) : ListAdapter(DIFF_CALLBACK) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MilestoneViewHolder = MilestoneViewHolder(parent).apply { + itemView.let { view -> + view.setOnClickListener { + getItem(adapterPosition)?.let(clickCallback) + } + } + } + + override fun onBindViewHolder(holder: MilestoneViewHolder, position: Int) { + val item = getItem(position) + holder.bind(item) + } + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: MilestoneModel, newItem: MilestoneModel): Boolean = oldItem.id == newItem.id + override fun areContentsTheSame(oldItem: MilestoneModel, newItem: MilestoneModel): Boolean = oldItem == newItem + } + } +} diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/MyIssuesPrsAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/MyIssuesPrsAdapter.kt new file mode 100644 index 000000000..df2eec936 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/MyIssuesPrsAdapter.kt @@ -0,0 +1,34 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.data.persistence.models.MyIssuesPullsModel +import com.fastaccess.github.ui.adapter.viewholder.MyIssuesPrsViewHolder + +/** + * Created by Kosh on 20.01.19. + */ +class MyIssuesPrsAdapter( + private val onClick: (model: MyIssuesPullsModel) -> Unit +) : ListAdapter(DIFF_CALLBACK) { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyIssuesPrsViewHolder = MyIssuesPrsViewHolder(parent).apply { + itemView?.setOnClickListener { _ -> + val position = adapterPosition + if (position == RecyclerView.NO_POSITION) return@setOnClickListener + kotlin.runCatching { getItem(position) }.onSuccess { + onClick(it) + } + } + } + + override fun onBindViewHolder(holder: MyIssuesPrsViewHolder, position: Int) = holder.bind(getItem(position)) + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: MyIssuesPullsModel, newItem: MyIssuesPullsModel): Boolean = oldItem.id == newItem.id + override fun areContentsTheSame(oldItem: MyIssuesPullsModel, newItem: MyIssuesPullsModel): Boolean = oldItem == newItem + } + } +} diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/OrganizationsAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/OrganizationsAdapter.kt new file mode 100644 index 000000000..b5fa36fb1 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/OrganizationsAdapter.kt @@ -0,0 +1,30 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.data.persistence.models.OrganizationModel +import com.fastaccess.github.ui.adapter.base.BasePagedAdapter +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.ui.adapter.viewholder.OrganizationViewHolder + +/** + * Created by Kosh on 12.10.18. + */ +class OrganizationsAdapter(private val onClick: (url: String) -> Unit) : BasePagedAdapter(DIFF_CALLBACK) { + + override fun contentViewHolder(parent: ViewGroup): BaseViewHolder = OrganizationViewHolder(parent).apply { + itemView.setOnClickListener { + val position = adapterPosition + if (position == RecyclerView.NO_POSITION) return@setOnClickListener + getItem(position)?.url?.let(onClick) + } + } + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: OrganizationModel, newItem: OrganizationModel): Boolean = oldItem.login == newItem.login + override fun areContentsTheSame(oldItem: OrganizationModel, newItem: OrganizationModel): Boolean = oldItem == newItem + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/PagerAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/PagerAdapter.kt new file mode 100644 index 000000000..fe6abb0aa --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/PagerAdapter.kt @@ -0,0 +1,20 @@ +package com.fastaccess.github.ui.adapter + +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentStatePagerAdapter +import com.fastaccess.data.model.FragmentType +import com.fastaccess.data.model.ViewPagerModel + +/** + * Created by Kosh on 05.10.18. + */ +class PagerAdapter( + fragmentManager: FragmentManager, + private val list: ArrayList +) : FragmentStatePagerAdapter(fragmentManager) { + override fun getItem(position: Int) = list[position].fragment + override fun getCount() = list.size + override fun getPageTitle(position: Int) = list[position].text + fun getModel(position: Int) = list.getOrNull(position) + fun getIndex(type: FragmentType) = list.indexOfFirst { it.fragmentType == type } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileFeedsAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileFeedsAdapter.kt new file mode 100644 index 000000000..8d254d726 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileFeedsAdapter.kt @@ -0,0 +1,30 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.data.persistence.models.FeedModel +import com.fastaccess.github.ui.adapter.base.BasePagedAdapter +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.ui.adapter.viewholder.FeedsViewHolder + +/** + * Created by Kosh on 12.10.18. + */ +class ProfileFeedsAdapter(private val onClick: (model: FeedModel) -> Unit) : BasePagedAdapter(DIFF_CALLBACK) { + + override fun contentViewHolder(parent: ViewGroup): BaseViewHolder = FeedsViewHolder(parent).apply { + itemView.setOnClickListener { + val position = adapterPosition + if (position == RecyclerView.NO_POSITION) return@setOnClickListener + getItem(position)?.let(onClick) + } + } + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: FeedModel, newItem: FeedModel): Boolean = oldItem.id == newItem.id + override fun areContentsTheSame(oldItem: FeedModel, newItem: FeedModel): Boolean = oldItem == newItem + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileFollowingFollowersAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileFollowingFollowersAdapter.kt new file mode 100644 index 000000000..cd3a0653c --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileFollowingFollowersAdapter.kt @@ -0,0 +1,30 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.data.persistence.models.FollowingFollowerModel +import com.fastaccess.github.ui.adapter.base.BasePagedAdapter +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.ui.adapter.viewholder.ProfileFollowerFollowingViewHolder + +/** + * Created by Kosh on 12.10.18. + */ +class ProfileFollowingFollowersAdapter(private val onClick: (url: String) -> Unit) : BasePagedAdapter(DIFF_CALLBACK) { + + override fun contentViewHolder(parent: ViewGroup): BaseViewHolder = ProfileFollowerFollowingViewHolder(parent).apply { + itemView.setOnClickListener { + val position = adapterPosition + if (position == RecyclerView.NO_POSITION) return@setOnClickListener + getItem(position)?.url?.let(onClick) + } + } + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: FollowingFollowerModel, newItem: FollowingFollowerModel): Boolean = oldItem.login == newItem.login + override fun areContentsTheSame(oldItem: FollowingFollowerModel, newItem: FollowingFollowerModel): Boolean = oldItem == newItem + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileGistsAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileGistsAdapter.kt new file mode 100644 index 000000000..c80c36710 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileGistsAdapter.kt @@ -0,0 +1,23 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import com.fastaccess.data.persistence.models.ProfileGistModel +import com.fastaccess.github.ui.adapter.base.BasePagedAdapter +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.ui.adapter.viewholder.ProfileGistsViewHolder + +/** + * Created by Kosh on 12.10.18. + */ +class ProfileGistsAdapter : BasePagedAdapter(DIFF_CALLBACK) { + + override fun contentViewHolder(parent: ViewGroup): BaseViewHolder = ProfileGistsViewHolder(parent) + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: ProfileGistModel, newItem: ProfileGistModel): Boolean = oldItem.id == newItem.id + override fun areContentsTheSame(oldItem: ProfileGistModel, newItem: ProfileGistModel): Boolean = oldItem == newItem + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileOrgsAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileOrgsAdapter.kt new file mode 100644 index 000000000..2aa75b6c3 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileOrgsAdapter.kt @@ -0,0 +1,24 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.data.persistence.models.UserOrganizationNodesModel +import com.fastaccess.github.ui.adapter.viewholder.ProfileOrgsViewHolder + +/** + * Created by Kosh on 2018-11-17. + */ +class ProfileOrgsAdapter(private val list: ArrayList) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileOrgsViewHolder = ProfileOrgsViewHolder(parent) + override fun getItemCount(): Int = list.size + override fun onBindViewHolder(holder: ProfileOrgsViewHolder, position: Int) = holder.bind(list[position]) + + fun insertNew(list: List) { + this.list.apply { + clear() + addAll(list) + notifyDataSetChanged() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/ProfilePinnedReposAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfilePinnedReposAdapter.kt new file mode 100644 index 000000000..126daa8b9 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfilePinnedReposAdapter.kt @@ -0,0 +1,24 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.data.persistence.models.UserPinnedRepoNodesModel +import com.fastaccess.github.ui.adapter.viewholder.ProfilePinnedReposViewHolder + +/** + * Created by Kosh on 2018-11-17. + */ +class ProfilePinnedReposAdapter(private val list: ArrayList) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfilePinnedReposViewHolder = ProfilePinnedReposViewHolder(parent) + override fun getItemCount(): Int = list.size + override fun onBindViewHolder(holder: ProfilePinnedReposViewHolder, position: Int) = holder.bind(list[position]) + + fun insertNew(list: List) { + this.list.apply { + clear() + addAll(list) + notifyDataSetChanged() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileReposAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileReposAdapter.kt new file mode 100644 index 000000000..361dbf8b5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileReposAdapter.kt @@ -0,0 +1,23 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import com.fastaccess.data.persistence.models.ProfileRepoModel +import com.fastaccess.github.ui.adapter.base.BasePagedAdapter +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.ui.adapter.viewholder.ReposProfileViewHolder + +/** + * Created by Kosh on 12.10.18. + */ +class ProfileReposAdapter : BasePagedAdapter(DIFF_CALLBACK) { + + override fun contentViewHolder(parent: ViewGroup): BaseViewHolder = ReposProfileViewHolder(parent) + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: ProfileRepoModel, newItem: ProfileRepoModel): Boolean = oldItem.id == newItem.id + override fun areContentsTheSame(oldItem: ProfileRepoModel, newItem: ProfileRepoModel): Boolean = oldItem == newItem + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileStarredReposAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileStarredReposAdapter.kt new file mode 100644 index 000000000..f9584ada1 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/ProfileStarredReposAdapter.kt @@ -0,0 +1,23 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import com.fastaccess.data.persistence.models.ProfileStarredRepoModel +import com.fastaccess.github.ui.adapter.base.BasePagedAdapter +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.ui.adapter.viewholder.ReposStarredProfileViewHolder + +/** + * Created by Kosh on 12.10.18. + */ +class ProfileStarredReposAdapter : BasePagedAdapter(DIFF_CALLBACK) { + + override fun contentViewHolder(parent: ViewGroup): BaseViewHolder = ReposStarredProfileViewHolder(parent) + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: ProfileStarredRepoModel, newItem: ProfileStarredRepoModel): Boolean = oldItem.id == newItem.id + override fun areContentsTheSame(oldItem: ProfileStarredRepoModel, newItem: ProfileStarredRepoModel): Boolean = oldItem == newItem + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/SearchReposAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/SearchReposAdapter.kt new file mode 100644 index 000000000..e958afc15 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/SearchReposAdapter.kt @@ -0,0 +1,22 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import com.fastaccess.data.model.ShortRepoModel +import com.fastaccess.github.ui.adapter.viewholder.ShortRepoViewHolder + +/** + * Created by Kosh on 20.01.19. + */ +class SearchReposAdapter : ListAdapter(DIFF_CALLBACK) { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShortRepoViewHolder = ShortRepoViewHolder(parent) + override fun onBindViewHolder(holder: ShortRepoViewHolder, position: Int) = holder.bind(getItem(position)) + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: ShortRepoModel, newItem: ShortRepoModel): Boolean = oldItem.id == newItem.id + override fun areContentsTheSame(oldItem: ShortRepoModel, newItem: ShortRepoModel): Boolean = oldItem == newItem + } + } +} diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/ShortUsersAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/ShortUsersAdapter.kt new file mode 100644 index 000000000..ca18e67fc --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/ShortUsersAdapter.kt @@ -0,0 +1,30 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.data.model.ShortUserModel +import com.fastaccess.github.ui.adapter.viewholder.ShortUserViewHolder + +/** + * Created by Kosh on 12.10.18. + */ +class ShortUsersAdapter(private val onClick: (url: String) -> Unit) : ListAdapter(DIFF_CALLBACK) { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ShortUserViewHolder = ShortUserViewHolder(parent).apply { + itemView.setOnClickListener { + val position = adapterPosition + if (position == RecyclerView.NO_POSITION) return@setOnClickListener + getItem(position)?.url?.let(onClick) + } + } + + override fun onBindViewHolder(holder: ShortUserViewHolder, position: Int) = holder.bind(getItem(position)) + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: ShortUserModel, newItem: ShortUserModel): Boolean = oldItem.login == newItem.login + override fun areContentsTheSame(oldItem: ShortUserModel, newItem: ShortUserModel): Boolean = oldItem == newItem + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/TrendingsAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/TrendingsAdapter.kt new file mode 100644 index 000000000..b6d8ded4f --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/TrendingsAdapter.kt @@ -0,0 +1,22 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import com.fastaccess.data.model.TrendingModel +import com.fastaccess.github.ui.adapter.viewholder.TrendingViewHolder + +/** + * Created by Kosh on 20.01.19. + */ +class TrendingsAdapter : ListAdapter(DIFF_CALLBACK) { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TrendingViewHolder = TrendingViewHolder(parent) + override fun onBindViewHolder(holder: TrendingViewHolder, position: Int) = holder.bind(getItem(position)) + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: TrendingModel, newItem: TrendingModel): Boolean = oldItem.title == newItem.title + override fun areContentsTheSame(oldItem: TrendingModel, newItem: TrendingModel): Boolean = oldItem == newItem + } + } +} diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/UnreadNotificationsAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/UnreadNotificationsAdapter.kt new file mode 100644 index 000000000..546144f1e --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/UnreadNotificationsAdapter.kt @@ -0,0 +1,23 @@ +package com.fastaccess.github.ui.adapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import com.fastaccess.data.persistence.models.NotificationModel +import com.fastaccess.github.ui.adapter.base.BasePagedAdapter +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.ui.adapter.viewholder.NotificationsViewHolder + +/** + * Created by Kosh on 12.10.18. + */ +class UnreadNotificationsAdapter : BasePagedAdapter(DIFF_CALLBACK) { + + override fun contentViewHolder(parent: ViewGroup): BaseViewHolder = NotificationsViewHolder(parent) + + companion object { + private val DIFF_CALLBACK = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: NotificationModel, newItem: NotificationModel): Boolean = oldItem.id == newItem.id + override fun areContentsTheSame(oldItem: NotificationModel, newItem: NotificationModel): Boolean = oldItem == newItem + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/base/BasePagedAdapter.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/base/BasePagedAdapter.kt new file mode 100644 index 000000000..fc21d9230 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/base/BasePagedAdapter.kt @@ -0,0 +1,56 @@ +package com.fastaccess.github.ui.adapter.base + +import android.view.ViewGroup +import androidx.paging.PagedListAdapter +import androidx.recyclerview.widget.DiffUtil +import com.fastaccess.github.ui.adapter.viewholder.LoadingViewHolder + +/** + * Created by Kosh on 12.10.18. + */ +abstract class BasePagedAdapter( + diffCallback: DiffUtil.ItemCallback +) : PagedListAdapter>(diffCallback) { + + var currentState = CurrentState.LOADING + set(value) { + field = value + if (itemCount < 10) return // do not add progress if we are in first page! + notifyItemChanged(itemCount) + } + + abstract fun contentViewHolder(parent: ViewGroup): BaseViewHolder + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder { + return if (viewType == CONTENT_VIEW_TYPE) contentViewHolder(parent) else LoadingViewHolder(parent) + } + + override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { + if (getItemViewType(position) == CONTENT_VIEW_TYPE) { + getItem(position)?.let { holder.bind(it) } + } + } + + override fun getItemViewType(position: Int): Int { + return if (position < super.getItemCount()) CONTENT_VIEW_TYPE else FOOTER_VIEW_TYPE + } + + override fun getItemCount(): Int { + return super.getItemCount() + if (hasFooter()) 1 else 0 + } + + fun getValue(position: Int) = getItem(position) + + private fun hasFooter(): Boolean { + return super.getItemCount() != 0 && (currentState == CurrentState.LOADING || currentState == CurrentState.ERROR) + } + + companion object { + const val CONTENT_VIEW_TYPE = 1 + const val FOOTER_VIEW_TYPE = 2 + } +} + +enum class CurrentState { + DONE, LOADING, ERROR +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/base/BaseViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/base/BaseViewHolder.kt new file mode 100644 index 000000000..ed5819c45 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/base/BaseViewHolder.kt @@ -0,0 +1,14 @@ +package com.fastaccess.github.ui.adapter.base + +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import com.fastaccess.github.ui.widget.recyclerview.decoration.InsetDividerDecoration + +/** + * Created by Kosh on 23.06.18. + */ +abstract class BaseViewHolder(view: View) : RecyclerView.ViewHolder(view), InsetDividerDecoration.HasDivider { + abstract fun bind(item: T) + override fun canDivide(): Boolean = true + open fun onDetached() = Unit +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/AssigneeViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/AssigneeViewHolder.kt new file mode 100644 index 000000000..9ac452008 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/AssigneeViewHolder.kt @@ -0,0 +1,25 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.model.ShortUserModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import kotlinx.android.synthetic.main.assignees_row_item.view.* + +/** + * Created by Kosh on 04.11.18. + */ +class AssigneeViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.assignees_row_item, parent, false)) { + override fun bind(item: ShortUserModel) = Unit + + fun bind(item: ShortUserModel, isSelected: Boolean) { + itemView.apply { + backgroundLayout.isVisible = isSelected + userIcon.loadAvatar(item.avatarUrl, item.url) + title.text = item.login ?: item.name ?: "" + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/CommentViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/CommentViewHolder.kt new file mode 100644 index 000000000..e017a432e --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/CommentViewHolder.kt @@ -0,0 +1,83 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.model.CommentAuthorAssociation +import com.fastaccess.data.model.CommentModel +import com.fastaccess.data.model.getEmoji +import com.fastaccess.github.R +import com.fastaccess.github.base.engine.ThemeEngine +import com.fastaccess.github.extensions.timeAgo +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.utils.extensions.popupEmoji +import com.fastaccess.markdown.MarkdownProvider +import com.fastaccess.markdown.spans.drawable.DrawableGetter +import kotlinx.android.synthetic.main.comment_row_item.view.* +import net.nightwhistler.htmlspanner.HtmlSpanner + +/** + * Created by Kosh on 12.10.18. + */ + +class CommentViewHolder( + parent: ViewGroup, + private val htmlSpanner: HtmlSpanner, + private val theme: Int, + private val callback: (position: Int) -> Unit +) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.comment_row_item, parent, false)) { + + @SuppressLint("SetTextI18n") + override fun bind(item: CommentModel?) { + val model = item ?: kotlin.run { + itemView.isVisible = false + return + } + itemView.apply { + userIcon.loadAvatar(model.author?.avatarUrl, model.author?.url ?: "") + author.text = model.author?.login ?: "" + association.text = if (CommentAuthorAssociation.NONE == model.authorAssociation) { + model.updatedAt?.timeAgo() + } else { + "${model.authorAssociation?.value?.toLowerCase()?.replace("_", "")} ${model.updatedAt?.timeAgo()}" + } + + MarkdownProvider.loadIntoTextView(htmlSpanner, description, model.bodyHTML ?: "", ThemeEngine.getCodeBackground(theme), + ThemeEngine.isLightTheme(theme)) + + addEmoji.setOnClickListener { + it.popupEmoji(requireNotNull(model.id), model.reactionGroups) { + callback.invoke(adapterPosition) + } + } + + reactionsText.isVisible = model.reactionGroups?.any { it.users?.totalCount != 0 } ?: false + if (reactionsText.isVisible) { + val stringBuilder = StringBuilder() + model.reactionGroups?.forEach { + if (it.users?.totalCount != 0) { + stringBuilder.append(it.content.getEmoji()) + .append(" ") + .append("${it.users?.totalCount}") + .append(" ") + } + } + reactionsText.text = stringBuilder + } else { + reactionsText.text = "" + } + } + } + + override fun onDetached() { + super.onDetached() + itemView.description?.let { + if (it.tag is DrawableGetter) { + val target = it.tag as DrawableGetter + target.clear(target) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/FeedsViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/FeedsViewHolder.kt new file mode 100644 index 000000000..41fecee1b --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/FeedsViewHolder.kt @@ -0,0 +1,378 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.persistence.models.FeedModel +import com.fastaccess.domain.response.enums.EventsType +import com.fastaccess.github.R +import com.fastaccess.github.extensions.replaceAllNewLines +import com.fastaccess.github.extensions.timeAgo +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.markdown.MarkdownProvider +import com.fastaccess.markdown.widget.SpannableBuilder +import kotlinx.android.synthetic.main.feeds_row_item.view.* + +/** + * Created by Kosh on 20.10.18. + */ +class FeedsViewHolder( + parent: ViewGroup +) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.feeds_row_item, parent, false)) { + + override fun bind(item: FeedModel) { + itemView.apply { + feedDescription.text = "" + feedDescription.isVisible = false + feedTitle.text = context.getString(item.type?.titleId ?: 0).toLowerCase() + when (item.type) { + EventsType.WatchEvent -> watchEvent(this, item) + EventsType.CreateEvent -> createEvent(this, item) + EventsType.CommitCommentEvent -> commitCommentEvent(this, item) + EventsType.DownloadEvent -> downloadEvent(this, item) + EventsType.FollowEvent -> followEvent(this, item) + EventsType.ForkEvent -> forkEvent(this, item) + EventsType.GistEvent -> gistEvent(this, item) + EventsType.GollumEvent -> gollumEvent(this, item) + EventsType.IssueCommentEvent -> issueCommentEvent(this, item) + EventsType.IssuesEvent -> issueEvent(this, item) + EventsType.MemberEvent -> memberEvent(this, item) + EventsType.PublicEvent -> publicEvent(this, item) + EventsType.PullRequestEvent -> pullRequestEvent(this, item) + EventsType.PullRequestReviewCommentEvent -> pullRequestReviewCommentEvent(this, item) + EventsType.PullRequestReviewEvent -> pullRequestReviewEvent(this, item) + EventsType.RepositoryEvent -> repositoryEvent(this, item) + EventsType.PushEvent -> pushEvent(this, item) + EventsType.TeamAddEvent -> teamAddedEvent(this, item) + EventsType.DeleteEvent -> deleteEvent(this, item) + EventsType.ReleaseEvent -> releaseEvent(this, item) + EventsType.ForkApplyEvent -> forkApplyEvent(this, item) + EventsType.OrgBlockEvent -> orgBlockEvent(this, item) + EventsType.ProjectCardEvent -> projectCardEvent(this, item) + EventsType.ProjectColumnEvent -> projectColumnEvent(this, item) + EventsType.OrganizationEvent -> organizationEvent(this, item) + EventsType.ProjectEvent -> projectEvent(this, item) + else -> otherEvent(this, item) + } + dateWithIcon.text = item.createdAt?.timeAgo() + stateIcon.setImageResource(item.type?.drawableRes ?: 0) + userIcon.loadAvatar(item.actor?.avatarUrl, item.actor?.url) + } + } + + private fun otherEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold(item.payload?.action) + .space() + .append(item.repo?.name) + } + + private fun organizationEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold(item.payload?.action?.replace("_", "")) + .space() + .append(item.payload?.invitation?.login) + .space() + .append(item.payload?.organization?.login) + } + + private fun projectEvent(view: View, item: FeedModel) = projectCardEvent(view, item, false) + + private fun projectColumnEvent(view: View, item: FeedModel) = projectCardEvent(view, item, true) + + private fun projectCardEvent(view: View, item: FeedModel, isColumn: Boolean = false) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold(item.payload?.action) + .space() + .append(if (isColumn) "column" else "project") + .space() + .append(item.payload?.organization?.login) + } + + private fun orgBlockEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold(item.payload?.action) + .space() + .append(item.payload?.blockedUser?.login) + .space() + .append(item.payload?.organization?.login) + } + + private fun forkApplyEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold(item.payload?.head) + .space() + .append(item.payload?.before) + .space() + .append(item.repo?.name) + } + + private fun releaseEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("released") + .space() + .append(item.payload?.release?.name) + .space() + .append(item.repo?.name) + + } + + private fun deleteEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("deleted") + .space() + .append(item.payload?.refType) + .space() + .bold("at ") + .append(item.repo?.name) + } + + private fun teamAddedEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("added") + .space() + .append(item.payload?.user?.login ?: item.repo?.name) + .space() + .bold("in ") + .append(item.payload?.team?.name ?: item.payload?.team?.slug) + + } + + private fun pushEvent(view: View, item: FeedModel) { + val ref = if (item.payload?.ref?.startsWith("refs/heads/") == true) { + item.payload?.ref?.substring(11) + } else { + item.payload?.ref + } + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("push to") + .space() + .append(ref) + .space() + .bold("at") + .space() + .append(item.repo?.name) + + val builder = SpannableBuilder.builder() + val commits = item.payload?.commits + if (commits?.isNotEmpty() == true) { + if (commits.size != 1) { + builder.append("${item.payload?.size}") + .bold(" new commits") + .newline() + } else { + builder.bold("1 new commit").newline() + } + commits.take(5) + .filter { !it.sha.isNullOrEmpty() } + .forEach { + val sha = if ((it.sha?.length ?: 0) > 7) { + it.sha?.subSequence(0, 7) + } else { + it.sha + } + builder.url(sha ?: "") + .space() + .append(it.message?.replaceAllNewLines()) + .newline() + } + view.feedDescription.maxLines = 5 + view.feedDescription.text = builder + view.feedDescription.isVisible = true + } else { + view.feedDescription.maxLines = 2 + } + } + + private fun repositoryEvent(view: View, item: FeedModel) = publicEvent(view, item) + + private fun pullRequestReviewEvent(view: View, item: FeedModel) = pullRequestReviewCommentEvent(view, item) + + private fun pullRequestReviewCommentEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold(if (item.payload?.comment != null) "commented on a review in " else "reviewed a pull request in") + .space() + .append("${item.repo?.name}") + .bold("#${item.payload?.pullRequest?.number}") + view.feedDescription.apply { + text = item.payload?.comment?.body ?: "" + isVisible = !item.payload?.comment?.body.isNullOrEmpty() + } + } + + private fun pullRequestEvent(view: View, item: FeedModel) { + val pullRequest = item.payload?.pullRequest + val action = when { + "synchronize" == item.payload?.action -> "updated" + pullRequest?.isMerged == true -> "merged" + else -> item.payload?.action + } + + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold(action ?: "") + .space() + .append("${item.repo?.name}") + .bold("#${pullRequest?.number}") + if ("opened" == action || "closed" == action) { + view.feedDescription.text = pullRequest?.title?.replaceAllNewLines() ?: "" + view.feedDescription.isVisible = !pullRequest?.title?.replaceAllNewLines().isNullOrEmpty() + } + } + + private fun publicEvent(view: View, item: FeedModel) { + val action = if ("privatized" == item.payload?.action) { + "private" + } else { + "public" + } + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .append(item.repo?.name) + .space() + .bold(action) + } + + private fun memberEvent(view: View, item: FeedModel) { + val user = item.payload?.member + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("added") + .space() + .append(user?.login) + .space() + .append("as a collaborator to ") + .append(item.repo?.name) + } + + private fun issueEvent(view: View, item: FeedModel) { + val issue = item.payload?.issue + val label = item.payload?.issue?.labels?.lastOrNull() + val isLabel = "label" == item.payload?.action + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold(if (isLabel && label != null) "Labeled ${label.name}" else item.payload?.action ?: "") + .space() + .append(item.repo?.name) + .space() + .bold("#${issue?.number}") + view.feedDescription.text = issue?.title?.replaceAllNewLines() ?: "" + view.feedDescription.isVisible = !issue?.title?.replaceAllNewLines().isNullOrEmpty() + } + + private fun issueCommentEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("commented on ${if (item.payload?.issue?.htmlUrl?.contains("/pull/", true) == true) "a pull request" else "an issue"}") + .space() + .append("${item.repo?.name}") + .bold("#${item.payload?.issue?.number}") + + view.feedDescription.text = item.payload?.comment?.body?.replaceAllNewLines()?.let { MarkdownProvider.stripMd(it) } + view.feedDescription.isVisible = !item.payload?.comment?.body?.replaceAllNewLines().isNullOrEmpty() + } + + private fun gollumEvent(view: View, item: FeedModel) { + val wikies = item.payload?.pages + val builder = SpannableBuilder.builder().append(item.actor?.login) + .space() + if (wikies?.isNotEmpty() == true) { + wikies.forEach { + builder.bold(it.action) + .space() + .append(it.packageName) + .space() + } + } else { + builder.bold(view.resources.getString(R.string.gollum)) + .space() + } + builder.append(item.repo?.name) + view.feedTitle.text = builder + } + + private fun gistEvent(view: View, item: FeedModel) { + val action = if ("create" == item.payload?.action) "created" else if ("update" == item.payload?.action) "updated" else item.payload?.action + + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("$action ${view.resources.getString(R.string.gist).toLowerCase()}") + .space() + .append(item.payload?.gist?.id) + } + + private fun forkEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("forked") + .space() + .append(item.repo?.name) + } + + private fun followEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("started following") + .space() + .append(item.payload?.target?.login) + } + + private fun downloadEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("uploaded a file") + .space() + .append("${item.payload?.download?.name}") + .space() + .append("to") + .space() + .bold(item.repo?.name ?: "") + } + + private fun commitCommentEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("commented on commit") + .space() + .append("${item.repo?.name}") + .bold("#${item.payload?.issue?.number?.toString()}") + } + + private fun watchEvent(view: View, item: FeedModel) { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold(view.context.getString(item.type?.titleId ?: 0).toLowerCase()) + .space() + .append(item.repo?.name) + } + + private fun createEvent(view: View, item: FeedModel) { + item.payload?.let { + view.feedTitle.text = SpannableBuilder.builder().append(item.actor?.login) + .space() + .bold("created") + .space() + .append(it.refType) + .space() + .append(if ("repository" != it.refType) it.ref else "") + .space() + .append("at") + .space() + .append(item.repo?.name) + view.feedDescription.text = it.description?.replaceAllNewLines()?.let { MarkdownProvider.stripMd(it) } + view.feedDescription.isVisible = !it.description?.replaceAllNewLines().isNullOrEmpty() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/IssueContentViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/IssueContentViewHolder.kt new file mode 100644 index 000000000..4460f5ab4 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/IssueContentViewHolder.kt @@ -0,0 +1,219 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import com.fastaccess.data.model.* +import com.fastaccess.github.R +import com.fastaccess.github.extensions.timeAgo +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.markdown.spans.LabelSpan +import com.fastaccess.markdown.widget.SpannableBuilder +import kotlinx.android.synthetic.main.issue_content_row_item.view.* + +/** + * Created by Kosh on 04.02.19. + */ +class IssueContentViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.issue_content_row_item, parent, false)) { + override fun canDivide(): Boolean = false + + override fun bind(item: TimelineModel) { + itemView.text.text = "" + itemView.userIcon.setImageDrawable(null) + itemView.stateIcon.setImageDrawable(null) + item.commit?.let(this::presentCommit) + item.crossReferencedEventModel?.let(this::presentCrossReference) + item.referencedEventModel?.let(this::presentReference) + item.closeOpenEventModel?.let(this::presentClosedReopen) + item.lockUnlockEventModel?.let(this::presentLockUnlock) + item.labelUnlabeledEvent?.let(this::presentLabels) + item.subscribedUnsubscribedEvent?.let(this::presentSubscribeUnsubscribed) + item.assignedEventModel?.let(this::presentAssignedAndUnassigned) + item.milestoneEventModel?.let(this::presentMilestoneDemilestone) + item.renamedEventModel?.let(this::presentRenamed) + item.transferredEventModel?.let(this::presentTransferred) + } + + private fun presentTransferred(model: TransferredEventModel) { + itemView.apply { + stateIcon.setImageResource(R.drawable.ic_track_changes) + userIcon.loadAvatar(model.actor?.avatarUrl, model.actor?.url) + text.text = SpannableBuilder.builder() + .bold(model.actor?.login) + .space() + .append("transferred this from ") + .bold(model.fromRepository) + .space() + .append(model.createdAt?.timeAgo()) + } + } + + private fun presentRenamed(model: RenamedEventModel) { + itemView.apply { + stateIcon.setImageResource(R.drawable.ic_edit) + userIcon.loadAvatar(model.actor?.avatarUrl, model.actor?.url) + text.text = SpannableBuilder.builder() + .bold(model.actor?.login) + .space() + .append("renamed this from ") + .bold(model.previousTitle) + .append(" to ") + .bold(model.currentTitle) + .space() + .append(model.createdAt?.timeAgo()) + } + } + + private fun presentMilestoneDemilestone(model: MilestoneDemilestonedEventModel) { + itemView.apply { + stateIcon.setImageResource(R.drawable.ic_milestone) + userIcon.loadAvatar(model.actor?.avatarUrl, model.actor?.url) + text.text = SpannableBuilder.builder() + .bold(model.actor?.login) + .space() + .append(if (model.isMilestone == true) "added this to the milestone " else "demilestoned this from ") + .bold(model.milestoneTitle) + .space() + .append(model.createdAt?.timeAgo()) + } + } + + private fun presentAssignedAndUnassigned(model: AssignedUnAssignedEventModel) { + itemView.apply { + stateIcon.setImageResource(R.drawable.ic_profile) + userIcon.loadAvatar(model.actor?.avatarUrl, model.actor?.url) + text.text = SpannableBuilder.builder() + .bold(model.actor?.login) + .space() + .append(if (model.isAssigned == true) "assigned " else "unassigned ") + .apply { + model.users.forEachIndexed { index, shortUserModel -> + bold(shortUserModel.login).append(when { + index == model.users.size - 2 -> " and " + index != model.users.size - 1 -> ", " + else -> " " + }) + } + } + .append(model.createdAt?.timeAgo()) + } + } + + private fun presentSubscribeUnsubscribed(model: SubscribedUnsubscribedEventModel) { + itemView.apply { + stateIcon.setImageResource(if (model.isSubscribe == true) R.drawable.ic_subscribe else R.drawable.ic_unsubscribe) + userIcon.loadAvatar(model.actor?.avatarUrl, model.actor?.url) + text.text = SpannableBuilder.builder() + .bold(model.actor?.login) + .space() + .append(if (model.isSubscribe == true) "subscribed to this " else "unsubscribed from this ") + .append(model.createdAt?.timeAgo()) + } + } + + private fun presentLabels(model: LabelUnlabeledEventModel) { + itemView.apply { + stateIcon.setImageResource(R.drawable.ic_label) + userIcon.loadAvatar(model.actor?.avatarUrl, model.actor?.url) + val builder = SpannableBuilder.builder() + .apply { + bold(SpannableBuilder.builder().append(model.actor?.login ?: "", LabelSpan(Color.TRANSPARENT))) + space() + append(if (model.isLabel == true) "added " else "unlabeled ", LabelSpan(Color.TRANSPARENT)) + model.labels.forEach { + append(it.name ?: "", LabelSpan(kotlin.runCatching { Color.parseColor("#${it.color}") }.getOrDefault(Color.BLUE))) + .space() + } + append("${model.createdAt?.timeAgo()}", LabelSpan(Color.TRANSPARENT)) + } + text.text = builder + } + } + + private fun presentLockUnlock(model: LockUnlockEventModel) { + itemView.apply { + stateIcon.setImageResource(if (model.isLock == true) R.drawable.ic_lock else R.drawable.ic_unlock) + userIcon.loadAvatar(model.actor?.avatarUrl, model.actor?.url) + val builder = SpannableBuilder.builder() + .bold(model.actor?.login) + .space() + if (model.isLock == true) { + builder.append("locked ") + .bold(if (model.lockReason != null) "as ${model.lockReason?.replace("_", "")?.toLowerCase()} " else "") + .append("and limited conversation to collaborators ") + } else { + builder.append("unlocked this conversation ") + } + text.text = builder.append(model.createdAt?.timeAgo()) + } + } + + private fun presentClosedReopen(model: CloseOpenEventModel) { + itemView.apply { + stateIcon.setImageResource(if (model.isClosed == true) R.drawable.ic_issue_closed else R.drawable.ic_issue_opened) + userIcon.loadAvatar(model.actor?.avatarUrl, model.actor?.url) + val builder = SpannableBuilder.builder() + .bold(model.actor?.login) + .space() + if (model.isClosed == true) { + builder + .append("closed this ") + .clickable(when { + model.commit != null -> "in commit (${model.commit?.abbreviatedOid}) " + model.pullRequest != null -> "in pull request (#${model.pullRequest?.number}) " + else -> "" + }) + .append("${model.createdAt?.timeAgo()}") + } else { + builder.append("reopened this ${model.createdAt?.timeAgo()}") + } + text.text = builder + } + } + + private fun presentCrossReference(model: CrossReferencedEventModel) { + itemView.apply { + stateIcon.setImageResource(R.drawable.ic_format_quote) + userIcon.loadAvatar(model.actor?.avatarUrl, model.actor?.url) + text.text = SpannableBuilder.builder() + .bold(model.actor?.login) + .space() + .append("${if (model.isCrossRepository == true) "cross" else ""} referenced this in ") + .clickable(when { + model.issue != null -> "issue (#${model.issue?.number}) " + model.pullRequest != null -> "pull request (#${model.pullRequest?.number}) " + else -> "" + }) + .append("${model.referencedAt?.timeAgo()}") + } + } + + private fun presentCommit(model: CommitModel) { + itemView.apply { + stateIcon.setImageResource(R.drawable.ic_push) + userIcon.loadAvatar(model.author?.avatarUrl, model.author?.url) + text.text = SpannableBuilder.builder() + .append(model.author?.name) + .space() + .append("referenced this in ") + .clickable("commit ${model.abbreviatedOid} ") + .append(model.authoredDate?.timeAgo()) + } + } + + private fun presentReference(model: ReferencedEventModel) { + itemView.apply { + stateIcon.setImageResource(R.drawable.ic_format_quote) + userIcon.loadAvatar(model.actor?.avatarUrl, model.actor?.url) + text.text = SpannableBuilder.builder() + .bold(model.actor?.login) + .space() + .append("added a commit ") + .clickable("(${model.commit?.abbreviatedOid})") + .append(" that referenced this issue ${model.createdAt?.timeAgo()}") + .newline() + .append(model.commit?.message) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LabelColorViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LabelColorViewHolder.kt new file mode 100644 index 000000000..e2dde9567 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LabelColorViewHolder.kt @@ -0,0 +1,23 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.content.res.ColorStateList +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import kotlinx.android.synthetic.main.label_color_row_item.view.* + +/** + * Created by Kosh on 12.10.18. + */ +class LabelColorViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.label_color_row_item, parent, false)) { + + override fun bind(item: String) { + itemView.apply { + colorChip.text = item + colorChip.chipBackgroundColor = ColorStateList.valueOf(Color.parseColor(item)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LabelViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LabelViewHolder.kt new file mode 100644 index 000000000..4a67f3535 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LabelViewHolder.kt @@ -0,0 +1,24 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.model.parcelable.LabelModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import kotlinx.android.synthetic.main.label_row_item.view.* + +/** + * Created by Kosh on 04.11.18. + */ +class LabelViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.label_row_item, parent, false)) { + override fun bind(item: LabelModel) = Unit + + fun bind(item: LabelModel, isSelected: Boolean) { + itemView.apply { + backgroundLayout.isVisible = isSelected + label.text = item.name + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LanguagesViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LanguagesViewHolder.kt new file mode 100644 index 000000000..ccb2b9e9f --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LanguagesViewHolder.kt @@ -0,0 +1,33 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import com.fastaccess.data.model.LanguageColorsModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.LanguagesAdapter +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.extensions.getColorAttr +import kotlinx.android.synthetic.main.language_row_item.view.* + +/** + * Created by Kosh on 2018-11-17. + */ +class LanguagesViewHolder( + private val languagesAdapter: LanguagesAdapter, + parent: ViewGroup +) : BaseViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.language_row_item, parent, false)) { + + override fun bind(item: LanguageColorsModel) { + itemView.apply { + languageChip.text = item.name + languageChip.isChecked = languagesAdapter.checkedLanguage == item.name + languageChip.checkedIcon?.mutate()?.setTint(if (item.color.isNullOrEmpty()) { + context.getColorAttr(R.attr.colorAccent) + } else { + kotlin.runCatching { Color.parseColor(item.color) }.getOrDefault(context.getColorAttr(R.attr.colorAccent)) + }) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LoadingViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LoadingViewHolder.kt new file mode 100644 index 000000000..a019a4313 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LoadingViewHolder.kt @@ -0,0 +1,14 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder + +/** + * Created by Kosh on 12.10.18. + */ +class LoadingViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.progress_layout, parent, false)) { + override fun bind(item: A) = Unit +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LoggedInUserViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LoggedInUserViewHolder.kt new file mode 100644 index 000000000..c01315284 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/LoggedInUserViewHolder.kt @@ -0,0 +1,26 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.persistence.models.LoginModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import kotlinx.android.synthetic.main.profile_follower_following_row_item.view.* + +/** + * Created by Kosh on 12.10.18. + */ + +class LoggedInUserViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.profile_follower_following_row_item, parent, false)) { + + override fun bind(item: LoginModel) { + itemView.apply { + title.text = if (item.name.isNullOrEmpty()) item.login else item.name + description.isVisible = !item.bio.isNullOrEmpty() + description.text = item.bio + userIcon.loadAvatar(item.avatarUrl, null) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/MilestoneViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/MilestoneViewHolder.kt new file mode 100644 index 000000000..2877098b0 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/MilestoneViewHolder.kt @@ -0,0 +1,25 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import com.fastaccess.data.model.parcelable.MilestoneModel +import com.fastaccess.github.R +import com.fastaccess.github.extensions.DatePrettifier +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import kotlinx.android.synthetic.main.milestone_row_item.view.* + +/** + * Created by Kosh on 04.11.18. + */ +class MilestoneViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.milestone_row_item, parent, false)) { + + override fun bind(item: MilestoneModel) { + itemView.apply { + title.text = item.title ?: "${item.number ?: "N/A"}" + dueOn.text = item.dueOn?.let { + DatePrettifier.prettifyDate(it.time) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/MyIssuesPrsViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/MyIssuesPrsViewHolder.kt new file mode 100644 index 000000000..1d0c1d43e --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/MyIssuesPrsViewHolder.kt @@ -0,0 +1,47 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.persistence.models.MyIssuesPullsModel +import com.fastaccess.github.R +import com.fastaccess.github.extensions.getColorCompat +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import github.type.PullRequestState +import kotlinx.android.synthetic.main.issues_prs_main_screen_row_item.view.* + +class MyIssuesPrsViewHolder(viewGroup: ViewGroup) : BaseViewHolder( + LayoutInflater.from(viewGroup.context) + .inflate(R.layout.issues_prs_main_screen_row_item, viewGroup, false) +) { + + @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") + @SuppressLint("SetTextI18n") + override fun bind(model: MyIssuesPullsModel?) { + itemView.let { + val item = model ?: run { + itemView.isVisible = false + return + } + it.issueTitle.text = "${item.title}#${item.number}" + it.issueDescription.apply { + text = item.repoName ?: "" + isVisible = !item.repoName.isNullOrBlank() + } + it.commentCountBox.isVisible = item.commentCounts != 0 + it.commentCount.text = "${if (item.commentCounts ?: 0 > 99) "99" else item.commentCounts}" + if (!item.state.isNullOrEmpty()) { + it.stateIcon.isVisible = true + it.stateIcon.setImageResource( + when { + PullRequestState.OPEN.name == item.state -> R.drawable.circle_shape_green_small + PullRequestState.CLOSED.name == item.state -> R.drawable.circle_shape_red_small + PullRequestState.MERGED.name == item.state -> R.drawable.circle_shape_blue_small + else -> it.context.getColorCompat(R.color.material_green_700) + } + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/NotificationsViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/NotificationsViewHolder.kt new file mode 100644 index 000000000..e63b2e510 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/NotificationsViewHolder.kt @@ -0,0 +1,58 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.graphics.Color +import android.graphics.drawable.Drawable +import android.view.LayoutInflater +import android.view.ViewGroup +import com.fastaccess.data.persistence.models.NotificationModel +import com.fastaccess.github.R +import com.fastaccess.github.extensions.getColorCompat +import com.fastaccess.github.extensions.getDrawableCompat +import com.fastaccess.github.extensions.timeAgo +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.ui.widget.recyclerview.SwipeToDeleteCallback +import kotlinx.android.synthetic.main.notification_main_screen_row_item.view.* + +/** + * Created by Kosh on 12.10.18. + */ + +class NotificationsViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.notification_main_screen_row_item, parent, false)), SwipeToDeleteCallback.AllowSwipeToDeleteDelegate { + + private var item: NotificationModel? = null + + override val drawableStart: Drawable? = null + override val drawableStartBackground: Int = 0 + + override val drawableEnd: Drawable? + get() { + if (item?.unread == true) { + return itemView.context.getDrawableCompat(R.drawable.ic_done)?.apply { + setTint(Color.WHITE) + } + } + return null + } + + override val drawableEndBackground: Int = itemView.context.getColorCompat(R.color.material_green_700) + + override fun bind(item: NotificationModel) { + this.item = item + itemView.apply { + item.subject?.let { subject -> + notificationTitle.text = subject.title ?: "" + subject.type?.let { type -> + when (type) { + "PullRequest" -> typeIcon.setImageResource(R.drawable.ic_pull_requests) + "Issue" -> typeIcon.setImageResource(R.drawable.ic_issues) + "Commit" -> typeIcon.setImageResource(R.drawable.ic_branch) + else -> typeIcon.setImageResource(R.drawable.ic_issues) + } + } + } + repoName.text = item.repository?.fullName ?: "" + dateWithIcon.text = item.updatedAt?.timeAgo() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/OrganizationViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/OrganizationViewHolder.kt new file mode 100644 index 000000000..872ebceca --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/OrganizationViewHolder.kt @@ -0,0 +1,28 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import com.fastaccess.data.persistence.models.OrganizationModel +import com.fastaccess.github.R +import com.fastaccess.github.extensions.formatNumber +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import kotlinx.android.synthetic.main.organization_row_item.view.* + +/** + * Created by Kosh on 12.10.18. + */ + +class OrganizationViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.organization_row_item, parent, false)) { + + override fun bind(item: OrganizationModel) { + itemView.apply { + title.text = if (item.name.isNullOrEmpty()) item.login else item.name + avatar.loadAvatar(item.avatarUrl, item.url) + teams.text = item.teams?.totalCount?.formatNumber() ?: "0" + members.text = item.members?.totalCount?.formatNumber() ?: "0" + projects.text = item.projects?.totalCount?.formatNumber() ?: "0" + repos.text = item.repositories?.totalCount?.formatNumber() ?: "0" + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileFollowerFollowingViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileFollowerFollowingViewHolder.kt new file mode 100644 index 000000000..939cbfd93 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileFollowerFollowingViewHolder.kt @@ -0,0 +1,26 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.persistence.models.FollowingFollowerModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import kotlinx.android.synthetic.main.profile_follower_following_row_item.view.* + +/** + * Created by Kosh on 12.10.18. + */ + +class ProfileFollowerFollowingViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.profile_follower_following_row_item, parent, false)) { + + override fun bind(item: FollowingFollowerModel) { + itemView.apply { + title.text = if (item.name.isNullOrEmpty()) item.login else item.name + description.isVisible = !item.bio.isNullOrEmpty() + description.text = item.bio + userIcon.loadAvatar(item.avatarUrl, item.url) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileGistsViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileGistsViewHolder.kt new file mode 100644 index 000000000..3b8a7ef46 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileGistsViewHolder.kt @@ -0,0 +1,32 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import com.fastaccess.data.persistence.models.ProfileGistModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.extensions.formatNumber +import kotlinx.android.synthetic.main.profile_gist_repo_row_item.view.* + +/** + * Created by Kosh on 12.10.18. + */ + +class ProfileGistsViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.profile_gist_repo_row_item, parent, false)) { + + override fun bind(item: ProfileGistModel) { + itemView.apply { + title.text = if (item.description.isNullOrEmpty()) context.getString(R.string.no_data) else item.description + starCount.text = item.stargazers?.totalCount?.formatNumber() ?: "0" + commentCount.text = item.comments?.totalCount?.formatNumber() ?: "0" + if (item.isPublic == true) { + isPublic.text = context.getString(R.string.public_label) + isPublic.setChipIconResource(R.drawable.ic_brower) + } else { + isPublic.text = context.getString(R.string.private_label) + isPublic.setChipIconResource(R.drawable.ic_incognito) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileOrgsViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileOrgsViewHolder.kt new file mode 100644 index 000000000..e405880f2 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfileOrgsViewHolder.kt @@ -0,0 +1,20 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import com.fastaccess.data.persistence.models.UserOrganizationNodesModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import kotlinx.android.synthetic.main.icon_row_item.view.* + +/** + * Created by Kosh on 2018-11-17. + */ +class ProfileOrgsViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.icon_row_item, parent, false)) { + + override fun bind(item: UserOrganizationNodesModel) { + itemView.imageIcon.loadAvatar(item.avatarUrl, null) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt new file mode 100644 index 000000000..41aad084f --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt @@ -0,0 +1,35 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.content.res.ColorStateList +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.persistence.models.UserPinnedRepoNodesModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.github.extensions.formatNumber +import kotlinx.android.synthetic.main.profile_pinned_repo_row_item.view.* + +/** + * Created by Kosh on 2018-11-17. + */ +class ProfilePinnedReposViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.profile_pinned_repo_row_item, parent, false)) { + + override fun bind(item: UserPinnedRepoNodesModel) { + itemView.apply { + title.text = item.name + star.text = item.stargazers?.totalCount?.formatNumber() ?: "0" + forks.text = item.forkCount?.formatNumber() ?: "0" + issues.text = item.issues?.totalCount?.formatNumber() ?: "0" + pulls.text = item.pullRequests?.totalCount?.formatNumber() ?: "0" + language.isVisible = !item.primaryLanguage?.name.isNullOrEmpty() + language.text = item.primaryLanguage?.name ?: "" + if (!item.primaryLanguage?.color.isNullOrBlank()) { + language.chipIconTint = ColorStateList.valueOf(Color.parseColor(item.primaryLanguage?.color)) ?: null + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ReposProfileViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ReposProfileViewHolder.kt new file mode 100644 index 000000000..8c3b79ac6 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ReposProfileViewHolder.kt @@ -0,0 +1,48 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.content.res.ColorStateList +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.persistence.models.ProfileRepoModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.markdown.widget.SpannableBuilder +import com.fastaccess.markdown.spans.LabelSpan +import com.fastaccess.github.extensions.formatNumber +import com.fastaccess.github.extensions.getColorCompat +import kotlinx.android.synthetic.main.profile_pinned_repo_row_item.view.* + +/** + * Created by Kosh on 12.10.18. + */ + +class ReposProfileViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.profile_pinned_repo_row_item, parent, false)) { + + override fun bind(item: ProfileRepoModel) { + itemView.apply { + title.text = when { + item.isPrivate == true -> SpannableBuilder.builder() + .append(" ${context.getString(R.string.private_repo)} ", LabelSpan(context.getColorCompat(R.color.material_grey_700))) + .space() + .append(item.name ?: "", LabelSpan(Color.TRANSPARENT)) + item.isFork == true -> SpannableBuilder.builder() + .append(" ${context.getString(R.string.forked)} ", LabelSpan(context.getColorCompat(R.color.material_indigo_700))) + .space() + .append(item.name ?: "", LabelSpan(Color.TRANSPARENT)) + else -> item.name + } + star.text = item.stargazers?.totalCount?.formatNumber() ?: "0" + forks.text = item.forkCount?.formatNumber() ?: "0" + issues.text = item.issues?.totalCount?.formatNumber() ?: "0" + pulls.text = item.pullRequests?.totalCount?.formatNumber() ?: "0" + language.isVisible = !item.primaryLanguage?.name.isNullOrEmpty() + language.text = item.primaryLanguage?.name ?: "" + if (!item.primaryLanguage?.color.isNullOrBlank()) { + language.chipIconTint = ColorStateList.valueOf(Color.parseColor(item.primaryLanguage?.color)) ?: null + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ReposStarredProfileViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ReposStarredProfileViewHolder.kt new file mode 100644 index 000000000..9fb263eaa --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ReposStarredProfileViewHolder.kt @@ -0,0 +1,48 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.content.res.ColorStateList +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.persistence.models.ProfileStarredRepoModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.markdown.widget.SpannableBuilder +import com.fastaccess.markdown.spans.LabelSpan +import com.fastaccess.github.extensions.formatNumber +import com.fastaccess.github.extensions.getColorCompat +import kotlinx.android.synthetic.main.profile_pinned_repo_row_item.view.* + +/** + * Created by Kosh on 12.10.18. + */ + +class ReposStarredProfileViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.profile_pinned_repo_row_item, parent, false)) { + + override fun bind(item: ProfileStarredRepoModel) { + itemView.apply { + title.text = when { + item.isPrivate == true -> SpannableBuilder.builder() + .append(" ${context.getString(R.string.private_repo)} ", LabelSpan(context.getColorCompat(R.color.material_grey_700))) + .space() + .append(item.nameWithOwner ?: "", LabelSpan(Color.TRANSPARENT)) + item.isFork == true -> SpannableBuilder.builder() + .append(" ${context.getString(R.string.forked)} ", LabelSpan(context.getColorCompat(R.color.material_indigo_700))) + .space() + .append(item.nameWithOwner ?: "", LabelSpan(Color.TRANSPARENT)) + else -> item.nameWithOwner + } + star.text = item.stargazers?.totalCount?.formatNumber() ?: "0" + forks.text = item.forkCount?.formatNumber() ?: "0" + issues.text = item.issues?.totalCount?.formatNumber() ?: "0" + pulls.text = item.pullRequests?.totalCount?.formatNumber() ?: "0" + language.isVisible = !item.primaryLanguage?.name.isNullOrEmpty() + language.text = item.primaryLanguage?.name ?: "" + if (!item.primaryLanguage?.color.isNullOrBlank()) { + language.chipIconTint = ColorStateList.valueOf(Color.parseColor(item.primaryLanguage?.color)) ?: null + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ShortRepoViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ShortRepoViewHolder.kt new file mode 100644 index 000000000..04e0a499b --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ShortRepoViewHolder.kt @@ -0,0 +1,43 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.model.ShortRepoModel +import com.fastaccess.github.R +import com.fastaccess.github.extensions.formatNumber +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import com.fastaccess.markdown.widget.SpannableBuilder +import com.fastaccess.markdown.spans.LabelSpan +import com.fastaccess.github.extensions.getColorCompat +import kotlinx.android.synthetic.main.profile_pinned_repo_row_item.view.* + +/** + * Created by Kosh on 12.10.18. + */ + +class ShortRepoViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.profile_pinned_repo_row_item, parent, false)) { + + override fun bind(item: ShortRepoModel) { + itemView.apply { + title.text = when { + item.isPrivate == true -> SpannableBuilder.builder() + .append(" ${context.getString(R.string.private_repo)} ", LabelSpan(context.getColorCompat(R.color.material_grey_700))) + .space() + .append(item.name ?: "", LabelSpan(Color.TRANSPARENT)) + item.isFork == true -> SpannableBuilder.builder() + .append(" ${context.getString(R.string.forked)} ", LabelSpan(context.getColorCompat(R.color.material_indigo_700))) + .space() + .append(item.name ?: "", LabelSpan(Color.TRANSPARENT)) + else -> item.name + } + star.text = item.stargazers?.totalCount?.formatNumber() ?: "0" + forks.text = item.forkCount?.formatNumber() ?: "0" + issues.text = item.issues?.totalCount?.formatNumber() ?: "0" + pulls.text = item.pullRequests?.totalCount?.formatNumber() ?: "0" + language.isVisible = false + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ShortUserViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ShortUserViewHolder.kt new file mode 100644 index 000000000..06dcd9945 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/ShortUserViewHolder.kt @@ -0,0 +1,26 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.model.ShortUserModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import kotlinx.android.synthetic.main.profile_follower_following_row_item.view.* + +/** + * Created by Kosh on 12.10.18. + */ + +class ShortUserViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.profile_follower_following_row_item, parent, false)) { + + override fun bind(item: ShortUserModel) { + itemView.apply { + title.text = if (item.name.isNullOrEmpty()) item.login else item.name + description.isVisible = !item.bio.isNullOrEmpty() + description.text = item.bio + userIcon.loadAvatar(item.avatarUrl, item.url) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/TitleSectionViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/TitleSectionViewHolder.kt new file mode 100644 index 000000000..c69c4febe --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/TitleSectionViewHolder.kt @@ -0,0 +1,18 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import kotlinx.android.synthetic.main.title_section_row_item.view.* + +/** + * Created by Kosh on 04.11.18. + */ +class TitleSectionViewHolder(parent: ViewGroup) : BaseViewHolder( + LayoutInflater.from(parent.context).inflate(R.layout.title_section_row_item, parent, false) +) { + override fun bind(item: CharSequence) { + itemView.title.text = item + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/TrendingViewHolder.kt b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/TrendingViewHolder.kt new file mode 100644 index 000000000..f2293132b --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/adapter/viewholder/TrendingViewHolder.kt @@ -0,0 +1,31 @@ +package com.fastaccess.github.ui.adapter.viewholder + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.fastaccess.data.model.TrendingModel +import com.fastaccess.github.R +import com.fastaccess.github.ui.adapter.base.BaseViewHolder +import kotlinx.android.synthetic.main.trending_row_item.view.* + +/** + * Created by Kosh on 2018-11-17. + */ +class TrendingViewHolder(parent: ViewGroup) : BaseViewHolder(LayoutInflater.from(parent.context) + .inflate(R.layout.trending_row_item, parent, false)) { + + override fun bind(item: TrendingModel) { + itemView.apply { + title.text = item.title + description.isVisible = !item.description.isNullOrEmpty() + description.text = item.description + star.text = item.stars + forks.text = item.forks + todayStars.isVisible = !item.todayStars.isNullOrEmpty() + todayStars.text = item.todayStars + language.isVisible = !item.language.isNullOrEmpty() + language.text = item.language + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/auth/LoginChooserActivity.kt b/app/src/main/java/com/fastaccess/github/ui/modules/auth/LoginChooserActivity.kt new file mode 100644 index 000000000..3a42d03b5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/auth/LoginChooserActivity.kt @@ -0,0 +1,137 @@ +package com.fastaccess.github.ui.modules.auth + +import android.app.Activity +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.view.View +import androidx.browser.customtabs.CustomTabsIntent +import androidx.core.view.ViewCompat +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.persistence.models.LoginModel +import com.fastaccess.github.BuildConfig +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseActivity +import com.fastaccess.github.extensions.getColorAttr +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.ui.modules.auth.callback.LoginChooserCallback +import com.fastaccess.github.ui.modules.auth.chooser.LoginChooserFragment +import com.fastaccess.github.ui.modules.auth.login.AuthLoginFragment +import com.fastaccess.github.ui.modules.main.MainActivity +import com.fastaccess.github.utils.REDIRECT_URL +import com.fastaccess.github.utils.extensions.* +import javax.inject.Inject + +/** + * Created by Kosh on 18.05.18. + */ +class LoginChooserActivity : BaseActivity(), LoginChooserCallback { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(LoginChooserViewModel::class.java) } + + override fun layoutRes(): Int = R.layout.login_chooser_activity_layout + + override fun onCreate(savedInstanceState: Bundle?) { + setTheme(R.style.LoginTheme) + super.onCreate(savedInstanceState) + if (savedInstanceState == null) { + supportFragmentManager.beginTransaction() + .replace(R.id.container, LoginChooserFragment(), LoginChooserFragment.TAG) + .commit() + } + } + + override fun navToBasicAuth(view: View) { + supportFragmentManager.beginTransaction() + .addSharedElement(view, ViewCompat.getTransitionName(view) ?: "") + .replace(R.id.container, AuthLoginFragment.newInstance(), AuthLoginFragment.TAG) + .addToBackStack(AuthLoginFragment.TAG) + .commit() + } + + override fun navToAccessToken(view: View) { + supportFragmentManager.beginTransaction() + .addSharedElement(view, ViewCompat.getTransitionName(view) ?: "") + .replace(R.id.container, AuthLoginFragment.newInstance(accessToken = true), AuthLoginFragment.TAG) + .addToBackStack(AuthLoginFragment.TAG) + .commit() + } + + override fun navToEnterprise(view: View) { + supportFragmentManager.beginTransaction() + .addSharedElement(view, ViewCompat.getTransitionName(view) ?: "") + .replace(R.id.container, AuthLoginFragment.newInstance(isEnterprise = true), AuthLoginFragment.TAG) + .addToBackStack(AuthLoginFragment.TAG) + .commit() + } + + override fun loginWithBrowser() { + val tabIntent = CustomTabsIntent.Builder() + .setToolbarColor(getColorAttr(R.attr.colorPrimary)) + .enableUrlBarHiding() + .build() + + tabIntent.launchUrl(this, Uri.Builder() + .scheme("https") + .authority("github.com") + .appendPath("login") + .appendPath("oauth") + .appendPath("authorize") + .appendQueryParameter("client_id", BuildConfig.GITHUB_CLIENT_ID) + .appendQueryParameter("redirect_uri", REDIRECT_URL) + .appendQueryParameter("scope", "user,repo,gist,notifications,read:org") + .appendQueryParameter("state", BuildConfig.APPLICATION_ID) + .build()) + } + + override fun popStack() = supportFragmentManager.popBackStack() + + override fun onActivityCreatedWithUser(savedInstanceState: Bundle?) {} + + override fun onNewIntent(intent: Intent?) { + super.onNewIntent(intent) + handleIntent(intent) + setIntent(null) + } + + override fun onResume() { + super.onResume() + handleIntent(intent) + intent = null + } + + override fun onUserLoggedIn(login: LoginModel) { + if (BuildConfig.DEBUG) preference.theme = 1 + if (login.isEnterprise == true) { + preference.enterpriseOtpCode = login.otpCode + preference.enterpriseToken = login.token + preference.enterpriseUrl = login.enterpriseUrl + } else { + preference.token = login.token + preference.otpCode = login.otpCode + } + startActivity(Intent(this, MainActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + }) + finishAffinity() + } + + private fun handleIntent(intent: Intent?) { + if (!viewModel.loggedInUser.hasActiveObservers()) { + viewModel.loggedInUser.observeNotNull(this) { onUserLoggedIn(it) } + } + intent?.data?.let { viewModel.handleBrowserLogin(it) } + } + + companion object { + fun startActivity(activity: Activity, finish: Boolean = true) { + val intent = Intent(activity, LoginChooserActivity::class.java) + intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK + activity.startActivity(intent) + if (finish) activity.finishAffinity() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/auth/LoginChooserViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/auth/LoginChooserViewModel.kt new file mode 100644 index 000000000..303019d02 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/auth/LoginChooserViewModel.kt @@ -0,0 +1,70 @@ +package com.fastaccess.github.ui.modules.auth + +import android.net.Uri +import androidx.lifecycle.MutableLiveData +import com.fastaccess.data.persistence.db.FastHubDatabase +import com.fastaccess.data.persistence.models.LoginModel +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.di.modules.AuthenticationInterceptor +import com.fastaccess.github.usecase.auth.GetAccessTokenUseCase +import com.fastaccess.github.usecase.auth.LoginWithAccessTokenUseCase +import com.fastaccess.github.utils.REDIRECT_URL +import io.reactivex.Completable +import javax.inject.Inject + +/** + * Created by Kosh on 2018-11-23. + */ +class LoginChooserViewModel @Inject constructor( + private val accessTokenUseCase: GetAccessTokenUseCase, + private val loginWithAccessTokenUseCase: LoginWithAccessTokenUseCase, + private val interceptor: AuthenticationInterceptor, + private val loginRepositoryProvider: LoginRepositoryProvider, + private val fastHubDatabase: FastHubDatabase +) : BaseViewModel() { + + val loggedInUser = MutableLiveData() + val loggedInUsers = MutableLiveData>() + + init { + justSubscribe(loginRepositoryProvider.getAll() + .doOnSuccess { + loggedInUsers.postValue(ArrayList(it)) + } + .toObservable()) + } + + fun handleBrowserLogin(uri: Uri) { + if (uri.toString().startsWith(REDIRECT_URL)) { + val token = uri.getQueryParameter("code") + token?.let { code -> + accessTokenUseCase.code = code + add(callApi(accessTokenUseCase.buildObservable() + .flatMap { accessTokenResponse -> + interceptor.token = accessTokenResponse.token ?: accessTokenResponse.accessToken ?: "" + return@flatMap loginWithAccessTokenUseCase.buildObservable() + .flatMap { + it.token = interceptor.token + it.isLoggedIn = true + loginWithAccessTokenUseCase.insertUser(it) + } + }) + .subscribe({ loggedInUser.postValue(it) }, { it.printStackTrace() })) + } + } + } + + override fun onCleared() { + super.onCleared() + accessTokenUseCase.dispose() + loginWithAccessTokenUseCase.dispose() + } + + fun reLogin(user: LoginModel): Completable = user.let { me -> + loginRepositoryProvider.logoutAll() // logout everyone in case of adding account + fastHubDatabase.clearAll() // clear everything in db and start fresh! + me.isLoggedIn = true + return@let loginRepositoryProvider.update(me) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/auth/callback/LoginChooserCallback.kt b/app/src/main/java/com/fastaccess/github/ui/modules/auth/callback/LoginChooserCallback.kt new file mode 100644 index 000000000..c45650c63 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/auth/callback/LoginChooserCallback.kt @@ -0,0 +1,17 @@ +package com.fastaccess.github.ui.modules.auth.callback + +import android.view.View +import com.fastaccess.data.persistence.models.LoginModel + +/** + * Created by Kosh on 19.05.18. + */ + +interface LoginChooserCallback { + fun navToBasicAuth(view: View) + fun navToAccessToken(view: View) + fun navToEnterprise(view: View) + fun popStack() + fun onUserLoggedIn(login: LoginModel) + fun loginWithBrowser() +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/auth/chooser/LoginChooserFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/auth/chooser/LoginChooserFragment.kt new file mode 100644 index 000000000..5da49a68f --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/auth/chooser/LoginChooserFragment.kt @@ -0,0 +1,82 @@ +package com.fastaccess.github.ui.modules.auth.chooser + +import android.content.Context +import android.os.Bundle +import android.view.View +import androidx.core.view.isVisible +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.extension.uiThread +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.ui.adapter.LoggedInUsersAdapter +import com.fastaccess.github.ui.modules.auth.LoginChooserViewModel +import com.fastaccess.github.ui.modules.auth.callback.LoginChooserCallback +import com.fastaccess.github.utils.extensions.beginDelayedTransition +import kotlinx.android.synthetic.main.login_chooser_fragment_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 19.05.18. + */ +class LoginChooserFragment : BaseFragment() { + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + + private val viewModel by lazy { ViewModelProviders.of(requireActivity(), viewModelFactory).get(LoginChooserViewModel::class.java) } + private var callback: LoginChooserCallback? = null + private val adapter by lazy { + LoggedInUsersAdapter { user -> + addDisposal(viewModel.reLogin(user) + .uiThread() + .subscribe({ (requireActivity() as? LoginChooserCallback)?.onUserLoggedIn(user) }, + { throwable -> view?.let { showSnackBar(it, message = throwable.message) } })) + } + } + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = context as LoginChooserCallback + } + + override fun onDetach() { + callback = null + super.onDetach() + } + + override fun viewModel(): BaseViewModel? = null + override fun layoutRes() = R.layout.login_chooser_fragment_layout + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) {} + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + basicAuth.setOnClickListener { callback?.navToBasicAuth(loginCard) } + accessToken.setOnClickListener { callback?.navToAccessToken(loginCard) } + enterprise.setOnClickListener { callback?.navToEnterprise(loginCard) } + browserLogin.setOnClickListener { callback?.loginWithBrowser() } + + viewModel.progress.observeNotNull(this) { progress -> + this@LoginChooserFragment.view?.beginDelayedTransition() + buttonsLayout.isVisible = !progress + progressBar.isVisible = progress + } + + toggle.setOnClickListener { + parentLayout.beginDelayedTransition() + val isVisible = recycler.isVisible + recycler.isVisible = !isVisible + toggleImage.rotation = if (!isVisible) 180f else 0f + } + + viewModel.loggedInUsers.observeNotNull(this) { + if (it.isEmpty()) return@observeNotNull + multiAccLayout?.isVisible = true + adapter.submitList(it) + recycler.adapter = adapter + } + } + + companion object { + const val TAG = "LoginChooserFragment" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/auth/login/AuthLoginFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/auth/login/AuthLoginFragment.kt new file mode 100644 index 000000000..8c6db5180 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/auth/login/AuthLoginFragment.kt @@ -0,0 +1,149 @@ +package com.fastaccess.github.ui.modules.auth.login + +import android.content.Context +import android.os.Bundle +import android.view.Gravity +import android.view.View +import androidx.core.view.isVisible +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import androidx.transition.Slide +import com.fastaccess.data.model.FastHubErrors +import com.fastaccess.data.model.ValidationError.FieldType.* +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.ui.modules.auth.callback.LoginChooserCallback +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.EXTRA_TWO +import com.fastaccess.github.utils.extensions.asString +import com.fastaccess.github.utils.extensions.beginDelayedTransition +import com.fastaccess.github.utils.extensions.hideKeyboard +import kotlinx.android.synthetic.main.login_form_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 18.05.18. + */ +class AuthLoginFragment : BaseFragment() { + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private var callback: LoginChooserCallback? = null + + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(LoginViewModel::class.java) } + private val isAccessToken by lazy { arguments?.getBoolean(EXTRA) ?: false } + private val isEnterpriseBundle by lazy { arguments?.getBoolean(EXTRA_TWO) ?: false } + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = context as LoginChooserCallback + } + + override fun onDetach() { + callback = null + super.onDetach() + } + + override fun viewModel(): BaseViewModel? = null + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) = Unit + override fun layoutRes(): Int = R.layout.login_form_layout + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + isAccessToken.isTrue { + password.hint = getString(R.string.access_token) + } + isEnterpriseBundle.isTrue { + endpoint.isVisible = true + accessTokenCheckbox.isVisible = true + accessTokenCheckbox.setOnCheckedChangeListener { _, checked -> + password.hint = if (checked) { + getString(R.string.access_token) + } else { + getString(R.string.password) + } + } + } + + bottomBar.setNavigationOnClickListener { callback?.popStack() } + loginBtn.setOnClickListener { + it.isEnabled = false + if (progressBar.isVisible) return@setOnClickListener + viewModel.login(usernameEditText.asString(), + passwordEditText.asString(), + twoFactorEditText.asString(), + endpointEditText.asString(), + (isAccessToken || accessTokenCheckbox.isVisible && accessTokenCheckbox.isChecked)) + } + + passwordEditText.setOnEditorActionListener { v, _, _ -> + when { + twoFactor.isVisible -> twoFactor.requestFocus() + endpoint.isVisible -> endpoint.requestFocus() + else -> { + v.hideKeyboard() + loginBtn.callOnClick() + } + } + return@setOnEditorActionListener true + } + observeData() + } + + private fun observeData() { + viewModel.validationLiveData.observe(this, Observer { validationError -> + validationError?.let { + val requiredField = getString(R.string.required_field) + when (it.fieldType) { + USERNAME -> username.error = if (it.isValid) null else requiredField + PASSWORD -> password.error = if (it.isValid) null else requiredField + TWO_FACTOR -> twoFactor.error = if (it.isValid) null else requiredField + URL -> endpoint.error = if (it.isValid) null else requiredField + } + } + }) + + viewModel.progress.observe(this, Observer { isLoading -> + loginBtn.isEnabled = isLoading == false + view?.beginDelayedTransition() + loginForm.isVisible = isLoading == false + progressBar.isVisible = isLoading == true + }) + + viewModel.error.observe(this, Observer { errors -> + errors?.let { + if (it.errorType == FastHubErrors.ErrorType.TWO_FACTOR) { + twoFactor.isVisible = true + } + view?.let { view -> + showSnackBar(view, resId = it.resId, message = it.message) + } + } + }) + + viewModel.loggedInUser.observe(this, Observer { model -> + if (model != null) { + addDisposal(viewModel.clearDb() + .subscribe({ callback?.onUserLoggedIn(model) }, { throwable -> view?.let { showSnackBar(it, message = throwable.message) } })) + } else { + view?.let { showSnackBar(it, resId = R.string.failed_login) } + } + }) + } + + companion object { + const val TAG = "AuthLoginFragment" + fun newInstance(accessToken: Boolean = false, isEnterprise: Boolean = false): AuthLoginFragment = AuthLoginFragment() + .apply { + val enter = Slide(Gravity.END) + val exit = Slide(Gravity.START) + enterTransition = enter + exitTransition = exit + arguments = Bundle().apply { + putBoolean(EXTRA, accessToken) + putBoolean(EXTRA_TWO, isEnterprise) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/auth/login/LoginViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/auth/login/LoginViewModel.kt new file mode 100644 index 000000000..05f9b08df --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/auth/login/LoginViewModel.kt @@ -0,0 +1,108 @@ +package com.fastaccess.github.ui.modules.auth.login + +import androidx.lifecycle.MutableLiveData +import com.crashlytics.android.Crashlytics +import com.fastaccess.data.persistence.db.FastHubDatabase +import com.fastaccess.data.model.FastHubErrors +import com.fastaccess.data.persistence.models.LoginModel +import com.fastaccess.data.model.ValidationError +import com.fastaccess.extension.uiThread +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.di.modules.AuthenticationInterceptor +import com.fastaccess.github.usecase.auth.GetAccessTokenUseCase +import com.fastaccess.github.usecase.auth.LoginUseCase +import com.fastaccess.github.usecase.auth.LoginWithAccessTokenUseCase +import io.reactivex.Completable +import okhttp3.Credentials +import javax.inject.Inject + +/** + * Created by Kosh on 21.05.18. + */ +class LoginViewModel @Inject constructor( + private val loginUserCase: LoginUseCase, + private val accessTokenUseCase: GetAccessTokenUseCase, + private val loginWithAccessTokenUseCase: LoginWithAccessTokenUseCase, + private val interceptor: AuthenticationInterceptor, + private val fasthubDatabase: FastHubDatabase +) : BaseViewModel() { + + val validationLiveData = MutableLiveData() + val loggedInUser = MutableLiveData() + + fun login(userName: String? = null, + password: String? = null, + twoFactorCode: String? = null, + endPoint: String? = null, + isAccessToken: Boolean = true) { + validationLiveData.value = ValidationError(ValidationError.FieldType.TWO_FACTOR, !twoFactorCode.isNullOrBlank()) + validationLiveData.value = ValidationError(ValidationError.FieldType.URL, !endPoint.isNullOrBlank()) + validationLiveData.value = ValidationError(ValidationError.FieldType.PASSWORD, !password.isNullOrBlank()) + validationLiveData.value = ValidationError(ValidationError.FieldType.USERNAME, !userName.isNullOrBlank()) + if (userName == null || password == null) return // just to disable lint + if (!userName.isNullOrEmpty() && !password.isNullOrEmpty()) { + try { + val authToken = Credentials.basic(userName, password) + interceptor.otp = twoFactorCode + interceptor.token = authToken + if (!isAccessToken) { + loginBasic(twoFactorCode) + } else { + loginWithAccessToken(password) + } + } catch (e: Exception) { + error.postValue(FastHubErrors(FastHubErrors.ErrorType.OTHER, resId = R.string.failed_login)) + e.printStackTrace() + Crashlytics.logException(e) + } + } + } + + private fun loginWithAccessToken(password: String, + twoFactorCode: String? = null, + isEnterprise: Boolean? = false, + enterpriseUrl: String? = null) { + interceptor.token = password + loginWithAccessTokenUseCase.executeSafely(callApi(loginWithAccessTokenUseCase.buildObservable() + .flatMap { user -> + user.isLoggedIn = true + user.otpCode = twoFactorCode + user.token = password + user.isEnterprise = isEnterprise + user.enterpriseUrl = enterpriseUrl + return@flatMap loginWithAccessTokenUseCase.insertUser(user) + } + .doOnNext { loggedInUser.postValue(it) } + )) + } + + private fun loginBasic(twoFactorCode: String? = null, + isEnterprise: Boolean? = false, + enterpriseUrl: String? = null) { + loginUserCase.setAuthBody(twoFactorCode) + loginUserCase.executeSafely(callApi(loginUserCase.buildObservable() + .flatMap({ + interceptor.token = it.token ?: it.accessToken + return@flatMap loginWithAccessTokenUseCase.buildObservable() + }, { accessToken, user -> + user.isLoggedIn = true + user.otpCode = twoFactorCode + user.token = accessToken.token ?: accessToken.accessToken + user.isEnterprise = isEnterprise + user.enterpriseUrl = enterpriseUrl + return@flatMap user + }) + .flatMap { loginWithAccessTokenUseCase.insertUser(it) }) + .doOnNext { loggedInUser.postValue(it) }) + } + + override fun onCleared() { + loginUserCase.dispose() + accessTokenUseCase.dispose() + loginWithAccessTokenUseCase.dispose() + super.onCleared() + } + + fun clearDb() = Completable.fromCallable { fasthubDatabase.clearAll() }.uiThread() +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/editor/EditorWebViewActivity.kt b/app/src/main/java/com/fastaccess/github/ui/modules/editor/EditorWebViewActivity.kt new file mode 100644 index 000000000..8d3c16123 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/editor/EditorWebViewActivity.kt @@ -0,0 +1,24 @@ +package com.fastaccess.github.ui.modules.editor + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseActivity +import com.fastaccess.github.platform.deeplink.RawWebDeepLink + +/** + * Created by Kosh on 2019-04-11. + */ +@RawWebDeepLink("") +class EditorWebViewActivity : BaseActivity() { + override fun layoutRes(): Int = R.layout.code_editor_activity_layout + + override fun onActivityCreatedWithUser(savedInstanceState: Bundle?) {} + + companion object { + fun startActivity(context: Context) { + context.startActivity(Intent(context, EditorWebViewActivity::class.java)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/feed/fragment/FeedsFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/feed/fragment/FeedsFragment.kt new file mode 100644 index 000000000..8ac470f26 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/feed/fragment/FeedsFragment.kt @@ -0,0 +1,76 @@ +package com.fastaccess.github.ui.modules.feed.fragment + +import android.os.Bundle +import android.view.View +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.FragmentType +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.platform.extension.onClick +import com.fastaccess.github.ui.adapter.ProfileFeedsAdapter +import com.fastaccess.github.ui.adapter.base.CurrentState +import com.fastaccess.github.ui.modules.feed.fragment.viewmodel.FeedsViewModel +import com.fastaccess.github.utils.extensions.isConnected +import kotlinx.android.synthetic.main.appbar_center_title_layout.* +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 20.10.18. + */ +class FeedsFragment : BaseFragment() { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(FeedsViewModel::class.java) } + private val adapter by lazy { + ProfileFeedsAdapter { + it.onClick(this) + } + } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.toolbar_fragment_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + setupToolbar(R.string.feeds) + recyclerView.adapter = adapter + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView, appBar) + if (savedInstanceState == null) isConnected().isTrue { viewModel.loadFeeds(true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.loadFeeds(true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.loadFeeds() } } + listenToChanges() + } + + private fun listenToChanges() { + viewModel.progress.observeNotNull(this) { + adapter.currentState = if (it) CurrentState.LOADING else CurrentState.DONE + } + + viewModel.feeds().observeNotNull(this) { + adapter.currentState = CurrentState.DONE + adapter.submitList(it) + } + + viewModel.counter.observeNotNull(this) { + postCount(FragmentType.FEEDS, it) + } + } + + companion object { + fun newInstance() = FeedsFragment() + } +} + diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/feed/fragment/viewmodel/FeedsViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/feed/fragment/viewmodel/FeedsViewModel.kt new file mode 100644 index 000000000..c0bc00335 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/feed/fragment/viewmodel/FeedsViewModel.kt @@ -0,0 +1,48 @@ +package com.fastaccess.github.ui.modules.feed.fragment.viewmodel + +import androidx.lifecycle.LiveData +import androidx.paging.LivePagedListBuilder +import androidx.paging.PagedList +import com.fastaccess.data.persistence.models.FeedModel +import com.fastaccess.data.repository.FeedsRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.usecase.feed.FeedsUseCase +import javax.inject.Inject + +/** + * Created by Kosh on 20.10.18. + */ +class FeedsViewModel @Inject constructor( + private val provider: FeedsRepositoryProvider, + private val usecase: FeedsUseCase +) : BaseViewModel() { + + private var currentPage = 0 + private var isLastPage = false + + fun feeds(): LiveData> { + val dataSourceFactory = provider.getReceivedEventAsLiveData() + val config = PagedList.Config.Builder() + .setPrefetchDistance(com.fastaccess.github.utils.PRE_FETCH_SIZE) + .setPageSize(com.fastaccess.github.utils.PAGE_SIZE) + .build() + return LivePagedListBuilder(dataSourceFactory, config) + .build() + } + + fun loadFeeds(reload: Boolean = false) { + if (reload) { + currentPage = 0 + isLastPage = false + } + currentPage++ + if (!reload && isLastPage) return + usecase.page = currentPage + add(callApi(usecase.buildObservable()) + .subscribe({ + isLastPage = it.last == currentPage + }, ::println)) + } + + fun hasNext() = isLastPage +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issue/IssueActivity.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issue/IssueActivity.kt new file mode 100644 index 000000000..afa8f79e1 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issue/IssueActivity.kt @@ -0,0 +1,33 @@ +package com.fastaccess.github.ui.modules.issue + +import android.os.Bundle +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseActivity +import com.fastaccess.github.platform.deeplink.WebDeepLink +import com.fastaccess.github.ui.modules.issue.fragment.IssueFragment +import com.fastaccess.github.extensions.replace + +/** + * Created by Kosh on 28.01.19. + */ +@WebDeepLink("/{login}/{repo}/issues/{number}") +class IssueActivity : BaseActivity() { + + override fun layoutRes(): Int = R.layout.activity_main + override fun onActivityCreatedWithUser(savedInstanceState: Bundle?) { + if (savedInstanceState == null && intent != null) { + val login = intent?.extras?.getString("login") + val repo = intent?.extras?.getString("repo") + val number = intent?.extras?.getString("number")?.toIntOrNull() + if (login == null || repo == null || number == null) { + finish() + return + } + replace(R.id.container, IssueFragment.newInstance(login, repo, number), IssueFragment.TAG) + } + } + + override fun onBackPressed() { + super.onBackPressed() + } +} diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issue/fragment/IssueFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issue/fragment/IssueFragment.kt new file mode 100644 index 000000000..b90605fa7 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issue/fragment/IssueFragment.kt @@ -0,0 +1,292 @@ +package com.fastaccess.github.ui.modules.issue.fragment + +import android.graphics.Color +import android.os.Bundle +import android.view.View +import androidx.core.os.bundleOf +import androidx.core.view.isVisible +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import androidx.recyclerview.widget.SimpleItemAnimator +import com.fastaccess.data.model.ShortUserModel +import com.fastaccess.data.model.TimelineModel +import com.fastaccess.data.model.getEmoji +import com.fastaccess.data.model.parcelable.LabelModel +import com.fastaccess.data.model.parcelable.LoginRepoParcelableModel +import com.fastaccess.data.model.parcelable.MilestoneModel +import com.fastaccess.data.persistence.models.IssueModel +import com.fastaccess.data.persistence.models.LoginModel +import com.fastaccess.data.storage.FastHubSharedPreference +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.base.engine.ThemeEngine +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.extensions.shareUrl +import com.fastaccess.github.extensions.timeAgo +import com.fastaccess.github.ui.adapter.IssueTimelineAdapter +import com.fastaccess.github.ui.modules.issue.fragment.viewmodel.IssueTimelineViewModel +import com.fastaccess.github.ui.modules.issuesprs.edit.LockUnlockFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.assignees.AssigneesFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.labels.LabelsFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.milestone.MilestoneFragment +import com.fastaccess.github.ui.modules.multipurpose.MultiPurposeBottomSheetDialog +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.EXTRA_THREE +import com.fastaccess.github.utils.EXTRA_TWO +import com.fastaccess.github.utils.extensions.isConnected +import com.fastaccess.github.utils.extensions.popupEmoji +import com.fastaccess.github.utils.extensions.route +import com.fastaccess.github.utils.extensions.theme +import com.fastaccess.markdown.MarkdownProvider +import com.fastaccess.markdown.spans.LabelSpan +import com.fastaccess.markdown.widget.SpannableBuilder +import com.google.android.material.appbar.AppBarLayout +import github.type.LockReason +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.issue_header_row_item.* +import kotlinx.android.synthetic.main.issue_pr_fragment_layout.* +import net.nightwhistler.htmlspanner.HtmlSpanner +import timber.log.Timber +import javax.inject.Inject + +/** + * Created by Kosh on 28.01.19. + */ +class IssueFragment : BaseFragment(), LockUnlockFragment.OnLockReasonSelected, + LabelsFragment.OnLabelSelected, AssigneesFragment.OnAssigneesSelected, + MilestoneFragment.OnMilestoneChanged { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + @Inject lateinit var htmlSpanner: HtmlSpanner + @Inject lateinit var preference: FastHubSharedPreference + + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(IssueTimelineViewModel::class.java) } + private val login by lazy { arguments?.getString(EXTRA) ?: "" } + private val repo by lazy { arguments?.getString(EXTRA_TWO) ?: "" } + private val number by lazy { arguments?.getInt(EXTRA_THREE) ?: 0 } + private val adapter by lazy { IssueTimelineAdapter(htmlSpanner, preference.theme) } + + override fun layoutRes(): Int = R.layout.issue_pr_fragment_layout + override fun viewModel(): BaseViewModel? = viewModel + + override fun onFragmentCreatedWithUser( + view: View, + savedInstanceState: Bundle? + ) { + swipeRefresh.appBarLayout = appBar + appBar.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { p0, p1 -> + Timber.e("$p1") + toolbar.menu?.findItem(R.id.scrollTop)?.isVisible = p1 < 0 + }) + setupToolbar("", R.menu.issue_menu) + (recyclerView.itemAnimator as? SimpleItemAnimator)?.supportsChangeAnimations = false + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView, appBar) + recyclerView.adapter = adapter + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.loadData(login, repo, number) } } + if (savedInstanceState == null) { + isConnected().isTrue { viewModel.loadData(login, repo, number, true) } + } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.loadData(login, repo, number, true) + } else { + swipeRefresh.isRefreshing = false + } + } + observeChanges() + } + + override fun onLockReasonSelected(lockReason: LockReason?) { + viewModel.lockUnlockIssue(login, repo, number, lockReason, true) + } + + override fun onLabelsSelected(labels: List?) { + initLabels(labels) + } + + override fun onAssigneesSelected(assignees: List?) { + initAssignees(assignees) + } + + override fun onMilestoneAdded( + timeline: TimelineModel, + milestone: MilestoneModel + ) { + viewModel.addTimeline(timeline) + initMilestone(milestone) + } + + private fun menuClick(model: IssueModel) { + toolbar.setOnMenuItemClickListener { item -> + when (item.itemId) { + R.id.scrollTop -> { + appBar.setExpanded(true, true) + recyclerView.scrollToPosition(0) + } + R.id.refresh -> { + viewModel.loadData(login, repo, number, true) + appBar.setExpanded(true, true) + recyclerView.scrollToPosition(0) + } + R.id.closeIssue -> viewModel.closeOpenIssue(login, repo, number) + R.id.share -> requireActivity().shareUrl(model.url) + R.id.lockIssue -> if (item.title == getString(R.string.lock_issue)) { + MultiPurposeBottomSheetDialog.show(childFragmentManager, MultiPurposeBottomSheetDialog.BottomSheetFragmentType.LOCK_UNLOCK) + } else { + viewModel.lockUnlockIssue(login, repo, number) + } + R.id.labels -> MultiPurposeBottomSheetDialog.show( + childFragmentManager, + MultiPurposeBottomSheetDialog.BottomSheetFragmentType.LABELS, LoginRepoParcelableModel(login, repo, model.labels, number) + ) + R.id.assignees -> MultiPurposeBottomSheetDialog.show( + childFragmentManager, + MultiPurposeBottomSheetDialog.BottomSheetFragmentType.ASSIGNEES, LoginRepoParcelableModel(login, repo, model.assignees, number) + ) + R.id.milestone -> MultiPurposeBottomSheetDialog.show( + childFragmentManager, + MultiPurposeBottomSheetDialog.BottomSheetFragmentType.MILESTONE, LoginRepoParcelableModel(login, repo, model.assignees, number) + ) + } + return@setOnMenuItemClickListener true + } + } + + private fun observeChanges() { + viewModel.getIssue(login, repo, number).observeNotNull(this) { + initIssue(it.first, it.second) + } + viewModel.timeline.observeNotNull(this) { + adapter.submitList(it) + } + } + + private fun initIssue( + model: IssueModel, + me: LoginModel? + ) { + issueHeaderWrapper.isVisible = true + val theme = preference.theme + title.text = SpannableBuilder.builder() + .append(getString(R.string.issue)) + .bold("#${model.number}") + .newline() + .append(model.title) + opener.text = SpannableBuilder.builder() + .bold(model.author?.login) + .append(" opened this issue ") + .append(model.createdAt?.timeAgo()) + + userIcon.loadAvatar(model.author?.avatarUrl, model.author?.url ?: "") + author.text = model.author?.login + association.text = if ("NONE" == model.authorAssociation) { + model.updatedAt?.timeAgo() + } else { + "${model.authorAssociation?.toLowerCase()?.replace("_", "")} ${model.updatedAt?.timeAgo()}" + } + MarkdownProvider.loadIntoTextView( + htmlSpanner, description, model.bodyHTML ?: "", ThemeEngine.getCodeBackground(theme), + ThemeEngine.isLightTheme(theme) + ) + state.text = model.state?.toLowerCase() + state.setChipBackgroundColorResource( + if ("OPEN".equals(model.state, true)) { + R.color.material_green_700 + } else { + R.color.material_red_700 + } + ) + addEmoji.setOnClickListener { + it.popupEmoji(requireNotNull(model.id), model.reactionGroups) { + initReactions(model) + } + } + menuClick(model) + initReactions(model) + initLabels(model.labels) + initAssignees(model.assignees) + initMilestone(model.milestone) + toolbar.menu.let { + val isAuthor = login == me?.login || model.authorAssociation?.equals("OWNER", true) == true || + model.authorAssociation?.equals("COLLABORATOR", true) == true + it.findItem(R.id.edit).isVisible = model.viewerDidAuthor == true + it.findItem(R.id.assignees).isVisible = isAuthor + it.findItem(R.id.milestone).isVisible = isAuthor + it.findItem(R.id.labels).isVisible = isAuthor + it.findItem(R.id.closeIssue).isVisible = model.viewerDidAuthor == true || isAuthor + it.findItem(R.id.lockIssue).isVisible = isAuthor + it.findItem(R.id.closeIssue).title = if (!"OPEN".equals(model.state, true)) { + getString(R.string.re_open_issue) + } else { + getString(R.string.close_issue) + } + it.findItem(R.id.lockIssue).title = if (model.locked == true) getString(R.string.unlock_issue) else getString(R.string.lock_issue) + } + recyclerView.removeEmptyView() + } + + private fun initAssignees(assigneesList: List?) { + assigneesLayout.isVisible = !assigneesList.isNullOrEmpty() + val builder = SpannableBuilder.builder() + assigneesList?.forEachIndexed { index, item -> + builder.clickable("@${item.login}" ?: item.name ?: "", View.OnClickListener { + it.context.route(item.url) + }).append(if (index == assigneesList.size.minus(1)) "" else ", ") + } + assignees.text = builder + } + + private fun initMilestone(model: MilestoneModel?) { + model?.let { + milestoneLayout.isVisible = true + milestone.text = when { + it.title != null -> "${it.title}" + it.description != null -> "${it.description}" + else -> "" + } + } ?: run { milestoneLayout.isVisible = false } + } + + private fun initLabels(labelList: List?) { + labelsLayout.isVisible = !labelList.isNullOrEmpty() + val builder = SpannableBuilder.builder() + labelList?.forEach { + builder.append(it.name ?: "", LabelSpan(Color.parseColor("#${it.color}"))) + .append(" ") + } + labels.text = builder + } + + private fun initReactions(model: IssueModel) { + reactionsText.isVisible = model.reactionGroups?.any { it.users?.totalCount != 0 } ?: false + if (reactionsText.isVisible) { + val stringBuilder = StringBuilder() + model.reactionGroups?.forEach { + if (it.users?.totalCount != 0) { + stringBuilder.append(it.content.getEmoji()) + .append(" ") + .append("${it.users?.totalCount}") + .append(" ") + } + } + reactionsText.text = stringBuilder + } else { + reactionsText.text = "" + } + } + + companion object { + const val TAG = "IssueFragment" + fun newInstance( + login: String, + repo: String, + number: Int + ) = IssueFragment().apply { + arguments = bundleOf(EXTRA to login, EXTRA_TWO to repo, EXTRA_THREE to number) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issue/fragment/viewmodel/IssueTimelineViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issue/fragment/viewmodel/IssueTimelineViewModel.kt new file mode 100644 index 000000000..21041fdbf --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issue/fragment/viewmodel/IssueTimelineViewModel.kt @@ -0,0 +1,108 @@ +package com.fastaccess.github.ui.modules.issue.fragment.viewmodel + +import androidx.lifecycle.MutableLiveData +import com.apollographql.apollo.api.Input +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.TimelineModel +import com.fastaccess.data.repository.IssueRepositoryProvider +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.filterNull +import com.fastaccess.github.extensions.map +import com.fastaccess.github.usecase.issuesprs.CloseOpenIssuePrUseCase +import com.fastaccess.github.usecase.issuesprs.GetIssueTimelineUseCase +import com.fastaccess.github.usecase.issuesprs.GetIssueUseCase +import com.fastaccess.github.usecase.issuesprs.LockUnlockIssuePrUseCase +import github.type.LockReason +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 20.10.18. + */ +class IssueTimelineViewModel @Inject constructor( + private val issueUseCase: GetIssueUseCase, + private val timelineUseCase: GetIssueTimelineUseCase, + private val issueRepositoryProvider: IssueRepositoryProvider, + private val editIssuePrUseCase: CloseOpenIssuePrUseCase, + private val lockUnlockIssuePrUseCase: LockUnlockIssuePrUseCase, + private val loginRepositoryProvider: LoginRepositoryProvider +) : BaseViewModel() { + + private var pageInfo: PageInfoModel? = null + val timeline = MutableLiveData>() + private val list = arrayListOf() + + override fun onCleared() { + super.onCleared() + timelineUseCase.dispose() + editIssuePrUseCase.dispose() + issueUseCase.dispose() + lockUnlockIssuePrUseCase.dispose() + } + + fun getIssue(login: String, repo: String, number: Int) = issueRepositoryProvider.getIssueByNumber("$login/$repo", number) + .filterNull() + .map { Pair(it, loginRepositoryProvider.getLoginBlocking()) } + + fun loadData(login: String, repo: String, number: Int, reload: Boolean = false) { + if (reload) { + pageInfo = null + list.clear() + } + val pageInfo = pageInfo + if (!reload && (pageInfo != null && !pageInfo.hasNextPage)) return + val cursor = if (hasNext()) pageInfo?.endCursor else null + if (pageInfo == null) { + issueUseCase.login = login + issueUseCase.repo = repo + issueUseCase.number = number + justSubscribe(issueUseCase.buildObservable() + .flatMap { loadTimeline(login, repo, number, cursor) }) + } else { + justSubscribe(loadTimeline(login, repo, number, cursor)) + } + } + + private fun loadTimeline(login: String, repo: String, number: Int, cursor: String?): Observable>> { + timelineUseCase.login = login + timelineUseCase.repo = repo + timelineUseCase.number = number + timelineUseCase.page = Input.optional(cursor) + return timelineUseCase.buildObservable() + .doOnNext { + this.pageInfo = it.first + list.addAll(it.second) + timeline.postValue(ArrayList(list)) + } + } + + fun closeOpenIssue(login: String, repo: String, number: Int) { + editIssuePrUseCase.repo = repo + editIssuePrUseCase.login = login + editIssuePrUseCase.number = number + justSubscribe(editIssuePrUseCase.buildObservable() + .doOnNext { + addTimeline(it) + }) + } + + fun lockUnlockIssue(login: String, repo: String, number: Int, lockReason: LockReason? = null, lock: Boolean = false) { + lockUnlockIssuePrUseCase.repo = repo + lockUnlockIssuePrUseCase.login = login + lockUnlockIssuePrUseCase.number = number + lockUnlockIssuePrUseCase.lockReason = lockReason + lockUnlockIssuePrUseCase.lock = lock + justSubscribe(lockUnlockIssuePrUseCase.buildObservable() + .doOnNext { + addTimeline(it) + }) + } + + fun addTimeline(it: TimelineModel) { + list.add(it) + timeline.postValue(ArrayList(list)) + } + + fun hasNext() = pageInfo?.hasNextPage ?: false +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/LockUnlockFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/LockUnlockFragment.kt new file mode 100644 index 000000000..eafe7b552 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/LockUnlockFragment.kt @@ -0,0 +1,59 @@ +package com.fastaccess.github.ui.modules.issuesprs.edit + +import android.content.Context +import android.os.Bundle +import android.view.View +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import github.type.LockReason +import kotlinx.android.synthetic.main.appbar_center_title_round_background_layout.* +import kotlinx.android.synthetic.main.lock_unlock_issue_pr_layout.* + +/** + * Created by Kosh on 23.02.19. + */ +class LockUnlockFragment : BaseFragment() { + + private var callback: OnLockReasonSelected? = null + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = when { + context is OnLockReasonSelected -> context + parentFragment is OnLockReasonSelected -> parentFragment as OnLockReasonSelected + parentFragment?.parentFragment is OnLockReasonSelected -> parentFragment?.parentFragment as OnLockReasonSelected // deep hierarchy + else -> null + } + } + + override fun onDetach() { + super.onDetach() + callback = null + } + + override fun layoutRes(): Int = R.layout.lock_unlock_issue_pr_layout + override fun viewModel(): BaseViewModel? = null + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + toolbarTitle.text = getString(R.string.lock_issue) + submit.setOnClickListener { + callback?.onLockReasonSelected(when (reason.checkedChipId) { + R.id.spam -> LockReason.SPAM + R.id.tooHeated -> LockReason.TOO_HEATED + R.id.offTopic -> LockReason.OFF_TOPIC + R.id.resolved -> LockReason.RESOLVED + else -> null + }) + dismiss() + } + } + + interface OnLockReasonSelected { + fun onLockReasonSelected(lockReason: LockReason?) + } + + companion object { + fun newInstance() = LockUnlockFragment() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/assignees/AssigneesFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/assignees/AssigneesFragment.kt new file mode 100644 index 000000000..f3f402659 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/assignees/AssigneesFragment.kt @@ -0,0 +1,121 @@ +package com.fastaccess.github.ui.modules.issuesprs.edit.assignees + +import android.content.Context +import android.os.Bundle +import android.view.MenuItem +import android.view.View +import androidx.core.os.bundleOf +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.evernote.android.state.State +import com.fastaccess.data.model.ShortUserModel +import com.fastaccess.data.model.parcelable.LoginRepoParcelableModel +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.ui.adapter.AssigneesAdapter +import com.fastaccess.github.ui.modules.issuesprs.edit.assignees.viewmodel.AssigneesViewModel +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.extensions.isConnected +import kotlinx.android.synthetic.main.appbar_center_title_round_background_layout.* +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 2018-11-26. + */ +class AssigneesFragment : BaseFragment() { + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + @State var selection = hashSetOf() + @State var deselection = hashSetOf() + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(AssigneesViewModel::class.java) } + private val model by lazy { arguments?.getParcelable(EXTRA) as? LoginRepoParcelableModel } + private val adapter by lazy { + AssigneesAdapter(selection, deselection).apply { + model?.items?.forEach { this.selection.add(it) } + } + } + + private var callback: OnAssigneesSelected? = null + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = when { + context is OnAssigneesSelected -> context + parentFragment is OnAssigneesSelected -> parentFragment as OnAssigneesSelected + parentFragment?.parentFragment is OnAssigneesSelected -> parentFragment?.parentFragment as OnAssigneesSelected // deep hierarchy + else -> null + } + } + + override fun onDetach() { + super.onDetach() + callback = null + } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.rounded_toolbar_fragment_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + val login = model?.login + val repo = model?.repo + val number = model?.number + + if (login == null || repo == null || number == null) { + dismiss() + return + } + setupToolbar(R.string.assignees, R.menu.edit_submit_menu) { item: MenuItem -> + when (item.itemId) { + R.id.submit -> { + if (adapter.selection.toList() != model?.items) { + viewModel.addAssignees(login, repo, number, + adapter.selection.toList().map { it.login ?: "" }, + adapter.deselection.toList().map { it.login ?: "" }) + } + } + } + } + toolbar.menu?.findItem(R.id.add)?.isVisible = false + recyclerView.adapter = adapter + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView) + if (savedInstanceState == null) isConnected().isTrue { viewModel.load(login, repo, true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.load(login, repo, true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.load(login, repo) } } + listenToChanges() + } + + private fun listenToChanges() { + viewModel.data.observeNotNull(this) { + adapter.submitList(it) + } + viewModel.additionLiveData.observeNotNull(this) { + if (it == true) { + callback?.onAssigneesSelected(adapter.selection.toList()) + dismiss() + } + } + } + + + companion object { + fun newInstance(model: LoginRepoParcelableModel?) = AssigneesFragment().apply { + arguments = bundleOf(EXTRA to model) + } + } + + interface OnAssigneesSelected { + fun onAssigneesSelected(assignees: List?) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/assignees/viewmodel/AssigneesViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/assignees/viewmodel/AssigneesViewModel.kt new file mode 100644 index 000000000..0ee9edda5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/assignees/viewmodel/AssigneesViewModel.kt @@ -0,0 +1,60 @@ +package com.fastaccess.github.ui.modules.issuesprs.edit.assignees.viewmodel + +import androidx.lifecycle.MutableLiveData +import com.apollographql.apollo.api.Input +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.ShortUserModel +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.usecase.issuesprs.AddAssigneesUseCase +import com.fastaccess.github.usecase.issuesprs.GetAssigneesUseCase +import javax.inject.Inject + +/** + * Created by Kosh on 2018-11-26. + */ +class AssigneesViewModel @Inject constructor( + private val usecase: GetAssigneesUseCase, + private val addAssigneesUseCase: AddAssigneesUseCase +) : BaseViewModel() { + + private var pageInfo: PageInfoModel? = null + private val list = ArrayList() + val data = MutableLiveData>() + val additionLiveData = MutableLiveData() + + fun load(login: String, repo: String, reload: Boolean = false) { + if (reload) { + pageInfo = null + list.clear() + } + + val pageInfo = pageInfo + if (!reload && (pageInfo != null && !pageInfo.hasNextPage)) return + val cursor = if (hasNext()) pageInfo?.endCursor else null + + usecase.login = login + usecase.repo = repo + usecase.page = Input.optional(cursor) + justSubscribe(callApi(usecase.buildObservable()) + .doOnNext { + this.pageInfo = it.first + list.addAll(it.second) + data.postValue(ArrayList(list)) + }) + } + + fun hasNext() = pageInfo?.hasNextPage == true + + fun addAssignees(login: String, repo: String, number: Int, assignees: List?, + toRemove: List?) { + addAssigneesUseCase.login = login + addAssigneesUseCase.repo = repo + addAssigneesUseCase.number = number + addAssigneesUseCase.assignees = assignees + addAssigneesUseCase.toRemove = toRemove // remove all assignees and re-add them just in case. + justSubscribe(addAssigneesUseCase.buildObservable() + .doOnNext { + additionLiveData.postValue(it) + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/LabelsFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/LabelsFragment.kt new file mode 100644 index 000000000..e566de7b1 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/LabelsFragment.kt @@ -0,0 +1,133 @@ +package com.fastaccess.github.ui.modules.issuesprs.edit.labels + +import android.content.Context +import android.os.Bundle +import android.view.MenuItem +import android.view.View +import androidx.core.os.bundleOf +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.evernote.android.state.State +import com.fastaccess.data.model.parcelable.LabelModel +import com.fastaccess.data.model.parcelable.LoginRepoParcelableModel +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.extensions.show +import com.fastaccess.github.ui.adapter.LabelsAdapter +import com.fastaccess.github.ui.modules.issuesprs.edit.labels.create.CreateLabelFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.labels.viewmodel.LabelsViewModel +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.extensions.isConnected +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 2018-11-26. + */ +class LabelsFragment : BaseFragment(), CreateLabelFragment.OnCreateLabelCallback { + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + @State var selection = hashSetOf() + @State var deselection = hashSetOf() + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(LabelsViewModel::class.java) } + private val model by lazy { arguments?.getParcelable(EXTRA) as? LoginRepoParcelableModel } + private val adapter by lazy { + LabelsAdapter(selection, deselection).apply { + model?.items?.forEach { this.selection.add(it) } + } + } + + private var callback: OnLabelSelected? = null + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = when { + context is OnLabelSelected -> context + parentFragment is OnLabelSelected -> parentFragment as OnLabelSelected + parentFragment?.parentFragment is OnLabelSelected -> parentFragment?.parentFragment as OnLabelSelected // deep hierarchy + else -> null + } + } + + override fun onDetach() { + super.onDetach() + callback = null + } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.rounded_toolbar_fragment_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + val login = model?.login + val repo = model?.repo + val number = model?.number + + if (login == null || repo == null || number == null) { + dismiss() + return + } + setupToolbar(R.string.labels, R.menu.edit_submit_menu) { item: MenuItem -> + when (item.itemId) { + R.id.submit -> { + if (adapter.selection.toList() != model?.items) { + viewModel.putLabels(login, repo, number, adapter.selection, adapter.deselection) + } else { + dismiss() + } + } + R.id.add -> { + CreateLabelFragment.newInstance().show(childFragmentManager) + } + } + } + recyclerView.adapter = adapter + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView) + if (savedInstanceState == null) isConnected().isTrue { viewModel.load(login, repo, true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.load(login, repo, true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.load(login, repo) } } + listenToChanges() + } + + override fun onCreateLabel(name: String, color: String) { + val login = model?.login + val repo = model?.repo + + if (login == null || repo == null) { + dismiss() + return + } + viewModel.addLabel(login, repo, name, color) + } + + private fun listenToChanges() { + viewModel.data.observeNotNull(this) { + adapter.submitList(it) + } + viewModel.putLabelsLiveData.observeNotNull(this) { + callback?.onLabelsSelected(adapter.selection.toList()) + dismiss() + } + } + + + companion object { + fun newInstance(model: LoginRepoParcelableModel?) = LabelsFragment().apply { + arguments = bundleOf(EXTRA to model) + } + } + + interface OnLabelSelected { + fun onLabelsSelected(labels: List?) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/create/CreateLabelFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/create/CreateLabelFragment.kt new file mode 100644 index 000000000..2f2b1b95d --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/create/CreateLabelFragment.kt @@ -0,0 +1,62 @@ +package com.fastaccess.github.ui.modules.issuesprs.edit.labels.create + +import android.content.Context +import android.os.Bundle +import android.view.View +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseDialogFragment +import com.fastaccess.github.ui.adapter.LabelColorAdapter +import com.fastaccess.github.utils.extensions.asString +import kotlinx.android.synthetic.main.add_label_layout.* + +/** + * Created by Kosh on 07.03.19. + */ +class CreateLabelFragment : BaseDialogFragment() { + + private var callback: OnCreateLabelCallback? = null + + private val adapter by lazy { + LabelColorAdapter(resources.getStringArray(R.array.label_colors).toList()) { + color.editText?.setText(it) + } + } + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = when { + parentFragment is OnCreateLabelCallback -> parentFragment as OnCreateLabelCallback + context is OnCreateLabelCallback -> context + else -> throw IllegalAccessError("$context must impl OnCreateLabelCallback") + } + } + + override fun onDetach() { + callback = null + super.onDetach() + } + + override fun layoutRes(): Int = R.layout.add_label_layout + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + recycler.adapter = adapter + setupToolbar(getString(R.string.create_label), R.menu.submit_menu) { item -> + val colorText = color.editText?.asString() + val nameText = name.editText?.asString() + color.error = if (colorText.isNullOrEmpty()) getString(R.string.required_field) else null + name.error = if (nameText.isNullOrEmpty()) getString(R.string.required_field) else null + if (!colorText.isNullOrEmpty() && !nameText.isNullOrEmpty()) { + callback?.onCreateLabel(nameText, colorText.replace("#", "")) + dismissDialog() + } + } + } + + companion object { + fun newInstance() = CreateLabelFragment() + } + + interface OnCreateLabelCallback { + fun onCreateLabel(name: String, color: String) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/viewmodel/LabelsViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/viewmodel/LabelsViewModel.kt new file mode 100644 index 000000000..0619718ab --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/labels/viewmodel/LabelsViewModel.kt @@ -0,0 +1,75 @@ +package com.fastaccess.github.ui.modules.issuesprs.edit.labels.viewmodel + +import androidx.lifecycle.MutableLiveData +import com.apollographql.apollo.api.Input +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.parcelable.LabelModel +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.usecase.issuesprs.CreateLabelUseCase +import com.fastaccess.github.usecase.issuesprs.GetLabelsUseCase +import com.fastaccess.github.usecase.issuesprs.PutLabelsUseCase +import javax.inject.Inject + +/** + * Created by Kosh on 2018-11-26. + */ +class LabelsViewModel @Inject constructor( + private val usecase: GetLabelsUseCase, + private val createLabelUseCase: CreateLabelUseCase, + private val putLabelsUseCase: PutLabelsUseCase +) : BaseViewModel() { + + private var pageInfo: PageInfoModel? = null + private val list = ArrayList() + val data = MutableLiveData>() + val putLabelsLiveData = MutableLiveData() + + fun load(login: String, repo: String, reload: Boolean = false) { + if (reload) { + pageInfo = null + list.clear() + } + + val pageInfo = pageInfo + if (!reload && (pageInfo != null && !pageInfo.hasNextPage)) return + val cursor = if (hasNext()) pageInfo?.endCursor else null + + usecase.login = login + usecase.repo = repo + usecase.page = Input.optional(cursor) + justSubscribe(callApi(usecase.buildObservable()) + .doOnNext { + this.pageInfo = it.first + list.addAll(it.second) + data.postValue(ArrayList(list)) + }) + } + + fun hasNext() = pageInfo?.hasNextPage == true + + fun addLabel(login: String, repo: String, name: String, color: String) { + createLabelUseCase.login = login + createLabelUseCase.repo = repo + createLabelUseCase.name = name + createLabelUseCase.color = color + justSubscribe(createLabelUseCase.buildObservable() + .doOnNext { + list.add(0, it) + data.postValue(ArrayList(list)) + }) + } + + fun putLabels(login: String, repo: String, number: Int, + selection: HashSet, + deselection: HashSet) { + putLabelsUseCase.login = login + putLabelsUseCase.repo = repo + putLabelsUseCase.number = number + putLabelsUseCase.toAdd = selection.toList().map { it.name ?: "" } + putLabelsUseCase.toRemove = deselection.toList().map { it.name ?: "" } + justSubscribe(putLabelsUseCase.buildObservable() + .doOnNext { + putLabelsLiveData.postValue(true) + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/CreateMilestoneDialogFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/CreateMilestoneDialogFragment.kt new file mode 100644 index 000000000..f5a1846d7 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/CreateMilestoneDialogFragment.kt @@ -0,0 +1,71 @@ +package com.fastaccess.github.ui.modules.issuesprs.edit.milestone + +import android.content.Context +import android.os.Bundle +import android.view.MotionEvent +import android.view.View +import com.fastaccess.datetimepicker.DatePickerFragmentDialog +import com.fastaccess.datetimepicker.callback.DatePickerCallback +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseDialogFragment +import com.fastaccess.github.extensions.DatePrettifier +import com.fastaccess.github.extensions.show +import com.fastaccess.github.utils.extensions.asString +import kotlinx.android.synthetic.main.add_milestone_layout.* +import java.util.* + +/** + * Created by Kosh on 30.03.19. + */ +class CreateMilestoneDialogFragment : BaseDialogFragment(), DatePickerCallback { + private var callback: OnAddNewMilestone? = null + + override fun layoutRes(): Int = R.layout.add_milestone_layout + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = when { + parentFragment is OnAddNewMilestone -> parentFragment as OnAddNewMilestone + context is OnAddNewMilestone -> context + else -> throw IllegalAccessException("woops, your $context or $parentFragment must impl OnAddNewMilestone") + } + } + + override fun onDetach() { + callback = null + super.onDetach() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setupToolbar(getString(R.string.create_milestone), R.menu.submit_menu) { + if (it.itemId == R.id.submit) { + val timestamp = dueOn.tag as? Long + val title = milestoneTitle.editText?.asString() + val description = milestoneDescription.editText?.asString() + milestoneTitle.error = if (title.isNullOrEmpty()) getString(R.string.required_field) else null + dueOn.error = if (timestamp == null) getString(R.string.required_field) else null + if (timestamp != null && !title.isNullOrEmpty()) { + callback?.addNewMilestone(title, Date(timestamp), description) + dismissDialog() + } + } + } + dueOn.editText?.setOnTouchListener { _, event -> + if (event.action == MotionEvent.ACTION_UP) { + DatePickerFragmentDialog.newInstance().show(childFragmentManager) + return@setOnTouchListener true + } + return@setOnTouchListener false + } + } + + override fun onDateSet(date: Long) { + dueOn.tag = date + dueOn.editText?.setText(DatePrettifier.prettifyDate(date)) + } + + interface OnAddNewMilestone { + fun addNewMilestone(title: String, dueOn: Date, description: String?) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/MilestoneFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/MilestoneFragment.kt new file mode 100644 index 000000000..58de9bb69 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/MilestoneFragment.kt @@ -0,0 +1,130 @@ +package com.fastaccess.github.ui.modules.issuesprs.edit.milestone + +import android.content.Context +import android.os.Bundle +import android.view.MenuItem +import android.view.View +import androidx.core.os.bundleOf +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.TimelineModel +import com.fastaccess.data.model.parcelable.LabelModel +import com.fastaccess.data.model.parcelable.LoginRepoParcelableModel +import com.fastaccess.data.model.parcelable.MilestoneModel +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.extensions.show +import com.fastaccess.github.ui.adapter.MilestonesAdapter +import com.fastaccess.github.ui.modules.issuesprs.edit.milestone.viewmodel.MilestoneViewModel +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.extensions.addDivider +import com.fastaccess.github.utils.extensions.isConnected +import kotlinx.android.synthetic.main.appbar_center_title_round_background_layout.* +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import java.util.* +import javax.inject.Inject + +/** + * Created by Kosh on 2018-11-26. + */ +class MilestoneFragment : BaseFragment(), CreateMilestoneDialogFragment.OnAddNewMilestone { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(MilestoneViewModel::class.java) } + private val model by lazy { arguments?.getParcelable(EXTRA) as? LoginRepoParcelableModel } + private val adapter by lazy { + MilestonesAdapter { + val login = model?.login + val repo = model?.repo + val number = model?.number + if (login == null || repo == null || number == null) { + dismiss() + return@MilestonesAdapter + } + + viewModel.onSubmit(login, repo, number, it) + } + } + + private var callback: OnMilestoneChanged? = null + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = when { + context is OnMilestoneChanged -> context + parentFragment is OnMilestoneChanged -> parentFragment as OnMilestoneChanged + parentFragment?.parentFragment is OnMilestoneChanged -> parentFragment?.parentFragment as OnMilestoneChanged // deep hierarchy + else -> null + } + } + + override fun onDetach() { + super.onDetach() + callback = null + } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.rounded_toolbar_fragment_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + val login = model?.login + val repo = model?.repo + val number = model?.number + + if (login == null || repo == null || number == null) { + dismiss() + return + } + setupToolbar(R.string.milestones, R.menu.edit_submit_menu) { item: MenuItem -> + when (item.itemId) { + R.id.add -> { + CreateMilestoneDialogFragment().show(childFragmentManager) + } + } + } + toolbar.menu?.findItem(R.id.submit)?.isVisible = false + recyclerView.addDivider() + recyclerView.adapter = adapter + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView) + if (savedInstanceState == null) isConnected().isTrue { viewModel.load(login, repo, true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.load(login, repo, true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.load(login, repo) } } + listenToChanges() + } + + override fun addNewMilestone(title: String, dueOn: Date, description: String?) { + viewModel.addMilestone(title, dueOn, description, model?.login, model?.repo) + } + + private fun listenToChanges() { + viewModel.data.observeNotNull(this) { + adapter.submitList(it) + } + viewModel.response.observeNotNull(this) { + callback?.onMilestoneAdded(it.first, it.second) + dismiss() + } + } + + companion object { + fun newInstance(model: LoginRepoParcelableModel?) = MilestoneFragment().apply { + arguments = bundleOf(EXTRA to model) + } + } + + interface OnMilestoneChanged { + fun onMilestoneAdded(timeline: TimelineModel, milestone: MilestoneModel) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/viewmodel/MilestoneViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/viewmodel/MilestoneViewModel.kt new file mode 100644 index 000000000..b4b27a365 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/edit/milestone/viewmodel/MilestoneViewModel.kt @@ -0,0 +1,77 @@ +package com.fastaccess.github.ui.modules.issuesprs.edit.milestone.viewmodel + +import androidx.lifecycle.MutableLiveData +import com.apollographql.apollo.api.Input +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.TimelineModel +import com.fastaccess.data.model.parcelable.MilestoneModel +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.DatePrettifier +import com.fastaccess.github.usecase.issuesprs.CreateMilestoneUseCase +import com.fastaccess.github.usecase.issuesprs.GetMilestonesUseCase +import com.fastaccess.github.usecase.issuesprs.MilestoneIssuePrUseCase +import java.util.* +import javax.inject.Inject + +/** + * Created by Kosh on 2018-11-26. + */ +class MilestoneViewModel @Inject constructor( + private val usecase: GetMilestonesUseCase, + private val createMilestoneUseCase: CreateMilestoneUseCase, + private val milestoneIssuePrUseCase: MilestoneIssuePrUseCase +) : BaseViewModel() { + + private var pageInfo: PageInfoModel? = null + private val list = ArrayList() + val data = MutableLiveData>() + val response = MutableLiveData>() + + fun load(login: String, repo: String, reload: Boolean = false) { + if (reload) { + pageInfo = null + list.clear() + } + + val pageInfo = pageInfo + if (!reload && (pageInfo != null && !pageInfo.hasNextPage)) return + val cursor = if (hasNext()) pageInfo?.endCursor else null + + usecase.login = login + usecase.repo = repo + usecase.page = Input.optional(cursor) + justSubscribe(callApi(usecase.buildObservable()) + .doOnNext { + this.pageInfo = it.first + list.addAll(it.second) + data.postValue(ArrayList(list)) + }) + } + + fun hasNext() = pageInfo?.hasNextPage == true + + fun onSubmit(login: String, repo: String, number: Int, milestone: MilestoneModel) { + milestoneIssuePrUseCase.login = login + milestoneIssuePrUseCase.repo = repo + milestoneIssuePrUseCase.number = number + milestoneIssuePrUseCase.milestone = milestone.number ?: -1 + justSubscribe(milestoneIssuePrUseCase.buildObservable() + .doOnNext { + response.postValue(it) + }) + } + + fun addMilestone(title: String, dueOn: Date, description: String?, login: String?, repo: String?) { + createMilestoneUseCase.login = login ?: "" + createMilestoneUseCase.repo = repo ?: "" + createMilestoneUseCase.title = title + createMilestoneUseCase.description = description + createMilestoneUseCase.dueOn = DatePrettifier.toGithubDate(dueOn) + justSubscribe(createMilestoneUseCase.buildObservable() + .doOnNext { + list.add(0, MilestoneModel(title = title, description = description, dueOn = dueOn)) + data.postValue(ArrayList(list)) + }) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/filter/FilterIssuesPrsBottomSheet.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/filter/FilterIssuesPrsBottomSheet.kt new file mode 100644 index 000000000..a31b85cd5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/filter/FilterIssuesPrsBottomSheet.kt @@ -0,0 +1,126 @@ +package com.fastaccess.github.ui.modules.issuesprs.filter + +import android.content.Context +import android.os.Bundle +import android.view.View +import androidx.core.os.bundleOf +import androidx.core.view.isVisible +import com.fastaccess.data.model.parcelable.FilterIssuesPrsModel +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseBottomSheetDialogFragment +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.utils.EXTRA +import kotlinx.android.synthetic.main.filter_issue_pr_layout.* + +/** + * Created by Kosh on 19.01.19. + */ +class FilterIssuesPrsBottomSheet : BaseFragment() { + + private val model by lazy { (arguments?.getParcelable(EXTRA) as? FilterIssuesPrsModel) ?: FilterIssuesPrsModel() } + private var callback: FilterIssuesPrsCallback? = null + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = when { + context is FilterIssuesPrsCallback -> context + parentFragment is FilterIssuesPrsCallback -> parentFragment as FilterIssuesPrsCallback + parentFragment?.parentFragment is FilterIssuesPrsCallback -> parentFragment?.parentFragment as FilterIssuesPrsCallback // deep hierarchy + else -> null + } + } + + override fun onDetach() { + callback = null + super.onDetach() + } + + override fun layoutRes(): Int = R.layout.filter_issue_pr_layout + override fun viewModel(): BaseViewModel? = null + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + setupToolbar(R.string.filter) + reviewRequest.isVisible = model.isPr + + if (savedInstanceState == null) { + initState() + } + + assignCheckListener() + + submit.setOnClickListener { + callback?.onFilterApplied(model) + (parentFragment as? BaseBottomSheetDialogFragment)?.dismiss() + } + } + + private fun initState() { + filter.check(when (model.searchBy) { + FilterIssuesPrsModel.SearchBy.CREATED -> R.id.created + FilterIssuesPrsModel.SearchBy.ASSIGNED -> R.id.assigned + FilterIssuesPrsModel.SearchBy.MENTIONED -> R.id.mentioned + FilterIssuesPrsModel.SearchBy.REVIEW_REQUESTS -> R.id.reviewRequest + }) + type.check(when (model.searchType) { + FilterIssuesPrsModel.SearchType.OPEN -> R.id.open + FilterIssuesPrsModel.SearchType.CLOSED -> R.id.closed + }) + visibility.check(when (model.searchVisibility) { + FilterIssuesPrsModel.SearchVisibility.BOTH -> R.id.bothVisibility + FilterIssuesPrsModel.SearchVisibility.PUBLIC -> R.id.publicRepos + FilterIssuesPrsModel.SearchVisibility.PRIVATE -> R.id.privateRepos + }) + sort.check(when (model.searchSortBy) { + FilterIssuesPrsModel.SearchSortBy.NEWEST -> R.id.newest + FilterIssuesPrsModel.SearchSortBy.OLDEST -> R.id.oldest + FilterIssuesPrsModel.SearchSortBy.MOST_COMMENTED -> R.id.mostCommented + FilterIssuesPrsModel.SearchSortBy.LEAST_COMMENTED -> R.id.leastCommented + FilterIssuesPrsModel.SearchSortBy.RECENTLY_UPDATED -> R.id.recentlyUpdated + FilterIssuesPrsModel.SearchSortBy.LEAST_RECENTLY_UPDATED -> R.id.leastRecentlyUpdated + }) + } + + private fun assignCheckListener() { + filter.setOnCheckedChangeListener { _, id -> + when (id) { + R.id.created -> model.searchBy = FilterIssuesPrsModel.SearchBy.CREATED + R.id.assigned -> model.searchBy = FilterIssuesPrsModel.SearchBy.ASSIGNED + R.id.mentioned -> model.searchBy = FilterIssuesPrsModel.SearchBy.MENTIONED + R.id.reviewRequest -> model.searchBy = FilterIssuesPrsModel.SearchBy.REVIEW_REQUESTS + } + } + type.setOnCheckedChangeListener { _, id -> + when (id) { + R.id.open -> model.searchType = FilterIssuesPrsModel.SearchType.OPEN + R.id.closed -> model.searchType = FilterIssuesPrsModel.SearchType.CLOSED + } + } + visibility.setOnCheckedChangeListener { _, id -> + when (id) { + R.id.bothVisibility -> model.searchVisibility = FilterIssuesPrsModel.SearchVisibility.BOTH + R.id.privateRepos -> model.searchVisibility = FilterIssuesPrsModel.SearchVisibility.PRIVATE + R.id.publicRepos -> model.searchVisibility = FilterIssuesPrsModel.SearchVisibility.PUBLIC + } + } + sort.setOnCheckedChangeListener { _, id -> + when (id) { + R.id.newest -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.NEWEST + R.id.oldest -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.OLDEST + R.id.mostCommented -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.MOST_COMMENTED + R.id.leastCommented -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.LEAST_COMMENTED + R.id.recentlyUpdated -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.RECENTLY_UPDATED + R.id.leastRecentlyUpdated -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.LEAST_RECENTLY_UPDATED + } + } + } + + companion object { + fun newInstance(model: FilterIssuesPrsModel) = FilterIssuesPrsBottomSheet().apply { + arguments = bundleOf(EXTRA to model) + } + } + + interface FilterIssuesPrsCallback { + fun onFilterApplied(model: FilterIssuesPrsModel) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/fragment/FilterIssuePullRequestsFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/fragment/FilterIssuePullRequestsFragment.kt new file mode 100644 index 000000000..8d9e35248 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/fragment/FilterIssuePullRequestsFragment.kt @@ -0,0 +1,95 @@ +package com.fastaccess.github.ui.modules.issuesprs.fragment + +import android.os.Bundle +import android.view.View +import androidx.core.os.bundleOf +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.ActivityType +import com.fastaccess.data.model.FragmentType +import com.fastaccess.data.model.parcelable.FilterIssuesPrsModel +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.ui.adapter.MyIssuesPrsAdapter +import com.fastaccess.github.ui.modules.issuesprs.filter.FilterIssuesPrsBottomSheet +import com.fastaccess.github.ui.modules.issuesprs.fragment.viewmodel.FilterIssuePullRequestsViewModel +import com.fastaccess.github.ui.modules.multipurpose.MultiPurposeBottomSheetDialog +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.GITHUB_LINK +import com.fastaccess.github.utils.extensions.isConnected +import com.fastaccess.github.utils.extensions.route +import kotlinx.android.synthetic.main.appbar_center_title_layout.* +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.fab_simple_refresh_list_layout.* +import kotlinx.android.synthetic.main.issues_prs_fragment_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 20.10.18. + */ +class FilterIssuePullRequestsFragment : BaseFragment(), FilterIssuesPrsBottomSheet.FilterIssuesPrsCallback { + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(FilterIssuePullRequestsViewModel::class.java) } + private val adapter by lazy { + MyIssuesPrsAdapter { + val isPr = it.isPr + if (!isPr) { + route("$GITHUB_LINK${it.repoName}/issues/${it.number}") + } + } + } + private val fragmentType by lazy { arguments?.getSerializable(EXTRA) as? FragmentType } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.issues_prs_fragment_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + setupToolbar(when (fragmentType) { + FragmentType.FILTER_PRS -> R.string.pull_requests + else -> R.string.issues + }) + + viewModel.isPr = fragmentType == FragmentType.FILTER_PRS + recyclerView.adapter = adapter + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView, appBar) + if (savedInstanceState == null) isConnected().isTrue { viewModel.loadData(true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.loadData(true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.loadData() } } + filter.setOnClickListener { + val item = viewModel.filterModel.copy() // mutability! + MultiPurposeBottomSheetDialog.show(childFragmentManager, + MultiPurposeBottomSheetDialog.BottomSheetFragmentType.FILTER_ISSUES, item) + } + listenToChanges() + } + + override fun onFilterApplied(model: FilterIssuesPrsModel) { + viewModel.filter(model) + } + + private fun listenToChanges() { + viewModel.data.observeNotNull(this) { + adapter.submitList(it) + } + } + + companion object { + fun newInstance(activityType: ActivityType) = FilterIssuePullRequestsFragment().apply { + arguments = bundleOf(EXTRA to when (activityType) { + ActivityType.FILTER_PR -> FragmentType.FILTER_PRS + else -> FragmentType.FILTER_ISSUES + }) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/fragment/viewmodel/FilterIssuePullRequestsViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/fragment/viewmodel/FilterIssuePullRequestsViewModel.kt new file mode 100644 index 000000000..25f226823 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/issuesprs/fragment/viewmodel/FilterIssuePullRequestsViewModel.kt @@ -0,0 +1,75 @@ +package com.fastaccess.github.ui.modules.issuesprs.fragment.viewmodel + +import androidx.lifecycle.MutableLiveData +import com.apollographql.apollo.api.Input +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.parcelable.FilterIssuesPrsModel +import com.fastaccess.data.persistence.models.MyIssuesPullsModel +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.usecase.issuesprs.FilterIssuesUseCase +import com.fastaccess.github.usecase.issuesprs.FilterPullRequestsUseCase +import javax.inject.Inject + +/** + * Created by Kosh on 20.10.18. + */ +class FilterIssuePullRequestsViewModel @Inject constructor( + private val filterIssuesUseCase: FilterIssuesUseCase, + private val filterPullRequestsUseCase: FilterPullRequestsUseCase +) : BaseViewModel() { + + private var pageInfo: PageInfoModel? = null + var filterModel = FilterIssuesPrsModel() + var isPr = true + set(value) { + field = value + filterModel.isPr = field + } + val list = arrayListOf() + val data = MutableLiveData>() + + override fun onCleared() { + super.onCleared() + filterIssuesUseCase.dispose() + filterPullRequestsUseCase.dispose() + } + + fun loadData(reload: Boolean = false) { + if (reload) { + this.list.clear() + pageInfo = null + } + val pageInfo = pageInfo + if (!reload && (pageInfo != null && !pageInfo.hasNextPage)) return + val cursor = if (hasNext()) pageInfo?.endCursor else null + if (isPr) { + filterPullRequestsUseCase.cursor = Input.optional(cursor) + filterPullRequestsUseCase.filterModel = filterModel + justSubscribe(filterPullRequestsUseCase.buildObservable() + .doOnNext { + onRequestFinished(it) + }) + } else { + filterIssuesUseCase.cursor = Input.optional(cursor) + filterIssuesUseCase.filterModel = filterModel + justSubscribe(filterIssuesUseCase.buildObservable() + .doOnNext { + onRequestFinished(it) + }) + } + } + + private fun onRequestFinished(pair: Pair>) { + this.pageInfo = pair.first + this.list.addAll(pair.second) + this.data.postValue(ArrayList(list)) // create new copy of list as submitList will never be notified + } + + fun filter(model: FilterIssuesPrsModel) { + if (model == filterModel) return + this.filterModel = model + loadData(true) + } + + fun hasNext() = pageInfo?.hasNextPage ?: false +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/main/MainActivity.kt b/app/src/main/java/com/fastaccess/github/ui/modules/main/MainActivity.kt new file mode 100644 index 000000000..30bb89910 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/main/MainActivity.kt @@ -0,0 +1,25 @@ +package com.fastaccess.github.ui.modules.main + +import android.os.Bundle +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseActivity +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.replace +import com.fastaccess.github.ui.modules.main.fragment.MainFragment + +class MainActivity : BaseActivity() { + + override fun layoutRes(): Int = R.layout.activity_main + + override fun onActivityCreatedWithUser(savedInstanceState: Bundle?) { + if (savedInstanceState == null) { + replace(R.id.container, MainFragment.newInstance(), MainFragment.TAG) + } + } + + override fun onBackPressed() { + (supportFragmentManager.findFragmentByTag(MainFragment.TAG) as? MainFragment)?.onBackPressed()?.isTrue { + super.onBackPressed() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/main/fragment/MainFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/main/fragment/MainFragment.kt new file mode 100644 index 000000000..234d840f8 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/main/fragment/MainFragment.kt @@ -0,0 +1,176 @@ +package com.fastaccess.github.ui.modules.main.fragment + +import android.os.Bundle +import android.view.View +import androidx.core.view.isVisible +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.MainScreenModel +import com.fastaccess.data.persistence.models.LoginModel +import com.fastaccess.data.storage.FastHubSharedPreference +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.getDrawable +import com.fastaccess.github.extensions.getDrawableCompat +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.platform.extension.onClick +import com.fastaccess.github.ui.adapter.MainScreenAdapter +import com.fastaccess.github.ui.modules.auth.LoginChooserActivity +import com.fastaccess.github.ui.modules.main.fragment.viewmodel.MainFragmentViewModel +import com.fastaccess.github.ui.modules.multipurpose.MultiPurposeBottomSheetDialog +import com.fastaccess.github.ui.widget.dialog.IconDialogFragment +import com.fastaccess.github.utils.NOTIFICATION_LINK +import com.fastaccess.github.utils.SEARCH_LINK +import com.fastaccess.github.utils.TRENDING_LINK +import com.fastaccess.github.utils.extensions.* +import com.google.android.material.bottomsheet.BottomSheetBehavior +import kotlinx.android.synthetic.main.appbar_logo_center_title_layout.* +import kotlinx.android.synthetic.main.bottm_bar_menu_layout.* +import kotlinx.android.synthetic.main.main_fragment_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 12.06.18. + */ +class MainFragment : BaseFragment(), IconDialogFragment.IconDialogClickListener { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + @Inject lateinit var preference: FastHubSharedPreference + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(MainFragmentViewModel::class.java) } + private val behaviour by lazy { BottomSheetBehavior.from(bottomSheet) } + private val adapter by lazy { MainScreenAdapter(onClickListener()) } + + override fun layoutRes(): Int = R.layout.main_fragment_layout + override fun viewModel(): BaseViewModel? = viewModel + + override fun onFragmentCreatedWithUser( + view: View, + savedInstanceState: Bundle? + ) { + if (savedInstanceState == null) { + isConnected().isTrue { viewModel.load() } + } + setupToolbar(R.string.app_name) + toolbar.navigationIcon = null + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + viewModel.load() + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.adapter = adapter + bottomBar.inflateMenu(R.menu.main_bottom_bar_menu) + behaviour.setBottomSheetCallback({ state: Int -> + when (state) { + BottomSheetBehavior.STATE_EXPANDED -> { + shadow?.isVisible = false + bottomBar.navigationIcon = requireContext().getDrawableCompat(R.drawable.ic_arrow_drop_down) + } + BottomSheetBehavior.STATE_COLLAPSED -> { + shadow?.isVisible = true + bottomBar.navigationIcon = requireContext().getDrawableCompat(R.drawable.ic_menu) + } + } + }) + listenToDataChanges() + initClicks() + } + + override fun onBackPressed(): Boolean { + return if (behaviour.state == BottomSheetBehavior.STATE_COLLAPSED) { + true + } else { + behaviour.state = BottomSheetBehavior.STATE_COLLAPSED + false + } + } + + override fun onClick(positive: Boolean) { + positive.isTrue { viewModel.logout() } + } + + private fun initClicks() { + bottomBar.setOnMenuItemClickListener { item -> + when (item.itemId) { + R.id.profile -> addDisposal(viewModel.login.subscribe({ route(it?.htmlUrl) }, ::print)) + R.id.notifications -> route(NOTIFICATION_LINK) + R.id.search -> route(SEARCH_LINK) + } + return@setOnMenuItemClickListener true + } + navigationView.setNavigationItemSelectedListener { + behaviour.state = BottomSheetBehavior.STATE_COLLAPSED + when (it.itemId) { + R.id.logout -> IconDialogFragment.show( + childFragmentManager, R.drawable.ic_info_outline, getString(R.string.logout), + getString(R.string.confirm_message), getString(R.string.logout), getString(R.string.cancel) + ) + R.id.add_account -> LoginChooserActivity.startActivity(requireActivity(), false) + } + return@setNavigationItemSelectedListener true + } + bottomBar.setNavigationOnClickListener { + behaviour.apply { + state = if (state == BottomSheetBehavior.STATE_EXPANDED) { + BottomSheetBehavior.STATE_COLLAPSED + } else { + BottomSheetBehavior.STATE_EXPANDED + } + } + } + starred.setOnClickListener { onUserRetrieved { route(it?.toStarred()) } } + repos.setOnClickListener { onUserRetrieved { route(it?.toRepos()) } } + gists.setOnClickListener { onUserRetrieved { route(it?.toGists()) } } + orgs.setOnClickListener { + MultiPurposeBottomSheetDialog.show( + childFragmentManager, + MultiPurposeBottomSheetDialog.BottomSheetFragmentType.ORGANIZATIONS + ) + } + trending.setOnClickListener { route(TRENDING_LINK) } + } + + private fun onUserRetrieved(action: (user: LoginModel?) -> Unit) { + addDisposal( + viewModel.login + .subscribe({ action(it) }, ::print) + ) + } + + private fun listenToDataChanges() { + viewModel.progress.observeNotNull(this) { + swipeRefresh.isRefreshing = it == true + } + viewModel.list.observeNotNull(this) { + adapter.submitList(it.distinct()) + } + viewModel.logoutProcess.observeNotNull(this) { + if (it) { + preference.token = null + preference.otpCode = null + LoginChooserActivity.startActivity(requireActivity()) + } + } + viewModel.unreadNotificationLiveData.observeNotNull(this) { + bottomBar.menu?.findItem(R.id.notifications)?.icon = if (it) { + getDrawable(R.drawable.ic_notification_unread) + } else { + getDrawable(R.drawable.ic_notifications_none) + } + } + } + + private fun onClickListener(): (MainScreenModel) -> Unit { + return { model: MainScreenModel -> + model.onClick(this) + } + } + + companion object { + const val TAG = "MainFragment" + fun newInstance(): MainFragment = MainFragment() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/main/fragment/viewmodel/MainFragmentViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/main/fragment/viewmodel/MainFragmentViewModel.kt new file mode 100644 index 000000000..37bdea9f1 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/main/fragment/viewmodel/MainFragmentViewModel.kt @@ -0,0 +1,137 @@ +package com.fastaccess.github.ui.modules.main.fragment.viewmodel + +import androidx.lifecycle.LiveData +import com.fastaccess.data.model.FastHubErrors +import com.fastaccess.data.model.MainScreenModel +import com.fastaccess.data.model.MainScreenModelRowType +import com.fastaccess.data.persistence.db.FastHubDatabase +import com.fastaccess.data.persistence.models.FeedModel +import com.fastaccess.data.repository.FeedsRepositoryProvider +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.data.repository.MyIssuesPullsRepositoryProvider +import com.fastaccess.data.repository.NotificationRepositoryProvider +import com.fastaccess.extension.uiThread +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.map +import com.fastaccess.github.extensions.switchMap +import com.fastaccess.github.usecase.main.FeedsMainScreenUseCase +import com.fastaccess.github.usecase.main.IssuesMainScreenUseCase +import com.fastaccess.github.usecase.main.PullRequestsMainScreenUseCase +import com.fastaccess.github.usecase.notification.NotificationUseCase +import io.reactivex.Observable +import javax.inject.Inject + +@Suppress("HasPlatformType") +/** + * Created by Kosh on 16.06.18. + */ +class MainFragmentViewModel @Inject constructor( + private val issuesMainScreenUseCase: IssuesMainScreenUseCase, + private val pullRequestsMainScreenUseCase: PullRequestsMainScreenUseCase, + private val notificationUseCase: NotificationUseCase, + private val feedsMainScreenUseCase: FeedsMainScreenUseCase, + private val feedsRepositoryProvider: FeedsRepositoryProvider, + private val myIssuesPullsRepo: MyIssuesPullsRepositoryProvider, + private val notificationRepositoryProvider: NotificationRepositoryProvider, + private val fasthubDatabase: FastHubDatabase, + private val loginProvider: LoginRepositoryProvider +) : BaseViewModel() { + + val login = loginProvider.getLogin() + + val list: LiveData> by lazy { + feedsRepositoryProvider.getMainFeedsAsLiveData() + .map(mapFeed()) + .switchMap(mapNotifications()) + .switchMap(mapIssues()) + .switchMap(mapPulls()) + } + + val unreadNotificationLiveData = notificationRepositoryProvider.getMainNotifications().map { it.firstOrNull { it.unread == true } != null } + + fun load() { + feedsMainScreenUseCase.executeSafely(callApi( + feedsMainScreenUseCase.buildObservable() + .flatMap { notificationUseCase.buildObservable() } + .flatMap { issuesMainScreenUseCase.buildObservable() } + .flatMap { pullRequestsMainScreenUseCase.buildObservable() } + )) + } + + fun logout() { + add(Observable.fromCallable { + fasthubDatabase.clearAll() + loginProvider.logoutAll() + } + .uiThread() + .subscribe({ logoutProcess.postValue(true) }, + { error.postValue(FastHubErrors(FastHubErrors.ErrorType.OTHER, it.message)) }) + ) + } + + override fun onCleared() { + super.onCleared() + notificationUseCase.dispose() + issuesMainScreenUseCase.dispose() + pullRequestsMainScreenUseCase.dispose() + feedsMainScreenUseCase.dispose() + } + + /** + * Fixes Cannot infer a type for this parameter. Please specify it explicitly. 🤷‍🤷‍🤷‍🤷‍🤷‍🤷‍ + */ + private fun mapPulls(): (ArrayList) -> LiveData> { + return { list -> + myIssuesPullsRepo.getMainScreenPulls().map { prs -> + if (prs.isEmpty()) return@map list + list.add(MainScreenModel(MainScreenModelRowType.PRS_TITLE)) + list.addAll(prs.asSequence().map { MainScreenModel(MainScreenModelRowType.PRS, issuesPullsModel = it) }.toList()) + return@map list + } + } + } + + /** + * Fixes Cannot infer a type for this parameter. Please specify it explicitly. 🤷‍🤷‍🤷‍🤷‍🤷‍🤷‍ + */ + private fun mapIssues(): (ArrayList) -> LiveData> { + return { list -> + myIssuesPullsRepo.getMainScreenIssues().map { issues -> + if (issues.isEmpty()) return@map list + list.add(MainScreenModel(MainScreenModelRowType.ISSUES_TITLE)) + list.addAll(issues.asSequence().map { MainScreenModel(MainScreenModelRowType.ISSUES, issuesPullsModel = it) }.toList()) + return@map list + } + } + } + + /** + * Fixes Cannot infer a type for this parameter. Please specify it explicitly. 🤷‍🤷‍🤷‍🤷‍🤷‍🤷‍ + */ + private fun mapNotifications(): (ArrayList) -> LiveData> { + return { list -> + notificationRepositoryProvider.getMainNotifications().map { notifications -> + if (notifications.isEmpty()) return@map list + list.add(MainScreenModel(MainScreenModelRowType.NOTIFICATION_TITLE, + hasBubble = notifications.firstOrNull { it.unread == true } != null)) + list.addAll(notifications.asSequence().map { MainScreenModel(MainScreenModelRowType.NOTIFICATION, notificationModel = it) }.toList()) + return@map list + } + } + } + + /** + * Fixes Cannot infer a type for this parameter. Please specify it explicitly. 🤷‍🤷‍🤷‍🤷‍🤷‍🤷‍ + */ + private fun mapFeed(): (List) -> ArrayList { + return { feeds -> + val list = arrayListOf() + if (feeds.isNotEmpty()) { + list.add(MainScreenModel(MainScreenModelRowType.FEED_TITLE)) + list.addAll(feeds.asSequence().map { MainScreenModel(MainScreenModelRowType.FEED, feed = it) }.toList()) + } + list + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/multipurpose/MultiPurposeActivity.kt b/app/src/main/java/com/fastaccess/github/ui/modules/multipurpose/MultiPurposeActivity.kt new file mode 100644 index 000000000..41e3b1f9d --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/multipurpose/MultiPurposeActivity.kt @@ -0,0 +1,52 @@ +package com.fastaccess.github.ui.modules.multipurpose + +import android.os.Bundle +import com.evernote.android.state.State +import com.fastaccess.data.model.ActivityType +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseActivity +import com.fastaccess.github.platform.deeplink.AppDeepLink +import com.fastaccess.github.ui.modules.feed.fragment.FeedsFragment +import com.fastaccess.github.ui.modules.issuesprs.fragment.FilterIssuePullRequestsFragment +import com.fastaccess.github.ui.modules.notifications.NotificationPagerFragment +import com.fastaccess.github.ui.modules.search.fragment.SearchFragment +import com.fastaccess.github.extensions.fromDeepLink +import com.fastaccess.github.extensions.replace + +/** + * Created by Kosh on 20.10.18. + */ +@AppDeepLink("/me/{what}") +class MultiPurposeActivity : BaseActivity() { + + @State var activityType: ActivityType? = null + + override fun layoutRes(): Int = R.layout.fragment_activity_layout + + override fun onActivityCreatedWithUser(savedInstanceState: Bundle?) { + if (savedInstanceState == null) { + if (!fromDeepLink()) { + finish() + return + } + activityType = ActivityType.getTypeSafely(intent?.getStringExtra("what")) + activityType?.let { activityType -> + when (activityType) { + ActivityType.FEEDS -> replace(R.id.container, FeedsFragment.newInstance()) + ActivityType.NOTIFICATION -> replace(R.id.container, NotificationPagerFragment.newInstance()) + ActivityType.FILTER_ISSUE, ActivityType.FILTER_PR -> replace(R.id.container, + FilterIssuePullRequestsFragment.newInstance(activityType)) + ActivityType.SEARCH -> replace(R.id.container, SearchFragment.newInstance()) + } + } ?: run { + finish() + return@run + } + } + val activityType = activityType + if (activityType == null) { + finish() + return + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/multipurpose/MultiPurposeBottomSheetDialog.kt b/app/src/main/java/com/fastaccess/github/ui/modules/multipurpose/MultiPurposeBottomSheetDialog.kt new file mode 100644 index 000000000..9cceade60 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/multipurpose/MultiPurposeBottomSheetDialog.kt @@ -0,0 +1,80 @@ +package com.fastaccess.github.ui.modules.multipurpose + +import android.os.Bundle +import android.os.Parcelable +import android.view.View +import androidx.core.os.bundleOf +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.commit +import com.fastaccess.data.model.parcelable.FilterIssuesPrsModel +import com.fastaccess.data.model.parcelable.FilterSearchModel +import com.fastaccess.data.model.parcelable.FilterTrendingModel +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseBottomSheetDialogFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.show +import com.fastaccess.github.ui.modules.issuesprs.edit.LockUnlockFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.assignees.AssigneesFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.labels.LabelsFragment +import com.fastaccess.github.ui.modules.issuesprs.edit.milestone.MilestoneFragment +import com.fastaccess.github.ui.modules.issuesprs.filter.FilterIssuesPrsBottomSheet +import com.fastaccess.github.ui.modules.multipurpose.MultiPurposeBottomSheetDialog.BottomSheetFragmentType.* +import com.fastaccess.github.ui.modules.profile.orgs.userorgs.UserOrgsFragment +import com.fastaccess.github.ui.modules.search.filter.FilterSearchBottomSheet +import com.fastaccess.github.ui.modules.trending.filter.FilterTrendingBottomSheet +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.EXTRA_TWO + +/** + * Created by Kosh on 2018-11-25. + */ +class MultiPurposeBottomSheetDialog : BaseBottomSheetDialogFragment() { + + override fun layoutRes(): Int = R.layout.fragment_activity_layout + private val type by lazy { arguments?.getSerializable(EXTRA) as? BottomSheetFragmentType? } + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + if (savedInstanceState == null) { + childFragmentManager.commit { + when (type) { + ORGANIZATIONS -> replace(R.id.container, UserOrgsFragment.newInstance(), "UserOrgsFragment") + FILTER_ISSUES, FILTER_PRS -> + replace(R.id.container, FilterIssuesPrsBottomSheet + .newInstance(arguments?.getParcelable(EXTRA_TWO) ?: FilterIssuesPrsModel()), "FilterIssuesPrsBottomSheet") + FILTER_SEARCH -> replace(R.id.container, FilterSearchBottomSheet + .newInstance(arguments?.getParcelable(EXTRA_TWO) ?: FilterSearchModel()), "FilterSearchBottomSheet") + TRENDING -> replace(R.id.container, + FilterTrendingBottomSheet.newInstance(arguments?.getParcelable(EXTRA_TWO) + ?: FilterTrendingModel()), "FilterTrendingBottomSheet") + LOCK_UNLOCK -> replace(R.id.container, LockUnlockFragment.newInstance(), "LockUnlockFragment") + LABELS -> replace(R.id.container, + LabelsFragment.newInstance(arguments?.getParcelable(EXTRA_TWO)), "LabelsFragment") + ASSIGNEES -> replace(R.id.container, + AssigneesFragment.newInstance(arguments?.getParcelable(EXTRA_TWO)), "AssigneesFragment") + MILESTONE -> replace(R.id.container, + MilestoneFragment.newInstance(arguments?.getParcelable(EXTRA_TWO)), "MilestoneFragment") + null -> dialog?.dismiss() + } + } + } + } + + override fun viewModel(): BaseViewModel? = null + + companion object { + fun show(fragmentManager: FragmentManager, type: BottomSheetFragmentType, parcelable: Parcelable? = null) { + MultiPurposeBottomSheetDialog() + .apply { + arguments = bundleOf(EXTRA to type).apply { + if (parcelable != null) putParcelable(EXTRA_TWO, parcelable) + } + show(fragmentManager) + } + } + } + + enum class BottomSheetFragmentType { + ORGANIZATIONS, FILTER_ISSUES, FILTER_PRS, FILTER_SEARCH, + TRENDING, LOCK_UNLOCK, LABELS, ASSIGNEES, MILESTONE + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/notifications/NotificationPagerFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/notifications/NotificationPagerFragment.kt new file mode 100644 index 000000000..8e7b67864 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/notifications/NotificationPagerFragment.kt @@ -0,0 +1,61 @@ +package com.fastaccess.github.ui.modules.notifications + +import android.os.Bundle +import android.view.MenuItem +import android.view.View +import androidx.core.os.bundleOf +import androidx.viewpager.widget.ViewPager +import com.fastaccess.data.model.FragmentType +import com.fastaccess.data.model.ViewPagerModel +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BasePagerFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.ui.adapter.PagerAdapter +import com.fastaccess.github.ui.modules.notifications.fragment.read.AllNotificationsFragment +import com.fastaccess.github.ui.modules.notifications.fragment.unread.UnreadNotificationsFragment +import com.fastaccess.github.utils.EXTRA +import kotlinx.android.synthetic.main.appbar_tabs_center_title_layout.* +import kotlinx.android.synthetic.main.toolbar_fragment_pager_layout.* + +/** + * Created by Kosh on 04.11.18. + */ +class NotificationPagerFragment : BasePagerFragment() { + override fun viewModel(): BaseViewModel? = null + override fun layoutRes(): Int = R.layout.toolbar_fragment_pager_layout + override fun onPageSelected(page: Int) = (pager.adapter?.instantiateItem(pager, page) as? BaseFragment)?.onScrollToTop() ?: Unit + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + setupToolbar(R.string.notifications, R.menu.notification_menu) { item: MenuItem -> + if (item.itemId == R.id.markAllAsRead) { + (pager.adapter?.instantiateItem(pager, 0) as? UnreadNotificationsFragment)?.markAllAsRead() + } + } + + pager.isEnabled = false + pager.adapter = PagerAdapter(childFragmentManager, arrayListOf( + ViewPagerModel(getString(R.string.unread), UnreadNotificationsFragment.newInstance(), FragmentType.UNREAD_NOTIFICATIONS), + ViewPagerModel(getString(R.string.read), AllNotificationsFragment.newInstance(), FragmentType.ALL_NOTIFICATIONS) + )) + tabs.setupWithViewPager(pager) + if (savedInstanceState == null) { + FragmentType.getTypeSafely(arguments?.getString(EXTRA) ?: "")?.let { + val index = (pager.adapter as PagerAdapter).getIndex(it) + if (index >= 0) pager.currentItem = index + } + } + pager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() { + override fun onPageSelected(position: Int) { + super.onPageSelected(position) + toolbar?.menu?.findItem(R.id.markAllAsRead)?.isVisible = position == 0 + } + }) + toolbar?.menu?.findItem(R.id.markAllAsRead)?.isVisible = pager.currentItem == 0 + } + + companion object { + fun newInstance(page: String? = FragmentType.UNREAD_NOTIFICATIONS.tabName) = NotificationPagerFragment().apply { + arguments = bundleOf(Pair(EXTRA, page)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/read/AllNotificationsFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/read/AllNotificationsFragment.kt new file mode 100644 index 000000000..caabcf677 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/read/AllNotificationsFragment.kt @@ -0,0 +1,55 @@ +package com.fastaccess.github.ui.modules.notifications.fragment.read + +import android.os.Bundle +import android.view.View +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.ui.adapter.AllNotificationsAdapter +import com.fastaccess.github.ui.modules.notifications.NotificationPagerFragment +import com.fastaccess.github.utils.extensions.isConnected +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 04.11.18. + */ +class AllNotificationsFragment : BaseFragment() { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(AllNotificationsViewModel::class.java) } + private val adapter by lazy { AllNotificationsAdapter() } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.simple_refresh_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + recyclerView.adapter = adapter + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView, (parentFragment as? NotificationPagerFragment)?.view?.findViewById(R.id.appBar)) + if (savedInstanceState == null) isConnected().isTrue { viewModel.loadNotifications() } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + viewModel.loadNotifications() + } else { + swipeRefresh.isRefreshing = false + } + } + listenToChanges() + } + + private fun listenToChanges() { + viewModel.data.observeNotNull(this) { + adapter.submitList(it) + } + } + + companion object { + fun newInstance() = AllNotificationsFragment() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/read/AllNotificationsViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/read/AllNotificationsViewModel.kt new file mode 100644 index 000000000..ffbb898c0 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/read/AllNotificationsViewModel.kt @@ -0,0 +1,25 @@ +package com.fastaccess.github.ui.modules.notifications.fragment.read + +import androidx.lifecycle.LiveData +import com.fastaccess.data.model.GroupedNotificationsModel +import com.fastaccess.data.repository.NotificationRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.usecase.notification.NotificationUseCase +import javax.inject.Inject + +/** + * Created by Kosh on 04.11.18. + */ +class AllNotificationsViewModel @Inject constructor( + provider: NotificationRepositoryProvider, + private val usecase: NotificationUseCase +) : BaseViewModel() { + + val data: LiveData> = provider.getAllNotifications() + + fun loadNotifications() { + usecase.all = true + add(callApi(usecase.buildObservable()) + .subscribe({}, ::println)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/unread/UnreadNotificationsFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/unread/UnreadNotificationsFragment.kt new file mode 100644 index 000000000..bc237f885 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/unread/UnreadNotificationsFragment.kt @@ -0,0 +1,94 @@ +package com.fastaccess.github.ui.modules.notifications.fragment.unread + +import android.os.Bundle +import android.view.View +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import androidx.recyclerview.widget.ItemTouchHelper +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.platform.works.MarkAsReadNotificationWorker +import com.fastaccess.github.ui.adapter.UnreadNotificationsAdapter +import com.fastaccess.github.ui.adapter.base.CurrentState +import com.fastaccess.github.ui.modules.notifications.NotificationPagerFragment +import com.fastaccess.github.ui.modules.notifications.fragment.unread.viewmodel.UnreadNotificationsViewModel +import com.fastaccess.github.ui.widget.recyclerview.SwipeToDeleteCallback +import com.fastaccess.github.utils.extensions.isConnected +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 21.10.18. + */ +class UnreadNotificationsFragment : BaseFragment() { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(UnreadNotificationsViewModel::class.java) } + private val adapter by lazy { UnreadNotificationsAdapter() } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.simple_refresh_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + recyclerView.adapter = adapter + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView, (parentFragment as? NotificationPagerFragment)?.view?.findViewById(R.id.appBar)) + if (savedInstanceState == null) isConnected().isTrue { viewModel.loadNotifications(true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.loadNotifications(true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.loadNotifications() } } + listenToChanges() + + val swipeCallback = SwipeToDeleteCallback { viewHolder, _ -> + adapter.getValue(viewHolder.adapterPosition)?.let { + if (it.unread == true) { + MarkAsReadNotificationWorker.enqueue(it.id) + viewModel.markAsRead(it.id) + } + } + } + + val itemTouchHelper = ItemTouchHelper(swipeCallback) + itemTouchHelper.attachToRecyclerView(recyclerView) + } + + fun markAllAsRead() { + addDisposal(viewModel.getAllUnreadNotifications() + .subscribe({ list -> + if (list.isNullOrEmpty()) return@subscribe + list.map { it.id }.toTypedArray().let { + MarkAsReadNotificationWorker.enqueue(ids = it) + } + viewModel.markAllAsRead() + }, { + it.printStackTrace() + })) + } + + private fun listenToChanges() { + + viewModel.progress.observeNotNull(this) { + adapter.currentState = if (it) CurrentState.LOADING else CurrentState.DONE + } + + viewModel.notifications().observeNotNull(this) { + adapter.currentState = CurrentState.DONE + adapter.submitList(it) + } + } + + companion object { + fun newInstance() = UnreadNotificationsFragment() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/unread/viewmodel/UnreadNotificationsViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/unread/viewmodel/UnreadNotificationsViewModel.kt new file mode 100644 index 000000000..7c8fa6c04 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/notifications/fragment/unread/viewmodel/UnreadNotificationsViewModel.kt @@ -0,0 +1,52 @@ +package com.fastaccess.github.ui.modules.notifications.fragment.unread.viewmodel + +import androidx.lifecycle.LiveData +import androidx.paging.LivePagedListBuilder +import androidx.paging.PagedList +import com.fastaccess.data.persistence.models.NotificationModel +import com.fastaccess.data.repository.NotificationRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.usecase.notification.NotificationUseCase +import javax.inject.Inject + +/** + * Created by Kosh on 31.10.18. + */ +class UnreadNotificationsViewModel @Inject constructor( + private val provider: NotificationRepositoryProvider, + private val usecase: NotificationUseCase +) : BaseViewModel() { + + private var currentPage = 0 + private var isLastPage = false + + fun notifications(): LiveData> { + val dataSourceFactory = provider.getNotifications(true) + val config = PagedList.Config.Builder() + .setPrefetchDistance(com.fastaccess.github.utils.PRE_FETCH_SIZE) + .setPageSize(com.fastaccess.github.utils.PAGE_SIZE) + .build() + return LivePagedListBuilder(dataSourceFactory, config) + .build() + } + + fun loadNotifications(reload: Boolean = false) { + if (reload) { + currentPage = 0 + isLastPage = false + } + currentPage++ + if (!reload && isLastPage) return + usecase.page = currentPage + add(callApi(usecase.buildObservable()) + .subscribe({ + isLastPage = it.last == currentPage + }, ::println)) + } + + fun markAsRead(id: String) = add(provider.markAsRead(id).subscribe()) + fun markAllAsRead() = add(provider.markAllAsRead().subscribe({}, { it.printStackTrace() })) + fun getAllUnreadNotifications() = provider.getAllNotificationsAsMaybe(true) + + fun hasNext() = isLastPage +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/ProfileActivity.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/ProfileActivity.kt new file mode 100644 index 000000000..fb886bde0 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/ProfileActivity.kt @@ -0,0 +1,35 @@ +package com.fastaccess.github.ui.modules.profile + +import android.os.Bundle +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseActivity +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.platform.deeplink.WebDeepLink +import com.fastaccess.github.ui.modules.profile.fragment.ProfileFragment +import com.fastaccess.github.extensions.replace + +/** + * Created by Kosh on 18.08.18. + */ +@WebDeepLink("/{login}", "/users/{login}") +class ProfileActivity : BaseActivity() { + override fun layoutRes(): Int = R.layout.activity_main + + override fun onActivityCreatedWithUser(savedInstanceState: Bundle?) { + if (savedInstanceState == null && intent != null) { + val login = intent?.extras?.getString("login") + val tab = intent?.extras?.getString("tab") + if (login == null) { + finish() + return + } + replace(R.id.container, ProfileFragment.newInstance(login, tab), ProfileFragment.TAG) + } + } + + override fun onBackPressed() { + (supportFragmentManager.findFragmentByTag(ProfileFragment.TAG) as? ProfileFragment)?.onBackPressed()?.isTrue { + super.onBackPressed() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/feeds/ProfileFeedFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/feeds/ProfileFeedFragment.kt new file mode 100644 index 000000000..26a9adcb0 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/feeds/ProfileFeedFragment.kt @@ -0,0 +1,82 @@ +package com.fastaccess.github.ui.modules.profile.feeds + +import android.os.Bundle +import android.view.View +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.FragmentType +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.platform.extension.onClick +import com.fastaccess.github.ui.adapter.ProfileFeedsAdapter +import com.fastaccess.github.ui.adapter.base.CurrentState +import com.fastaccess.github.ui.modules.profile.feeds.viewmodel.ProfileFeedsViewModel +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.extensions.addDivider +import com.fastaccess.github.extensions.isConnected +import com.fastaccess.github.utils.extensions.isConnected +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 20.10.18. + */ +class ProfileFeedFragment : BaseFragment() { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(ProfileFeedsViewModel::class.java) } + private val loginBundle: String by lazy { arguments?.getString(EXTRA) ?: "" } + private val adapter by lazy { + ProfileFeedsAdapter { + it.onClick(this) + } + } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.simple_refresh_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + recyclerView.adapter = adapter + recyclerView.addDivider() + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView) + if (savedInstanceState == null) isConnected().isTrue { viewModel.loadFeeds(loginBundle, true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.loadFeeds(loginBundle, true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.loadFeeds(loginBundle) } } + listenToChanges() + } + + private fun listenToChanges() { + viewModel.progress.observeNotNull(this) { + adapter.currentState = if (it) CurrentState.LOADING else CurrentState.DONE + } + + viewModel.feeds(loginBundle).observeNotNull(this) { + adapter.currentState = CurrentState.DONE + adapter.submitList(it) + } + + viewModel.counter.observeNotNull(this) { + postCount(FragmentType.FEEDS, it) + } + } + + companion object { + fun newInstance(login: String) = ProfileFeedFragment().apply { + arguments = Bundle().apply { + putString(EXTRA, login) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/feeds/viewmodel/ProfileFeedsViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/feeds/viewmodel/ProfileFeedsViewModel.kt new file mode 100644 index 000000000..fd02f1535 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/feeds/viewmodel/ProfileFeedsViewModel.kt @@ -0,0 +1,49 @@ +package com.fastaccess.github.ui.modules.profile.feeds.viewmodel + +import androidx.lifecycle.LiveData +import androidx.paging.LivePagedListBuilder +import androidx.paging.PagedList +import com.fastaccess.data.persistence.models.FeedModel +import com.fastaccess.data.repository.FeedsRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.usecase.user.UserFeedsUseCase +import javax.inject.Inject + +/** + * Created by Kosh on 20.10.18. + */ +class ProfileFeedsViewModel @Inject constructor( + private val provider: FeedsRepositoryProvider, + private val usecase: UserFeedsUseCase +) : BaseViewModel() { + + private var currentPage = 0 + private var isLastPage = false + + fun feeds(login: String): LiveData> { + val dataSourceFactory = provider.getFeeds(login) + val config = PagedList.Config.Builder() + .setPrefetchDistance(com.fastaccess.github.utils.PRE_FETCH_SIZE) + .setPageSize(com.fastaccess.github.utils.PAGE_SIZE) + .build() + return LivePagedListBuilder(dataSourceFactory, config) + .build() + } + + fun loadFeeds(login: String, reload: Boolean = false) { + if (reload) { + currentPage = 0 + isLastPage = false + } + currentPage++ + if (!reload && isLastPage) return + usecase.page = currentPage + usecase.login = login + add(callApi(usecase.buildObservable()) + .subscribe({ + isLastPage = it.last == currentPage + }, ::println)) + } + + fun hasNext() = isLastPage +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/followersandfollowings/ProfileFollowersFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/followersandfollowings/ProfileFollowersFragment.kt new file mode 100644 index 000000000..c23afce91 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/followersandfollowings/ProfileFollowersFragment.kt @@ -0,0 +1,81 @@ +package com.fastaccess.github.ui.modules.profile.followersandfollowings + +import android.os.Bundle +import android.view.View +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.FragmentType +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.ui.adapter.ProfileFollowingFollowersAdapter +import com.fastaccess.github.ui.adapter.base.CurrentState +import com.fastaccess.github.ui.modules.profile.followersandfollowings.viewmodel.FollowersFollowingViewModel +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.EXTRA_TWO +import com.fastaccess.github.extensions.isConnected +import com.fastaccess.github.utils.extensions.addKeyLineDivider +import com.fastaccess.github.utils.extensions.isConnected +import com.fastaccess.github.utils.extensions.route +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 15.10.18. + */ +class ProfileFollowersFragment : BaseFragment() { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(FollowersFollowingViewModel::class.java) } + private val loginBundle: String by lazy { arguments?.getString(EXTRA) ?: "" } + private val isFollowers: Boolean by lazy { arguments?.getBoolean(EXTRA_TWO) ?: false } + private val adapter by lazy { ProfileFollowingFollowersAdapter { url -> route(url) } } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.simple_refresh_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + recyclerView.adapter = adapter + recyclerView.addKeyLineDivider() + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView) + if (savedInstanceState == null) isConnected().isTrue { viewModel.loadUsers(loginBundle, isFollowers, true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.loadUsers(loginBundle, isFollowers, true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.loadUsers(loginBundle, isFollowers) } } + listenToChanges() + } + + private fun listenToChanges() { + viewModel.progress.observeNotNull(this) { + adapter.currentState = if (it) CurrentState.LOADING else CurrentState.DONE + } + + viewModel.getUsers(loginBundle, isFollowers).observeNotNull(this) { + adapter.currentState = CurrentState.DONE + adapter.submitList(it) + } + + viewModel.counter.observeNotNull(this) { + postCount(if (isFollowers) FragmentType.FOLLOWERS else FragmentType.FOLLOWINGS, it) + } + } + + companion object { + fun newInstance(login: String, isFollowers: Boolean) = ProfileFollowersFragment().apply { + arguments = Bundle().apply { + putString(EXTRA, login) + putBoolean(EXTRA_TWO, isFollowers) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/followersandfollowings/viewmodel/FollowersFollowingViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/followersandfollowings/viewmodel/FollowersFollowingViewModel.kt new file mode 100644 index 000000000..993358f2f --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/followersandfollowings/viewmodel/FollowersFollowingViewModel.kt @@ -0,0 +1,51 @@ +package com.fastaccess.github.ui.modules.profile.followersandfollowings.viewmodel + +import androidx.lifecycle.LiveData +import androidx.paging.LivePagedListBuilder +import androidx.paging.PagedList +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.persistence.models.FollowingFollowerModel +import com.fastaccess.data.repository.UserFollowersFollowingRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import javax.inject.Inject + +/** + * Created by Kosh on 15.10.18. + */ +class FollowersFollowingViewModel @Inject constructor( + private val provider: UserFollowersFollowingRepositoryProvider +) : BaseViewModel() { + + private var pageInfo: PageInfoModel? = null + + fun getUsers(login: String, isFollowers: Boolean): LiveData> { + val dataSourceFactory = provider.getFollowersOrFollowing(login, isFollowers) + val config = PagedList.Config.Builder() + .setPrefetchDistance(com.fastaccess.github.utils.PRE_FETCH_SIZE) + .setPageSize(com.fastaccess.github.utils.PAGE_SIZE) + .build() + return LivePagedListBuilder(dataSourceFactory, config) + .build() + } + + fun loadUsers(login: String, isFollowers: Boolean, reload: Boolean = false) { + if (reload) { + pageInfo = null + } + val pageInfo = pageInfo + if (!reload && (pageInfo != null && !pageInfo.hasNextPage)) return + val cursor = if (hasNext()) pageInfo?.endCursor else null + val observable = if (isFollowers) { + provider.getFollowersFromRemote(login, cursor) + } else { + provider.getFollowingFromRemote(login, cursor) + } + add(callApi(observable) + .subscribe({ + this.pageInfo = it.pageInfo + postCounter(it.totalCount) + }, { it.printStackTrace() })) + } + + fun hasNext() = pageInfo?.hasNextPage == true +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/fragment/ProfileFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/fragment/ProfileFragment.kt new file mode 100644 index 000000000..9c52d7805 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/fragment/ProfileFragment.kt @@ -0,0 +1,229 @@ +package com.fastaccess.github.ui.modules.profile.fragment + +import android.annotation.SuppressLint +import android.os.Bundle +import android.view.View +import androidx.core.view.isVisible +import androidx.core.widget.NestedScrollView +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.FragmentType +import com.fastaccess.data.model.ViewPagerModel +import com.fastaccess.data.persistence.models.UserModel +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.data.repository.isMe +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BasePagerFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.extensions.observeNull +import com.fastaccess.github.extensions.timeAgo +import com.fastaccess.github.ui.adapter.PagerAdapter +import com.fastaccess.github.ui.adapter.ProfileOrgsAdapter +import com.fastaccess.github.ui.adapter.ProfilePinnedReposAdapter +import com.fastaccess.github.ui.modules.profile.feeds.ProfileFeedFragment +import com.fastaccess.github.ui.modules.profile.followersandfollowings.ProfileFollowersFragment +import com.fastaccess.github.ui.modules.profile.fragment.viewmodel.ProfileViewModel +import com.fastaccess.github.ui.modules.profile.gists.ProfileGistsFragment +import com.fastaccess.github.ui.modules.profile.repos.ProfileReposFragment +import com.fastaccess.github.ui.modules.profile.starred.ProfileStarredReposFragment +import com.fastaccess.github.ui.widget.AnchorSheetBehavior +import com.fastaccess.github.ui.widget.recyclerview.lm.SafeGridLayoutManager +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.EXTRA_TWO +import com.fastaccess.github.utils.extensions.addDivider +import com.fastaccess.github.extensions.getDrawable +import com.fastaccess.github.extensions.isConnected +import com.fastaccess.github.utils.extensions.isConnected +import com.fastaccess.github.utils.extensions.setBottomSheetCallback +import com.github.zagum.expandicon.ExpandIconView +import com.google.android.material.tabs.TabLayout +import kotlinx.android.synthetic.main.appbar_center_title_layout_bottomsheet.* +import kotlinx.android.synthetic.main.profile_bottom_sheet.* +import kotlinx.android.synthetic.main.profile_fragment_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 18.08.18. + */ +class ProfileFragment : BasePagerFragment() { + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + @Inject lateinit var loginRepositoryProvider: LoginRepositoryProvider + + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(ProfileViewModel::class.java) } + private val behaviour by lazy { AnchorSheetBehavior.from(bottomSheet) } + private val adapter by lazy { + PagerAdapter(childFragmentManager, arrayListOf( + ViewPagerModel(getString(R.string.feeds), ProfileFeedFragment.newInstance(loginBundle), FragmentType.FEEDS), + ViewPagerModel(getString(R.string.repos), ProfileReposFragment.newInstance(loginBundle), FragmentType.REPOS), + ViewPagerModel(getString(R.string.starred), ProfileStarredReposFragment.newInstance(loginBundle), FragmentType.STARRED), + ViewPagerModel(getString(R.string.gists), ProfileGistsFragment.newInstance(loginBundle), FragmentType.GISTS), + ViewPagerModel(getString(R.string.followers), ProfileFollowersFragment.newInstance(loginBundle, true), FragmentType.FOLLOWERS), + ViewPagerModel(getString(R.string.following), ProfileFollowersFragment.newInstance(loginBundle, false), FragmentType.FOLLOWINGS) + )) + } + private val pinnedReposAdapter by lazy { ProfilePinnedReposAdapter(arrayListOf()) } + private val orgsAdapter by lazy { ProfileOrgsAdapter(arrayListOf()) } + private val loginBundle: String by lazy { arguments?.getString(EXTRA) ?: "" } + private val tabBundle: String? by lazy { + val tabPosition = arguments?.getString(EXTRA_TWO) + arguments?.remove(EXTRA_TWO) // get this only once and then remove it from the bundle. + return@lazy tabPosition + } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.profile_fragment_layout + override fun onPageSelected(page: Int) = (pager.adapter?.instantiateItem(pager, page) as? BaseFragment)?.onScrollToTop() ?: Unit + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + setupToolbar(R.string.profile) + username.text = loginBundle + toolbar.navigationIcon = getDrawable(R.drawable.ic_back) + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + viewModel.getUserFromRemote(loginBundle) + } else { + swipeRefresh.isRefreshing = false + } + } + + (organizationList.layoutManager as SafeGridLayoutManager).setIconSize(resources.getDimensionPixelSize(R.dimen.header_icon_zie)) + organizationList.adapter = orgsAdapter + pinnedList.adapter = pinnedReposAdapter + pinnedList.addDivider() + + observeChanges() + + behaviour.state = AnchorSheetBehavior.STATE_ANCHOR + behaviour.setBottomSheetCallback({ newState -> + when (newState) { + AnchorSheetBehavior.STATE_EXPANDED -> toggleArrow.setState(ExpandIconView.MORE, true) + AnchorSheetBehavior.STATE_COLLAPSED -> toggleArrow.setState(ExpandIconView.LESS, true) + else -> toggleArrow.setFraction(0.5f, false) + } + }) + + + toggleArrow.setOnClickListener { + if (behaviour.state != AnchorSheetBehavior.STATE_EXPANDED) { + behaviour.state = AnchorSheetBehavior.STATE_EXPANDED + } else { + behaviour.state = AnchorSheetBehavior.STATE_COLLAPSED + } + } + + tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { + override fun onTabReselected(p0: TabLayout.Tab?) = expandBottomSheet() + override fun onTabUnselected(p0: TabLayout.Tab?) {} + override fun onTabSelected(p0: TabLayout.Tab?) = expandBottomSheet() + + private fun expandBottomSheet() { + if (viewModel.isFirstLaunch) { + viewModel.isFirstLaunch = false + return + } + (behaviour.state != AnchorSheetBehavior.STATE_EXPANDED).isTrue { + behaviour.state = AnchorSheetBehavior.STATE_EXPANDED + } + } + }) + scrollView.setOnScrollChangeListener { _: NestedScrollView?, _: Int, _: Int, _: Int, _: Int -> + (behaviour.state != AnchorSheetBehavior.STATE_COLLAPSED).isTrue { + behaviour.state = AnchorSheetBehavior.STATE_COLLAPSED + } + } + followers.setOnClickListener { if (pager.adapter != null) selectTab(FragmentType.FOLLOWERS) } + following.setOnClickListener { if (pager.adapter != null) selectTab(FragmentType.FOLLOWINGS) } + } + + override fun onBackPressed(): Boolean { + return if (behaviour.state == AnchorSheetBehavior.STATE_COLLAPSED) { + true + } else { + behaviour.state = AnchorSheetBehavior.STATE_COLLAPSED + false + } + } + + private fun observeChanges() { + viewModel.getUser(loginBundle).observeNull(this) { user -> + if (user == null) { + viewModel.getUserFromRemote(loginBundle) + } else { + initUI(user) + } + } + + viewModel.isBlocked.observeNotNull(this) { + blockBtn.isEnabled = true + blockBtn.text = if (it) getString(R.string.unblock) else getString(R.string.block) + } + } + + @SuppressLint("SetTextI18n") + private fun initUI(user: UserModel) { + addDisposal(loginRepositoryProvider.isMe(loginBundle) { isMe -> + actionsHolder.isVisible = !isMe + blockBtn.isVisible = !isMe + blockBtn.isEnabled = false + if (!isMe) viewModel.checkBlockingState(loginBundle) + }) + following.text = "${getString(R.string.following)}: ${user.following?.totalCount ?: 0}" + followers.text = "${getString(R.string.followers)}: ${user.followers?.totalCount ?: 0}" + swipeRefresh.isRefreshing = false + followBtn.setText(if (user.viewerIsFollowing == true) R.string.unfollow else R.string.follow) + followBtn.setOnClickListener { viewModel.followUnfollowUser(loginBundle, user.viewerIsFollowing) } + description.isVisible = user.bio?.isNotEmpty() == true + description.text = user.bio ?: "" + email.isVisible = user.email?.isNotEmpty() == true + email.text = user.email + company.isVisible = user.company?.isNotEmpty() == true + company.text = user.company ?: "" + joined.text = user.createdAt?.timeAgo() ?: "" + joined.isVisible = true + location.isVisible = user.location?.isNotEmpty() == true + location.text = user.location ?: "" + name.isVisible = user.name?.isNotEmpty() == true + name.text = user.name ?: "" + developerProgram.isVisible = user.isDeveloperProgramMember == true + user.organizations?.nodes?.let { orgs -> + organizationHolder.isVisible = orgs.isNotEmpty() + orgsAdapter.insertNew(orgs) + } + user.pinnedRepositories?.pinnedRepositories?.let { nodes -> + pinnedHolder.isVisible = nodes.isNotEmpty() + pinnedReposAdapter.insertNew(nodes) + } + blockBtn.setOnClickListener { viewModel.blockUnblockUser(loginBundle) } + userImageView.loadAvatar(user.avatarUrl) + + if (pager.adapter == null) { + pager.offscreenPageLimit = 5 + pager.adapter = adapter + tabs.setupWithViewPager(pager) + val type = FragmentType.getTypeSafely(tabBundle ?: "") + selectTab(type) + } + } + + private fun selectTab(type: FragmentType?) { + type?.let { + val index = adapter.getIndex(it) + if (index == -1) return + pager.currentItem = index + } + } + + companion object { + const val TAG = "ProfileFragment" + + fun newInstance(login: String, tab: String? = null) = ProfileFragment().apply { + arguments = Bundle().apply { + putString(EXTRA, login) + putString(EXTRA_TWO, tab) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/fragment/viewmodel/ProfileViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/fragment/viewmodel/ProfileViewModel.kt new file mode 100644 index 000000000..097e354b5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/fragment/viewmodel/ProfileViewModel.kt @@ -0,0 +1,64 @@ +package com.fastaccess.github.ui.modules.profile.fragment.viewmodel + +import androidx.lifecycle.MutableLiveData +import com.fastaccess.extension.uiThread +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.usecase.user.BlockUnblockUserUseCase +import com.fastaccess.github.usecase.user.FollowUnfollowUserUseCase +import com.fastaccess.github.usecase.user.IsUserBlockedUseCase +import com.fastaccess.github.usecase.user.UserUseCase +import javax.inject.Inject + +/** + * Created by Kosh on 26.08.18. + */ +class ProfileViewModel @Inject constructor( + private val userUseCase: UserUseCase, + private val unblockUserUseCase: BlockUnblockUserUseCase, + private val blockedUseCase: IsUserBlockedUseCase, + private val followUnfollowUserUseCase: FollowUnfollowUserUseCase +) : BaseViewModel() { + + var isFirstLaunch = true + val isBlocked = MutableLiveData() + + fun getUser(login: String) = userUseCase.getUser(login) + + fun getUserFromRemote(login: String) { + userUseCase.login = login + add(callApi(userUseCase.buildObservable()) + .subscribe({}, { it.printStackTrace() })) + } + + fun checkBlockingState(login: String) { + blockedUseCase.login = login + add(blockedUseCase.buildObservable() + .uiThread() + .subscribe({ + isBlocked.postValue(it) + }, { + isBlocked.postValue(false) + it.printStackTrace() + })) + } + + fun blockUnblockUser(login: String) { + unblockUserUseCase.login = login + unblockUserUseCase.block = isBlocked.value == false + add(callApi(unblockUserUseCase.buildObservable()) + .subscribe({ isBlocked.postValue(it) }, { it.printStackTrace() })) + } + + fun followUnfollowUser(login: String, viewerIsFollowing: Boolean?) { + followUnfollowUserUseCase.login = login + followUnfollowUserUseCase.follow = viewerIsFollowing == false + justSubscribe(followUnfollowUserUseCase.buildObservable()) + } + + override fun onCleared() { + super.onCleared() + userUseCase.dispose() + unblockUserUseCase.dispose() + blockedUseCase.dispose() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/gists/ProfileGistsFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/gists/ProfileGistsFragment.kt new file mode 100644 index 000000000..96bb73ccc --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/gists/ProfileGistsFragment.kt @@ -0,0 +1,77 @@ +package com.fastaccess.github.ui.modules.profile.gists + +import android.os.Bundle +import android.view.View +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.FragmentType +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.ui.adapter.ProfileGistsAdapter +import com.fastaccess.github.ui.adapter.base.CurrentState +import com.fastaccess.github.ui.modules.profile.gists.viewmodel.ProfileGistsViewModel +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.extensions.addDivider +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.extensions.isConnected +import com.fastaccess.github.utils.extensions.isConnected +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 14.10.18. + */ +class ProfileGistsFragment : BaseFragment() { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(ProfileGistsViewModel::class.java) } + private val loginBundle: String by lazy { arguments?.getString(EXTRA) ?: "" } + private val adapter by lazy { ProfileGistsAdapter() } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.simple_refresh_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + recyclerView.adapter = adapter + recyclerView.addDivider() + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView) + if (savedInstanceState == null) isConnected().isTrue { viewModel.loadGists(loginBundle, true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.loadGists(loginBundle, true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.loadGists(loginBundle) } } + listenToChanges() + } + + private fun listenToChanges() { + viewModel.progress.observeNotNull(this) { + adapter.currentState = if (it) CurrentState.LOADING else CurrentState.DONE + } + + viewModel.getGists(loginBundle).observeNotNull(this) { + adapter.currentState = CurrentState.DONE + adapter.submitList(it) + } + + viewModel.counter.observeNotNull(this) { + postCount(FragmentType.GISTS, it) + } + } + + companion object { + fun newInstance(login: String) = ProfileGistsFragment().apply { + arguments = Bundle().apply { + putString(EXTRA, login) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/gists/viewmodel/ProfileGistsViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/gists/viewmodel/ProfileGistsViewModel.kt new file mode 100644 index 000000000..5a99eea0b --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/gists/viewmodel/ProfileGistsViewModel.kt @@ -0,0 +1,45 @@ +package com.fastaccess.github.ui.modules.profile.gists.viewmodel + +import androidx.lifecycle.LiveData +import androidx.paging.LivePagedListBuilder +import androidx.paging.PagedList +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.persistence.models.ProfileGistModel +import com.fastaccess.data.repository.UserGistsRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import javax.inject.Inject + +/** + * Created by Kosh on 14.10.18. + */ +class ProfileGistsViewModel @Inject constructor( + private val reposProvider: UserGistsRepositoryProvider +) : BaseViewModel() { + + private var pageInfo: PageInfoModel? = null + + fun getGists(login: String): LiveData> { + val dataSourceFactory = reposProvider.getGists(login) + val config = PagedList.Config.Builder() + .setPrefetchDistance(com.fastaccess.github.utils.PRE_FETCH_SIZE) + .setPageSize(com.fastaccess.github.utils.PAGE_SIZE) + .build() + return LivePagedListBuilder(dataSourceFactory, config) + .build() + } + + fun loadGists(login: String, reload: Boolean = false) { + if (reload) { + pageInfo = null + } + val pageInfo = pageInfo + if (!reload && (pageInfo != null && !pageInfo.hasNextPage)) return + add(callApi(reposProvider.getGistsFromRemote(login, if (hasNext()) pageInfo?.endCursor else null)) + .subscribe({ + this.pageInfo = it.pageInfo + postCounter(it.totalCount) + }, { it.printStackTrace() })) + } + + fun hasNext() = pageInfo?.hasNextPage == true +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/orgs/userorgs/UserOrgsFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/orgs/userorgs/UserOrgsFragment.kt new file mode 100644 index 000000000..7a77e2ffe --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/orgs/userorgs/UserOrgsFragment.kt @@ -0,0 +1,71 @@ +package com.fastaccess.github.ui.modules.profile.orgs.userorgs + +import android.os.Bundle +import android.view.View +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.ui.adapter.OrganizationsAdapter +import com.fastaccess.github.ui.adapter.base.CurrentState +import com.fastaccess.github.ui.modules.profile.orgs.userorgs.viewmodel.UserOrgsViewModel +import com.fastaccess.github.utils.extensions.addDivider +import com.fastaccess.github.utils.extensions.isConnected +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import timber.log.Timber +import javax.inject.Inject + +/** + * Created by Kosh on 2018-11-26. + */ +class UserOrgsFragment : BaseFragment() { + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(UserOrgsViewModel::class.java) } + private val adapter by lazy { + OrganizationsAdapter { url -> + Timber.e(url) + } + } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.rounded_toolbar_fragment_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + setupToolbar(R.string.organizations) + recyclerView.adapter = adapter + recyclerView.addDivider() + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView) + if (savedInstanceState == null) isConnected().isTrue { viewModel.loadOrgs(true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.loadOrgs(true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.loadOrgs() } } + listenToChanges() + } + + private fun listenToChanges() { + viewModel.progress.observeNotNull(this) { + adapter.currentState = if (it) CurrentState.LOADING else CurrentState.DONE + } + + viewModel.getOrgs().observeNotNull(this) { + adapter.currentState = CurrentState.DONE + adapter.submitList(it) + } + } + + + companion object { + fun newInstance() = UserOrgsFragment() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/orgs/userorgs/viewmodel/UserOrgsViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/orgs/userorgs/viewmodel/UserOrgsViewModel.kt new file mode 100644 index 000000000..fb73b4b40 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/orgs/userorgs/viewmodel/UserOrgsViewModel.kt @@ -0,0 +1,43 @@ +package com.fastaccess.github.ui.modules.profile.orgs.userorgs.viewmodel + +import androidx.lifecycle.LiveData +import androidx.paging.LivePagedListBuilder +import androidx.paging.PagedList +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.persistence.models.OrganizationModel +import com.fastaccess.data.repository.OrgRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import javax.inject.Inject + +/** + * Created by Kosh on 2018-11-26. + */ +class UserOrgsViewModel @Inject constructor( + private val provider: OrgRepositoryProvider +) : BaseViewModel() { + + private var pageInfo: PageInfoModel? = null + + fun getOrgs(): LiveData> { + val dataSourceFactory = provider.getOrgs() + val config = PagedList.Config.Builder() + .setPrefetchDistance(com.fastaccess.github.utils.PRE_FETCH_SIZE) + .setPageSize(com.fastaccess.github.utils.PAGE_SIZE) + .build() + return LivePagedListBuilder(dataSourceFactory, config) + .build() + } + + fun loadOrgs(reload: Boolean = false) { + val pageInfo = pageInfo + if (!reload && (pageInfo != null && !pageInfo.hasNextPage)) return + val cursor = if (hasNext()) pageInfo?.endCursor else null + + justSubscribe(callApi(provider.getOrgFromRemote(cursor)) + .doOnNext { + this.pageInfo = it.pageInfo + }) + } + + fun hasNext() = pageInfo?.hasNextPage == true +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/repos/ProfileReposFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/repos/ProfileReposFragment.kt new file mode 100644 index 000000000..b33c6a135 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/repos/ProfileReposFragment.kt @@ -0,0 +1,76 @@ +package com.fastaccess.github.ui.modules.profile.repos + +import android.os.Bundle +import android.view.View +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.FragmentType +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.ui.adapter.ProfileReposAdapter +import com.fastaccess.github.ui.adapter.base.CurrentState +import com.fastaccess.github.ui.modules.profile.repos.viewmodel.ProfileReposViewModel +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.extensions.addDivider +import com.fastaccess.github.utils.extensions.isConnected +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 06.10.18. + */ +class ProfileReposFragment : BaseFragment() { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(ProfileReposViewModel::class.java) } + private val loginBundle: String by lazy { arguments?.getString(EXTRA) ?: "" } + private val adapter by lazy { ProfileReposAdapter() } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.simple_refresh_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + recyclerView.adapter = adapter + recyclerView.addDivider() + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView) + if (savedInstanceState == null) isConnected().isTrue { viewModel.loadRepos(loginBundle, true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.loadRepos(loginBundle, true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.loadRepos(loginBundle) } } + listenToChanges() + } + + private fun listenToChanges() { + viewModel.progress.observeNotNull(this) { + adapter.currentState = if (it) CurrentState.LOADING else CurrentState.DONE + } + + viewModel.repos(loginBundle).observeNotNull(this) { + adapter.currentState = CurrentState.DONE + adapter.submitList(it) + } + + viewModel.counter.observeNotNull(this) { + postCount(FragmentType.REPOS, it) + } + } + + companion object { + fun newInstance(login: String) = ProfileReposFragment().apply { + arguments = Bundle().apply { + putString(EXTRA, login) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/repos/viewmodel/ProfileReposViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/repos/viewmodel/ProfileReposViewModel.kt new file mode 100644 index 000000000..9c2669219 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/repos/viewmodel/ProfileReposViewModel.kt @@ -0,0 +1,45 @@ +package com.fastaccess.github.ui.modules.profile.repos.viewmodel + +import androidx.lifecycle.LiveData +import androidx.paging.LivePagedListBuilder +import androidx.paging.PagedList +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.persistence.models.ProfileRepoModel +import com.fastaccess.data.repository.UserReposRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import javax.inject.Inject + +/** + * Created by Kosh on 08.10.18. + */ +class ProfileReposViewModel @Inject constructor( + private val reposProvider: UserReposRepositoryProvider +) : BaseViewModel() { + + private var pageInfo: PageInfoModel? = null + + fun repos(login: String): LiveData> { + val dataSourceFactory = reposProvider.getRepos(login) + val config = PagedList.Config.Builder() + .setPrefetchDistance(com.fastaccess.github.utils.PRE_FETCH_SIZE) + .setPageSize(com.fastaccess.github.utils.PAGE_SIZE) + .build() + return LivePagedListBuilder(dataSourceFactory, config) + .build() + } + + fun loadRepos(login: String, reload: Boolean = false) { + if (reload) { + pageInfo = null + } + val pageInfo = pageInfo + if (!reload && (pageInfo != null && !pageInfo.hasNextPage)) return + add(callApi(reposProvider.getReposFromRemote(login, if (hasNext()) pageInfo?.endCursor else null)) + .subscribe({ + this.pageInfo = it.pageInfo + postCounter(it.totalCount) + }, { it.printStackTrace() })) + } + + fun hasNext() = pageInfo?.hasNextPage == true +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/starred/ProfileStarredReposFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/starred/ProfileStarredReposFragment.kt new file mode 100644 index 000000000..9d8705088 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/starred/ProfileStarredReposFragment.kt @@ -0,0 +1,76 @@ +package com.fastaccess.github.ui.modules.profile.starred + +import android.os.Bundle +import android.view.View +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.FragmentType +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.ui.adapter.ProfileStarredReposAdapter +import com.fastaccess.github.ui.adapter.base.CurrentState +import com.fastaccess.github.ui.modules.profile.starred.viewmodel.ProfileStarredReposViewModel +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.extensions.addDivider +import com.fastaccess.github.utils.extensions.isConnected +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.simple_refresh_list_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 13.10.18. + */ +class ProfileStarredReposFragment : BaseFragment() { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(ProfileStarredReposViewModel::class.java) } + private val loginBundle: String by lazy { arguments?.getString(EXTRA) ?: "" } + private val adapter by lazy { ProfileStarredReposAdapter() } + + override fun viewModel(): BaseViewModel? = viewModel + override fun layoutRes(): Int = R.layout.simple_refresh_list_layout + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + recyclerView.adapter = adapter + recyclerView.addDivider() + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView) + if (savedInstanceState == null) isConnected().isTrue { viewModel.loadStarredRepos(loginBundle, true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.loadStarredRepos(loginBundle, true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.loadStarredRepos(loginBundle) } } + listenToChanges() + } + + private fun listenToChanges() { + viewModel.progress.observeNotNull(this) { + adapter.currentState = if (it) CurrentState.LOADING else CurrentState.DONE + } + + viewModel.starredRepos(loginBundle).observeNotNull(this) { + adapter.currentState = CurrentState.DONE + adapter.submitList(it) + } + + viewModel.counter.observeNotNull(this) { + postCount(FragmentType.STARRED, it) + } + } + + companion object { + fun newInstance(login: String) = ProfileStarredReposFragment().apply { + arguments = Bundle().apply { + putString(EXTRA, login) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/profile/starred/viewmodel/ProfileStarredReposViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/profile/starred/viewmodel/ProfileStarredReposViewModel.kt new file mode 100644 index 000000000..9cd3b95b5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/profile/starred/viewmodel/ProfileStarredReposViewModel.kt @@ -0,0 +1,45 @@ +package com.fastaccess.github.ui.modules.profile.starred.viewmodel + +import androidx.lifecycle.LiveData +import androidx.paging.LivePagedListBuilder +import androidx.paging.PagedList +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.persistence.models.ProfileStarredRepoModel +import com.fastaccess.data.repository.UserStarredReposRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import javax.inject.Inject + +/** + * Created by Kosh on 13.10.18. + */ +class ProfileStarredReposViewModel @Inject constructor( + private val reposProvider: UserStarredReposRepositoryProvider +) : BaseViewModel() { + + private var pageInfo: PageInfoModel? = null + + fun starredRepos(login: String): LiveData> { + val dataSourceFactory = reposProvider.getStarredRepos(login) + val config = PagedList.Config.Builder() + .setPrefetchDistance(com.fastaccess.github.utils.PRE_FETCH_SIZE) + .setPageSize(com.fastaccess.github.utils.PAGE_SIZE) + .build() + return LivePagedListBuilder(dataSourceFactory, config) + .build() + } + + fun loadStarredRepos(login: String, reload: Boolean = false) { + if (reload) { + pageInfo = null + } + val pageInfo = pageInfo + if (!reload && (pageInfo != null && !pageInfo.hasNextPage)) return + add(callApi(reposProvider.getStarredReposFromRemote(login, if (hasNext()) pageInfo?.endCursor else null)) + .subscribe({ + this.pageInfo = it.pageInfo + postCounter(it.totalCount) + }, { it.printStackTrace() })) + } + + fun hasNext() = pageInfo?.hasNextPage == true +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/routing/RoutingActivity.kt b/app/src/main/java/com/fastaccess/github/ui/modules/routing/RoutingActivity.kt new file mode 100644 index 000000000..06452a45c --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/routing/RoutingActivity.kt @@ -0,0 +1,24 @@ +package com.fastaccess.github.ui.modules.routing + +import android.app.Activity +import android.os.Bundle +import com.airbnb.deeplinkdispatch.DeepLinkHandler +import timber.log.Timber + +/** + * Created by Kosh on 26.09.18. + */ +@DeepLinkHandler(value = [RoutingModule::class]) +class RoutingActivity : Activity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val delegate = DeepLinkDelegate(RoutingModuleLoader()) + .dispatchFrom(this) + Timber.e("$delegate") + if (!delegate.isSuccessful) { + //TODO FIXME + } + finish() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/routing/RoutingModule.kt b/app/src/main/java/com/fastaccess/github/ui/modules/routing/RoutingModule.kt new file mode 100644 index 000000000..3e4000cfa --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/routing/RoutingModule.kt @@ -0,0 +1,9 @@ +package com.fastaccess.github.ui.modules.routing + +import com.airbnb.deeplinkdispatch.DeepLinkModule + +/** + * Created by Kosh on 26.09.18. + */ +@DeepLinkModule +class RoutingModule \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/search/filter/FilterSearchBottomSheet.kt b/app/src/main/java/com/fastaccess/github/ui/modules/search/filter/FilterSearchBottomSheet.kt new file mode 100644 index 000000000..b6abc8c99 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/search/filter/FilterSearchBottomSheet.kt @@ -0,0 +1,250 @@ +package com.fastaccess.github.ui.modules.search.filter + +import android.content.Context +import android.os.Bundle +import android.view.View +import androidx.core.os.bundleOf +import androidx.core.view.isVisible +import com.evernote.android.state.State +import com.fastaccess.data.model.parcelable.FilterByRepo +import com.fastaccess.data.model.parcelable.FilterIssuesPrsModel +import com.fastaccess.data.model.parcelable.FilterSearchModel +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseBottomSheetDialogFragment +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.utils.EXTRA +import com.google.android.material.chip.Chip +import kotlinx.android.synthetic.main.filter_search_layout.* + +/** + * Created by Kosh on 19.01.19. + */ +class FilterSearchBottomSheet : BaseFragment() { + + @State lateinit var model: FilterSearchModel + private var callback: FilterSearchCallback? = null + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = when { + context is FilterSearchCallback -> context + parentFragment is FilterSearchCallback -> parentFragment as FilterSearchCallback + parentFragment?.parentFragment is FilterSearchCallback -> parentFragment?.parentFragment as FilterSearchCallback // deep hierarchy + else -> null + } + } + + override fun onDetach() { + callback = null + super.onDetach() + } + + override fun layoutRes(): Int = R.layout.filter_search_layout + override fun viewModel(): BaseViewModel? = null + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + if (savedInstanceState == null) { + model = (arguments?.getParcelable(EXTRA) as? FilterSearchModel) ?: FilterSearchModel() + } + setupToolbar(R.string.filter) + submit.setOnClickListener { + model.filterByRepo.name = limitByEditText.text?.toString() + model.filterByRepo.language = languageEditText.text?.toString() + callback?.onFilterApplied(model) + (parentFragment as? BaseBottomSheetDialogFragment)?.dismiss() + } + initState() + } + + private fun initState() { + when (model.searchBy) { + FilterSearchModel.SearchBy.REPOS -> { + filterIssuesPr.isVisible = false + filterRepos.isVisible = true + initRepoCheckState() + initRepoCheckListener() + } + FilterSearchModel.SearchBy.ISSUES -> { + filterRepos.isVisible = false + filterIssuesPr.isVisible = true + reviewRequest.isVisible = false + searchType.check(R.id.issues) + initIssuePrCheckState() + initIssuesPrsCheckListener() + } + FilterSearchModel.SearchBy.PRS -> { + filterRepos.isVisible = false + filterIssuesPr.isVisible = true + reviewRequest.isVisible = true + searchType.check(R.id.prs) + initIssuePrCheckState() + initIssuesPrsCheckListener() + } + FilterSearchModel.SearchBy.USERS -> { + searchType.check(R.id.users) + filterIssuesPr.isVisible = false + filterRepos.isVisible = false + } + FilterSearchModel.SearchBy.NONE -> { + filterIssuesPr.isVisible = false + filterRepos.isVisible = false + } + } + + searchType.setOnCheckedChangeListener { _, id -> + when (id) { + -1 -> model = FilterSearchModel() + R.id.repos -> { + filterIssuesPr.isVisible = false + filterRepos.isVisible = true + model.searchBy = FilterSearchModel.SearchBy.REPOS + initRepoCheckListener() + } + R.id.prs, R.id.issues -> { + filterIssuesPr.isVisible = true + reviewRequest.isVisible = false + model.searchBy = FilterSearchModel.SearchBy.ISSUES + (id == R.id.prs).isTrue { + model.searchBy = FilterSearchModel.SearchBy.PRS + model.filterIssuesPrsModel.isPr = true + reviewRequest.isVisible = true + } + filterRepos.isVisible = false + initIssuesPrsCheckListener() + } + R.id.users -> { + model.searchBy = FilterSearchModel.SearchBy.USERS + filterIssuesPr.isVisible = false + filterRepos.isVisible = false + } + } + } + } + + private fun initRepoCheckState() { + searchType.check(R.id.repos) + model.filterByRepo.let { model -> + searchIn.check(when (model.filterByRepoIn) { + FilterByRepo.FilterByRepoIn.ALL -> R.id.all + FilterByRepo.FilterByRepoIn.NAME -> R.id.name + FilterByRepo.FilterByRepoIn.DESCRIPTION -> R.id.description + FilterByRepo.FilterByRepoIn.README -> R.id.readme + }) + model.filterByRepoLimitBy?.let { limit -> + limitBy.check(when (limit) { + FilterByRepo.FilterByRepoLimitBy.USERNAME -> R.id.username + FilterByRepo.FilterByRepoLimitBy.ORG -> R.id.org + }) + limitByText.isVisible = true + } + + limitByEditText.setText(model.name ?: "") + languageEditText.setText(model.language ?: "") + } + } + + private fun initIssuePrCheckState() { + model.filterIssuesPrsModel.let { model -> + reviewRequest.isVisible = model.isPr == true + filter.check(when (model.searchBy) { + FilterIssuesPrsModel.SearchBy.CREATED -> R.id.created + FilterIssuesPrsModel.SearchBy.ASSIGNED -> R.id.assigned + FilterIssuesPrsModel.SearchBy.MENTIONED -> R.id.mentioned + FilterIssuesPrsModel.SearchBy.REVIEW_REQUESTS -> R.id.reviewRequest + }) + type.check(when (model.searchType) { + FilterIssuesPrsModel.SearchType.OPEN -> R.id.open + FilterIssuesPrsModel.SearchType.CLOSED -> R.id.closed + }) + visibility.check(when (model.searchVisibility) { + FilterIssuesPrsModel.SearchVisibility.BOTH -> R.id.bothVisibility + FilterIssuesPrsModel.SearchVisibility.PUBLIC -> R.id.publicRepos + FilterIssuesPrsModel.SearchVisibility.PRIVATE -> R.id.privateRepos + }) + sort.check(when (model.searchSortBy) { + FilterIssuesPrsModel.SearchSortBy.NEWEST -> R.id.newest + FilterIssuesPrsModel.SearchSortBy.OLDEST -> R.id.oldest + FilterIssuesPrsModel.SearchSortBy.MOST_COMMENTED -> R.id.mostCommented + FilterIssuesPrsModel.SearchSortBy.LEAST_COMMENTED -> R.id.leastCommented + FilterIssuesPrsModel.SearchSortBy.RECENTLY_UPDATED -> R.id.recentlyUpdated + FilterIssuesPrsModel.SearchSortBy.LEAST_RECENTLY_UPDATED -> R.id.leastRecentlyUpdated + }) + } + } + + private fun initRepoCheckListener() { + searchIn.setOnCheckedChangeListener { _, id -> + when (id) { + R.id.all -> model.filterByRepo.filterByRepoIn = FilterByRepo.FilterByRepoIn.ALL + R.id.name -> model.filterByRepo.filterByRepoIn = FilterByRepo.FilterByRepoIn.NAME + R.id.description -> model.filterByRepo.filterByRepoIn = FilterByRepo.FilterByRepoIn.DESCRIPTION + R.id.readme -> model.filterByRepo.filterByRepoIn = FilterByRepo.FilterByRepoIn.README + } + } + limitBy.setOnCheckedChangeListener { group, id -> + when (id) { + R.id.username -> model.filterByRepo.filterByRepoLimitBy = FilterByRepo.FilterByRepoLimitBy.USERNAME + R.id.org -> model.filterByRepo.filterByRepoLimitBy = FilterByRepo.FilterByRepoLimitBy.ORG + -1 -> { + model.filterByRepo.filterByRepoLimitBy = null + limitByText.editText?.setText("") + } + } + limitByText.isVisible = group.checkedChipId != -1 + } + languages.setOnCheckedChangeListener { chipGroup, id -> + if (id != -1) { + languageEditText.setText(chipGroup.findViewById(id).text) + } else { + languageEditText.setText("") + } + } + } + + private fun initIssuesPrsCheckListener() { + model.filterIssuesPrsModel.let { model -> + filter.setOnCheckedChangeListener { _, id -> + when (id) { + R.id.created -> model.searchBy = FilterIssuesPrsModel.SearchBy.CREATED + R.id.assigned -> model.searchBy = FilterIssuesPrsModel.SearchBy.ASSIGNED + R.id.mentioned -> model.searchBy = FilterIssuesPrsModel.SearchBy.MENTIONED + R.id.reviewRequest -> model.searchBy = FilterIssuesPrsModel.SearchBy.REVIEW_REQUESTS + } + } + type.setOnCheckedChangeListener { _, id -> + when (id) { + R.id.open -> model.searchType = FilterIssuesPrsModel.SearchType.OPEN + R.id.closed -> model.searchType = FilterIssuesPrsModel.SearchType.CLOSED + } + } + visibility.setOnCheckedChangeListener { _, id -> + when (id) { + R.id.bothVisibility -> model.searchVisibility = FilterIssuesPrsModel.SearchVisibility.BOTH + R.id.privateRepos -> model.searchVisibility = FilterIssuesPrsModel.SearchVisibility.PRIVATE + R.id.publicRepos -> model.searchVisibility = FilterIssuesPrsModel.SearchVisibility.PUBLIC + } + } + sort.setOnCheckedChangeListener { _, id -> + when (id) { + R.id.newest -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.NEWEST + R.id.oldest -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.OLDEST + R.id.mostCommented -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.MOST_COMMENTED + R.id.leastCommented -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.LEAST_COMMENTED + R.id.recentlyUpdated -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.RECENTLY_UPDATED + R.id.leastRecentlyUpdated -> model.searchSortBy = FilterIssuesPrsModel.SearchSortBy.LEAST_RECENTLY_UPDATED + } + } + } + } + + companion object { + fun newInstance(model: FilterSearchModel) = FilterSearchBottomSheet().apply { + arguments = bundleOf(EXTRA to model) + } + } + + interface FilterSearchCallback { + fun onFilterApplied(model: FilterSearchModel) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/search/fragment/SearchFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/search/fragment/SearchFragment.kt new file mode 100644 index 000000000..c3c26bd24 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/search/fragment/SearchFragment.kt @@ -0,0 +1,149 @@ +package com.fastaccess.github.ui.modules.search.fragment + +import android.os.Bundle +import android.text.Editable +import android.view.View +import android.view.inputmethod.EditorInfo +import android.widget.ArrayAdapter +import androidx.core.view.isVisible +import androidx.core.widget.doAfterTextChanged +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.parcelable.FilterSearchModel +import com.fastaccess.data.persistence.models.SuggestionsModel +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.extensions.observeNull +import com.fastaccess.github.ui.adapter.MyIssuesPrsAdapter +import com.fastaccess.github.ui.adapter.SearchReposAdapter +import com.fastaccess.github.ui.adapter.ShortUsersAdapter +import com.fastaccess.github.ui.modules.multipurpose.MultiPurposeBottomSheetDialog +import com.fastaccess.github.ui.modules.multipurpose.MultiPurposeBottomSheetDialog.BottomSheetFragmentType.FILTER_SEARCH +import com.fastaccess.github.ui.modules.search.filter.FilterSearchBottomSheet +import com.fastaccess.github.ui.modules.search.fragment.viewmodel.FilterSearchViewModel +import com.fastaccess.github.utils.extensions.* +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.fab_simple_refresh_list_layout.* +import kotlinx.android.synthetic.main.search_fragment_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 20.01.19. + */ +class SearchFragment : BaseFragment(), FilterSearchBottomSheet.FilterSearchCallback { + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(FilterSearchViewModel::class.java) } + private val issuesPrsAdapter by lazy { + MyIssuesPrsAdapter { + route(it.url) + } + } + private val reposAdapter by lazy { SearchReposAdapter() } + private val usersAdapter by lazy { + ShortUsersAdapter { url -> + requireContext().route(url) + } + } + + override fun layoutRes(): Int = R.layout.search_fragment_layout + override fun viewModel(): BaseViewModel? = viewModel + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + recyclerView.addDivider() + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView) + if (savedInstanceState == null) isConnected().isTrue { viewModel.loadData(true) } + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.loadData(true) + } else { + swipeRefresh.isRefreshing = false + } + } + recyclerView.addOnLoadMore { isConnected().isTrue { viewModel.loadData() } } + backBtn.setOnClickListener { activity?.onBackPressed() } + clear.setOnClickListener { searchEditText.setText("") } + filter.setOnClickListener { + val model = viewModel.filterModel.copy() + MultiPurposeBottomSheetDialog.show(childFragmentManager, FILTER_SEARCH, model) + } + + searchEditText.setAdapter(ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1)) + + searchEditText.setOnEditorActionListener { v, actionId, _ -> + return@setOnEditorActionListener if (actionId == EditorInfo.IME_ACTION_DONE || + actionId == EditorInfo.IME_ACTION_SEARCH || + actionId == EditorInfo.IME_ACTION_GO) { + v.hideKeyboard() + if (viewModel.filterModel.searchBy == FilterSearchModel.SearchBy.NONE) { + filter.callOnClick() + } else { + onFilterApplied(viewModel.filterModel) + } + true + } else { + false + } + } + searchEditText.doAfterTextChanged { text -> + val show = !text.isNullOrEmpty() + if (show != clear.isVisible) { // prevent multiple hide/show + clear.isVisible = show + } + searchSuggestions(text) + } + + listenToChanges() + } + + override fun onFilterApplied(model: FilterSearchModel) { + if (searchEditText.asString().isEmpty()) { + viewModel.filterModel = model + searchEditText.error = getString(R.string.required_field) + } else { + model.searchQuery = searchEditText.asString() + searchEditText.error = null + isConnected().isTrue { viewModel.filter(model) } + } + } + + private fun listenToChanges() { + viewModel.issuesPrsData.observeNotNull(this) { + if (recyclerView.adapter !is MyIssuesPrsAdapter) { + recyclerView.adapter = issuesPrsAdapter + } + (recyclerView.adapter as? MyIssuesPrsAdapter)?.submitList(it) + } + viewModel.reposData.observeNotNull(this) { + if (recyclerView.adapter !is SearchReposAdapter) { + recyclerView.adapter = reposAdapter + } + (recyclerView.adapter as? SearchReposAdapter)?.submitList(it) + } + viewModel.usersData.observeNotNull(this) { + if (recyclerView.adapter !is ShortUsersAdapter) { + recyclerView.adapter = usersAdapter + } + (recyclerView.adapter as? ShortUsersAdapter)?.submitList(it) + } + } + + private fun searchSuggestions(text: Editable?) { + if (!text.isNullOrEmpty()) { + viewModel.querySuggestion(text.toString()).observeNull(this) { + val adapter = searchEditText?.adapter as? ArrayAdapter ?: return@observeNull + adapter.clear() + it?.let { list -> adapter.addAll(list) } + } + } + } + + companion object { + fun newInstance() = SearchFragment() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/search/fragment/viewmodel/FilterSearchViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/search/fragment/viewmodel/FilterSearchViewModel.kt new file mode 100644 index 000000000..e501ba97b --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/search/fragment/viewmodel/FilterSearchViewModel.kt @@ -0,0 +1,133 @@ +package com.fastaccess.github.ui.modules.search.fragment.viewmodel + +import androidx.lifecycle.MutableLiveData +import com.apollographql.apollo.api.Input +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.ShortRepoModel +import com.fastaccess.data.model.ShortUserModel +import com.fastaccess.data.model.parcelable.FilterSearchModel +import com.fastaccess.data.persistence.models.MyIssuesPullsModel +import com.fastaccess.data.repository.SuggestionRepositoryProvider +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.usecase.issuesprs.FilterIssuesUseCase +import com.fastaccess.github.usecase.issuesprs.FilterPullRequestsUseCase +import com.fastaccess.github.usecase.search.FilterSearchReposUseCase +import com.fastaccess.github.usecase.search.FilterSearchUsersUseCase +import io.reactivex.internal.observers.EmptyCompletableObserver +import javax.inject.Inject + +/** + * Created by Kosh on 20.10.18. + */ +class FilterSearchViewModel @Inject constructor( + private val filterIssuesUseCase: FilterIssuesUseCase, + private val filterPullRequestsUseCase: FilterPullRequestsUseCase, + private val filterSearchReposUseCase: FilterSearchReposUseCase, + private val filterSearchUsersUseCase: FilterSearchUsersUseCase, + private val suggestionRepositoryProvider: SuggestionRepositoryProvider +) : BaseViewModel() { + + private var pageInfo: PageInfoModel? = null + var filterModel = FilterSearchModel() + val issuesPrsList = arrayListOf() + val issuesPrsData = MutableLiveData>() + val reposList = arrayListOf() + val reposData = MutableLiveData>() + val usersList = arrayListOf() + val usersData = MutableLiveData>() + + override fun onCleared() { + super.onCleared() + filterIssuesUseCase.dispose() + filterPullRequestsUseCase.dispose() + filterSearchReposUseCase.dispose() + filterSearchUsersUseCase.dispose() + } + + + fun querySuggestion(query: String) = suggestionRepositoryProvider.getSuggestions(query) + + fun loadData(reload: Boolean = false) { + if (reload) { + this.issuesPrsList.clear() + this.reposList.clear() + this.usersList.clear() + pageInfo = null + } + val pageInfo = pageInfo + if (!reload && (pageInfo != null && !pageInfo.hasNextPage)) return + val cursor = if (hasNext()) pageInfo?.endCursor else null + when (filterModel.searchBy) { + FilterSearchModel.SearchBy.REPOS -> searchByRepo(filterModel, cursor) + FilterSearchModel.SearchBy.ISSUES -> searchByIssue(filterModel, cursor) + FilterSearchModel.SearchBy.PRS -> searchByPr(filterModel, cursor) + FilterSearchModel.SearchBy.USERS -> searchByUser(filterModel, cursor) + FilterSearchModel.SearchBy.NONE -> { + // Nothing! + } + } + suggestionRepositoryProvider.upsert(filterModel.searchQuery).subscribe(EmptyCompletableObserver()) + } + + private fun searchByRepo(filterModel: FilterSearchModel, cursor: String?) { + filterSearchReposUseCase.cursor = Input.optional(cursor) + filterSearchReposUseCase.keyword = filterModel.searchQuery + filterSearchReposUseCase.filterModel = filterModel.filterByRepo + justSubscribe(filterSearchReposUseCase.buildObservable() + .doOnNext { + this.usersData.postValue(null) + this.issuesPrsData.postValue(null) + this.pageInfo = it.first + this.reposList.addAll(it.second) + this.reposData.postValue(ArrayList(reposList)) + }) + } + + private fun searchByPr(filterModel: FilterSearchModel, cursor: String?) { + filterPullRequestsUseCase.cursor = Input.optional(cursor) + filterPullRequestsUseCase.filterModel = filterModel.filterIssuesPrsModel + filterPullRequestsUseCase.keyword = filterModel.searchQuery + justSubscribe(filterPullRequestsUseCase.buildObservable() + .doOnNext { + onRequestFinished(it) + }) + } + + private fun searchByIssue(filterModel: FilterSearchModel, cursor: String?) { + filterIssuesUseCase.cursor = Input.optional(cursor) + filterIssuesUseCase.filterModel = filterModel.filterIssuesPrsModel + filterIssuesUseCase.keyword = filterModel.searchQuery + justSubscribe(filterIssuesUseCase.buildObservable() + .doOnNext { + onRequestFinished(it) + }) + } + + private fun searchByUser(filterModel: FilterSearchModel, cursor: String?) { + filterSearchUsersUseCase.cursor = Input.optional(cursor) + filterSearchUsersUseCase.keyword = filterModel.searchQuery + justSubscribe(filterSearchUsersUseCase.buildObservable() + .doOnNext { + this.reposData.postValue(null) + this.issuesPrsData.postValue(null) + this.pageInfo = it.first + this.usersList.addAll(it.second) + this.usersData.postValue(ArrayList(usersList)) + }) + } + + private fun onRequestFinished(pair: Pair>) { + this.reposData.postValue(null) + this.usersData.postValue(null) + this.pageInfo = pair.first + this.issuesPrsList.addAll(pair.second) + this.issuesPrsData.postValue(ArrayList(issuesPrsList)) // create new copy of list as submitList will never be notified + } + + fun filter(model: FilterSearchModel) { + this.filterModel = model + loadData(true) + } + + fun hasNext() = pageInfo?.hasNextPage ?: false +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/trending/TrendingActivity.kt b/app/src/main/java/com/fastaccess/github/ui/modules/trending/TrendingActivity.kt new file mode 100644 index 000000000..0fbc463cf --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/trending/TrendingActivity.kt @@ -0,0 +1,25 @@ +package com.fastaccess.github.ui.modules.trending + +import android.os.Bundle +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseActivity +import com.fastaccess.github.platform.deeplink.WebDeepLink +import com.fastaccess.github.ui.modules.trending.fragment.TrendingFragment +import com.fastaccess.github.extensions.replace + +/** + * Created by Kosh on 18.08.18. + */ +@WebDeepLink("/trending", "/trending/{lang}") +class TrendingActivity : BaseActivity() { + override fun layoutRes(): Int = R.layout.activity_main + + override fun onActivityCreatedWithUser(savedInstanceState: Bundle?) { + if (savedInstanceState == null && intent != null) { + val lan = intent?.extras?.getString("lang") + val since = intent?.extras?.getString("since") + + replace(R.id.container, TrendingFragment.newInstance(lan, since)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/trending/filter/FilterTrendingBottomSheet.kt b/app/src/main/java/com/fastaccess/github/ui/modules/trending/filter/FilterTrendingBottomSheet.kt new file mode 100644 index 000000000..e44d34b26 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/trending/filter/FilterTrendingBottomSheet.kt @@ -0,0 +1,89 @@ +package com.fastaccess.github.ui.modules.trending.filter + +import android.content.Context +import android.os.Bundle +import android.view.View +import androidx.core.os.bundleOf +import com.fastaccess.data.model.LanguageColorsModel +import com.fastaccess.data.model.parcelable.FilterTrendingModel +import com.fastaccess.extension.uiThread +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.ui.adapter.LanguagesAdapter +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.extensions.addDivider +import com.google.android.material.chip.Chip +import com.google.gson.Gson +import kotlinx.android.synthetic.main.filter_trending_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 23.01.19. + */ +class FilterTrendingBottomSheet : BaseFragment() { + + @Inject lateinit var gson: Gson + + private var callback: FilterTrendingCallback? = null + private val adapter by lazy { LanguagesAdapter() } + private val model by lazy { arguments?.getParcelable(EXTRA) ?: FilterTrendingModel() } + + + override fun layoutRes(): Int = R.layout.filter_trending_layout + override fun viewModel(): BaseViewModel? = null + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = when { + context is FilterTrendingCallback -> context + parentFragment is FilterTrendingCallback -> parentFragment as FilterTrendingCallback + parentFragment?.parentFragment is FilterTrendingCallback -> parentFragment?.parentFragment as FilterTrendingCallback // deep hierarchy + else -> null + } + } + + override fun onDetach() { + callback = null + super.onDetach() + } + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + setupToolbar(R.string.filter) + adapter.checkedLanguage = model.lang + languageRecyclerView.adapter = adapter + languageRecyclerView.addDivider() + sinceGroup.check(when (model.since) { + FilterTrendingModel.TrendingSince.DAILY -> R.id.daily + FilterTrendingModel.TrendingSince.WEEKLY -> R.id.weekly + FilterTrendingModel.TrendingSince.MONTHLY -> R.id.monthly + }) + addDisposal(LanguageColorsModel.newInstance(gson, requireContext()) + .uiThread() + .subscribe({ adapter.submitList(it) }, { showSnackBar(view, message = it.message) })) + + submit.setOnClickListener { + model.lang = adapter.checkedLanguage + model.since = if (sinceGroup.checkedChipId != -1) { + FilterTrendingModel.TrendingSince.getSince(sinceGroup.findViewById(sinceGroup.checkedChipId)?.text?.toString()) + } else { + FilterTrendingModel.TrendingSince.DAILY + } + callback?.onFilterApplied(model) + dismiss() + } + } + + + companion object { + fun newInstance(model: FilterTrendingModel): FilterTrendingBottomSheet { + return FilterTrendingBottomSheet().apply { + arguments = bundleOf(EXTRA to model) + } + } + } + + interface FilterTrendingCallback { + fun onFilterApplied(model: FilterTrendingModel) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/trending/fragment/TrendingFragment.kt b/app/src/main/java/com/fastaccess/github/ui/modules/trending/fragment/TrendingFragment.kt new file mode 100644 index 000000000..ca370d84c --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/trending/fragment/TrendingFragment.kt @@ -0,0 +1,84 @@ +package com.fastaccess.github.ui.modules.trending.fragment + +import android.os.Bundle +import android.view.View +import androidx.core.os.bundleOf +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.ViewModelProviders +import com.fastaccess.data.model.parcelable.FilterTrendingModel +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.base.BaseViewModel +import com.fastaccess.github.extensions.isTrue +import com.fastaccess.github.extensions.observeNotNull +import com.fastaccess.github.ui.adapter.TrendingsAdapter +import com.fastaccess.github.ui.modules.multipurpose.MultiPurposeBottomSheetDialog +import com.fastaccess.github.ui.modules.trending.filter.FilterTrendingBottomSheet +import com.fastaccess.github.ui.modules.trending.fragment.viewmodel.TrendingViewModel +import com.fastaccess.github.utils.EXTRA +import com.fastaccess.github.utils.extensions.addDivider +import com.fastaccess.github.utils.extensions.isConnected +import com.google.gson.Gson +import kotlinx.android.synthetic.main.appbar_center_title_layout.* +import kotlinx.android.synthetic.main.empty_state_layout.* +import kotlinx.android.synthetic.main.fab_simple_refresh_list_layout.* +import kotlinx.android.synthetic.main.trending_fragment_layout.* +import javax.inject.Inject + +/** + * Created by Kosh on 23.01.19. + */ +class TrendingFragment : BaseFragment(), FilterTrendingBottomSheet.FilterTrendingCallback { + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + @Inject lateinit var gson: Gson + + private val viewModel by lazy { ViewModelProviders.of(this, viewModelFactory).get(TrendingViewModel::class.java) } + private val adapter by lazy { TrendingsAdapter() } + + override fun layoutRes(): Int = R.layout.trending_fragment_layout + override fun viewModel(): BaseViewModel? = viewModel + + override fun onFragmentCreatedWithUser(view: View, savedInstanceState: Bundle?) { + setupToolbar(R.string.trending) + recyclerView.adapter = adapter + recyclerView.addDivider() + recyclerView.setEmptyView(emptyLayout) + fastScroller.attachRecyclerView(recyclerView, appBar) + swipeRefresh.setOnRefreshListener { + if (isConnected()) { + recyclerView.resetScrollState() + viewModel.load(viewModel.filterTrendingModel) + } else { + swipeRefresh.isRefreshing = false + } + } + filterTrending.setOnClickListener { + val modelCopy = viewModel.filterTrendingModel.copy() + MultiPurposeBottomSheetDialog.show(childFragmentManager, + MultiPurposeBottomSheetDialog.BottomSheetFragmentType.TRENDING, modelCopy) + } + listenToChanges() + if (savedInstanceState == null) { + val model = arguments?.getParcelable(EXTRA) ?: FilterTrendingModel() + isConnected().isTrue { viewModel.load(model) } + } + } + + override fun onFilterApplied(model: FilterTrendingModel) { + viewModel.filterTrendingModel = model + isConnected().isTrue { viewModel.load(model) } + } + + private fun listenToChanges() { + viewModel.trendingLiveData.observeNotNull(this) { + adapter.submitList(it) + } + } + + companion object { + fun newInstance(lan: String? = null, since: String? = null) = TrendingFragment().apply { + arguments = bundleOf(EXTRA to FilterTrendingModel(lan ?: "", FilterTrendingModel.TrendingSince.getSince(since))) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/modules/trending/fragment/viewmodel/TrendingViewModel.kt b/app/src/main/java/com/fastaccess/github/ui/modules/trending/fragment/viewmodel/TrendingViewModel.kt new file mode 100644 index 000000000..e8b6edf0b --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/modules/trending/fragment/viewmodel/TrendingViewModel.kt @@ -0,0 +1,78 @@ +package com.fastaccess.github.ui.modules.trending.fragment.viewmodel + +import androidx.lifecycle.MutableLiveData +import com.fastaccess.data.model.FirebaseTrendingConfigModel +import com.fastaccess.data.model.TrendingModel +import com.fastaccess.data.model.parcelable.FilterTrendingModel +import com.fastaccess.domain.repository.services.ScrapService +import com.fastaccess.github.BuildConfig +import com.fastaccess.github.base.BaseViewModel +import com.github.b3er.rxfirebase.database.RxFirebaseDatabase +import com.google.firebase.database.DatabaseReference +import org.jsoup.Jsoup +import retrofit2.Retrofit +import timber.log.Timber +import javax.inject.Inject +import javax.inject.Named + +/** + * Created by Kosh on 20.10.18. + */ +class TrendingViewModel @Inject constructor( + @Named(value = "github_trending") private val databaseReference: DatabaseReference, + private val retrofitBuilder: Retrofit.Builder +) : BaseViewModel() { + + private var trendingModel = FirebaseTrendingConfigModel() + private var service: ScrapService? = null + val trendingLiveData = MutableLiveData>() + var filterTrendingModel = FilterTrendingModel() + + init { + if (BuildConfig.DEBUG) { + onFirstLoad() + } else { + justSubscribe(RxFirebaseDatabase.childEvents(databaseReference) + .map { it.dataSnapshot() } + .doOnError { onFirstLoad() } // if we failed to load firebase database lets fallback to local data + .doOnNext { + @Suppress("UNCHECKED_CAST") + trendingModel = FirebaseTrendingConfigModel.map(it.value as? HashMap) + }) + } + } + + private fun onFirstLoad() { + service = retrofitBuilder.baseUrl(trendingModel.pathUrl).build().create(ScrapService::class.java) + } + + fun load(model: FilterTrendingModel) { + val language = if (model.lang == "All") "" else model.lang.replace(" ", "_").toLowerCase() + service?.getTrending(language, model.since.name.toLowerCase())?.let { observable -> + justSubscribe(observable + .map { html -> + val document = Jsoup.parse(html, "") + val list = document.select(trendingModel.listName) + val trendingList = arrayListOf() + list.select(trendingModel.listNameSublistTag)?.let { li -> + trendingList.addAll(li.map { body -> + val trendingLang = kotlin.runCatching { body.select(trendingModel.language).text() } + .getOrNull() ?: kotlin.runCatching { body.select(trendingModel.languageFallback).text() }.getOrNull() + val todayStars = kotlin.runCatching { body.select(trendingModel.todayStars).text() } + .getOrNull() ?: kotlin.runCatching { body.select(trendingModel.todayStarsFallback).text() }.getOrNull() + val title = kotlin.runCatching { body.select(trendingModel.title).text() }.getOrNull() + val description = kotlin.runCatching { body.select(trendingModel.description).text() }.getOrNull() + val stars = kotlin.runCatching { body.select(trendingModel.stars).text() }.getOrNull() + val forks = kotlin.runCatching { body.select(trendingModel.forks).text() }.getOrNull() + TrendingModel(title, description, trendingLang, stars, forks, todayStars) + }) + } + return@map trendingList + } + .doOnNext { + Timber.e("here :) (${it.size})") + trendingLiveData.postValue(it) + }) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/AnchorSheetBehavior.java b/app/src/main/java/com/fastaccess/github/ui/widget/AnchorSheetBehavior.java new file mode 100644 index 000000000..aced44a10 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/AnchorSheetBehavior.java @@ -0,0 +1,950 @@ +/* + * Copyright (c) 2016 HERE Europe B.V. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.fastaccess.github.ui.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; + +import com.fastaccess.github.R; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.ref.WeakReference; + +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.math.MathUtils; +import androidx.customview.view.AbsSavedState; +import androidx.customview.widget.ViewDragHelper; + +import static androidx.core.view.ViewCompat.NestedScrollType; +import static androidx.core.view.ViewCompat.SCROLL_AXIS_VERTICAL; +import static androidx.core.view.ViewCompat.ScrollAxis; +import static androidx.core.view.ViewCompat.getFitsSystemWindows; +import static androidx.core.view.ViewCompat.isAttachedToWindow; +import static androidx.core.view.ViewCompat.isNestedScrollingEnabled; +import static androidx.core.view.ViewCompat.offsetTopAndBottom; +import static androidx.core.view.ViewCompat.postOnAnimation; + +/** + * An interaction behavior plugin for a child view of {@link CoordinatorLayout} to make it work as + * a bottom sheet. + *

    + * Modification of the {@link } with an Anchor state. + */ +public class AnchorSheetBehavior extends CoordinatorLayout.Behavior { + + /** + * Callback for monitoring events about bottom sheets. + */ + public abstract static class AnchorSheetCallback { + + /** + * Called when the bottom sheet changes its state. + * + * @param bottomSheet The bottom sheet view. + * @param newState The new state. This will be one of {@link #STATE_DRAGGING}, + * {@link #STATE_SETTLING}, {@link #STATE_EXPANDED}, + * {@link #STATE_COLLAPSED}, or {@link #STATE_HIDDEN}. + */ + public abstract void onStateChanged(@NonNull View bottomSheet, @State int newState); + + /** + * Called when the bottom sheet is being dragged. + * + * @param bottomSheet The bottom sheet view. + * @param slideOffset The new offset of this bottom sheet within [-1,1] range. Offset + * increases as this bottom sheet is moving upward. From 0 to 1 the sheet + * is between collapsed and expanded states and from -1 to 0 it is + * between hidden and collapsed states. + */ + public abstract void onSlide(@NonNull View bottomSheet, float slideOffset); + } + + /** + * The bottom sheet is dragging. + */ + public static final int STATE_DRAGGING = 1; + + /** + * The bottom sheet is settling. + */ + public static final int STATE_SETTLING = 2; + + /** + * The bottom sheet is expanded. + */ + public static final int STATE_EXPANDED = 3; + + /** + * The bottom sheet is collapsed. + */ + public static final int STATE_COLLAPSED = 4; + + /** + * The bottom sheet is hidden. + */ + public static final int STATE_HIDDEN = 5; + + /** + * The bottom sheet is anchor. + */ + public static final int STATE_ANCHOR = 6; + + /** + * The bottom sheet is forced to be hidden programmatically. + */ + public static final int STATE_FORCE_HIDDEN = 7; + + /** + * @hide + */ + @IntDef({ + STATE_EXPANDED, + STATE_COLLAPSED, + STATE_DRAGGING, + STATE_SETTLING, + STATE_HIDDEN, + STATE_ANCHOR, + STATE_FORCE_HIDDEN + }) + @Retention(RetentionPolicy.SOURCE) + public @interface State { + } + + /** + * Peek at the 16:9 ratio keyline of its parent. + *

    + *

    This can be used as a parameter for {@link #setPeekHeight(int)}. + * {@link #getPeekHeight()} will return this when the value is set.

    + */ + public static final int PEEK_HEIGHT_AUTO = -1; + + private static final float HIDE_THRESHOLD = 0.5f; + + private static final float HIDE_FRICTION = 0.1f; + + private static final float ANCHOR_THRESHOLD = 0.50f; + + private float mAnchorThreshold = ANCHOR_THRESHOLD; + + private float mMaximumVelocity; + + private int mPeekHeight; + + private boolean mPeekHeightAuto; + + private int mPeekHeightMin; + + private int mMinOffset; + + private int mMaxOffset; + + private int mAnchorOffset; + + private boolean mHideable; + + private boolean mSkipCollapsed; + + @State + private int mState = STATE_COLLAPSED; + + private ViewDragHelper mViewDragHelper; + + private boolean mIgnoreEvents; + + private int mLastNestedScrollDy; + + private boolean mNestedScrolled; + + private int mParentHeight; + + private WeakReference mViewRef; + + private WeakReference mNestedScrollingChildRef; + + private AnchorSheetCallback mCallback; + + private VelocityTracker mVelocityTracker; + + private int mActivePointerId; + + private int mInitialY; + + private boolean mTouchingScrollingChild; + + /** + * Default constructor for instantiating AnchorSheetBehavior. + */ + public AnchorSheetBehavior() { + } + + /** + * Default constructor for inflating AnchorSheetBehavior from layout. + * + * @param context The {@link Context}. + * @param attrs The {@link AttributeSet}. + */ + public AnchorSheetBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.BottomSheetBehavior_Layout); + TypedValue value = a.peekValue( + R.styleable.BottomSheetBehavior_Layout_behavior_peekHeight); + if (value != null && value.data == PEEK_HEIGHT_AUTO) { + setPeekHeight(value.data); + } else { + setPeekHeight(a.getDimensionPixelSize( + R.styleable.BottomSheetBehavior_Layout_behavior_peekHeight, + PEEK_HEIGHT_AUTO + )); + } + setHideable(a.getBoolean( + R.styleable.BottomSheetBehavior_Layout_behavior_hideable, false)); + setSkipCollapsed(a.getBoolean( + R.styleable.BottomSheetBehavior_Layout_behavior_skipCollapsed, false)); + a.recycle(); + ViewConfiguration configuration = ViewConfiguration.get(context); + mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); + } + + @Override + public Parcelable onSaveInstanceState(CoordinatorLayout parent, V child) { + return new SavedState(super.onSaveInstanceState(parent, child), mState); + } + + @Override + public void onRestoreInstanceState(CoordinatorLayout parent, V child, Parcelable state) { + SavedState ss = (SavedState) state; + super.onRestoreInstanceState(parent, child, ss.getSuperState()); + // Intermediate states are restored as collapsed state + if (ss.state == STATE_DRAGGING || ss.state == STATE_SETTLING) { + mState = STATE_COLLAPSED; + } else { + mState = ss.state; + } + } + + @Override + public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) { + if (getFitsSystemWindows(parent) && !getFitsSystemWindows(child)) { + child.setFitsSystemWindows(true); + } + int savedTop = child.getTop(); + // First let the parent lay it out + parent.onLayoutChild(child, layoutDirection); + // Offset the bottom sheet + mParentHeight = parent.getHeight(); + int peekHeight; + if (mPeekHeightAuto) { + if (mPeekHeightMin == 0) { + mPeekHeightMin = parent.getResources().getDimensionPixelSize( + R.dimen.design_bottom_sheet_peek_height_min); + } + peekHeight = Math.max(mPeekHeightMin, mParentHeight - parent.getWidth() * 9 / 16); + } else { + peekHeight = mPeekHeight; + } + mMinOffset = Math.max(0, mParentHeight - child.getHeight()); + mMaxOffset = Math.max(mParentHeight - peekHeight, mMinOffset); + mAnchorOffset = (int) Math.max(mParentHeight * mAnchorThreshold, mMinOffset); + if (mState == STATE_EXPANDED) { + offsetTopAndBottom(child, mMinOffset); + } else if (mState == STATE_ANCHOR) { + offsetTopAndBottom(child, mAnchorOffset); + } else if ((mHideable && mState == STATE_HIDDEN) || mState == STATE_FORCE_HIDDEN) { + offsetTopAndBottom(child, mParentHeight); + } else if (mState == STATE_COLLAPSED) { + offsetTopAndBottom(child, mMaxOffset); + } else if (mState == STATE_DRAGGING || mState == STATE_SETTLING) { + offsetTopAndBottom(child, savedTop - child.getTop()); + } + if (mViewDragHelper == null) { + mViewDragHelper = ViewDragHelper.create(parent, mDragCallback); + } + mViewRef = new WeakReference<>(child); + mNestedScrollingChildRef = new WeakReference<>(findScrollingChild(child)); + return true; + } + + @Override + public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) { + if (!child.isShown()) { + mIgnoreEvents = true; + return false; + } + int action = event.getActionMasked(); + // Record the velocity + if (action == MotionEvent.ACTION_DOWN) { + reset(); + } + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(event); + switch (action) { + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mTouchingScrollingChild = false; + mActivePointerId = MotionEvent.INVALID_POINTER_ID; + // Reset the ignore flag + if (mIgnoreEvents) { + mIgnoreEvents = false; + return false; + } + break; + case MotionEvent.ACTION_DOWN: + int initialX = (int) event.getX(); + mInitialY = (int) event.getY(); + View scroll = mNestedScrollingChildRef != null + ? mNestedScrollingChildRef.get() : null; + if (scroll != null && parent.isPointInChildBounds(scroll, initialX, mInitialY)) { + mActivePointerId = event.getPointerId(event.getActionIndex()); + mTouchingScrollingChild = true; + } + mIgnoreEvents = mActivePointerId == MotionEvent.INVALID_POINTER_ID && + !parent.isPointInChildBounds(child, initialX, mInitialY); + break; + } + if (!mIgnoreEvents && mViewDragHelper.shouldInterceptTouchEvent(event)) { + return true; + } + // We have to handle cases that the ViewDragHelper does not capture the bottom sheet because + // it is not the top most view of its parent. This is not necessary when the touch event is + // happening over the scrolling content as nested scrolling logic handles that case. + View scroll = mNestedScrollingChildRef.get(); + return action == MotionEvent.ACTION_MOVE && scroll != null && + !mIgnoreEvents && mState != STATE_DRAGGING && + !parent.isPointInChildBounds(scroll, (int) event.getX(), (int) event.getY()) && + Math.abs(mInitialY - event.getY()) > mViewDragHelper.getTouchSlop(); + } + + @Override + public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) { + if (!child.isShown() || mViewDragHelper == null) { + return false; + } + int action = event.getActionMasked(); + if (mState == STATE_DRAGGING && action == MotionEvent.ACTION_DOWN) { + return true; + } + mViewDragHelper.processTouchEvent(event); + // Record the velocity + if (action == MotionEvent.ACTION_DOWN) { + reset(); + } + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(event); + // The ViewDragHelper tries to capture only the top-most View. We have to explicitly tell it + // to capture the bottom sheet in case it is not captured and the touch slop is passed. + if (action == MotionEvent.ACTION_MOVE && !mIgnoreEvents) { + if (Math.abs(mInitialY - event.getY()) > mViewDragHelper.getTouchSlop()) { + mViewDragHelper.captureChildView(child, event.getPointerId(event.getActionIndex())); + } + } + return !mIgnoreEvents; + } + + @Override + public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, + @NonNull V child, + @NonNull View directTargetChild, + @NonNull View target, + @ScrollAxis int nestedScrollAxes, + @NestedScrollType int type) { + mLastNestedScrollDy = 0; + mNestedScrolled = false; + return (nestedScrollAxes & SCROLL_AXIS_VERTICAL) != 0; + } + + @Override + public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, + @NonNull V child, + @NonNull View target, + int dx, + int dy, + @NonNull int[] consumed, + @NestedScrollType int type) { + View scrollingChild = mNestedScrollingChildRef.get(); + if (target != scrollingChild) { + return; + } + int currentTop = child.getTop(); + int newTop = currentTop - dy; + if (dy > 0) { // Upward + if (newTop < mMinOffset) { + consumed[1] = currentTop - mMinOffset; + offsetTopAndBottom(child, -consumed[1]); + setStateInternal(STATE_EXPANDED); + } else { + consumed[1] = dy; + offsetTopAndBottom(child, -dy); + setStateInternal(STATE_DRAGGING); + } + } else if (dy < 0) { // Downward + if (!target.canScrollVertically(-1)) { + if (newTop <= mMaxOffset || mHideable) { + consumed[1] = dy; + offsetTopAndBottom(child, -dy); + setStateInternal(STATE_DRAGGING); + } else { + consumed[1] = currentTop - mMaxOffset; + offsetTopAndBottom(child, -consumed[1]); + setStateInternal(STATE_COLLAPSED); + } + } + } + dispatchOnSlide(child.getTop()); + mLastNestedScrollDy = dy; + mNestedScrolled = true; + } + + @Override + public void onStopNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, + @NonNull V child, + @NonNull View target, + @NestedScrollType int type) { + if (child.getTop() == mMinOffset) { + setStateInternal(STATE_EXPANDED); + return; + } + if (mNestedScrollingChildRef == null || target != mNestedScrollingChildRef.get() + || !mNestedScrolled) { + return; + } + int top; + int targetState; + if (mLastNestedScrollDy > 0) { + int currentTop = child.getTop(); + if (Math.abs(currentTop - mMinOffset) < Math.abs(currentTop - mAnchorOffset)) { + top = mMinOffset; + targetState = STATE_EXPANDED; + } else { + top = mAnchorOffset; + targetState = STATE_ANCHOR; + } + } else if (mHideable && shouldHide(child, getYVelocity())) { + top = mParentHeight; + targetState = STATE_HIDDEN; + } else if (mLastNestedScrollDy == 0) { + int currentTop = child.getTop(); + if (Math.abs(currentTop - mAnchorOffset) < Math.abs(currentTop - mMinOffset)) { + top = mAnchorOffset; + targetState = STATE_ANCHOR; + } else if (Math.abs(currentTop - mMinOffset) < Math.abs(currentTop - mMaxOffset)) { + top = mMinOffset; + targetState = STATE_EXPANDED; + } else { + top = mMaxOffset; + targetState = STATE_COLLAPSED; + } + } else { + int currentTop = child.getTop(); + if (Math.abs(currentTop - mAnchorOffset) < Math.abs(currentTop - mMaxOffset)) { + top = mAnchorOffset; + targetState = STATE_ANCHOR; + } else { + top = mMaxOffset; + targetState = STATE_COLLAPSED; + } + } + if (mViewDragHelper.smoothSlideViewTo(child, child.getLeft(), top)) { + setStateInternal(STATE_SETTLING); + postOnAnimation(child, new SettleRunnable(child, targetState)); + } else { + setStateInternal(targetState); + } + mNestedScrolled = false; + } + + @Override + public boolean onNestedPreFling(@NonNull CoordinatorLayout coordinatorLayout, + @NonNull V child, + @NonNull View target, + float velocityX, + float velocityY) { + return target == mNestedScrollingChildRef.get() && + (mState != STATE_EXPANDED || + super.onNestedPreFling(coordinatorLayout, child, target, + velocityX, velocityY)); + } + + /** + * Sets the height of the bottom sheet when it is collapsed. + * + * @param peekHeight The height of the collapsed bottom sheet in pixels. + * @attr ref R.styleable#AnchorBehavior_Params_behavior_peekHeight + */ + public final void setPeekHeight(int peekHeight) { + boolean layout = false; + if (peekHeight == PEEK_HEIGHT_AUTO) { + if (!mPeekHeightAuto) { + mPeekHeightAuto = true; + layout = true; + } + } else if (mPeekHeightAuto || mPeekHeight != peekHeight) { + mPeekHeightAuto = false; + mPeekHeight = Math.max(0, peekHeight); + mMaxOffset = mParentHeight - peekHeight; + layout = true; + } + if (layout && mState == STATE_COLLAPSED && mViewRef != null) { + V view = mViewRef.get(); + if (view != null) { + view.requestLayout(); + } + } + } + + /** + * Gets the height of the bottom sheet when it is collapsed. + * + * @return The height of the collapsed bottom sheet in pixels, or {@link #PEEK_HEIGHT_AUTO} + * if the sheet is configured to peek automatically at 16:9 ratio keyline + * @attr ref R.styleable#BottomSheetBehavior_Layout_behavior_peekHeight + */ + public final int getPeekHeight() { + return mPeekHeightAuto ? PEEK_HEIGHT_AUTO : mPeekHeight; + } + + /** + * Gets the offset from the panel till the top + * + * @return the offset in pixel size + */ + public final int getPanelOffset() { + if (mState == STATE_EXPANDED) { + return mMinOffset; + } else if (mState == STATE_ANCHOR) { + return mAnchorOffset; + } else if (mHideable && mState == STATE_HIDDEN) { + return mParentHeight; + } + return mMaxOffset; + } + + /** + * Get the size in pixels from the anchor state to the top of the parent (Expanded state) + * + * @return pixel size of the anchor state + */ + public int getAnchorOffset() { + return mAnchorOffset; + } + + /** + * The multiplier between 0..1 to calculate the Anchor offset + * + * @return float between 0..1 + */ + public float getAnchorThreshold() { + return mAnchorThreshold; + } + + /** + * Set the offset for the anchor state. Number between 0..1 + * i.e: Anchor the panel at 1/3 of the screen: setAnchorOffset(0.25) + * + * @param threshold {@link Float} from 0..1 + */ + public void setAnchorOffset(float threshold) { + this.mAnchorThreshold = threshold; + this.mAnchorOffset = (int) Math.max(mParentHeight * mAnchorThreshold, mMinOffset); + } + + /** + * Sets whether this bottom sheet can hide when it is swiped down. + * + * @param hideable {@code true} to make this bottom sheet hideable. + * @attr ref R.styleable#BottomSheetBehavior_Layout_behavior_hideable + */ + public void setHideable(boolean hideable) { + mHideable = hideable; + } + + /** + * Gets whether this bottom sheet can hide when it is swiped down. + * + * @return {@code true} if this bottom sheet can hide. + * @attr ref R.styleable#AnchorBehavior_Params_behavior_hideable + */ + public boolean isHideable() { + return mHideable; + } + + /** + * Sets whether this bottom sheet should skip the collapsed state when it is being hidden + * after it is expanded once. Setting this to true has no effect unless the sheet is hideable. + * + * @param skipCollapsed True if the bottom sheet should skip the collapsed state. + * @attr ref R.styleable#BottomSheetBehavior_Layout_behavior_skipCollapsed + */ + public void setSkipCollapsed(boolean skipCollapsed) { + mSkipCollapsed = skipCollapsed; + } + + /** + * Sets whether this bottom sheet should skip the collapsed state when it is being hidden + * after it is expanded once. + * + * @return Whether the bottom sheet should skip the collapsed state. + * @attr ref R.styleable#BottomSheetBehavior_Layout_behavior_skipCollapsed + */ + public boolean getSkipCollapsed() { + return mSkipCollapsed; + } + + /** + * Sets a callback to be notified of bottom sheet events. + * + * @param callback The callback to notify when bottom sheet events occur. + */ + public void setAnchorSheetCallback(AnchorSheetCallback callback) { + mCallback = callback; + } + + /** + * Sets the state of the bottom sheet. The bottom sheet will transition to that state with + * animation. + * + * @param state One of {@link #STATE_COLLAPSED}, {@link #STATE_EXPANDED}, or + * {@link #STATE_HIDDEN}. + */ + public final void setState(@State final int state) { + if (state == mState) { + return; + } + if (mViewRef == null) { + // The view is not laid out yet; modify mState and let onLayoutChild handle it later + if (state == STATE_COLLAPSED || state == STATE_EXPANDED || state == STATE_ANCHOR || + ((mHideable && state == STATE_HIDDEN) || state == STATE_FORCE_HIDDEN)) { + mState = state; + } + return; + } + final V child = mViewRef.get(); + if (child == null) { + return; + } + // Start the animation; wait until a pending layout if there is one. + ViewParent parent = child.getParent(); + if (parent != null && parent.isLayoutRequested() && isAttachedToWindow(child)) { + child.post(new Runnable() { + @Override + public void run() { + startSettlingAnimation(child, state); + } + }); + } else { + startSettlingAnimation(child, state); + } + } + + /** + * Gets the current state of the bottom sheet. + * + * @return One of {@link #STATE_EXPANDED}, {@link #STATE_COLLAPSED}, {@link #STATE_DRAGGING}, + * and {@link #STATE_SETTLING}. + */ + @State + public final int getState() { + return mState; + } + + private void setStateInternal(@State int state) { + if (mState == state) { + return; + } + mState = state; + View bottomSheet = mViewRef.get(); + if (bottomSheet != null && mCallback != null) { + mCallback.onStateChanged(bottomSheet, state); + } + } + + private void reset() { + mActivePointerId = ViewDragHelper.INVALID_POINTER; + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + boolean shouldHide(View child, float yvel) { + if (mSkipCollapsed) { + return true; + } + if (child.getTop() < mMaxOffset) { + // It should not hide, but collapse. + return false; + } + final float newTop = child.getTop() + yvel * HIDE_FRICTION; + return Math.abs(newTop - mMaxOffset) / (float) mPeekHeight > HIDE_THRESHOLD; + } + + @VisibleForTesting + View findScrollingChild(View view) { + if (isNestedScrollingEnabled(view)) { + return view; + } + if (view instanceof ViewGroup) { + ViewGroup group = (ViewGroup) view; + for (int i = 0, count = group.getChildCount(); i < count; i++) { + View scrollingChild = findScrollingChild(group.getChildAt(i)); + if (scrollingChild != null) { + return scrollingChild; + } + } + } + return null; + } + + private float getYVelocity() { + mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); + return mVelocityTracker.getYVelocity(mActivePointerId); + } + + void startSettlingAnimation(View child, int state) { + int top; + if (state == STATE_ANCHOR) { + top = mAnchorOffset; + } else if (state == STATE_COLLAPSED) { + top = mMaxOffset; + } else if (state == STATE_EXPANDED) { + top = mMinOffset; + } else if ((mHideable && state == STATE_HIDDEN) || state == STATE_FORCE_HIDDEN) { + top = mParentHeight; + } else { + throw new IllegalArgumentException("Illegal state argument: " + state); + } + if (mViewDragHelper.smoothSlideViewTo(child, child.getLeft(), top)) { + setStateInternal(STATE_SETTLING); + postOnAnimation(child, new SettleRunnable(child, state)); + } else { + setStateInternal(state); + } + } + + private final ViewDragHelper.Callback mDragCallback = new ViewDragHelper.Callback() { + + @Override + public boolean tryCaptureView(View child, int pointerId) { + if (mState == STATE_DRAGGING) { + return false; + } + if (mTouchingScrollingChild) { + return false; + } + if (mState == STATE_EXPANDED && mActivePointerId == pointerId) { + View scroll = mNestedScrollingChildRef.get(); + if (scroll != null && scroll.canScrollVertically(-1)) { + // Let the content scroll up + return false; + } + } + return mViewRef != null && mViewRef.get() == child; + } + + @Override + public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { + dispatchOnSlide(top); + } + + @Override + public void onViewDragStateChanged(int state) { + if (state == ViewDragHelper.STATE_DRAGGING) { + setStateInternal(STATE_DRAGGING); + } + } + + @Override + public void onViewReleased(View releasedChild, float xvel, float yvel) { + int top; + @State int targetState; + if (yvel < 0) { // Moving up + int currentTop = releasedChild.getTop(); + if (Math.abs(currentTop - mMinOffset) < Math.abs(currentTop - mAnchorOffset)) { + top = mMinOffset; + targetState = STATE_EXPANDED; + } else { + top = mAnchorOffset; + targetState = STATE_ANCHOR; + } + } else if (mHideable && shouldHide(releasedChild, yvel)) { + top = mParentHeight; + targetState = STATE_HIDDEN; + } else if (yvel == 0.f) { + int currentTop = releasedChild.getTop(); + if (Math.abs(currentTop - mMinOffset) < Math.abs(currentTop - mAnchorOffset)) { + top = mMinOffset; + targetState = STATE_EXPANDED; + } else if (Math.abs(currentTop - mAnchorOffset) < Math.abs(currentTop - mMaxOffset)) { + top = mAnchorOffset; + targetState = STATE_ANCHOR; + } else { + top = mMaxOffset; + targetState = STATE_COLLAPSED; + } + } else { + top = mMaxOffset; + targetState = STATE_COLLAPSED; + } + if (mViewDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top)) { + setStateInternal(STATE_SETTLING); + postOnAnimation(releasedChild, + new SettleRunnable(releasedChild, targetState)); + } else { + setStateInternal(targetState); + } + } + + @Override + public int clampViewPositionVertical(View child, int top, int dy) { + return MathUtils.clamp(top, mMinOffset, mHideable ? mParentHeight : mMaxOffset); + } + + @Override + public int clampViewPositionHorizontal(View child, int left, int dx) { + return child.getLeft(); + } + + @Override + public int getViewVerticalDragRange(View child) { + if (mHideable) { + return mParentHeight - mMinOffset; + } else { + return mMaxOffset - mMinOffset; + } + } + }; + + void dispatchOnSlide(int top) { + View bottomSheet = mViewRef.get(); + if (bottomSheet != null && mCallback != null) { + if (top > mMaxOffset) { + mCallback.onSlide(bottomSheet, (float) (mMaxOffset - top) / + (mParentHeight - mMaxOffset)); + } else { + mCallback.onSlide(bottomSheet, + (float) (mMaxOffset - top) / ((mMaxOffset - mMinOffset))); + } + } + } + + @VisibleForTesting + int getPeekHeightMin() { + return mPeekHeightMin; + } + + private class SettleRunnable implements Runnable { + + private final View mView; + + @State + private final int mTargetState; + + SettleRunnable(View view, @State int targetState) { + mView = view; + mTargetState = targetState; + } + + @Override + public void run() { + if (mViewDragHelper != null && mViewDragHelper.continueSettling(true)) { + postOnAnimation(mView, this); + } else { + setStateInternal(mTargetState); + } + } + } + + protected static class SavedState extends AbsSavedState { + @State + final int state; + + public SavedState(Parcel source) { + this(source, null); + } + + public SavedState(Parcel source, ClassLoader loader) { + super(source, loader); + //noinspection ResourceType + state = source.readInt(); + } + + public SavedState(Parcelable superState, @State int state) { + super(superState); + this.state = state; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeInt(state); + } + + public static final Creator CREATOR = new ClassLoaderCreator() { + @Override + public SavedState createFromParcel(Parcel in, ClassLoader loader) { + return new SavedState(in, loader); + } + + @Override + public SavedState createFromParcel(Parcel in) { + return new SavedState(in, null); + } + + @Override + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } + + /** + * A utility function to get the {@link AnchorSheetBehavior} associated with the {@code view}. + * + * @param view The {@link View} with {@link AnchorSheetBehavior}. + * @return The {@link AnchorSheetBehavior} associated with the {@code view}. + */ + @SuppressWarnings("unchecked") + public static AnchorSheetBehavior from(V view) { + ViewGroup.LayoutParams params = view.getLayoutParams(); + if (!(params instanceof CoordinatorLayout.LayoutParams)) { + throw new IllegalArgumentException("The view is not a child of CoordinatorLayout"); + } + CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) params).getBehavior(); + if (!(behavior instanceof AnchorSheetBehavior)) { + throw new IllegalArgumentException("The view is not associated with AnchorSheetBehavior"); + } + return (AnchorSheetBehavior) behavior; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/AppBarBottomSheetBehaviour.kt b/app/src/main/java/com/fastaccess/github/ui/widget/AppBarBottomSheetBehaviour.kt new file mode 100644 index 000000000..cb952c3cd --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/AppBarBottomSheetBehaviour.kt @@ -0,0 +1,39 @@ +package com.fastaccess.github.ui.widget + +import android.content.Context +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import androidx.coordinatorlayout.widget.CoordinatorLayout +import com.fastaccess.github.R +import com.google.android.material.appbar.AppBarLayout +import com.google.android.material.bottomsheet.BottomSheetBehavior + +class AppBarBottomSheetBehaviour(context: Context, attrs: AttributeSet?) : AppBarLayout.Behavior(context, attrs) { + private var hasBottomSheet = false + + override fun onStartNestedScroll(parent: CoordinatorLayout, child: AppBarLayout, directTargetChild: View, target: View, nestedScrollAxes: Int, + type: Int): Boolean { + val bottomSheet = parent.findViewById(R.id.bottomSheet) + hasBottomSheet = isOpen(bottomSheet) + return !hasBottomSheet && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes, type) + } + + override fun onInterceptTouchEvent(parent: CoordinatorLayout, child: AppBarLayout, ev: MotionEvent): Boolean { + if (ev.actionMasked == MotionEvent.ACTION_CANCEL) { + hasBottomSheet = false + } + return !hasBottomSheet && super.onInterceptTouchEvent(parent, child, ev) + } + + private fun isOpen(bottomSheet: View?): Boolean = getBottomSheetState(bottomSheet) != BottomSheetBehavior.STATE_COLLAPSED + + private fun getBottomSheetState(bottomSheet: View?): Int? { + val view = bottomSheet ?: return null + return try { + BottomSheetBehavior.from(view)?.state + } catch (e: Exception) { + AnchorSheetBehavior.from(view)?.state + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/AvatarImageView.kt b/app/src/main/java/com/fastaccess/github/ui/widget/AvatarImageView.kt new file mode 100644 index 000000000..9ff086485 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/AvatarImageView.kt @@ -0,0 +1,38 @@ +package com.fastaccess.github.ui.widget + +import android.content.Context +import android.util.AttributeSet +import androidx.appcompat.widget.AppCompatImageView +import com.fastaccess.github.R +import com.fastaccess.github.extensions.getDrawableCompat +import com.fastaccess.github.platform.glide.GlideApp +import com.fastaccess.github.utils.extensions.route + +/** + * Created by Kosh on 27.12.18. + */ +class AvatarImageView constructor(context: Context, + attrs: AttributeSet? = null, + defStyle: Int = 0) : AppCompatImageView(context, attrs, defStyle) { + constructor(context: Context) : this(context, null) + constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) + + + fun loadAvatar(url: String? = null, userUrl: String? = null) { + setBackgroundResource(R.drawable.circle_shape) + if (url.isNullOrEmpty()) { + setImageResource(R.drawable.ic_profile) + scaleType = ScaleType.CENTER_CROP + } else { + val drawable = context.getDrawableCompat(R.drawable.ic_profile) + GlideApp.with(this) + .load(url) + .circleCrop() + .fallback(drawable) + .error(drawable) + .dontAnimate() + .into(this) + } + userUrl?.let { setOnClickListener { it.context.route(userUrl) } } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/ParentSwipeRefreshLayout.kt b/app/src/main/java/com/fastaccess/github/ui/widget/ParentSwipeRefreshLayout.kt new file mode 100644 index 000000000..856e62132 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/ParentSwipeRefreshLayout.kt @@ -0,0 +1,35 @@ +package com.fastaccess.github.ui.widget + +import android.content.Context +import android.util.AttributeSet +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import com.fastaccess.github.R +import com.fastaccess.github.extensions.getColorCompat +import com.google.android.material.appbar.AppBarLayout + +class ParentSwipeRefreshLayout : SwipeRefreshLayout, AppBarLayout.OnOffsetChangedListener { + var appBarLayout: AppBarLayout? = null + set(value) { + field = value + value?.addOnOffsetChangedListener(this) + } + + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + setColorSchemeColors(context.getColorCompat(R.color.material_indigo_600), context.getColorCompat(R.color.material_indigo_700), + context.getColorCompat(R.color.material_indigo_800), context.getColorCompat(R.color.material_indigo_900)) + } + + override fun onDetachedFromWindow() { + appBarLayout?.removeOnOffsetChangedListener(this) + appBarLayout = null + super.onDetachedFromWindow() + } + + override fun onOffsetChanged(appBarLayout: AppBarLayout, i: Int) { + this.isEnabled = i == 0 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/ReactionsChipGroup.kt b/app/src/main/java/com/fastaccess/github/ui/widget/ReactionsChipGroup.kt new file mode 100644 index 000000000..0925f5748 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/ReactionsChipGroup.kt @@ -0,0 +1,91 @@ +package com.fastaccess.github.ui.widget + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.PopupWindow +import com.fastaccess.data.model.ReactionContent +import com.fastaccess.data.model.ReactionGroupModel +import com.fastaccess.data.model.getEmoji +import com.fastaccess.github.R +import com.fastaccess.github.platform.works.ReactionWorker +import com.google.android.material.chip.ChipGroup +import kotlinx.android.synthetic.main.reactions_chips_layout.view.* + +/** + * Created by Kosh on 06.02.19. + */ +class ReactionsChipGroup : ChipGroup { + constructor(context: Context?) : super(context) + constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + + @SuppressLint("RestrictedApi") + override fun onFinishInflate() { + super.onFinishInflate() + View.inflate(context, R.layout.reactions_chips_layout, this) + } + + @SuppressLint("SetTextI18n") fun setup( + id: String, + reactionGroups: List?, + popupWindow: PopupWindow? = null, + callback: (() -> Unit)?) { + thumbsUp.text = "${ReactionContent.THUMBS_UP.getEmoji()} ${reactionGroups + ?.firstOrNull { it.content == ReactionContent.THUMBS_UP } + ?.users?.totalCount}" + thumbsDown.text = "${ReactionContent.THUMBS_DOWN.getEmoji()} ${reactionGroups + ?.firstOrNull { it.content == ReactionContent.THUMBS_DOWN } + ?.users?.totalCount}" + confused.text = "${ReactionContent.CONFUSED.getEmoji()} ${reactionGroups + ?.firstOrNull { it.content == ReactionContent.CONFUSED } + ?.users?.totalCount}" + laugh.text = "${ReactionContent.LAUGH.getEmoji()} ${reactionGroups + ?.firstOrNull { it.content == ReactionContent.LAUGH } + ?.users?.totalCount}" + hooray.text = "${ReactionContent.HOORAY.getEmoji()} ${reactionGroups + ?.firstOrNull { it.content == ReactionContent.HOORAY } + ?.users?.totalCount}" + heart.text = "${ReactionContent.HEART.getEmoji()} ${reactionGroups + ?.firstOrNull { it.content == ReactionContent.HEART } + ?.users?.totalCount}" + rocket.text = "${ReactionContent.ROCKET.getEmoji()} ${reactionGroups + ?.firstOrNull { it.content == ReactionContent.ROCKET } + ?.users?.totalCount}" + eyes.text = "${ReactionContent.EYES.getEmoji()} ${reactionGroups + ?.firstOrNull { it.content == ReactionContent.EYES } + ?.users?.totalCount}" + + thumbsUp.setOnClickListener { react(id, reactionGroups?.firstOrNull { it.content == ReactionContent.THUMBS_UP }, popupWindow, callback) } + thumbsDown.setOnClickListener { react(id, reactionGroups?.firstOrNull { it.content == ReactionContent.THUMBS_DOWN }, popupWindow, callback) } + confused.setOnClickListener { react(id, reactionGroups?.firstOrNull { it.content == ReactionContent.CONFUSED }, popupWindow, callback) } + laugh.setOnClickListener { react(id, reactionGroups?.firstOrNull { it.content == ReactionContent.LAUGH }, popupWindow, callback) } + hooray.setOnClickListener { react(id, reactionGroups?.firstOrNull { it.content == ReactionContent.HOORAY }, popupWindow, callback) } + heart.setOnClickListener { react(id, reactionGroups?.firstOrNull { it.content == ReactionContent.HEART }, popupWindow, callback) } + rocket.setOnClickListener { react(id, reactionGroups?.firstOrNull { it.content == ReactionContent.ROCKET }, popupWindow, callback) } + eyes.setOnClickListener { react(id, reactionGroups?.firstOrNull { it.content == ReactionContent.EYES }, popupWindow, callback) } + } + + private fun react( + id: String, + model: ReactionGroupModel?, + popupWindow: PopupWindow?, + callback: (() -> Unit)?) { + model?.let { reaction -> + val add: Boolean + if (reaction.viewerHasReacted == true) { + reaction.users?.totalCount = reaction.users?.totalCount?.minus(1) + model.viewerHasReacted = false + add = false + } else { + reaction.users?.totalCount = reaction.users?.totalCount?.plus(1) + model.viewerHasReacted = true + add = true + } + ReactionWorker.enqueue(model.content?.value ?: "", id, add) + callback?.invoke() + popupWindow?.dismiss() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/ViewPagerView.kt b/app/src/main/java/com/fastaccess/github/ui/widget/ViewPagerView.kt new file mode 100644 index 000000000..6b0438703 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/ViewPagerView.kt @@ -0,0 +1,67 @@ +package com.fastaccess.github.ui.widget + +import android.R.attr.enabled +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.MotionEvent +import androidx.viewpager.widget.PagerAdapter +import androidx.viewpager.widget.ViewPager + + +/** + * Created by kosh20111 on 10/8/2015. + * + * + * Viewpager that has scrolling animation by default + */ +class ViewPagerView : ViewPager { + + private var isEnabled: Boolean = false + + constructor(context: Context) : super(context) + + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { + val attrsArray = intArrayOf(enabled) + val array = context.obtainStyledAttributes(attrs, attrsArray) + isEnabled = array.getBoolean(0, true) + array.recycle() + } + + override fun isEnabled(): Boolean { + return isEnabled + } + + override fun setEnabled(enabled: Boolean) { + this.isEnabled = enabled + requestLayout() + } + + override fun setAdapter(adapter: PagerAdapter?) { + super.setAdapter(adapter) + if (isInEditMode) return + if (adapter != null) { + offscreenPageLimit = adapter.count + } + } + + @SuppressLint("ClickableViewAccessibility") override fun onTouchEvent(event: MotionEvent): Boolean { + try { + return !isEnabled() || super.onTouchEvent(event) + } catch (ex: IllegalArgumentException) { + ex.printStackTrace() + } + + return false + } + + override fun onInterceptTouchEvent(event: MotionEvent): Boolean { + try { + return isEnabled() && super.onInterceptTouchEvent(event) + } catch (ex: IllegalArgumentException) { + ex.printStackTrace() + } + + return false + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/dialog/IconDialogFragment.kt b/app/src/main/java/com/fastaccess/github/ui/widget/dialog/IconDialogFragment.kt new file mode 100644 index 000000000..922a2291b --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/dialog/IconDialogFragment.kt @@ -0,0 +1,82 @@ +package com.fastaccess.github.ui.widget.dialog + +import android.content.Context +import android.os.Bundle +import android.view.View +import androidx.core.os.bundleOf +import androidx.fragment.app.FragmentManager +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseDialogFragment +import com.fastaccess.github.extensions.show +import com.fastaccess.github.utils.* +import kotlinx.android.synthetic.main.icon_dialog_layout.* + + +/** + * Created by Kosh on 26.01.19. + */ +class IconDialogFragment : BaseDialogFragment() { + override fun layoutRes(): Int = R.layout.icon_dialog_layout + + private var callback: IconDialogClickListener? = null + + private val bundleDrawable by lazy { arguments?.getInt(EXTRA) ?: com.fastaccess.github.R.drawable.ic_info_outline } + private val bundleTitle by lazy { arguments?.getString(EXTRA_TWO) } + private val bundleDescription by lazy { arguments?.getString(EXTRA_THREE) } + private val bundlePositiveBtnText by lazy { arguments?.getString(EXTRA_FOUR) } + private val bundleNegativeBtnText by lazy { arguments?.getString(EXTRA_FIVE) } + + override fun onAttach(context: Context) { + super.onAttach(context) + callback = when { + parentFragment is IconDialogClickListener -> parentFragment as IconDialogClickListener + context is IconDialogClickListener -> context + else -> null + } + } + + override fun onDetach() { + callback = null + super.onDetach() + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + dialogIcon.setImageResource(bundleDrawable) + dialogTitle.text = bundleTitle + dialogDescription.text = bundleDescription + dialogPositiveBtn.text = bundlePositiveBtnText + dialogNegativeBtn.text = bundleNegativeBtnText + + dialogPositiveBtn.setOnClickListener { + callback?.onClick(true) + dialog?.cancel() + } + dialogNegativeBtn.setOnClickListener { + callback?.onClick(false) + dialog?.cancel() + } + } + + companion object { + fun show( + fragmentManager: FragmentManager, + drawable: Int, + title: String, + description: String, + positiveBtnText: String, + negativeBtnText: String + ): IconDialogFragment = IconDialogFragment().apply { + arguments = bundleOf(EXTRA to drawable, + EXTRA_TWO to title, + EXTRA_THREE to description, + EXTRA_FOUR to positiveBtnText, + EXTRA_FIVE to negativeBtnText) + show(fragmentManager) + } + } + + interface IconDialogClickListener { + fun onClick(positive: Boolean) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/BaseRecyclerView.kt b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/BaseRecyclerView.kt new file mode 100644 index 000000000..29525a495 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/BaseRecyclerView.kt @@ -0,0 +1,104 @@ +package com.fastaccess.github.ui.widget.recyclerview + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import androidx.core.view.isVisible +import androidx.recyclerview.widget.RecyclerView + + +/** + * Created by Kosh on 23.06.18. + */ +class BaseRecyclerView constructor(context: Context, + attrs: AttributeSet? = null, + defStyle: Int = 0) : RecyclerView(context, attrs, defStyle) { + constructor(context: Context) : this(context, null) + constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) + + private var emptyView: View? = null + private var parentView: View? = null + private var onLoadMore: (() -> Unit)? = null + + private val onScrollMore = EndlessRecyclerViewScrollListener { if (it >= 20) onLoadMore?.invoke() } + + private val observer = object : RecyclerView.AdapterDataObserver() { + override fun onChanged() { + showEmptyView() + } + + override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { + super.onItemRangeInserted(positionStart, itemCount) + showEmptyView() + } + + override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { + super.onItemRangeRemoved(positionStart, itemCount) + showEmptyView() + } + } + + override fun setAdapter(adapter: RecyclerView.Adapter<*>?) { + super.setAdapter(adapter) + if (isInEditMode) return + if (adapter != null) { + adapter.registerAdapterDataObserver(observer) + observer.onChanged() + } + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + runCatching { + removeOnScrollListener(onScrollMore) + } + } + + fun setEmptyView(emptyView: View, parentView: View? = null) { + this.emptyView = emptyView + this.parentView = parentView + showEmptyView() + } + + fun addOnLoadMore(onLoadMore: (() -> Unit)? = null) { + this.onLoadMore = onLoadMore + if (onLoadMore == null) { + removeOnScrollListener(onScrollMore) + } else { + addOnScrollListener(onScrollMore) + } + } + + fun resetScrollState() { + onScrollMore.resetState() + } + + fun removeEmptyView() { + showParentOrSelf(true) + emptyView = null + } + + private fun showEmptyView() { + val adapter = adapter + if (adapter != null) { + if (emptyView != null) { + if (adapter.itemCount == 0) { + onScrollMore.resetState() + showParentOrSelf(false) + } else { + showParentOrSelf(true) + } + } + } else { + if (emptyView != null) { + showParentOrSelf(false) + } + } + } + + private fun showParentOrSelf(showRecyclerView: Boolean) { + parentView?.isVisible = parentView != null + isVisible = true + emptyView?.isVisible = !showRecyclerView + } +} diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/EndlessRecyclerViewScrollListener.kt b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/EndlessRecyclerViewScrollListener.kt new file mode 100644 index 000000000..788c0d3ce --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/EndlessRecyclerViewScrollListener.kt @@ -0,0 +1,90 @@ +package com.fastaccess.github.ui.widget.recyclerview + +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.StaggeredGridLayoutManager + +class EndlessRecyclerViewScrollListener(private val onLoadMore: (totalCount: Int) -> Unit) : RecyclerView.OnScrollListener() { + private var visibleThreshold = 5 + private var previousTotalItemCount = 0 + private var loading = true + private var layoutManager: RecyclerView.LayoutManager? = null + private var firstAttach = true + + private fun init(recyclerView: RecyclerView) { + this.layoutManager = recyclerView.layoutManager + val lm = layoutManager ?: return + when (lm) { + is GridLayoutManager -> init(lm) + is StaggeredGridLayoutManager -> init(lm) + } + } + + private fun init(layoutManager: GridLayoutManager) { + this.layoutManager = layoutManager + visibleThreshold *= layoutManager.spanCount + } + + private fun init(layoutManager: StaggeredGridLayoutManager) { + this.layoutManager = layoutManager + visibleThreshold *= layoutManager.spanCount + } + + private fun getLastVisibleItem(lastVisibleItemPositions: IntArray): Int { + var maxSize = 0 + for (i in lastVisibleItemPositions.indices) { + if (i == 0) { + maxSize = lastVisibleItemPositions[i] + } else if (lastVisibleItemPositions[i] > maxSize) { + maxSize = lastVisibleItemPositions[i] + } + } + return maxSize + } + + override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) { + if (firstAttach) { + firstAttach = false + return + } + + if (layoutManager == null) init(view) + + val layoutManager = layoutManager ?: return + val totalItemCount = layoutManager.itemCount + var lastVisibleItemPosition = 0 + + when (layoutManager) { + is StaggeredGridLayoutManager -> { + val lastVisibleItemPositions = layoutManager.findLastVisibleItemPositions(null) + lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions) + } + is GridLayoutManager -> lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition() + is LinearLayoutManager -> lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition() + } + + if (totalItemCount < previousTotalItemCount) { + this.previousTotalItemCount = totalItemCount + if (totalItemCount == 0) { + this.loading = true + } + } + + if (loading && totalItemCount > previousTotalItemCount) { + loading = false + previousTotalItemCount = totalItemCount + } + + if (!loading && lastVisibleItemPosition + visibleThreshold > totalItemCount) { + onLoadMore.invoke(totalItemCount) + loading = true + } + } + + fun resetState() { + this.previousTotalItemCount = 0 + this.loading = true + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/RecyclerViewFastScroller.kt b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/RecyclerViewFastScroller.kt new file mode 100644 index 000000000..cf165dfd2 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/RecyclerViewFastScroller.kt @@ -0,0 +1,206 @@ +package com.fastaccess.github.ui.widget.recyclerview + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.MotionEvent +import android.view.View +import android.view.ViewTreeObserver +import android.widget.FrameLayout +import android.widget.ImageView +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.StaggeredGridLayoutManager +import com.fastaccess.github.R +import com.google.android.material.appbar.AppBarLayout + +open class RecyclerViewFastScroller : FrameLayout { + + private lateinit var scrollerView: ImageView + private var scrollerHeight: Int = 0 + private var recyclerView: RecyclerView? = null + private var layoutManager: RecyclerView.LayoutManager? = null + private var appBarLayout: AppBarLayout? = null + private var toggled: Boolean = false + + private val onScrollListener = object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + if (scrollerView.isSelected) return + val verticalScrollOffset = recyclerView.computeVerticalScrollOffset() + val verticalScrollRange = recyclerView.computeVerticalScrollRange() + val proportion = verticalScrollOffset.toFloat() / (verticalScrollRange.toFloat() - scrollerHeight) + setScrollerHeight(scrollerHeight * proportion) + } + } + + private val observer = object : RecyclerView.AdapterDataObserver() { + override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { + super.onItemRangeInserted(positionStart, itemCount) + hideShow() + } + + override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { + super.onItemRangeRemoved(positionStart, itemCount) + hideShow() + } + + override fun onChanged() { + super.onChanged() + hideShow() + + } + } + + constructor(context: Context) : super(context) { + init() + } + + @JvmOverloads constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int = 0) : super(context, attrs, defStyleAttr) { + init() + } + + override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { + super.onSizeChanged(w, h, oldw, oldh) + scrollerHeight = h + } + + @SuppressLint("ClickableViewAccessibility") override fun onTouchEvent(event: MotionEvent): Boolean { + val action = event.action + when (action) { + MotionEvent.ACTION_DOWN -> { + if (event.x < scrollerView.x - scrollerView.paddingStart) return false + scrollerView.isSelected = true + hideAppbar() + val y = event.y + setScrollerHeight(y) + setRecyclerViewPosition(y) + return true + } + MotionEvent.ACTION_MOVE -> { + val y = event.y + setScrollerHeight(y) + setRecyclerViewPosition(y) + return true + } + MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { + scrollerView.isSelected = false + showAppbar() + return true + } + } + return super.onTouchEvent(event) + } + + override fun onDetachedFromWindow() { + recyclerView?.removeOnScrollListener(onScrollListener) + safelyUnregisterObserver() + appBarLayout = null + super.onDetachedFromWindow() + } + + private fun safelyUnregisterObserver() { + kotlin.runCatching { + recyclerView?.adapter?.unregisterAdapterDataObserver(observer) + } + } + + private fun init() { + visibility = View.GONE + clipChildren = false + val inflater = LayoutInflater.from(context) + inflater.inflate(R.layout.fastscroller_layout, this) + scrollerView = findViewById(R.id.fast_scroller_handle) + visibility = View.VISIBLE + } + + private fun hideAppbar() { + if (!toggled) { + appBarLayout?.setExpanded(false, true) + toggled = true + } + } + + private fun showAppbar() { + if (toggled) { + if (scrollerView.y == 0f) { + appBarLayout?.setExpanded(true, true) + toggled = false + } + } + } + + fun attachRecyclerView(recyclerView: RecyclerView, appBarLayout: AppBarLayout? = null) { + this.appBarLayout = appBarLayout + if (this.recyclerView == null) { + this.recyclerView = recyclerView + this.layoutManager = recyclerView.layoutManager + this.recyclerView?.addOnScrollListener(onScrollListener) + if (recyclerView.adapter != null) { + runCatching { recyclerView.adapter?.registerAdapterDataObserver(observer) } + } + hideShow() + initScrollHeight() + } + } + + private fun initScrollHeight() { + if (recyclerView?.computeVerticalScrollOffset() == 0) { + this.recyclerView?.viewTreeObserver?.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { + override fun onPreDraw(): Boolean { + this@RecyclerViewFastScroller.recyclerView?.viewTreeObserver?.removeOnPreDrawListener(this) + iniHeight() + return true + } + }) + } else { + iniHeight() + } + } + + protected fun iniHeight() { + if (scrollerView.isSelected) return + val verticalScrollOffset = this@RecyclerViewFastScroller.recyclerView?.computeVerticalScrollOffset() ?: 0 + val verticalScrollRange = this@RecyclerViewFastScroller.computeVerticalScrollRange() + val proportion = verticalScrollOffset.toFloat() / (verticalScrollRange.toFloat() - scrollerHeight) + setScrollerHeight(scrollerHeight * proportion) + } + + private fun setRecyclerViewPosition(y: Float) { + if (recyclerView != null) { + val itemCount = recyclerView?.adapter?.itemCount ?: 0 + val proportion: Float = when { + scrollerView.y == 0f -> 0f + scrollerView.y + scrollerView.height >= scrollerHeight - TRACK_SNAP_RANGE -> 1f + else -> y / scrollerHeight.toFloat() + } + val targetPos = getValueInRange(itemCount - 1, (proportion * itemCount).toInt()) + when (layoutManager) { + is StaggeredGridLayoutManager -> (layoutManager as StaggeredGridLayoutManager).scrollToPositionWithOffset(targetPos, 0) + is GridLayoutManager -> (layoutManager as GridLayoutManager).scrollToPositionWithOffset(targetPos, 0) + else -> (layoutManager as LinearLayoutManager).scrollToPositionWithOffset(targetPos, 0) + } + } + } + + private fun setScrollerHeight(y: Float) { + val handleHeight = scrollerView.height + scrollerView.y = getValueInRange(scrollerHeight - handleHeight, (y - handleHeight / 2).toInt()).toFloat() + } + + protected fun hideShow() { + visibility = if (recyclerView != null && recyclerView?.adapter != null) { + if (recyclerView?.adapter?.itemCount ?: 0 > 10) View.VISIBLE else View.GONE + } else { + View.GONE + } + } + + companion object { + private const val TRACK_SNAP_RANGE = 5 + private fun getValueInRange(max: Int, value: Int): Int { + return Math.min(Math.max(0, value), max) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/SwipeToDeleteCallback.kt b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/SwipeToDeleteCallback.kt new file mode 100644 index 000000000..7d802a377 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/SwipeToDeleteCallback.kt @@ -0,0 +1,107 @@ +package com.fastaccess.github.ui.widget.recyclerview + +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.PorterDuff +import android.graphics.PorterDuffXfermode +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.RecyclerView +import timber.log.Timber + +class SwipeToDeleteCallback( + private val callback: (viewHolder: RecyclerView.ViewHolder, direction: Int) -> Unit +) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) { + + private val background = ColorDrawable() + private val clearPaint = Paint().apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) } + + + override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int { + if (viewHolder !is AllowSwipeToDeleteDelegate) return 0 // if the viewholder doesn't impl AllowSwipeToDeleteDelegate then lets stop. + val delegate = viewHolder as AllowSwipeToDeleteDelegate + when { + delegate.drawableEnd == null && delegate.drawableStart == null -> return 0 + delegate.drawableEnd != null && delegate.drawableStart != null -> { + setDefaultSwipeDirs(ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) + } + delegate.drawableStart != null -> setDefaultSwipeDirs(ItemTouchHelper.RIGHT) + delegate.drawableEnd != null -> setDefaultSwipeDirs(ItemTouchHelper.LEFT) + } + return super.getMovementFlags(recyclerView, viewHolder) + } + + override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean { + return false + } + + override fun onChildDraw(canvas: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, + dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) { + + val delegate = viewHolder as? AllowSwipeToDeleteDelegate + ?: return super.onChildDraw(canvas, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) + + Timber.e("$dX") + val itemView = viewHolder.itemView + val itemHeight = itemView.bottom - itemView.top + val isCanceled = dX == 0f && !isCurrentlyActive + + if (isCanceled) { + clearCanvas(canvas, itemView.right + dX, itemView.top.toFloat(), itemView.right.toFloat(), itemView.bottom.toFloat()) + super.onChildDraw(canvas, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) + return + } + + if (dX > 0f) { // swipe right + delegate.drawableStart?.let { + background.color = delegate.drawableStartBackground + background.setBounds(itemView.left, itemView.top, dX.toInt(), itemView.bottom) + background.draw(canvas) + + val iconTop = itemView.top + (itemHeight - it.intrinsicHeight) / 2 + val iconMargin = (itemHeight - it.intrinsicHeight) / 2 + val iconLeft = itemView.left + iconMargin + val iconRight = iconLeft + it.intrinsicWidth + val iconBottom = iconTop + it.intrinsicHeight + + it.setBounds(iconLeft, iconTop, iconRight, iconBottom) + it.draw(canvas) + + } + } else { // swipe left + delegate.drawableEnd?.let { firstAction -> + background.color = delegate.drawableEndBackground + background.setBounds(itemView.right + dX.toInt(), itemView.top, itemView.right, itemView.bottom) + background.draw(canvas) + + val firstIconTop = itemView.top + (itemHeight - firstAction.intrinsicHeight) / 2 + val firstIconMargin = (itemHeight - firstAction.intrinsicHeight) / 2 + val firstIconLeft = itemView.right - firstIconMargin - firstAction.intrinsicWidth + val firstIconRight = itemView.right - firstIconMargin + val firstIconBottom = firstIconTop + firstAction.intrinsicHeight + firstAction.setBounds(firstIconLeft, firstIconTop, firstIconRight, firstIconBottom) + firstAction.draw(canvas) + } + } + + super.onChildDraw(canvas, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) + } + + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { + callback.invoke(viewHolder, direction) + } + + private fun clearCanvas(c: Canvas?, left: Float, top: Float, right: Float, bottom: Float) { + c?.drawRect(left, top, right, bottom, clearPaint) + } + + + interface AllowSwipeToDeleteDelegate { + val drawableStart: Drawable? + val drawableStartBackground: Int + val drawableEnd: Drawable? + val drawableEndBackground: Int + } +} + diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/decoration/InsetDividerDecoration.kt b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/decoration/InsetDividerDecoration.kt new file mode 100644 index 000000000..e3dbd77fe --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/decoration/InsetDividerDecoration.kt @@ -0,0 +1,59 @@ +package com.fastaccess.github.ui.widget.recyclerview.decoration + +import android.graphics.Canvas +import android.graphics.Paint +import androidx.recyclerview.widget.RecyclerView + +/** + * A decoration which draws a horizontal divider between [RecyclerView.ViewHolder]s of a given + * type; with a left inset. + * this class adopted from Plaid + */ +class InsetDividerDecoration constructor( + private val height: Int, + private val inset: Int, + dividerColor: Int +) : RecyclerView.ItemDecoration() { + + private val paint = Paint() + + init { + this.paint.color = dividerColor + this.paint.style = Paint.Style.STROKE + this.paint.strokeWidth = height.toFloat() + } + + override fun onDrawOver(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) { + val childCount = parent.childCount + if (childCount < 2) return + val lm = parent.layoutManager ?: return + val lines = FloatArray(childCount * 4) + var hasDividers = false + for (i in 0 until childCount) { + val child = parent.getChildAt(i) + val viewHolder = parent.getChildViewHolder(child) + val canDivide = viewHolder is HasDivider && viewHolder.canDivide() + if (canDivide) { + val position = parent.getChildAdapterPosition(child) + if (child.isActivated || i + 1 < childCount && parent.getChildAt(i + 1).isActivated) { + continue + } + if (position != state.itemCount - 1) { + lines[i * 4] = (if (inset == 0) inset else inset + lm.getDecoratedLeft(child)).toFloat() + lines[i * 4 + 2] = lm.getDecoratedRight(child).toFloat() + val y = lm.getDecoratedBottom(child) + child.translationY.toInt() - height + lines[i * 4 + 1] = y.toFloat() + lines[i * 4 + 3] = y.toFloat() + hasDividers = true + } + } + } + if (hasDividers) { + canvas.drawLines(lines, paint) + } + } + + interface HasDivider { + fun canDivide(): Boolean + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeGridLayoutManager.kt b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeGridLayoutManager.kt new file mode 100644 index 000000000..9211a3101 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeGridLayoutManager.kt @@ -0,0 +1,52 @@ +package com.fastaccess.github.ui.widget.recyclerview.lm + +import android.content.Context +import android.util.AttributeSet +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView + +/** + * Created by Kosh on 31.10.18. + */ +class SafeGridLayoutManager : GridLayoutManager { + + private var iconSize: Int = 0 + + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) + constructor(context: Context?, spanCount: Int) : super(context, spanCount) + constructor(context: Context?, spanCount: Int, orientation: Int, reverseLayout: Boolean) : super(context, spanCount, orientation, reverseLayout) + + override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State) { + try { + super.onLayoutChildren(recycler, state) + updateCount() + } catch (ignored: Exception) { + } + } + + override fun onMeasure(recycler: RecyclerView.Recycler, state: RecyclerView.State, widthSpec: Int, heightSpec: Int) { + try { + super.onMeasure(recycler, state, widthSpec, heightSpec) + } catch (ignored: Exception) { + } + } + + private fun updateCount() { + if (iconSize > 1) { + var spanCount = Math.max(1, width / iconSize) + if (spanCount < 1) { + spanCount = 1 + } + this.spanCount = spanCount + } + } + + fun getIconSize(): Int { + return iconSize + } + + fun setIconSize(iconSize: Int) { + this.iconSize = iconSize + updateCount() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeLinearLayoutManager.kt b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeLinearLayoutManager.kt new file mode 100644 index 000000000..80acac230 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeLinearLayoutManager.kt @@ -0,0 +1,31 @@ +package com.fastaccess.github.ui.widget.recyclerview.lm + +import android.content.Context +import android.util.AttributeSet +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView + +/** + * Created by Kosh on 31.10.18. + */ +class SafeLinearLayoutManager : LinearLayoutManager { + constructor(context: Context?) : super(context) + constructor(context: Context?, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout) + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) + + override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State) { + try { + super.onLayoutChildren(recycler, state) + } catch (ignored: Exception) { + ignored.printStackTrace() + } + } + + override fun onMeasure(recycler: RecyclerView.Recycler, state: RecyclerView.State, widthSpec: Int, heightSpec: Int) { + try { + super.onMeasure(recycler, state, widthSpec, heightSpec) + } catch (ignored: Exception) { + ignored.printStackTrace() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeStaggeredLayoutManager.kt b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeStaggeredLayoutManager.kt new file mode 100644 index 000000000..5d0107887 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/ui/widget/recyclerview/lm/SafeStaggeredLayoutManager.kt @@ -0,0 +1,28 @@ +package com.fastaccess.github.ui.widget.recyclerview.lm + +import android.content.Context +import android.util.AttributeSet +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.StaggeredGridLayoutManager + +/** + * Created by Kosh on 31.10.18. + */ +class SafeStaggeredLayoutManager : StaggeredGridLayoutManager { + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) + constructor(spanCount: Int, orientation: Int) : super(spanCount, orientation) + + override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State) { + try { + super.onLayoutChildren(recycler, state) + } catch (ignored: Exception) { + } + } + + override fun onMeasure(recycler: RecyclerView.Recycler, state: RecyclerView.State, widthSpec: Int, heightSpec: Int) { + try { + super.onMeasure(recycler, state, widthSpec, heightSpec) + } catch (ignored: Exception) { + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/auth/GetAccessTokenUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/auth/GetAccessTokenUseCase.kt new file mode 100644 index 000000000..9ea6ca466 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/auth/GetAccessTokenUseCase.kt @@ -0,0 +1,24 @@ +package com.fastaccess.github.usecase.auth + +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.domain.response.AccessTokenResponse +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import com.fastaccess.github.BuildConfig +import com.fastaccess.github.utils.REDIRECT_URL +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 12.05.18. + */ +class GetAccessTokenUseCase @Inject constructor(private val loginRemoteRepository: LoginRepositoryProvider) : + BaseObservableUseCase() { + + var code: String? = null + + override fun buildObservable(): Observable = code?.let { + loginRemoteRepository.getAccessToken(it, BuildConfig.GITHUB_CLIENT_ID, BuildConfig.GITHUB_SECRET, + BuildConfig.APPLICATION_ID, REDIRECT_URL) + } ?: Observable.empty() + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/auth/LoginUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/auth/LoginUseCase.kt new file mode 100644 index 000000000..70ed872b1 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/auth/LoginUseCase.kt @@ -0,0 +1,33 @@ +package com.fastaccess.github.usecase.auth + +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.domain.response.AccessTokenResponse +import com.fastaccess.domain.response.AuthBodyModel +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import com.fastaccess.github.BuildConfig +import com.fastaccess.github.utils.REDIRECT_URL +import com.fastaccess.github.utils.SCOPE_LIST +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 12.05.18. + */ +class LoginUseCase @Inject constructor(private val loginRemoteRepository: LoginRepositoryProvider) : BaseObservableUseCase() { + private var authBodyModel: AuthBodyModel? = null + + override fun buildObservable(): Observable = authBodyModel?.let { loginRemoteRepository.login(it) } ?: Observable.empty() + + fun setAuthBody(twoFactorCode: String? = null) { + this.authBodyModel = AuthBodyModel().apply { + clientId = BuildConfig.GITHUB_CLIENT_ID + clientSecret = BuildConfig.GITHUB_SECRET + redirectUri = REDIRECT_URL + scopes = SCOPE_LIST.split(",") + state = BuildConfig.APPLICATION_ID + note = BuildConfig.APPLICATION_ID + noteUrl = "fasthub://login" + otpCode = twoFactorCode + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/auth/LoginWithAccessTokenUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/auth/LoginWithAccessTokenUseCase.kt new file mode 100644 index 000000000..80656fbbc --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/auth/LoginWithAccessTokenUseCase.kt @@ -0,0 +1,28 @@ +package com.fastaccess.github.usecase.auth + +import com.fastaccess.data.persistence.models.LoginModel +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import com.google.gson.Gson +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 12.05.18. + */ +class LoginWithAccessTokenUseCase @Inject constructor(private val loginRemoteRepository: LoginRepositoryProvider, + private val gson: Gson) : BaseObservableUseCase() { + override fun buildObservable(): Observable = loginRemoteRepository.loginAccessToken() + .map { gson.fromJson(gson.toJson(it), LoginModel::class.java) } + + fun insertUser(loginModel: LoginModel): Observable = Observable.fromCallable { + loginRemoteRepository.logoutAll() + loginRemoteRepository.insert(loginModel) + val login = loginRemoteRepository.getLoginBlocking() + return@fromCallable if (login?.id == loginModel.id) { + login + } else { + null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/feed/FeedsUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/feed/FeedsUseCase.kt new file mode 100644 index 000000000..74c7c93ff --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/feed/FeedsUseCase.kt @@ -0,0 +1,16 @@ +package com.fastaccess.github.usecase.feed + +import com.fastaccess.data.repository.FeedsRepositoryProvider +import com.fastaccess.domain.response.FeedResponse +import com.fastaccess.domain.response.PageableResponse +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 26.06.18. + */ +class FeedsUseCase @Inject constructor(private val feedsRepositoryProvider: FeedsRepositoryProvider) : BaseObservableUseCase() { + var page: Int = 0 + override fun buildObservable(): Observable> = feedsRepositoryProvider.getReceivedEvents(page) +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/AddAssigneesUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/AddAssigneesUseCase.kt new file mode 100644 index 000000000..3598d2adc --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/AddAssigneesUseCase.kt @@ -0,0 +1,28 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.fastaccess.domain.repository.services.RepoService +import com.fastaccess.domain.response.body.AssigneesBodyModel +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 16.02.19. + */ +class AddAssigneesUseCase @Inject constructor( + private val repoService: RepoService +) : BaseObservableUseCase() { + + var repo: String = "" + var login: String = "" + var number: Int = 0 + var assignees: List? = null + var toRemove: List? = null + + override fun buildObservable(): Observable = when (toRemove.isNullOrEmpty()) { + true -> repoService.addAssignees(login, repo, number, AssigneesBodyModel(assignees)).map { true } + else -> repoService.removeAssignees(login, repo, number, AssigneesBodyModel(toRemove)) + .flatMap { repoService.addAssignees(login, repo, number, AssigneesBodyModel(assignees)) } + .map { true } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/CloseOpenIssuePrUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/CloseOpenIssuePrUseCase.kt new file mode 100644 index 000000000..b340df12f --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/CloseOpenIssuePrUseCase.kt @@ -0,0 +1,40 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.fastaccess.data.model.CloseOpenEventModel +import com.fastaccess.data.model.TimelineModel +import com.fastaccess.data.persistence.models.MyIssuesPullsModel +import com.fastaccess.data.repository.IssueRepositoryProvider +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.domain.repository.services.IssuePrService +import com.fastaccess.domain.response.IssueRequestModel +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import com.fastaccess.extension.me +import io.reactivex.Observable +import java.util.* +import javax.inject.Inject + +/** + * Created by Kosh on 16.02.19. + */ +class CloseOpenIssuePrUseCase @Inject constructor( + private val issueRepositoryProvider: IssueRepositoryProvider, + private val issuePrService: IssuePrService, + private val loginRepositoryProvider: LoginRepositoryProvider +) : BaseObservableUseCase() { + + var repo: String = "" + var login: String = "" + var number: Int = -1 + + override fun buildObservable(): Observable = issueRepositoryProvider.getIssueByNumberMaybe("$login/$repo", number) + .flatMapObservable { issue -> + issuePrService.editIssue(login, repo, number, IssueRequestModel(state = if ("closed".equals(issue.state, true)) "open" else "closed")) + .map { + issue.state = it.issueState + issueRepositoryProvider.upsert(issue) + val me = loginRepositoryProvider.getLoginBlocking()?.me() + return@map TimelineModel(closeOpenEventModel = CloseOpenEventModel(Date(), me, null, + MyIssuesPullsModel(issue.id, issue.databaseId, issue.number, issue.title, issue.repo?.nameWithOwner, 0, it.issueState, issue.url))) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/CreateLabelUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/CreateLabelUseCase.kt new file mode 100644 index 000000000..d01b63fec --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/CreateLabelUseCase.kt @@ -0,0 +1,26 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.fastaccess.data.model.parcelable.LabelModel +import com.fastaccess.domain.repository.services.RepoService +import com.fastaccess.domain.response.LabelResponse +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 16.02.19. + */ +class CreateLabelUseCase @Inject constructor( + private val repoService: RepoService +) : BaseObservableUseCase() { + + var repo: String = "" + var login: String = "" + var name: String = "" + var color: String = "" + + override fun buildObservable(): Observable = repoService.addLabel(login, repo, LabelResponse(color = color, name = name)) + .map { + LabelModel(it.name, it.color, it.url) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/CreateMilestoneUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/CreateMilestoneUseCase.kt new file mode 100644 index 000000000..0b8a56f96 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/CreateMilestoneUseCase.kt @@ -0,0 +1,24 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.fastaccess.domain.repository.services.RepoService +import com.fastaccess.domain.response.body.MilestoneBodyModel +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 16.02.19. + */ +class CreateMilestoneUseCase @Inject constructor( + private val repoService: RepoService +) : BaseObservableUseCase() { + + var repo: String = "" + var login: String = "" + var title: String = "" + var description: String? = null + var dueOn: String = "" + + override fun buildObservable(): Observable = repoService.createMilestone(login, repo, MilestoneBodyModel(title, description, dueOn)) + .map { true } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/FilterIssuesUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/FilterIssuesUseCase.kt new file mode 100644 index 000000000..59cdf57c4 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/FilterIssuesUseCase.kt @@ -0,0 +1,119 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.api.Input +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.parcelable.FilterIssuesPrsModel +import com.fastaccess.data.persistence.models.MyIssuesPullsModel +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import github.SearchIssuesQuery +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 20.01.19. + */ +class FilterIssuesUseCase @Inject constructor( + private val loginRepository: LoginRepositoryProvider, + private val apolloClient: ApolloClient +) : BaseObservableUseCase() { + + var cursor: Input = Input.absent() + var filterModel = FilterIssuesPrsModel() + var keyword: String? = null + + override fun buildObservable(): Observable>> { + val query = keyword + return if (query.isNullOrEmpty()) { + loginRepository.getLogin() + .flatMapObservable { user -> + return@flatMapObservable user.login?.let { login -> + searchObservable(login = login) + } ?: Observable.empty() + } + } else { + searchObservable(query = query) + } + } + + private fun searchObservable( + login: String? = null, + query: String? = null + ): Observable>> { + return Rx2Apollo.from(apolloClient.query(SearchIssuesQuery(constructQuery(filterModel, login, query), cursor))) + .map { it.data()?.search } + .map { search -> + val list = search.nodes?.asSequence()?.mapNotNull { it.fragments.shortIssueRowItem } + ?.map { + MyIssuesPullsModel( + it.id, it.databaseId, it.number, it.title, + it.repository.nameWithOwner, it.comments.totalCount, it.issueState.rawValue(), it.url.toString() + ) + } + ?.toList() ?: arrayListOf() + val pageInfo = PageInfoModel( + search.pageInfo.startCursor, search.pageInfo.endCursor, + search.pageInfo.isHasNextPage, search.pageInfo.isHasPreviousPage + ) + return@map Pair(pageInfo, list) + } + } + + + /** + * Example: is:open is:issue author:k0shk0sh archived:false sort:created-desc + */ + private fun constructQuery( + model: FilterIssuesPrsModel, + login: String? = null, + query: String? = null + ): String { + return StringBuilder() + .append(if (query.isNullOrEmpty()) "" else "$query ") + .append( + "is:${when (model.searchType) { + FilterIssuesPrsModel.SearchType.OPEN -> "open" + FilterIssuesPrsModel.SearchType.CLOSED -> "closed" + }}" + ) + .append(" ") + .append("is:issue") + .append(" ") + .append("archived:false") + .append(" ") + .append( + "sort:${when (model.searchSortBy) { + FilterIssuesPrsModel.SearchSortBy.NEWEST -> "created-desc" + FilterIssuesPrsModel.SearchSortBy.OLDEST -> "created-asc" + FilterIssuesPrsModel.SearchSortBy.MOST_COMMENTED -> "comments-desc" + FilterIssuesPrsModel.SearchSortBy.LEAST_COMMENTED -> "comments-asc" + FilterIssuesPrsModel.SearchSortBy.RECENTLY_UPDATED -> "updated-desc" + FilterIssuesPrsModel.SearchSortBy.LEAST_RECENTLY_UPDATED -> "updated-asc" + }}" + ) + .append(" ") + .apply { + if (!login.isNullOrEmpty()) { + append( + "${when (model.searchBy) { + FilterIssuesPrsModel.SearchBy.ASSIGNED -> "assignee" + FilterIssuesPrsModel.SearchBy.MENTIONED -> "mentions" + else -> "author" + }}:$login" + ).append(" ") + } + if (model.searchVisibility != FilterIssuesPrsModel.SearchVisibility.BOTH) { + append( + "is:${when (model.searchVisibility) { + FilterIssuesPrsModel.SearchVisibility.PUBLIC -> "public" + FilterIssuesPrsModel.SearchVisibility.PRIVATE -> "private" + else -> "" + }}" + ) + } + } + .toString() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/FilterPullRequestsUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/FilterPullRequestsUseCase.kt new file mode 100644 index 000000000..15b1d5f57 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/FilterPullRequestsUseCase.kt @@ -0,0 +1,100 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.api.Input +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.parcelable.FilterIssuesPrsModel +import com.fastaccess.data.persistence.models.MyIssuesPullsModel +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import github.SearchPullRequestsQuery +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 20.01.19. + */ +class FilterPullRequestsUseCase @Inject constructor( + private val loginRepository: LoginRepositoryProvider, + private val apolloClient: ApolloClient +) : BaseObservableUseCase() { + + var cursor: Input = Input.absent() + var filterModel = FilterIssuesPrsModel() + var keyword: String? = null + + override fun buildObservable(): Observable>> { + val query = keyword + return if (query.isNullOrEmpty()) { + loginRepository.getLogin() + .flatMapObservable { user -> + return@flatMapObservable user.login?.let { login -> + searchObservable(login = login) + } ?: Observable.empty() + } + } else { + searchObservable(query = query) + } + } + + private fun searchObservable(login: String? = null, query: String? = null): Observable>> { + return Rx2Apollo.from(apolloClient.query(SearchPullRequestsQuery(constructQuery(filterModel, login, query), cursor))) + .map { it.data()?.search } + .map { search -> + val list = search.nodes?.asSequence()?.mapNotNull { it.fragments.shortPullRequestRowItem } + ?.map { + MyIssuesPullsModel(it.id, it.databaseId, it.number, it.title, + it.repository.nameWithOwner, it.comments.totalCount, it.state.name, it.url.toString(), true) + } + ?.toList() ?: arrayListOf() + val pageInfo = PageInfoModel(search.pageInfo.startCursor, search.pageInfo.endCursor, + search.pageInfo.isHasNextPage, search.pageInfo.isHasPreviousPage) + return@map Pair(pageInfo, list) + } + } + + /** + * Example: is:open is:pr author:k0shk0sh archived:false sort:created-desc + */ + private fun constructQuery(model: FilterIssuesPrsModel, login: String? = null, query: String? = null): String { + return StringBuilder() + .append(if (query.isNullOrEmpty()) "" else "$query ") + .append("is:${when (model.searchType) { + FilterIssuesPrsModel.SearchType.OPEN -> "open" + FilterIssuesPrsModel.SearchType.CLOSED -> "closed" + }}") + .append(" ") + .append("is:pr") + .append(" ") + .append("archived:false") + .append(" ") + .append("sort:${when (model.searchSortBy) { + FilterIssuesPrsModel.SearchSortBy.NEWEST -> "created-desc" + FilterIssuesPrsModel.SearchSortBy.OLDEST -> "created-asc" + FilterIssuesPrsModel.SearchSortBy.MOST_COMMENTED -> "comments-desc" + FilterIssuesPrsModel.SearchSortBy.LEAST_COMMENTED -> "comments-asc" + FilterIssuesPrsModel.SearchSortBy.RECENTLY_UPDATED -> "updated-desc" + FilterIssuesPrsModel.SearchSortBy.LEAST_RECENTLY_UPDATED -> "updated-asc" + }}") + .append(" ") + .apply { + if (!login.isNullOrEmpty()) { + append("${when (model.searchBy) { + FilterIssuesPrsModel.SearchBy.ASSIGNED -> "assignee" + FilterIssuesPrsModel.SearchBy.MENTIONED -> "mentions" + FilterIssuesPrsModel.SearchBy.REVIEW_REQUESTS -> "review-requested" + else -> "author" + }}:$login").append(" ") + } + if (model.searchVisibility != FilterIssuesPrsModel.SearchVisibility.BOTH) { + append("is:${when (model.searchVisibility) { + FilterIssuesPrsModel.SearchVisibility.PUBLIC -> "public" + FilterIssuesPrsModel.SearchVisibility.PRIVATE -> "private" + else -> "" + }}") + } + } + .toString() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetAssigneesUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetAssigneesUseCase.kt new file mode 100644 index 000000000..ea24dd5e1 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetAssigneesUseCase.kt @@ -0,0 +1,40 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.api.Input +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.ShortUserModel +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import com.fastaccess.extension.toUser +import github.GetAssigneesQuery +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 27.01.19. + */ +class GetAssigneesUseCase @Inject constructor( + private val apolloClient: ApolloClient +) : BaseObservableUseCase() { + + var login: String? = null + var repo: String? = null + var page: Input = Input.absent() + + override fun buildObservable(): Observable>> { + val login = login + val repo = repo + + if (login.isNullOrEmpty() || repo.isNullOrEmpty()) { + return Observable.error(Throwable("this should never happen ;)")) + } + return Rx2Apollo.from(apolloClient.query(GetAssigneesQuery(login, repo, page))) + .map { it.data()?.repositoryOwner?.repository?.assignableUsers } + .map { data -> + val pageInfo = PageInfoModel(data.pageInfo.startCursor, data.pageInfo.endCursor, + data.pageInfo.isHasNextPage, data.pageInfo.isHasPreviousPage) + return@map Pair(pageInfo, data.nodes?.map { it.fragments.shortUserRowItem.toUser() } ?: listOf()) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetIssueTimelineUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetIssueTimelineUseCase.kt new file mode 100644 index 000000000..f5cba6ec5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetIssueTimelineUseCase.kt @@ -0,0 +1,234 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.api.Input +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.model.* +import com.fastaccess.data.model.parcelable.LabelModel +import com.fastaccess.data.repository.IssueRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import com.fastaccess.extension.* +import com.fastaccess.github.extensions.addIfNotNull +import github.GetIssueTimelineQuery +import github.GetIssueTimelineQuery.* +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 27.01.19. + */ +class GetIssueTimelineUseCase @Inject constructor( + private val issueRepositoryProvider: IssueRepositoryProvider, + private val apolloClient: ApolloClient +) : BaseObservableUseCase() { + + var login: String? = null + var repo: String? = null + var number: Int? = null + var page: Input = Input.absent() + + override fun buildObservable(): Observable>> { + val login = login + val repo = repo + val number = number + + if (login.isNullOrEmpty() || repo.isNullOrEmpty() || number == null) { + return Observable.error(Throwable("this should never happen ;)")) + } + + return Rx2Apollo.from(apolloClient.query(GetIssueTimelineQuery(login, repo, number, page))) + .map { it.data()?.repositoryOwner?.repository?.issue } + .map { + val list = arrayListOf() + val timeline = it.timeline + val pageInfo = PageInfoModel(timeline.pageInfo.startCursor, timeline.pageInfo.endCursor, + timeline.pageInfo.isHasNextPage, timeline.pageInfo.isHasPreviousPage) + timeline.nodes?.forEach { node -> + when (node) { + is AsCommit -> list.add(getCommit(node)) + is AsIssueComment -> list.add(getComment(node)) + is AsCrossReferencedEvent -> list.add(getCrossReference(node)) + is AsClosedEvent -> list.add(getClosed(node)) + is AsReopenedEvent -> list.add(getReopened(node)) + is AsSubscribedEvent -> list.add(getSubscribed(node)) + is AsUnsubscribedEvent -> list.add(getUnsubscribed(node)) + is AsReferencedEvent -> list.add(getReference(node)) + is AsAssignedEvent -> list.addIfNotNull(getAssigned(node, list)) + is AsUnassignedEvent -> list.addIfNotNull(getUnassigned(node, list)) + is AsLabeledEvent -> list.addIfNotNull(getLabel(node, list)) + is AsUnlabeledEvent -> list.addIfNotNull(getUnlabeled(node, list)) + is AsMilestonedEvent -> list.add(getMilestone(node)) + is AsDemilestonedEvent -> list.add(getDemilestoned(node)) + is AsRenamedTitleEvent -> list.add(getRenamed(node)) + is AsLockedEvent -> list.add(getLock(node)) + is AsUnlockedEvent -> list.add(getUnlocked(node)) + is AsTransferredEvent -> list.add(getTransferred(node)) + } + } + return@map Pair(pageInfo, list) + } + } + + private fun getTransferred(node: AsTransferredEvent): TimelineModel = TimelineModel(transferredEventModel = TransferredEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), node.fromRepository?.nameWithOwner + )) + + private fun getRenamed(node: AsRenamedTitleEvent): TimelineModel = TimelineModel(renamedEventModel = RenamedEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), node.currentTitle, node.previousTitle + )) + + private fun getDemilestoned(node: AsDemilestonedEvent): TimelineModel = TimelineModel(milestoneEventModel = MilestoneDemilestonedEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), node.milestoneTitle, false + )) + + private fun getMilestone(node: AsMilestonedEvent): TimelineModel = TimelineModel(milestoneEventModel = MilestoneDemilestonedEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), node.milestoneTitle, true + )) + + private fun getUnassigned( + node: AsUnassignedEvent, + list: ArrayList + ): TimelineModel? { + var shouldAdd = true + list.filter { it.assignedEventModel != null }.map { + if (it.assignedEventModel?.createdAt?.time == node.createdAt.time) { + it.assignedEventModel?.users?.add(ShortUserModel(node.user?.login, node.user?.login, avatarUrl = node.user?.avatarUrl?.toString())) + shouldAdd = false + } + } + if (shouldAdd) { + return TimelineModel(assignedEventModel = AssignedUnAssignedEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), false, + arrayListOf(ShortUserModel(node.user?.login, node.user?.login, avatarUrl = node.user?.avatarUrl?.toString())) + )) + } + return null + } + + private fun getAssigned( + node: AsAssignedEvent, + list: ArrayList + ): TimelineModel? { + var shouldAdd = true + list.filter { it.assignedEventModel != null }.map { + if (it.assignedEventModel?.createdAt?.time == node.createdAt.time) { + it.assignedEventModel?.users?.add(ShortUserModel(node.user?.login, node.user?.login, avatarUrl = node.user?.avatarUrl?.toString())) + shouldAdd = false + } + } + if (shouldAdd) { + return TimelineModel(assignedEventModel = AssignedUnAssignedEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), true, + arrayListOf(ShortUserModel(node.user?.login, node.user?.login, avatarUrl = node.user?.avatarUrl?.toString())) + )) + } + return null + } + + private fun getUnsubscribed( + node: AsUnsubscribedEvent + ): TimelineModel = TimelineModel(subscribedUnsubscribedEvent = SubscribedUnsubscribedEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), false + )) + + private fun getSubscribed(node: AsSubscribedEvent): TimelineModel = TimelineModel(subscribedUnsubscribedEvent = SubscribedUnsubscribedEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), false + )) + + private fun getUnlabeled( + node: AsUnlabeledEvent, + list: ArrayList + ): TimelineModel? { + var shouldAdd = true + list.filter { it.labelUnlabeledEvent != null }.map { + if (it.labelUnlabeledEvent?.createdAt?.time == node.createdAt.time) { + it.labelUnlabeledEvent?.labels?.add(constructLabel(node.label)) + shouldAdd = false + } + } + if (shouldAdd) { + return TimelineModel(labelUnlabeledEvent = LabelUnlabeledEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), false, arrayListOf(constructLabel(node.label)) + )) + } + return null + } + + private fun getLabel( + node: AsLabeledEvent, + list: ArrayList + ): TimelineModel? { + var shouldAdd = true + list.filter { it.labelUnlabeledEvent != null }.map { + if (it.labelUnlabeledEvent?.createdAt?.time == node.createdAt.time) { + it.labelUnlabeledEvent?.labels?.add(constructLabel(node.label)) + shouldAdd = false + } + } + if (shouldAdd) { + return TimelineModel(labelUnlabeledEvent = LabelUnlabeledEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), true, arrayListOf(constructLabel(node.label)) + )) + } + return null + } + + private fun constructLabel(m: Any): LabelModel { + return when (m) { + is Label -> LabelModel(m.name, m.color) + is Label1 -> LabelModel(m.name, m.color) + else -> throw IllegalArgumentException("$m is not instance of any Label") + } + } + + + private fun getUnlocked(node: AsUnlockedEvent): TimelineModel = TimelineModel(lockUnlockEventModel = LockUnlockEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), null, node.lockable.activeLockReason?.rawValue() + )) + + private fun getLock(node: AsLockedEvent): TimelineModel = TimelineModel(lockUnlockEventModel = LockUnlockEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), node.lockReason?.rawValue(), node.lockable.activeLockReason?.rawValue(), true + )) + + private fun getReopened(node: AsReopenedEvent): TimelineModel { + return TimelineModel(closeOpenEventModel = CloseOpenEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser()) + ) + } + + private fun getClosed(node: AsClosedEvent): TimelineModel { + val commit = node.closer?.fragments?.commitFragment?.toCommit() + val pr = node.closer?.fragments?.shortPullRequestRowItem?.toPullRequest() + return TimelineModel(closeOpenEventModel = CloseOpenEventModel( + node.createdAt, node.actor?.fragments?.shortActor?.toUser(), commit, pr, true) + ) + } + + private fun getReference(node: AsReferencedEvent): TimelineModel { + val issueModel = node.subject.fragments.shortIssueRowItem?.toIssue() + val pullRequest = node.subject.fragments.shortPullRequestRowItem?.toPullRequest() + return TimelineModel(referencedEventModel = ReferencedEventModel( + node.commitRepository.nameWithOwner, node.createdAt, ShortUserModel( + node.actor?.fragments?.shortActor?.login, node.actor?.fragments?.shortActor?.login, node.actor?.fragments?.shortActor?.url?.toString(), + avatarUrl = node.actor?.fragments?.shortActor?.avatarUrl?.toString()), node.isCrossRepository, node.isDirectReference, + node.commit?.fragments?.commitFragment?.toCommit(), issueModel, pullRequest)) + } + + private fun getCrossReference(node: AsCrossReferencedEvent): TimelineModel { + val actor = node.actor?.fragments?.shortActor?.toUser() + val issueModel = node.source.fragments.shortIssueRowItem?.toIssue() + val pullRequest = node.source.fragments.shortPullRequestRowItem?.toPullRequest() + return TimelineModel(crossReferencedEventModel = CrossReferencedEventModel(node.createdAt, node.referencedAt, + node.isCrossRepository, node.isWillCloseTarget, actor, issueModel, pullRequest)) + } + + private fun getComment(node: AsIssueComment) = TimelineModel(comment = CommentModel(node.id, + ShortUserModel(node.author?.login, node.author?.login, avatarUrl = node.author?.avatarUrl.toString()), + node.bodyHTML.toString(), node.body, CommentAuthorAssociation.fromName(node.authorAssociation.rawValue()), + node.viewerCannotUpdateReasons.map { reason -> CommentCannotUpdateReason.fromName(reason.rawValue()) }.toList(), + node.reactionGroups?.map { it.fragments.reactions.toReactionGroup() }, node.createdAt, node.updatedAt, + node.isViewerCanReact, node.isViewerCanDelete, node.isViewerCanUpdate, node.isViewerDidAuthor, node.isViewerCanMinimize + )) + + private fun getCommit(node: AsCommit) = TimelineModel(commit = node.fragments.commitFragment?.toCommit()) +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetIssueUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetIssueUseCase.kt new file mode 100644 index 000000000..d9b8f4637 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetIssueUseCase.kt @@ -0,0 +1,55 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.model.CountModel +import com.fastaccess.data.model.EmbeddedRepoModel +import com.fastaccess.data.model.ShortUserModel +import com.fastaccess.data.persistence.models.IssueModel +import com.fastaccess.data.repository.IssueRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import com.fastaccess.extension.toLabels +import com.fastaccess.extension.toMilestone +import com.fastaccess.extension.toReactionGroup +import com.fastaccess.extension.toUser +import github.GetIssueQuery +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 27.01.19. + */ +class GetIssueUseCase @Inject constructor( + private val issueRepositoryProvider: IssueRepositoryProvider, + private val apolloClient: ApolloClient +) : BaseObservableUseCase() { + + var login: String? = null + var repo: String? = null + var number: Int? = null + + override fun buildObservable(): Observable<*> { + val login = login + val repo = repo + val number = number + + if (login.isNullOrEmpty() || repo.isNullOrEmpty() || number == null) { + return Observable.error(Throwable("this should never happen ;)")) + } + + return Rx2Apollo.from(apolloClient.query(GetIssueQuery(login, repo, number))) + .map { it.data()?.repositoryOwner?.repository?.issue?.fragments?.fullIssue } + .map { issue -> + issueRepositoryProvider.upsert(IssueModel(issue.id, issue.databaseId, issue.number, issue.activeLockReason?.rawValue(), + issue.body, issue.bodyHTML.toString(), issue.closedAt, issue.createdAt, issue.updatedAt, issue.state.rawValue(), + issue.title, issue.viewerSubscription?.rawValue(), ShortUserModel(issue.author?.login, issue.author?.login, + issue.author?.url?.toString(), avatarUrl = issue.author?.avatarUrl?.toString()), + EmbeddedRepoModel(issue.repository.nameWithOwner), CountModel(issue.userContentEdits?.totalCount), + issue.reactionGroups?.map { it.fragments.reactions.toReactionGroup() }, + issue.viewerCannotUpdateReasons.map { it.rawValue() }, issue.isClosed, issue.isCreatedViaEmail, issue.isLocked, + issue.isViewerCanReact, issue.isViewerCanSubscribe, issue.isViewerCanUpdate, issue.isViewerDidAuthor, + issue.authorAssociation.rawValue(), issue.url.toString(), issue.labels?.nodes?.map { it.fragments.labels.toLabels() }, + issue.milestone?.toMilestone(), issue.assignees.nodes?.map { it.fragments }?.map { it.shortUserRowItem.toUser() })) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetLabelsUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetLabelsUseCase.kt new file mode 100644 index 000000000..f1fbffae9 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetLabelsUseCase.kt @@ -0,0 +1,40 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.api.Input +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.parcelable.LabelModel +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import com.fastaccess.extension.toLabels +import github.GetLabelsQuery +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 27.01.19. + */ +class GetLabelsUseCase @Inject constructor( + private val apolloClient: ApolloClient +) : BaseObservableUseCase() { + + var login: String? = null + var repo: String? = null + var page: Input = Input.absent() + + override fun buildObservable(): Observable>> { + val login = login + val repo = repo + + if (login.isNullOrEmpty() || repo.isNullOrEmpty()) { + return Observable.error(Throwable("this should never happen ;)")) + } + return Rx2Apollo.from(apolloClient.query(GetLabelsQuery(login, repo, page))) + .map { it.data()?.repositoryOwner?.repository?.labels } + .map { data -> + val pageInfo = PageInfoModel(data.pageInfo.startCursor, data.pageInfo.endCursor, + data.pageInfo.isHasNextPage, data.pageInfo.isHasPreviousPage) + return@map Pair(pageInfo, data.nodes?.map { it.fragments.labels.toLabels() } ?: listOf()) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetMilestonesUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetMilestonesUseCase.kt new file mode 100644 index 000000000..76b24d6a9 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/GetMilestonesUseCase.kt @@ -0,0 +1,43 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.api.Input +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.parcelable.MilestoneModel +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import github.GetMilestonesQuery +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 27.01.19. + */ +class GetMilestonesUseCase @Inject constructor( + private val apolloClient: ApolloClient +) : BaseObservableUseCase() { + + var login: String? = null + var repo: String? = null + var page: Input = Input.absent() + + override fun buildObservable(): Observable>> { + val login = login + val repo = repo + + if (login.isNullOrEmpty() || repo.isNullOrEmpty()) { + return Observable.error(Throwable("this should never happen ;)")) + } + return Rx2Apollo.from(apolloClient.query(GetMilestonesQuery(login, repo, page))) + .map { it.data()?.repositoryOwner?.repository?.milestones } + .map { data -> + val pageInfo = PageInfoModel(data.pageInfo.startCursor, data.pageInfo.endCursor, + data.pageInfo.isHasNextPage, data.pageInfo.isHasPreviousPage) + return@map Pair(pageInfo, data.nodes?.map { it.fragments.milestoneFragment } + ?.map { + MilestoneModel(it.id, it.title, it.description, it.state.toString(), + it.url.toString(), it.number, it.isClosed, it.dueOn) + } ?: listOf()) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/LockUnlockIssuePrUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/LockUnlockIssuePrUseCase.kt new file mode 100644 index 000000000..29b2621ab --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/LockUnlockIssuePrUseCase.kt @@ -0,0 +1,53 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.api.Input +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.model.LockUnlockEventModel +import com.fastaccess.data.model.TimelineModel +import com.fastaccess.data.repository.IssueRepositoryProvider +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import com.fastaccess.extension.me +import github.LockMutation +import github.UnlockMutation +import github.type.LockReason +import io.reactivex.Observable +import java.util.* +import javax.inject.Inject + +/** + * Created by Kosh on 16.02.19. + */ +class LockUnlockIssuePrUseCase @Inject constructor( + private val issueRepositoryProvider: IssueRepositoryProvider, + private val apolloClient: ApolloClient, + private val loginRepositoryProvider: LoginRepositoryProvider +) : BaseObservableUseCase() { + + var repo: String = "" + var login: String = "" + var number: Int = -1 + var lockReason: LockReason? = null + var lock: Boolean = false + + override fun buildObservable(): Observable = issueRepositoryProvider.getIssueByNumberMaybe("$login/$repo", number) + .flatMapObservable { issue -> + if (lockReason == null) { + Rx2Apollo.from(apolloClient.mutate(LockMutation(issue.id, Input.optional(lockReason)))) + } else { + Rx2Apollo.from(apolloClient.mutate(UnlockMutation(issue.id))) + } + .map { + issue.locked = lock == true + issue.activeLockReason = lockReason?.rawValue() + issueRepositoryProvider.upsert(issue) + val me = loginRepositoryProvider.getLoginBlocking()?.me() + return@map if (lock) { + TimelineModel(lockUnlockEventModel = LockUnlockEventModel(Date(), me, lockReason?.rawValue(), null, true)) + } else { + TimelineModel(lockUnlockEventModel = LockUnlockEventModel(Date(), me, null, null, false)) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/MilestoneIssuePrUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/MilestoneIssuePrUseCase.kt new file mode 100644 index 000000000..66a0d1b3c --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/MilestoneIssuePrUseCase.kt @@ -0,0 +1,45 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.fastaccess.data.model.MilestoneDemilestonedEventModel +import com.fastaccess.data.model.TimelineModel +import com.fastaccess.data.model.parcelable.MilestoneModel +import com.fastaccess.data.repository.IssueRepositoryProvider +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.domain.repository.services.IssuePrService +import com.fastaccess.domain.response.IssueRequestModel +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import com.fastaccess.extension.me +import io.reactivex.Observable +import java.util.* +import javax.inject.Inject + +/** + * Created by Kosh on 16.02.19. + */ +class MilestoneIssuePrUseCase @Inject constructor( + private val issueRepositoryProvider: IssueRepositoryProvider, + private val issuePrService: IssuePrService, + private val loginRepositoryProvider: LoginRepositoryProvider +) : BaseObservableUseCase() { + + var repo: String = "" + var login: String = "" + var number: Int = -1 + var milestone: Int = -1 + + override fun buildObservable(): Observable> = + issueRepositoryProvider.getIssueByNumberMaybe("$login/$repo", number) + .flatMapObservable { issue -> + issuePrService.editIssue(login, repo, number, IssueRequestModel(milestone = milestone)) + .map { + val milestone = MilestoneModel(it.milestone?.id?.toString(), + it.milestone?.title, it.milestone?.description, + it.milestone?.state, it.milestone?.url, it.milestone?.number, it.milestone?.closedAt != null, it.milestone?.dueOn) + issue.milestone = milestone + issueRepositoryProvider.upsert(issue) + val me = loginRepositoryProvider.getLoginBlocking()?.me() + return@map Pair(TimelineModel(milestoneEventModel = MilestoneDemilestonedEventModel(Date(), me, + it.milestone?.title ?: it.milestone?.number?.toString(), true)), milestone) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/issuesprs/PutLabelsUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/PutLabelsUseCase.kt new file mode 100644 index 000000000..d14ba13bd --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/issuesprs/PutLabelsUseCase.kt @@ -0,0 +1,30 @@ +package com.fastaccess.github.usecase.issuesprs + +import com.fastaccess.domain.repository.services.RepoService +import com.fastaccess.domain.response.body.LabelsBodyModel +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 16.02.19. + */ +class PutLabelsUseCase @Inject constructor( + private val repoService: RepoService +) : BaseObservableUseCase() { + + var repo: String = "" + var login: String = "" + var number: Int = 0 + var toAdd: List? = null + var toRemove: List? = null + + override fun buildObservable(): Observable = when (toRemove.isNullOrEmpty()) { + true -> repoService.addLabelsToIssue(login, repo, number, LabelsBodyModel(toAdd)) + .map { true } + else -> repoService.addLabelsToIssue(login, repo, number, LabelsBodyModel(toAdd)) + .flatMap { Observable.fromIterable(toRemove) } + .flatMap { repoService.removeLabelsToIssue(login, repo, number, it) } + .map { true } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/main/FeedsMainScreenUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/main/FeedsMainScreenUseCase.kt new file mode 100644 index 000000000..4dd3284b5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/main/FeedsMainScreenUseCase.kt @@ -0,0 +1,13 @@ +package com.fastaccess.github.usecase.main + +import com.fastaccess.data.repository.FeedsRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 26.06.18. + */ +class FeedsMainScreenUseCase @Inject constructor(private val feedsRepositoryProvider: FeedsRepositoryProvider) : BaseObservableUseCase() { + override fun buildObservable(): Observable<*> = feedsRepositoryProvider.getMainFeeds() +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/main/IssuesMainScreenUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/main/IssuesMainScreenUseCase.kt new file mode 100644 index 000000000..7ac1c57b0 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/main/IssuesMainScreenUseCase.kt @@ -0,0 +1,48 @@ +package com.fastaccess.github.usecase.main + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.persistence.models.MyIssuesPullsModel +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.data.repository.MyIssuesPullsRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import github.GetIssuesWithoutStateQuery +import github.type.IssueState +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 16.06.18. + */ +class IssuesMainScreenUseCase @Inject constructor( + private val loginRepository: LoginRepositoryProvider, + private val myIssues: MyIssuesPullsRepositoryProvider, + private val apolloClient: ApolloClient +) : BaseObservableUseCase() { + + var state: IssueState = IssueState.OPEN + + override fun buildObservable(): Observable<*> = loginRepository.getLogin() + .flatMapObservable { it -> + return@flatMapObservable it.login?.let { login -> + Rx2Apollo.from( + apolloClient.query( + GetIssuesWithoutStateQuery.builder() + .login(login) + .count(5) + .build() + ) + ) + .map { it.data()?.user?.issues?.nodes } + .map { value -> + myIssues.deleteAllIssues() + myIssues.insert(value.asSequence().map { it.fragments.shortIssueRowItem }.map { + MyIssuesPullsModel( + it.id, it.databaseId, it.number, it.title, + it.repository.nameWithOwner, it.comments.totalCount, it.issueState.rawValue(), it.url.toString() + ) + }.toList()) + } + } ?: Observable.empty() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/main/PullRequestsMainScreenUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/main/PullRequestsMainScreenUseCase.kt new file mode 100644 index 000000000..b14dff4fb --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/main/PullRequestsMainScreenUseCase.kt @@ -0,0 +1,47 @@ +package com.fastaccess.github.usecase.main + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.persistence.models.MyIssuesPullsModel +import com.fastaccess.data.repository.LoginRepositoryProvider +import com.fastaccess.data.repository.MyIssuesPullsRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import github.GetPullRequestsQuery +import github.type.IssueState +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 16.06.18. + */ +class PullRequestsMainScreenUseCase @Inject constructor( + private val loginRepository: LoginRepositoryProvider, + private val myIssues: MyIssuesPullsRepositoryProvider, + private val apolloClient: ApolloClient +) : BaseObservableUseCase() { + var state: IssueState = IssueState.OPEN + + override fun buildObservable(): Observable<*> = loginRepository.getLogin() + .flatMapObservable { loginModel -> + return@flatMapObservable loginModel.login?.let { login -> + Rx2Apollo.from( + apolloClient.query( + GetPullRequestsQuery.builder() + .login(login) + .count(5) + .build() + ) + ) + .map { it.data()?.user?.pullRequests?.nodes } + .map { value -> + myIssues.deleteAllPrs() + myIssues.insert(value.asSequence().map { it.fragments.shortPullRequestRowItem }.map { + MyIssuesPullsModel( + it.id, it.databaseId, it.number, it.title, + it.repository.nameWithOwner, it.comments.totalCount, it.state.name, it.url.toString(), true + ) + }.toList()) + } + } ?: Observable.empty() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/notification/NotificationUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/notification/NotificationUseCase.kt new file mode 100644 index 000000000..ce4ac4f92 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/notification/NotificationUseCase.kt @@ -0,0 +1,53 @@ +package com.fastaccess.github.usecase.notification + +import com.fastaccess.data.persistence.models.NotificationModel +import com.fastaccess.data.repository.NotificationRepositoryProvider +import com.fastaccess.domain.repository.services.NotificationService +import com.fastaccess.domain.response.NotificationResponse +import com.fastaccess.domain.response.PageableResponse +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import com.fastaccess.github.extensions.getLastWeekDate +import com.google.gson.Gson +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 22.06.18. + */ + +class NotificationUseCase @Inject constructor( + private val notificationRepositoryProvider: NotificationRepositoryProvider, + private val notificationService: NotificationService, + private val gson: Gson +) : BaseObservableUseCase() { + + var page: Int? = null + var all: Boolean? = null + + override fun buildObservable(): Observable> { + val page = page + val all = all + val observable = if (all == true) { + notificationService.getAllNotifications() + } else { + if (page == null) { + notificationService.getMainNotifications() + } else { + notificationService.getNotifications(getLastWeekDate(), page) + } + } + return observable.map { it -> + it.items?.let { items -> + if (all == true) { + notificationRepositoryProvider.deleteAll(false) + val list = items.asSequence().filter { it.unread == false }.toList() + notificationRepositoryProvider.insert(NotificationModel.convert(gson, list)) + return@map it + } + if (page ?: 0 <= 1) notificationRepositoryProvider.deleteAll(true) + notificationRepositoryProvider.insert(NotificationModel.convert(gson, items)) + } + return@map it + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/search/FilterSearchReposUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/search/FilterSearchReposUseCase.kt new file mode 100644 index 000000000..d35f63d39 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/search/FilterSearchReposUseCase.kt @@ -0,0 +1,68 @@ +package com.fastaccess.github.usecase.search + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.api.Input +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.model.CountModel +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.ShortRepoModel +import com.fastaccess.data.model.parcelable.FilterByRepo +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import github.SearchReposQuery +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 20.01.19. + */ +class FilterSearchReposUseCase @Inject constructor( + private val apolloClient: ApolloClient +) : BaseObservableUseCase() { + + var cursor: Input = Input.absent() + var filterModel = FilterByRepo() + var keyword: String = "" + + override fun buildObservable(): Observable>> = Rx2Apollo + .from(apolloClient.query(SearchReposQuery(constructQuery(keyword), cursor))) + .map { it.data()?.search } + .map { search -> + val list = search.nodes + ?.mapNotNull { it.fragments.shortRepoRowItem } + ?.map { repo -> + ShortRepoModel(repo.id, repo.databaseId, repo.name, + CountModel(repo.stargazers.totalCount), CountModel(repo.issues.totalCount), + CountModel(repo.pullRequests.totalCount), repo.forkCount, repo.isFork, repo.isPrivate) + } ?: arrayListOf() + return@map Pair(PageInfoModel(search.pageInfo.startCursor, search.pageInfo.endCursor, + search.pageInfo.isHasNextPage, search.pageInfo.isHasPreviousPage), list) + } + + + private fun constructQuery(keyword: String): String { + return StringBuilder() + .apply { + append(keyword).append(" ") + when (filterModel.filterByRepoIn) { + FilterByRepo.FilterByRepoIn.NAME -> append("in:name").append(" ") + FilterByRepo.FilterByRepoIn.DESCRIPTION -> append("in:description").append(" ") + FilterByRepo.FilterByRepoIn.README -> append("in:readme").append(" ") + FilterByRepo.FilterByRepoIn.ALL -> { + //ignored for now! + } + } + if (!filterModel.name.isNullOrEmpty()) { + when (filterModel.filterByRepoLimitBy) { + FilterByRepo.FilterByRepoLimitBy.USERNAME -> append("user:${filterModel.name}").append(" ") + FilterByRepo.FilterByRepoLimitBy.ORG -> append("org:${filterModel.name}").append(" ") + null -> { + } + } + } + if (!filterModel.language.isNullOrEmpty()) { + append("language:${filterModel.language}").append(" ") + } + } + .toString() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/search/FilterSearchUsersUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/search/FilterSearchUsersUseCase.kt new file mode 100644 index 000000000..cc60ad691 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/search/FilterSearchUsersUseCase.kt @@ -0,0 +1,38 @@ +package com.fastaccess.github.usecase.search + +import com.apollographql.apollo.ApolloClient +import com.apollographql.apollo.api.Input +import com.apollographql.apollo.rx2.Rx2Apollo +import com.fastaccess.data.model.PageInfoModel +import com.fastaccess.data.model.ShortUserModel +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import github.SearchUserQuery +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 20.01.19. + */ +class FilterSearchUsersUseCase @Inject constructor( + private val apolloClient: ApolloClient +) : BaseObservableUseCase() { + + var cursor: Input = Input.absent() + var keyword: String = "" + + override fun buildObservable(): Observable>> = Rx2Apollo + .from(apolloClient.query(SearchUserQuery(keyword, cursor))) + .map { it.data()?.search } + .map { search -> + val list = search.nodes + ?.mapNotNull { it.fragments.shortUserRowItem } + ?.map { user -> + ShortUserModel(user.id, user.login, user.url.toString(), user.name, user.location, + user.bio, user.avatarUrl.toString(), user.isViewerCanFollow, user.isViewerIsFollowing) + } ?: arrayListOf() + return@map Pair(PageInfoModel(search.pageInfo.startCursor, search.pageInfo.endCursor, + search.pageInfo.isHasNextPage, search.pageInfo.isHasPreviousPage), list) + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/user/BlockUnblockUserUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/user/BlockUnblockUserUseCase.kt new file mode 100644 index 000000000..7e3827a61 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/user/BlockUnblockUserUseCase.kt @@ -0,0 +1,25 @@ +package com.fastaccess.github.usecase.user + +import com.fastaccess.data.repository.UserRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 10.06.18. + */ +class BlockUnblockUserUseCase @Inject constructor(private val userRepository: UserRepositoryProvider) : BaseObservableUseCase() { + var login: String? = null + var block: Boolean = false + + override fun buildObservable(): Observable = login?.let { login -> + userRepository.blockUnblockUser(login, block) + .map { + val isSuccess = it.isSuccessful && it.code() == 204 + if (isSuccess) { + return@map block + } + return@map isSuccess + } + } ?: Observable.empty() +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/user/FollowUnfollowUserUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/user/FollowUnfollowUserUseCase.kt new file mode 100644 index 000000000..c38779534 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/user/FollowUnfollowUserUseCase.kt @@ -0,0 +1,29 @@ +package com.fastaccess.github.usecase.user + +import com.fastaccess.data.repository.UserRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 10.06.18. + */ +class FollowUnfollowUserUseCase @Inject constructor(private val userRepository: UserRepositoryProvider) : BaseObservableUseCase() { + var login: String? = null + var follow: Boolean = false + + override fun buildObservable(): Observable = login?.let { login -> + userRepository.followUnfollowUser(login, follow) + .map { response -> + val isSuccess = response.isSuccessful && response.code() == 204 + if (isSuccess) { + userRepository.getUserBlocking(login)?.let { + it.viewerIsFollowing = follow + userRepository.updateUser(it) + } + return@map follow + } + return@map isSuccess + } + } ?: Observable.empty() +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/user/IsUserBlockedUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/user/IsUserBlockedUseCase.kt new file mode 100644 index 000000000..1c7950292 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/user/IsUserBlockedUseCase.kt @@ -0,0 +1,18 @@ +package com.fastaccess.github.usecase.user + +import com.fastaccess.data.repository.UserRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 10.06.18. + */ +class IsUserBlockedUseCase @Inject constructor(private val userRepository: UserRepositoryProvider) : BaseObservableUseCase() { + var login: String? = null + + override fun buildObservable(): Observable = login?.let { login -> + userRepository.isUserBlock(login) + .map { it.isSuccessful && it.code() == 204 } + } ?: Observable.empty() +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/user/UserFeedsUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/user/UserFeedsUseCase.kt new file mode 100644 index 000000000..44d89420b --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/user/UserFeedsUseCase.kt @@ -0,0 +1,21 @@ +package com.fastaccess.github.usecase.user + +import com.fastaccess.data.repository.FeedsRepositoryProvider +import com.fastaccess.domain.response.FeedResponse +import com.fastaccess.domain.response.PageableResponse +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 20.10.18. + */ +class UserFeedsUseCase @Inject constructor(private val feedsRepositoryProvider: FeedsRepositoryProvider) : BaseObservableUseCase() { + var page: Int = 0 + var login: String? = null + + override fun buildObservable(): Observable> = when { + login.isNullOrEmpty() -> Observable.empty() + else -> feedsRepositoryProvider.getFeeds(login ?: "", page) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/usecase/user/UserUseCase.kt b/app/src/main/java/com/fastaccess/github/usecase/user/UserUseCase.kt new file mode 100644 index 000000000..07586ed83 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/usecase/user/UserUseCase.kt @@ -0,0 +1,18 @@ +package com.fastaccess.github.usecase.user + +import com.fastaccess.data.persistence.models.UserModel +import com.fastaccess.data.repository.UserRepositoryProvider +import com.fastaccess.domain.usecase.base.BaseObservableUseCase +import io.reactivex.Observable +import javax.inject.Inject + +/** + * Created by Kosh on 10.06.18. + */ +class UserUseCase @Inject constructor(private val userRepository: UserRepositoryProvider) : BaseObservableUseCase() { + var login: String? = null + + override fun buildObservable(): Observable = login?.let { userRepository.getUserFromRemote(it) } ?: Observable.empty() + + fun getUser(login: String) = userRepository.getUser(login) +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/utils/Constants.kt b/app/src/main/java/com/fastaccess/github/utils/Constants.kt new file mode 100644 index 000000000..a07f2cb6b --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/utils/Constants.kt @@ -0,0 +1,51 @@ +package com.fastaccess.github.utils + +import com.fastaccess.data.model.ActivityType + +/** + * Created by Kosh on 12 Nov 2016, 3:55 PM + */ + +const val ITEM = "item" +const val ID = "id" +const val EXTRA = "extra" +const val EXTRA_TWO = "extra2_id" +const val EXTRA_THREE = "extra3_id" +const val EXTRA_FOUR = "extra4_id" +const val EXTRA_FIVE = "extra5_id" +const val EXTRA_SIX = "extra6_id" +const val EXTRA_SEVEN = "extra7_id" +const val EXTRA_EIGHT = "extra8_id" +const val EXTRA_TYPE = "extra_type" +const val YES_NO_EXTRA = "yes_no_extra" +const val NOTIFICATION_ID = "notification_id" +const val IS_ENTERPRISE = "is_enterprise" +const val REVIEW_EXTRA = "review_extra" +const val SCHEME_URL = "scheme_url" +const val REQUEST_CODE = 2016 +const val REVIEW_REQUEST_CODE = 2017 +const val REFRESH_CODE = 64 +const val FOR_RESULT_EXTRA = "for_result_extra" +const val EDIT_GIST_COMMENT_EXTRA = "edit_comment_extra" +const val NEW_GIST_COMMENT_EXTRA = "new_gist_comment_extra" +const val EDIT_ISSUE_COMMENT_EXTRA = "edit_issue_comment_extra" +const val NEW_ISSUE_COMMENT_EXTRA = "new_issue_comment_extra" +const val EDIT_COMMIT_COMMENT_EXTRA = "edit_commit_comment_extra" +const val NEW_COMMIT_COMMENT_EXTRA = "new_commit_comment_extra" +const val NEW_REVIEW_COMMENT_EXTRA = "new_review_comment_extra" +const val EDIT_REVIEW_COMMENT_EXTRA = "edit_review_comment_extra" +const val PAGE_SIZE = 30 +const val PRE_FETCH_SIZE = 30 + +// DEEP LINKS + +const val REDIRECT_URL = "fasthub://login" +const val SCOPE_LIST = "user,repo,gist,notifications,read:org" +const val IN_APP_LINK = "app://fasthub" +const val GITHUB_LINK = "https://github.com/" +val FEEDS_LINK = "$IN_APP_LINK/me/${ActivityType.FEEDS.name}" +val NOTIFICATION_LINK = "$IN_APP_LINK/me/${ActivityType.NOTIFICATION.name}" +val FILTER_ISSUE_LINK = "$IN_APP_LINK/me/${ActivityType.FILTER_ISSUE.name}" +val FILTER_PR_LINK = "$IN_APP_LINK/me/${ActivityType.FILTER_PR.name}" +val SEARCH_LINK = "$IN_APP_LINK/me/${ActivityType.SEARCH.name}" +val TRENDING_LINK = "${GITHUB_LINK}trending" diff --git a/app/src/main/java/com/fastaccess/github/utils/extensions/ActivityFragmentExtension.kt b/app/src/main/java/com/fastaccess/github/utils/extensions/ActivityFragmentExtension.kt new file mode 100644 index 000000000..3130b8fc5 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/utils/extensions/ActivityFragmentExtension.kt @@ -0,0 +1,41 @@ +package com.fastaccess.github.utils.extensions + +import android.content.Context +import android.content.Intent +import android.net.Uri +import androidx.fragment.app.Fragment +import com.fastaccess.github.R +import com.fastaccess.github.base.BaseFragment +import com.fastaccess.github.extensions.isConnected +import com.fastaccess.github.ui.modules.routing.RoutingActivity +import com.google.android.material.snackbar.Snackbar +import timber.log.Timber + +/** + * Created by Kosh on 12.06.18. + */ + +fun Fragment.route(url: String?) { + context?.route(url) +} + +fun Context.route(url: String?) { + url?.let { + Timber.e("routing to: $url") + val intent = Intent(this, RoutingActivity::class.java) + intent.data = Uri.parse(url) + startActivity(intent) + } +} + +fun BaseFragment.isConnected(): Boolean { + val isConnected = context?.isConnected() ?: false + if (!isConnected) { + view?.let { + Snackbar.make(it.findViewById(R.id.coordinatorLayout) ?: it, getString(R.string.no_internet_connection), Snackbar.LENGTH_LONG) + .materialize(R.drawable.snackbar_background_error) + .show() + } + } + return isConnected +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/github/utils/extensions/PrefExtension.kt b/app/src/main/java/com/fastaccess/github/utils/extensions/PrefExtension.kt new file mode 100644 index 000000000..7f851662e --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/utils/extensions/PrefExtension.kt @@ -0,0 +1,96 @@ +package com.fastaccess.github.utils.extensions + +import com.fastaccess.data.storage.FastHubSharedPreference + +/** + * Created by Kosh on 10.06.18. + */ + +inline var FastHubSharedPreference.token: String? + get() = this.getString("token") + set(value) = this.set("token", value) + +inline var FastHubSharedPreference.enterpriseToken: String? + get() = this.getString("enterprise_token") + set(value) = this.set("enterprise_token", value) + +inline var FastHubSharedPreference.otpCode: String? + get() = this.getString("otp_code") + set(value) = this.set("otp_code", value) + +inline var FastHubSharedPreference.enterpriseOtpCode: String? + get() = this.getString("enterprise_otp_code") + set(value) = this.set("enterprise_otp_code", value) + +inline var FastHubSharedPreference.enterpriseUrl: String? + get() = this.getString("enterprise_url") + set(value) = this.set("enterprise_url", value) + +inline var FastHubSharedPreference.notificationDuration: Int + get() = this.getInt("notification_duration", 30).times(60) + set(value) = this.set("notification_duration", value) + +inline var FastHubSharedPreference.backButton: Boolean + get() = this.getBoolean("press_twice_back_button", false) + set(value) = this.set("press_twice_back_button", value) + +inline var FastHubSharedPreference.isRectAvatar: Boolean + get() = this.getBoolean("rect_avatar", false) + set(value) = this.set("rect_avatar", value) + +inline var FastHubSharedPreference.markNotificationAsRead: Boolean + get() = this.getBoolean("markNotificationAsRead", false) + set(value) = this.set("markNotificationAsRead", value) + +inline var FastHubSharedPreference.sentVia: Boolean + get() = this.getBoolean("fasthub_signature", false) + set(value) = this.set("fasthub_signature", value) + +inline var FastHubSharedPreference.theme: Int + get() = this.getInt("appTheme", 1) + set(value) = this.set("appTheme", value) + +inline var FastHubSharedPreference.language: String + get() = this.getString("app_language", "en") ?: "en" + set(value) = this.set("app_language", value) + +inline var FastHubSharedPreference.showWhatsNew: Boolean + get() = this.getBoolean("whats_new", false) + set(value) = this.set("whats_new", value) + +inline var FastHubSharedPreference.notificationSound: Boolean + get() = this.getBoolean("notificationSound", false) + set(value) = this.set("notificationSound", value) + +inline var FastHubSharedPreference.amlodTheme: Boolean + get() = this.getBoolean("amlod_theme_enabled", false) + set(value) = this.set("amlod_theme_enabled", value) + +inline var FastHubSharedPreference.bluishTheme: Boolean + get() = this.getBoolean("bluish_theme_enabled", false) + set(value) = this.set("bluish_theme_enabled", value) + +inline var FastHubSharedPreference.isPro: Boolean + get() = this.getBoolean("fasthub_pro_items", false) + set(value) = this.set("fasthub_pro_items", value) + +inline var FastHubSharedPreference.isEnterprisePurchased: Boolean + get() = this.getBoolean("enterprise_item", false) + set(value) = this.set("enterprise_item", value) + +inline var FastHubSharedPreference.tineNavBar: Boolean + get() = this.getBoolean("navigation_color", false) + set(value) = this.set("navigation_color", value) + +inline val FastHubSharedPreference.allFeatures: Boolean get() = isEnterprise && isPro + +inline val FastHubSharedPreference.hasSupported: Boolean get() = isPro || amlodTheme || bluishTheme + +inline val FastHubSharedPreference.isEnterprise: Boolean get() = !enterpriseUrl.isNullOrEmpty() + +fun FastHubSharedPreference.resetEnterprise() { + enterpriseUrl = null + enterpriseToken = null + enterpriseOtpCode = null +} + diff --git a/app/src/main/java/com/fastaccess/github/utils/extensions/ViewExtension.kt b/app/src/main/java/com/fastaccess/github/utils/extensions/ViewExtension.kt new file mode 100644 index 000000000..a274d3453 --- /dev/null +++ b/app/src/main/java/com/fastaccess/github/utils/extensions/ViewExtension.kt @@ -0,0 +1,174 @@ +package com.fastaccess.github.utils.extensions + +import android.content.Context +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import android.widget.PopupWindow +import android.widget.TextView +import androidx.core.view.ViewCompat +import androidx.interpolator.view.animation.FastOutLinearInInterpolator +import androidx.interpolator.view.animation.LinearOutSlowInInterpolator +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.StaggeredGridLayoutManager +import androidx.transition.TransitionManager +import com.fastaccess.data.model.ReactionGroupModel +import com.fastaccess.github.R +import com.fastaccess.github.extensions.getColorAttr +import com.fastaccess.github.extensions.getDrawableCompat +import com.fastaccess.github.ui.widget.AnchorSheetBehavior +import com.fastaccess.github.ui.widget.recyclerview.decoration.InsetDividerDecoration +import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.snackbar.Snackbar +import kotlinx.android.synthetic.main.reaction_group_chip_widget.view.* + +/** + * Created by Kosh on 03.06.18. + */ + +private val FAST_OUT_LINEAR_IN_INTERPOLATOR = FastOutLinearInInterpolator() +private val LINEAR_OUT_SLOW_IN_INTERPOLATOR = LinearOutSlowInInterpolator() + +fun TextView.asString(): String = this.text?.toString() ?: "" + +fun Snackbar.materialize(drawable: Int? = null): Snackbar { + val params = this.view.layoutParams as ViewGroup.MarginLayoutParams + val margin = context.resources.getDimensionPixelSize(R.dimen.spacing_xs_large) + params.setMargins(margin, margin, margin, 12) + this.view.layoutParams = params + this.view.background = context.getDrawableCompat(drawable ?: R.drawable.snackbar_background) + ViewCompat.setElevation(this.view, 6f) + return this +} + +fun View.showHideFabAnimation(show: Boolean, listener: ((show: Boolean) -> Unit)? = null) { + val view = this + if (show) { + view.animate().cancel() + if (ViewCompat.isLaidOut(view)) { + if (view.visibility != View.VISIBLE) { + view.alpha = 0f + view.scaleY = 0f + view.scaleX = 0f + } + view.animate() + .scaleX(1f) + .scaleY(1f) + .alpha(1f) + .setDuration(200) + .setInterpolator(LINEAR_OUT_SLOW_IN_INTERPOLATOR) + .withStartAction { + view.visibility = View.VISIBLE + listener?.invoke(true) + } + } else { + view.visibility = View.VISIBLE + view.alpha = 1f + view.scaleY = 1f + view.scaleX = 1f + listener?.invoke(true) + } + } else { + view.animate() + .scaleX(0f) + .scaleY(0f) + .alpha(0f) + .setDuration(150) + .setInterpolator(FAST_OUT_LINEAR_IN_INTERPOLATOR) + .withEndAction { + view.visibility = View.GONE + listener?.invoke(false) + } + } +} + +fun RecyclerView.addKeyLineDivider() { + if (canAddDivider()) { + val resources = resources + addItemDecoration(InsetDividerDecoration(resources.getDimensionPixelSize(R.dimen.divider_height), + resources.getDimensionPixelSize(R.dimen.keyline_2), context.getColorAttr(R.attr.dividerColor))) + } +} + +fun RecyclerView.addDivider() { + if (canAddDivider()) { + val resources = resources + addItemDecoration(InsetDividerDecoration(resources.getDimensionPixelSize(R.dimen.divider_height), 0, context.getColorAttr(R.attr.dividerColor))) + } +} + +fun RecyclerView.canAddDivider(): Boolean { + if (layoutManager != null) { + val layoutManager = this.layoutManager + when (layoutManager) { + is GridLayoutManager -> return layoutManager.spanCount == 1 + is LinearLayoutManager -> return true + is StaggeredGridLayoutManager -> return layoutManager.spanCount == 1 + } + } + return false +} + +fun AnchorSheetBehavior.setBottomSheetCallback( + onStateChanged: ((newState: Int) -> Unit)? = null, + onSlide: ((slideOffset: Float) -> Unit)? = null +) { + this.setAnchorSheetCallback(object : AnchorSheetBehavior.AnchorSheetCallback() { + override fun onSlide(bottomSheet: View, slideOffset: Float) { + onSlide?.invoke(slideOffset) + } + + override fun onStateChanged(bottomSheet: View, newState: Int) { + onStateChanged?.invoke(newState) + } + }) +} + +fun BottomSheetBehavior.setBottomSheetCallback( + onStateChanged: ((newState: Int) -> Unit)? = null, + onSlide: ((slideOffset: Float) -> Unit)? = null +) { + this.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { + override fun onSlide(bottomSheet: View, slideOffset: Float) { + onSlide?.invoke(slideOffset) + } + + override fun onStateChanged(bottomSheet: View, newState: Int) { + onStateChanged?.invoke(newState) + } + }) +} + +fun View.beginDelayedTransition() = TransitionManager.beginDelayedTransition(this as ViewGroup) + +fun View.focusAndshowKeyboard() { + requestFocusFromTouch() + val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY) +} + +fun View.showKeyboard() { + val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY) +} + +fun View.hideKeyboard() { + val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(windowToken, 0) +} + +fun View.popupEmoji(id: String, list: List?, callback: (() -> Unit)?) { + val popupWindow = PopupWindow(context) + + val view = View.inflate(context, R.layout.reaction_group_chip_widget, null) + view.reactionGroup.setup(id, list, popupWindow, callback) + popupWindow.contentView = view + popupWindow.setBackgroundDrawable(context.getDrawableCompat(R.drawable.popup_window_background)) + popupWindow.elevation = resources.getDimension(R.dimen.spacing_normal) + popupWindow.isOutsideTouchable = true + popupWindow.isFocusable = true + popupWindow.isTouchable = true + popupWindow.showAsDropDown(this) +} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/helper/ActivityHelper.java b/app/src/main/java/com/fastaccess/helper/ActivityHelper.java deleted file mode 100644 index 777c64ec3..000000000 --- a/app/src/main/java/com/fastaccess/helper/ActivityHelper.java +++ /dev/null @@ -1,266 +0,0 @@ -package com.fastaccess.helper; - -import android.Manifest; -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.ComponentName; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.customtabs.CustomTabsIntent; -import android.support.v4.app.ActivityCompat; -import android.support.v4.app.ActivityOptionsCompat; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.ShareCompat; -import android.support.v4.util.Pair; -import android.view.View; -import android.widget.Toast; - -import com.fastaccess.App; -import com.fastaccess.R; -import com.fastaccess.ui.modules.main.drawer.AccountDrawerFragment; -import com.fastaccess.ui.modules.main.drawer.MainDrawerFragment; -import com.fastaccess.ui.modules.parser.LinksParserActivity; - -import java.util.ArrayList; -import java.util.List; - -import es.dmoral.toasty.Toasty; - -/** - * Created by Kosh on 12/12/15 10:51 PM - */ -public class ActivityHelper { - - @Nullable public static Activity getActivity(@Nullable Context content) { - if (content == null) return null; - else if (content instanceof Activity) return (Activity) content; - else if (content instanceof ContextWrapper) return getActivity(((ContextWrapper) content).getBaseContext()); - return null; - } - - public static void startCustomTab(@NonNull Activity context, @NonNull Uri url) { - String packageNameToUse = CustomTabsHelper.getPackageNameToUse(context); - if (packageNameToUse != null) { - CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder() - .setToolbarColor(ViewHelper.getPrimaryColor(context)) - .setShowTitle(true) - .build(); - customTabsIntent.intent.setPackage(packageNameToUse); - try { - customTabsIntent.launchUrl(context, url); - } catch (ActivityNotFoundException ignored) { - openChooser(context, url, true); - } - } else { - openChooser(context, url, true); - } - } - - public static void startCustomTab(@NonNull Activity context, @NonNull String url) { - startCustomTab(context, Uri.parse(url)); - } - - public static void openChooser(@NonNull Context context, @NonNull Uri url) { - openChooser(context, url, false); - } - - private static void openChooser(@NonNull Context context, @NonNull Uri url, boolean fromCustomTab) { - Intent i = new Intent(Intent.ACTION_VIEW, url); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - Intent finalIntent = chooserIntent(context, i, url); - if (finalIntent != null) { - try { - context.startActivity(finalIntent); - } catch (ActivityNotFoundException ignored) { - } - } else { - if (!fromCustomTab) { - Activity activity = ActivityHelper.getActivity(context); - if (activity == null) { - try { - context.startActivity(i); - } catch (ActivityNotFoundException ignored) { - } - return; - } - startCustomTab(activity, url); - } else { - try { - context.startActivity(i); - } catch (ActivityNotFoundException ignored) { - } - } - } - } - - public static void openChooser(@NonNull Context context, @NonNull String url) { - openChooser(context, Uri.parse(url)); - } - - @SafeVarargs public static void start(@NonNull Activity activity, Class cl, Pair... sharedElements) { - Intent intent = new Intent(activity, cl); - ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, sharedElements); - activity.startActivity(intent, options.toBundle()); - } - - public static void start(@NonNull Activity activity, Intent intent, @NonNull View sharedElement) { - ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, - sharedElement, ViewHelper.getTransitionName(sharedElement)); - activity.startActivity(intent, options.toBundle()); - } - - public static void startReveal(@NonNull Activity activity, Intent intent, @NonNull View sharedElement, int requestCode) { - if (!PrefGetter.isAppAnimationDisabled()) { - ActivityOptionsCompat options = ActivityOptionsCompat.makeClipRevealAnimation(sharedElement, sharedElement.getWidth() / 2, - sharedElement.getHeight() / 2, - sharedElement.getWidth(), sharedElement.getHeight()); - activity.startActivityForResult(intent, requestCode, options.toBundle()); - } else { - activity.startActivityForResult(intent, requestCode); - } - } - - public static void startReveal(@NonNull Fragment fragment, Intent intent, @NonNull View sharedElement, int requestCode) { - if (!PrefGetter.isAppAnimationDisabled()) { - ActivityOptionsCompat options = ActivityOptionsCompat.makeClipRevealAnimation(sharedElement, sharedElement.getWidth() / 2, - sharedElement.getHeight() / 2, - sharedElement.getWidth(), sharedElement.getHeight()); - fragment.startActivityForResult(intent, requestCode, options.toBundle()); - } else { - fragment.startActivityForResult(intent, requestCode); - } - } - - public static void startReveal(@NonNull Activity activity, Intent intent, @NonNull View sharedElement) { - if (!PrefGetter.isAppAnimationDisabled()) { - ActivityOptionsCompat options = ActivityOptionsCompat.makeClipRevealAnimation(sharedElement, sharedElement.getWidth() / 2, - sharedElement.getHeight() / 2, - sharedElement.getWidth(), sharedElement.getHeight()); - activity.startActivity(intent, options.toBundle()); - } else { - activity.startActivity(intent); - } - } - - @SafeVarargs public static void start(@NonNull Activity activity, @NonNull Intent intent, - @NonNull Pair... sharedElements) { - ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, sharedElements); - activity.startActivity(intent, options.toBundle()); - - } - - public static void shareUrl(@NonNull Context context, @NonNull String url) { - Activity activity = getActivity(context); - if (activity == null) throw new IllegalArgumentException("Context given is not an instance of activity " + context.getClass().getName()); - try { - ShareCompat.IntentBuilder.from(activity) - .setChooserTitle(context.getString(R.string.share)) - .setType("text/plain") - .setText(url) - .startChooser(); - } catch (ActivityNotFoundException e) { - Toasty.error(App.getInstance(), e.getMessage(), Toast.LENGTH_LONG).show(); - } - } - - @SuppressWarnings("RestrictedApi") - @Nullable public static Fragment getVisibleFragment(@NonNull FragmentManager manager) { - List fragments = manager.getFragments(); - if (fragments != null && !fragments.isEmpty()) { - for (Fragment fragment : fragments) { - if (fragment != null && fragment.isVisible() && - !(fragment instanceof MainDrawerFragment || fragment instanceof AccountDrawerFragment)) { - return fragment; - } - } - } - return null; - } - - private static boolean isPermissionGranted(@NonNull Context context, @NonNull String permission) { - return ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED; - } - - private static boolean isExplanationNeeded(@NonNull Activity context, @NonNull String permissionName) { - return ActivityCompat.shouldShowRequestPermissionRationale(context, permissionName); - } - - private static boolean isReadWritePermissionIsGranted(@NonNull Context context) { - return isPermissionGranted(context, Manifest.permission.READ_EXTERNAL_STORAGE) - && isPermissionGranted(context, Manifest.permission.WRITE_EXTERNAL_STORAGE); - } - - private static void requestReadWritePermission(@NonNull Activity context) { - ActivityCompat.requestPermissions(context, new String[]{ - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE, - }, 1); - } - - public static boolean checkAndRequestReadWritePermission(@NonNull Activity activity) { - if (!isReadWritePermissionIsGranted(activity)) { - requestReadWritePermission(activity); - return false; - } else if (isExplanationNeeded(activity, Manifest.permission.READ_EXTERNAL_STORAGE) - || isExplanationNeeded(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - Toasty.error(App.getInstance(), activity.getString(R.string.read_write_permission_explanation), Toast.LENGTH_LONG).show(); - return false; - } - return true; - } - - private static Intent chooserIntent(@NonNull Context context, @NonNull Intent intent, @NonNull Uri uri) { - final PackageManager pm = context.getPackageManager(); - final List activities = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); - final ArrayList chooserIntents = new ArrayList<>(); - final String ourPackageName = context.getPackageName(); - for (ResolveInfo resInfo : activities) { - ActivityInfo info = resInfo.activityInfo; - if (!info.enabled || !info.exported) { - continue; - } - if (info.packageName.equals(ourPackageName)) { - continue; - } - Intent targetIntent = new Intent(intent); - targetIntent.setPackage(info.packageName); - targetIntent.setDataAndType(uri, intent.getType()); - chooserIntents.add(targetIntent); - } - if (chooserIntents.isEmpty()) { - return null; - } - final Intent lastIntent = chooserIntents.remove(chooserIntents.size() - 1); - if (chooserIntents.isEmpty()) { - return lastIntent; - } - Intent chooserIntent = Intent.createChooser(lastIntent, null); - chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, chooserIntents.toArray(new Intent[chooserIntents.size()])); - return chooserIntent; - } - - public static void activateLinkInterceptorActivity(Context context, boolean activate) { - final PackageManager pm = context.getPackageManager(); - final int flag = activate ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED; - pm.setComponentEnabledSetting(new ComponentName(context, LinksParserActivity.class), flag, PackageManager.DONT_KILL_APP); - } - - public static Intent editBundle(@NonNull Intent intent, boolean isEnterprise) { - Bundle bundle = intent.getExtras(); - if (bundle != null) { - bundle.putBoolean(BundleConstant.IS_ENTERPRISE, isEnterprise); - intent.putExtras(bundle); - } - return intent; - } - -} diff --git a/app/src/main/java/com/fastaccess/helper/AnimHelper.java b/app/src/main/java/com/fastaccess/helper/AnimHelper.java deleted file mode 100644 index 2faa8d41e..000000000 --- a/app/src/main/java/com/fastaccess/helper/AnimHelper.java +++ /dev/null @@ -1,208 +0,0 @@ -package com.fastaccess.helper; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.ObjectAnimator; -import android.app.Dialog; -import android.graphics.Rect; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.UiThread; -import android.support.design.widget.FloatingActionButton; -import android.support.v4.app.DialogFragment; -import android.support.v4.view.ViewCompat; -import android.support.v4.view.animation.FastOutLinearInInterpolator; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; -import android.view.View; -import android.view.ViewAnimationUtils; -import android.view.ViewPropertyAnimator; -import android.view.ViewTreeObserver; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.Interpolator; -import android.view.animation.LinearInterpolator; -import android.widget.PopupWindow; - -import java.util.Arrays; -import java.util.List; - - -/** - * Created by Kosh on 27 May 2016, 9:04 PM - */ - -public class AnimHelper { - - private static final Interpolator FAST_OUT_LINEAR_IN_INTERPOLATOR = new FastOutLinearInInterpolator(); - private static final Interpolator LINEAR_OUT_SLOW_IN_INTERPOLATOR = new LinearOutSlowInInterpolator(); - private static final Interpolator interpolator = new LinearInterpolator(); - - @UiThread private static void animateVisibility(@Nullable final View view, final boolean show, int visibility) { - if (view == null) { - return; - } - if (!ViewCompat.isAttachedToWindow(view)) { - view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override public boolean onPreDraw() { - view.getViewTreeObserver().removeOnPreDrawListener(this); - animateSafeVisibility(show, view, visibility); - return true; - } - }); - } else { - animateSafeVisibility(show, view, visibility); - } - } - - @UiThread public static void animateVisibility(@Nullable final View view, final boolean show) { - animateVisibility(view, show, View.GONE); - } - - @UiThread private static void animateSafeVisibility(final boolean show, @NonNull final View view, int visibility) { - view.animate().cancel(); - ViewPropertyAnimator animator = view.animate().setDuration(200).alpha(show ? 1F : 0F).setInterpolator(new AccelerateInterpolator()) - .setListener(new AnimatorListenerAdapter() { - @Override public void onAnimationStart(Animator animation) { - super.onAnimationStart(animation); - if (show) { - view.setScaleX(1); - view.setScaleY(1); - view.setVisibility(View.VISIBLE); - } - } - - @Override public void onAnimationEnd(@NonNull Animator animation) { - super.onAnimationEnd(animation); - if (!show) { - view.setVisibility(visibility); - view.setScaleX(0); - view.setScaleY(0); - } - animation.removeListener(this); - view.clearAnimation(); - } - }); - animator.scaleX(show ? 1 : 0).scaleY(show ? 1 : 0); - } - - @UiThread @NonNull private static List getBeats(@NonNull View view) { - ObjectAnimator[] animator = new ObjectAnimator[]{ - ObjectAnimator.ofFloat(view, "scaleY", 1, 1.1f, 1), - ObjectAnimator.ofFloat(view, "scaleX", 1, 1.1f, 1) - }; - return Arrays.asList(animator); - } - - @UiThread public static void startBeatsAnimation(@NonNull View view) { - view.clearAnimation(); - if (view.getAnimation() != null) { - view.getAnimation().cancel(); - } - List animators = getBeats(view); - for (ObjectAnimator anim : animators) { - anim.setDuration(300).start(); - anim.setInterpolator(interpolator); - } - } - - @UiThread public static void revealPopupWindow(@NonNull PopupWindow popupWindow, @NonNull View from) { - Rect rect = ViewHelper.getLayoutPosition(from); - int x = (int) rect.exactCenterX(); - int y = (int) rect.exactCenterY(); - if (popupWindow.getContentView() != null) { - View view = popupWindow.getContentView(); - if (view != null) { - popupWindow.showAsDropDown(from); - view.post(() -> { - if (ViewCompat.isAttachedToWindow(view)) { - Animator animator = ViewAnimationUtils.createCircularReveal(view, x, y, 0, - (float) Math.hypot(rect.width(), rect.height())); - animator.setDuration(view.getResources().getInteger(android.R.integer.config_shortAnimTime)); - animator.start(); - } - }); - } - } - } - - @UiThread public static void revealDialog(@NonNull Dialog dialog, int animDuration) { - if (dialog.getWindow() != null) { - View view = dialog.getWindow().getDecorView(); - if (view != null) { - view.post(() -> { - if (ViewCompat.isAttachedToWindow(view)) { - int centerX = view.getWidth() / 2; - int centerY = view.getHeight() / 2; - Animator animator = ViewAnimationUtils.createCircularReveal(view, centerX, centerY, 20, view.getHeight()); - animator.setDuration(animDuration); - animator.start(); - } - }); - } - } - } - - @UiThread public static void dismissDialog(@NonNull DialogFragment dialogFragment, int duration, AnimatorListenerAdapter listenerAdapter) { - Dialog dialog = dialogFragment.getDialog(); - if (dialog != null) { - if (dialog.getWindow() != null) { - View view = dialog.getWindow().getDecorView(); - if (view != null) { - int centerX = view.getWidth() / 2; - int centerY = view.getHeight() / 2; - float radius = (float) Math.sqrt(view.getWidth() * view.getWidth() / 4 + view.getHeight() * view.getHeight() / 4); - view.post(() -> { - if (ViewCompat.isAttachedToWindow(view)) { - Animator animator = ViewAnimationUtils.createCircularReveal(view, centerX, centerY, radius, 0); - animator.setDuration(duration); - animator.addListener(listenerAdapter); - animator.start(); - } else { - listenerAdapter.onAnimationEnd(null); - } - }); - } - } - } else { - listenerAdapter.onAnimationEnd(null); - } - } - - @UiThread public static void mimicFabVisibility(boolean show, @NonNull View view, - @Nullable FloatingActionButton.OnVisibilityChangedListener listener) { - if (show) { - view.animate().cancel(); - if (ViewCompat.isLaidOut(view)) { - if (view.getVisibility() != View.VISIBLE) { - view.setAlpha(0f); - view.setScaleY(0f); - view.setScaleX(0f); - } - view.animate() - .scaleX(1f) - .scaleY(1f) - .alpha(1f) - .setDuration(200) - .setInterpolator(LINEAR_OUT_SLOW_IN_INTERPOLATOR) - .withStartAction(() -> { - view.setVisibility(View.VISIBLE); - if (listener != null) listener.onShown(null); - }); - } else { - view.setVisibility(View.VISIBLE); - view.setAlpha(1f); - view.setScaleY(1f); - view.setScaleX(1f); - if (listener != null) listener.onShown(null); - } - } else { - view.animate() - .scaleX(0f) - .scaleY(0f) - .alpha(0f) - .setDuration(40) - .setInterpolator(FAST_OUT_LINEAR_IN_INTERPOLATOR); - view.setVisibility(View.GONE); - if (listener != null) listener.onHidden(null); - } - } -} diff --git a/app/src/main/java/com/fastaccess/helper/AppHelper.java b/app/src/main/java/com/fastaccess/helper/AppHelper.java deleted file mode 100644 index 3cffe09ce..000000000 --- a/app/src/main/java/com/fastaccess/helper/AppHelper.java +++ /dev/null @@ -1,200 +0,0 @@ -package com.fastaccess.helper; - -import android.app.NotificationManager; -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.net.ConnectivityManager; -import android.os.Build; -import android.provider.Settings; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.view.View; -import android.view.inputmethod.InputMethodManager; - -import com.fastaccess.App; -import com.fastaccess.BuildConfig; -import com.fastaccess.R; -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; - -import java.util.Locale; - -import es.dmoral.toasty.Toasty; - -/** - * Created by kosh20111 on 18 Oct 2016, 9:29 PM - */ - -public class AppHelper { - - public static void hideKeyboard(@NonNull View view) { - InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - if (inputManager != null) { - inputManager.hideSoftInputFromWindow(view.getWindowToken(), 0); - } - } - - @Nullable public static Fragment getFragmentByTag(@NonNull FragmentManager fragmentManager, @NonNull String tag) { - return fragmentManager.findFragmentByTag(tag); - } - - public static void cancelNotification(@NonNull Context context) { - cancelNotification(context, BundleConstant.REQUEST_CODE); - } - - public static void cancelNotification(@NonNull Context context, int id) { - NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - if (notificationManager != null) { - notificationManager.cancel(id); - } - } - - public static void cancelAllNotifications(@NonNull Context context) { - NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - if (notificationManager != null) { - notificationManager.cancelAll(); - } - } - - public static void copyToClipboard(@NonNull Context context, @NonNull String uri) { - ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText(context.getString(R.string.app_name), uri); - if (clipboard != null) { - clipboard.setPrimaryClip(clip); - Toasty.success(App.getInstance(), context.getString(R.string.success_copied)).show(); - } - } - - public static boolean isNightMode(@NonNull Resources resources) { - @PrefGetter.ThemeType int themeType = PrefGetter.getThemeType(resources); - return themeType != PrefGetter.LIGHT; - } - - public static String getFastHubIssueTemplate(boolean enterprise) { - String brand = (!isEmulator()) ? Build.BRAND : "Android Emulator"; - String model = (!isEmulator()) ? DeviceNameGetter.getInstance().getDeviceName() : "Android Emulator"; - StringBuilder builder = new StringBuilder() - .append("**FastHub Version: ").append(BuildConfig.VERSION_NAME).append(enterprise ? " Enterprise**" : "**").append(" \n") - .append(!isInstalledFromPlaySore(App.getInstance()) ? "**APK Source: Unknown** \n" : "") - .append("**Android Version: ").append(String.valueOf(Build.VERSION.RELEASE)).append(" (SDK: ") - .append(String.valueOf(Build.VERSION.SDK_INT)).append(")**").append(" \n") - .append("**Device Information:**").append(" \n") - .append("- **") - .append(!model.equalsIgnoreCase(brand) ? "Manufacturer" : "Manufacturer&Brand") - .append(":** ") - .append(Build.MANUFACTURER) - .append(" \n"); - if (!(model.equalsIgnoreCase(brand) || "google".equals(Build.BRAND))) { - builder.append("- **Brand:** ").append(brand).append(" \n"); - } - builder.append("- **Model:** ").append(model).append(" \n") - .append("---").append("\n\n"); - if (!Locale.getDefault().getLanguage().equals(new Locale("en").getLanguage())) { - builder.append("") - .append("\n"); - } - return builder.toString(); - } - - public static void updateAppLanguage(@NonNull Context context) { - String lang = PrefGetter.getAppLanguage(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - updateResources(context, lang); - } - updateResourcesLegacy(context, lang); - } - - private static void updateResources(Context context, String language) { - Locale locale = getLocale(language); - Locale.setDefault(locale); - Configuration configuration = context.getResources().getConfiguration(); - configuration.setLocale(locale); - context.createConfigurationContext(configuration); - } - - @SuppressWarnings("deprecation") - private static void updateResourcesLegacy(Context context, String language) { - Locale locale = getLocale(language); - Locale.setDefault(locale); - Resources resources = context.getResources(); - Configuration configuration = resources.getConfiguration(); - configuration.locale = locale; - resources.updateConfiguration(configuration, resources.getDisplayMetrics()); - } - - @NonNull private static Locale getLocale(String language) { - Locale locale = null; - if (language.equalsIgnoreCase("zh-rCN")) { - locale = Locale.SIMPLIFIED_CHINESE; - } else if (language.equalsIgnoreCase("zh-rTW")) { - locale = Locale.TRADITIONAL_CHINESE; - } - if (locale != null) return locale; - String[] split = language.split("-"); - if (split.length > 1) { - locale = new Locale(split[0], split[1]); - } else { - locale = new Locale(language); - } - return locale; - } - - public static String getDeviceName() { - if (isEmulator()) { - return "Android Emulator"; - } - return DeviceNameGetter.getInstance().getDeviceName(); - } - - public static boolean isEmulator() { - return Build.FINGERPRINT.startsWith("generic") - || Build.FINGERPRINT.startsWith("unknown") - || Build.MODEL.contains("google_sdk") - || Build.MODEL.contains("Emulator") - || Build.MODEL.contains("Android SDK built for x86") - || Build.MANUFACTURER.contains("Genymotion") - || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")) - || "google_sdk".equals(Build.PRODUCT); - } - - private static boolean isInstalledFromPlaySore(@NonNull Context context) { - final String ipn = context.getPackageManager().getInstallerPackageName(BuildConfig.APPLICATION_ID); - return !InputHelper.isEmpty(ipn); - } - - public static boolean isGoogleAvailable(@NonNull Context context) { - ApplicationInfo applicationInfo = null; - try { - applicationInfo = context.getPackageManager().getApplicationInfo("com.google.android.gms", 0); - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - } - return applicationInfo != null && applicationInfo.enabled && - GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS; - } - - public static boolean isDeviceAnimationEnabled(@NonNull Context context) { - float duration = Settings.Global.getFloat(context.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1); - float transition = Settings.Global.getFloat(context.getContentResolver(), Settings.Global.TRANSITION_ANIMATION_SCALE, 1); - return (duration != 0 && transition != 0); - } - - public static boolean isDataPlan() { - final ConnectivityManager connectivityManager = (ConnectivityManager) App.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE); - if (connectivityManager != null) { - final android.net.NetworkInfo mobile = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); - return mobile.isConnectedOrConnecting(); - } - return false; - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/helper/BundleConstant.java b/app/src/main/java/com/fastaccess/helper/BundleConstant.java deleted file mode 100644 index 2360472ea..000000000 --- a/app/src/main/java/com/fastaccess/helper/BundleConstant.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.fastaccess.helper; - -import android.support.annotation.StringDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import static com.fastaccess.helper.BundleConstant.ExtraType.EDIT_COMMIT_COMMENT_EXTRA; -import static com.fastaccess.helper.BundleConstant.ExtraType.EDIT_GIST_COMMENT_EXTRA; -import static com.fastaccess.helper.BundleConstant.ExtraType.EDIT_ISSUE_COMMENT_EXTRA; -import static com.fastaccess.helper.BundleConstant.ExtraType.EDIT_REVIEW_COMMENT_EXTRA; -import static com.fastaccess.helper.BundleConstant.ExtraType.FOR_RESULT_EXTRA; -import static com.fastaccess.helper.BundleConstant.ExtraType.NEW_COMMIT_COMMENT_EXTRA; -import static com.fastaccess.helper.BundleConstant.ExtraType.NEW_GIST_COMMENT_EXTRA; -import static com.fastaccess.helper.BundleConstant.ExtraType.NEW_ISSUE_COMMENT_EXTRA; -import static com.fastaccess.helper.BundleConstant.ExtraType.NEW_REVIEW_COMMENT_EXTRA; - -/** - * Created by Kosh on 12 Nov 2016, 3:55 PM - */ - -public class BundleConstant { - public static final String ITEM = "item"; - public static final String ID = "id"; - public static final String EXTRA = "extra"; - public static final String EXTRA_TWO = "extra2_id"; - public static final String EXTRA_THREE = "extra3_id"; - public static final String EXTRA_FOUR = "extra4_id"; - public static final String EXTRA_FIVE = "extra5_id"; - public static final String EXTRA_SIX = "extra6_id"; - public static final String EXTRA_SEVEN = "extra7_id"; - public static final String EXTRA_EIGHT = "extra8_id"; - public static final String EXTRA_TYPE = "extra_type"; - public static final String YES_NO_EXTRA = "yes_no_extra"; - public static final String NOTIFICATION_ID = "notification_id"; - public static final String IS_ENTERPRISE = "is_enterprise"; - public static final String REVIEW_EXTRA = "review_extra"; - public static final String SCHEME_URL = "scheme_url"; - public static final int REQUEST_CODE = 2016; - public static final int REVIEW_REQUEST_CODE = 2017; - public static int REFRESH_CODE = 64; - - - @StringDef({ - FOR_RESULT_EXTRA, - EDIT_GIST_COMMENT_EXTRA, - NEW_GIST_COMMENT_EXTRA, - EDIT_ISSUE_COMMENT_EXTRA, - NEW_ISSUE_COMMENT_EXTRA, - EDIT_COMMIT_COMMENT_EXTRA, - NEW_COMMIT_COMMENT_EXTRA, - NEW_REVIEW_COMMENT_EXTRA, - EDIT_REVIEW_COMMENT_EXTRA - }) - - @Retention(RetentionPolicy.SOURCE) public @interface ExtraType { - String FOR_RESULT_EXTRA = "for_result_extra"; - String EDIT_GIST_COMMENT_EXTRA = "edit_comment_extra"; - String NEW_GIST_COMMENT_EXTRA = "new_gist_comment_extra"; - String EDIT_ISSUE_COMMENT_EXTRA = "edit_issue_comment_extra"; - String NEW_ISSUE_COMMENT_EXTRA = "new_issue_comment_extra"; - String EDIT_COMMIT_COMMENT_EXTRA = "edit_commit_comment_extra"; - String NEW_COMMIT_COMMENT_EXTRA = "new_commit_comment_extra"; - String NEW_REVIEW_COMMENT_EXTRA = "new_review_comment_extra"; - String EDIT_REVIEW_COMMENT_EXTRA = "edit_review_comment_extra"; - } -} diff --git a/app/src/main/java/com/fastaccess/helper/Bundler.java b/app/src/main/java/com/fastaccess/helper/Bundler.java deleted file mode 100644 index 0ceb5bb4b..000000000 --- a/app/src/main/java/com/fastaccess/helper/Bundler.java +++ /dev/null @@ -1,239 +0,0 @@ -package com.fastaccess.helper; - -import android.os.Bundle; -import android.os.IBinder; -import android.os.Parcel; -import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.util.SparseArray; - -import java.io.Serializable; -import java.util.ArrayList; - -/** - * Created by Kosh on 23 May 2016, 3:37 PM - */ - -public class Bundler { - - private final Bundle bundle; - - private Bundler() { - bundle = new Bundle(); - } - - public static Bundler start() { - return new Bundler(); - } - - public Bundler put(@NonNull String key, boolean value) { - bundle.putBoolean(key, value); - return this; - } - - public Bundler put(@NonNull String key, boolean[] value) { - bundle.putBooleanArray(key, value); - return this; - } - - public Bundler put(@NonNull String key, IBinder value) { - // Uncommment this line if your minimum sdk version is API level 18 - //start.putBinder(key, value); - return this; - } - - public Bundler put(@NonNull String key, int value) { - bundle.putInt(key, value); - return this; - } - - public Bundler put(@NonNull String key, int[] value) { - bundle.putIntArray(key, value); - return this; - } - - public Bundler putIntegerArrayList(@NonNull String key, ArrayList value) { - bundle.putIntegerArrayList(key, value); - return this; - } - - public Bundler put(@NonNull String key, Bundle value) { - bundle.putBundle(key, value); - return this; - } - - public Bundler put(@NonNull String key, byte value) { - bundle.putByte(key, value); - return this; - } - - public Bundler put(@NonNull String key, byte[] value) { - bundle.putByteArray(key, value); - return this; - } - - public Bundler put(@NonNull String key, String value) { - bundle.putString(key, value); - return this; - } - - public Bundler put(@NonNull String key, String[] value) { - bundle.putStringArray(key, value); - return this; - } - - public Bundler putStringArrayList(@NonNull String key, ArrayList value) { - bundle.putStringArrayList(key, value); - return this; - } - - public Bundler put(@NonNull String key, long value) { - bundle.putLong(key, value); - return this; - } - - public Bundler put(@NonNull String key, long[] value) { - bundle.putLongArray(key, value); - return this; - } - - public Bundler put(@NonNull String key, float value) { - bundle.putFloat(key, value); - return this; - } - - public Bundler put(@NonNull String key, float[] value) { - bundle.putFloatArray(key, value); - return this; - } - - public Bundler put(@NonNull String key, char value) { - bundle.putChar(key, value); - return this; - } - - public Bundler put(@NonNull String key, char[] value) { - bundle.putCharArray(key, value); - return this; - } - - public Bundler put(@NonNull String key, CharSequence value) { - bundle.putCharSequence(key, value); - return this; - } - - public Bundler put(@NonNull String key, CharSequence[] value) { - bundle.putCharSequenceArray(key, value); - return this; - } - - public Bundler putCharSequenceArrayList(@NonNull String key, ArrayList value) { - bundle.putCharSequenceArrayList(key, value); - return this; - } - - public Bundler put(@NonNull String key, double value) { - bundle.putDouble(key, value); - return this; - } - - public Bundler put(@NonNull String key, double[] value) { - bundle.putDoubleArray(key, value); - return this; - } - - public Bundler put(@NonNull String key, Parcelable value) { - Bundle safeBundle = new Bundle(); - safeBundle.putParcelable(key, value); - if (isValidBundleSize(safeBundle)) { - bundle.putParcelable(key, value); - } - clearBundle(safeBundle); - return this; - } - - public Bundler put(@NonNull String key, Parcelable[] value) { - Bundle safeBundle = new Bundle(); - safeBundle.putParcelableArray(key, value); - if (isValidBundleSize(safeBundle)) { - bundle.putParcelableArray(key, value); - } - clearBundle(safeBundle); - return this; - } - - public Bundler putParcelableArrayList(@NonNull String key, ArrayList value) { - Bundle safeBundle = new Bundle(); - safeBundle.putParcelableArrayList(key, value); - if (isValidBundleSize(safeBundle)) { - bundle.putParcelableArrayList(key, value); - } - clearBundle(safeBundle); - return this; - } - - public Bundler putSparseParcelableArray(@NonNull String key, SparseArray value) { - Bundle safeBundle = new Bundle(); - safeBundle.putSparseParcelableArray(key, value); - if (isValidBundleSize(safeBundle)) { - bundle.putSparseParcelableArray(key, value); - } - clearBundle(safeBundle); - return this; - } - - public Bundler put(@NonNull String key, short value) { - bundle.putShort(key, value); - return this; - } - - public Bundler put(@NonNull String key, short[] value) { - bundle.putShortArray(key, value); - return this; - } - - public Bundler put(@NonNull String key, Serializable value) { - Bundle safeBundle = new Bundle(); - safeBundle.putSerializable(key, value); - if (isValidBundleSize(safeBundle)) { - bundle.putSerializable(key, value); - } - clearBundle(safeBundle); - return this; - } - - public Bundler putAll(Bundle map) { - bundle.putAll(map); - return this; - } - - /** - * Get the underlying start. - */ - private Bundle get() { - return bundle; - } - - @NonNull public Bundle end() { - Parcel parcel = Parcel.obtain(); - bundle.writeToParcel(parcel, 0); - int size = parcel.dataSize(); - Logger.e(size); - if (size > 500000) { - bundle.clear(); - } - return get(); - } - - public static boolean isValidBundleSize(@NonNull Bundle bundle) { - Parcel parcel = Parcel.obtain(); - bundle.writeToParcel(parcel, 0); - return parcel.dataSize() < 500000; - } - - private void clearBundle(Bundle safeBundle) { - safeBundle.clear(); - safeBundle = null; - } - -} diff --git a/app/src/main/java/com/fastaccess/helper/CustomTabsHelper.java b/app/src/main/java/com/fastaccess/helper/CustomTabsHelper.java deleted file mode 100644 index 722820ed4..000000000 --- a/app/src/main/java/com/fastaccess/helper/CustomTabsHelper.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.fastaccess.helper; - -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.net.Uri; -import android.text.TextUtils; -import android.util.Log; - -import java.util.ArrayList; -import java.util.List; - -class CustomTabsHelper { - private static final String TAG = "CustomTabsHelper"; - private static final String STABLE_PACKAGE = "com.android.chrome"; - private static final String BETA_PACKAGE = "com.chrome.beta"; - private static final String DEV_PACKAGE = "com.chrome.dev"; - private static final String LOCAL_PACKAGE = "com.google.android.apps.chrome"; - private static final String ACTION_CUSTOM_TABS_CONNECTION = - "android.support.customtabs.action.CustomTabsService"; - - private static String sPackageNameToUse; - - private CustomTabsHelper() {} - - /** - * Goes through all apps that handle VIEW intents and have a warmup service. Picks - * the one chosen by the user if there is one, otherwise makes a best effort to return a - * valid package name. - *

    - * This is not threadsafe. - * - * @param context - * {@link Context} to use for accessing {@link PackageManager}. - * @return The package name recommended to use for connecting to custom tabs related components. - */ - static String getPackageNameToUse(Context context) { - if (sPackageNameToUse != null) return sPackageNameToUse; - - PackageManager pm = context.getPackageManager(); - // Get default VIEW intent handler. - Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com")); - ResolveInfo defaultViewHandlerInfo = pm.resolveActivity(activityIntent, 0); - String defaultViewHandlerPackageName = null; - if (defaultViewHandlerInfo != null) { - defaultViewHandlerPackageName = defaultViewHandlerInfo.activityInfo.packageName; - } - - // Get all apps that can handle VIEW intents. - List resolvedActivityList = pm.queryIntentActivities(activityIntent, 0); - List packagesSupportingCustomTabs = new ArrayList<>(); - for (ResolveInfo info : resolvedActivityList) { - Intent serviceIntent = new Intent(); - serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION); - serviceIntent.setPackage(info.activityInfo.packageName); - if (pm.resolveService(serviceIntent, 0) != null) { - packagesSupportingCustomTabs.add(info.activityInfo.packageName); - } - } - - // Now packagesSupportingCustomTabs contains all apps that can handle both VIEW intents - // and service calls. - if (packagesSupportingCustomTabs.isEmpty()) { - sPackageNameToUse = null; - } else if (packagesSupportingCustomTabs.size() == 1) { - sPackageNameToUse = packagesSupportingCustomTabs.get(0); - } else if (!TextUtils.isEmpty(defaultViewHandlerPackageName) - && !hasSpecializedHandlerIntents(context, activityIntent) - && packagesSupportingCustomTabs.contains(defaultViewHandlerPackageName)) { - sPackageNameToUse = defaultViewHandlerPackageName; - } else if (packagesSupportingCustomTabs.contains(STABLE_PACKAGE)) { - sPackageNameToUse = STABLE_PACKAGE; - } else if (packagesSupportingCustomTabs.contains(BETA_PACKAGE)) { - sPackageNameToUse = BETA_PACKAGE; - } else if (packagesSupportingCustomTabs.contains(DEV_PACKAGE)) { - sPackageNameToUse = DEV_PACKAGE; - } else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) { - sPackageNameToUse = LOCAL_PACKAGE; - } - return sPackageNameToUse; - } - - /** - * Used to check whether there is a specialized handler for a given intent. - * - * @param intent - * The intent to check with. - * @return Whether there is a specialized handler for the given intent. - */ - private static boolean hasSpecializedHandlerIntents(Context context, Intent intent) { - try { - PackageManager pm = context.getPackageManager(); - List handlers = pm.queryIntentActivities( - intent, - PackageManager.GET_RESOLVED_FILTER); - if (handlers == null || handlers.size() == 0) { - return false; - } - for (ResolveInfo resolveInfo : handlers) { - IntentFilter filter = resolveInfo.filter; - if (filter == null) continue; - if (filter.countDataAuthorities() == 0 || filter.countDataPaths() == 0) continue; - if (resolveInfo.activityInfo == null) continue; - return true; - } - } catch (RuntimeException e) { - Log.e(TAG, "Runtime exception while getting specialized handlers"); - } - return false; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/helper/DeviceNameGetter.java b/app/src/main/java/com/fastaccess/helper/DeviceNameGetter.java deleted file mode 100644 index 57f7cd020..000000000 --- a/app/src/main/java/com/fastaccess/helper/DeviceNameGetter.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.fastaccess.helper; - -import android.os.Build; - -import com.fastaccess.App; -import com.jaredrummler.android.device.DeviceName; - -import io.reactivex.Observable; - -/** - * Created by Front Desk on 8/7/2017. - */ - -public class DeviceNameGetter { - private static final DeviceNameGetter ourInstance = new DeviceNameGetter(); - private String deviceName; - - public static DeviceNameGetter getInstance() { - return ourInstance; - } - - private DeviceNameGetter() {} - - public void loadDevice() { - DeviceName.with(App.getInstance()) - .request((info, error) -> { - if (error == null && null != info) { - deviceName = info.marketName; - } - }); - } - - String getDeviceName() { - if (deviceName == null) { - deviceName = blockingDeviceName(); - } - return deviceName; - } - - private String blockingDeviceName() { - return (String) Observable.fromPublisher(s -> { - DeviceName.with(App.getInstance()) - .request((info, error) -> { - if (error == null && info != null) s.onNext(info.marketName); - else s.onError(error); - }); - s.onComplete(); - }).blockingFirst(Build.MODEL); - } -} diff --git a/app/src/main/java/com/fastaccess/helper/FileHelper.java b/app/src/main/java/com/fastaccess/helper/FileHelper.java deleted file mode 100644 index 2b281396d..000000000 --- a/app/src/main/java/com/fastaccess/helper/FileHelper.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.fastaccess.helper; - -import android.content.Context; -import android.database.Cursor; -import android.media.Ringtone; -import android.media.RingtoneManager; -import android.net.Uri; -import android.os.Environment; -import android.provider.DocumentsContract; -import android.provider.MediaStore; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.R; -import com.fastaccess.data.dao.NotificationSoundModel; - -import java.io.File; -import java.util.ArrayList; - -/** - * Created by kosh20111 on 10/7/2015. CopyRights @ - */ -public class FileHelper { - - public static final String PATH = Environment.getExternalStorageDirectory() + File.separator + "FastHub"; - - public static final long ONE_MB = 1048576L; - - @Nullable public static String getPath(@NonNull Context context, @NonNull Uri uri) { - String filePath = null; - try { - String wholeID = DocumentsContract.getDocumentId(uri); - String id = wholeID.split(":")[1]; - String[] column = {MediaStore.Images.Media.DATA}; - String sel = MediaStore.Images.Media._ID + "=?"; - try (Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - column, sel, new String[]{id}, null)) { - if (cursor != null) { - int columnIndex = cursor.getColumnIndex(column[0]); - if (cursor.moveToFirst()) { - filePath = cursor.getString(columnIndex); - } - } - } - } catch (Exception ignored) {} - return filePath; - } - - @NonNull public static String getRingtoneName(@NonNull Context context, @Nullable Uri uri) { - String title = context.getString(R.string.sound_chooser_summary); - if (uri != null) { - Ringtone ringtone = RingtoneManager.getRingtone(context, uri); - if (ringtone != null) { - return ringtone.getTitle(context); - } else { - try (Cursor cur = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, - new String[]{MediaStore.Audio.Media.TITLE}, MediaStore.Audio.Media._ID + " =?", - new String[]{uri.getLastPathSegment()}, null)) { - if (cur != null) { - title = cur.getString(1); - if (InputHelper.isEmpty(title)) { - title = cur.getString(cur.getColumnIndex(MediaStore.Audio.Media.TITLE)); - } - } - } catch (Exception ignored) {} - } - } - return title; - } - - public static ArrayList getNotificationSounds(Context context, @Nullable String defaultValue) { - ArrayList notificationSounds = new ArrayList<>(); - RingtoneManager ringtoneManager = new RingtoneManager(context); - ringtoneManager.setType(RingtoneManager.TYPE_NOTIFICATION); - try (Cursor ringsCursor = ringtoneManager.getCursor()) { - while (ringsCursor.moveToNext()) { - String title = ringsCursor.getString(RingtoneManager.TITLE_COLUMN_INDEX); - Uri uri = Uri.parse(ringsCursor.getString(RingtoneManager.URI_COLUMN_INDEX) + "/" - + ringsCursor.getString(RingtoneManager.ID_COLUMN_INDEX)); - boolean selected = defaultValue != null && (uri.toString().contains(defaultValue) || - title.equalsIgnoreCase(defaultValue) || defaultValue.contains(title)); - Logger.e(defaultValue, title, uri, selected); - notificationSounds.add(new NotificationSoundModel(title, uri, selected)); - } - } - return notificationSounds; - } - - -} diff --git a/app/src/main/java/com/fastaccess/helper/GithubConfigHelper.java b/app/src/main/java/com/fastaccess/helper/GithubConfigHelper.java deleted file mode 100644 index ebe7a7454..000000000 --- a/app/src/main/java/com/fastaccess/helper/GithubConfigHelper.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.fastaccess.helper; - -import com.fastaccess.BuildConfig; - -/** - * Created by thermatk on 12.04.17. - */ - -public class GithubConfigHelper { - private static final String REDIRECT_URL = "fasthub://login"; - - public static String getRedirectUrl() { - return REDIRECT_URL; - } - - public static String getClientId() { - return BuildConfig.GITHUB_CLIENT_ID; - } - - public static String getSecret() { - return BuildConfig.GITHUB_SECRET; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/helper/InputHelper.java b/app/src/main/java/com/fastaccess/helper/InputHelper.java deleted file mode 100644 index f838e0452..000000000 --- a/app/src/main/java/com/fastaccess/helper/InputHelper.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.fastaccess.helper; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TextInputLayout; -import android.text.TextUtils; -import android.widget.EditText; -import android.widget.TextView; - -/** - * Created by kosh20111 on 3/11/2015. CopyRights @ - *

    - * Input Helper to validate stuff related to input fields. - */ -public class InputHelper { - - public static final String SPACE = "\u202F\u202F"; - - private static boolean isWhiteSpaces(@Nullable String s) { - return s != null && s.matches("\\s+"); - } - - public static boolean isEmpty(@Nullable String text) { - return text == null || TextUtils.isEmpty(text) || isWhiteSpaces(text) || text.equalsIgnoreCase("null"); - } - - public static boolean isEmpty(@Nullable Object text) { - return text == null || isEmpty(text.toString()); - } - - public static boolean isEmpty(@Nullable EditText text) { - return text == null || isEmpty(text.getText().toString()); - } - - public static boolean isEmpty(@Nullable TextView text) { - return text == null || isEmpty(text.getText().toString()); - } - - public static boolean isEmpty(@Nullable TextInputLayout txt) { - return txt == null || isEmpty(txt.getEditText()); - } - - public static String toString(@NonNull EditText editText) { - return editText.getText().toString(); - } - - public static String toString(@NonNull TextView editText) { - return editText.getText().toString(); - } - - public static String toString(@NonNull TextInputLayout textInputLayout) { - return textInputLayout.getEditText() != null ? toString(textInputLayout.getEditText()) : ""; - } - - @NonNull public static String toNA(@Nullable String value) { - return isEmpty(value) ? "N/A" : value; - } - - @NonNull public static String toString(@Nullable Object object) { - return !isEmpty(object) ? object.toString() : ""; - } - - public static long toLong(@NonNull TextView textView) { - return toLong(toString(textView)); - } - - public static long toLong(@NonNull String text) { - if (!isEmpty(text)) { - try { - return Long.valueOf(text.replaceAll("[^0-9]", "")); - } catch (NumberFormatException ignored) {} - } - return 0; - } - - public static int getSafeIntId(long id) { - return id > Integer.MAX_VALUE ? (int) (id - Integer.MAX_VALUE) : (int) id; - } - - public static String capitalizeFirstLetter(String s) { - if (isEmpty(s)) { - return ""; - } - char first = s.charAt(0); - if (Character.isUpperCase(first)) { - return s; - } else { - return Character.toUpperCase(first) + s.substring(1); - } - } -} diff --git a/app/src/main/java/com/fastaccess/helper/Logger.java b/app/src/main/java/com/fastaccess/helper/Logger.java deleted file mode 100644 index f00ea1193..000000000 --- a/app/src/main/java/com/fastaccess/helper/Logger.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.fastaccess.helper; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.Log; - -import com.fastaccess.BuildConfig; - -import java.util.Arrays; -import java.util.List; - -/** - * Created by Kosh on 04/12/15 11:52 PM. copyrights @ - */ -public class Logger { - - private final static String TAG = Logger.class.getSimpleName(); - - private static final boolean DEBUG = BuildConfig.DEBUG; - - private static void e(@NonNull String tag, @Nullable Object text) { - if (!DEBUG) return; - Log.e(tag, text != null ? text.toString() : "LOGGER IS NULL");//avoid null - } - - private static void d(@NonNull String tag, @Nullable Object text) { - if (!DEBUG) return; - Log.d(tag, text != null ? text.toString() : "LOGGER IS NULL");//avoid null - } - - private static void i(@NonNull String tag, @Nullable Object text) { - if (!DEBUG) return; - Log.i(tag, text != null ? text.toString() : "LOGGER IS NULL");//avoid null - } - - public static void d(@Nullable Object text) { - d(getCurrentClassName() + " || " + getCurrentMethodName(), text);//avoid null - } - - public static void i(@Nullable Object text) { - i(getCurrentClassName() + " || " + getCurrentMethodName(), text);//avoid null - } - - public static void e(Object... objects) { - if (objects != null && objects.length > 0) { - e(getCurrentClassName() + " || " + getCurrentMethodName(), Arrays.toString(objects)); - } else { - e(getCurrentClassName() + " || " + getCurrentMethodName(), getCurrentMethodName()); - } - } - - public static void e(List objects) { - if (objects != null) { - e(getCurrentClassName() + " || " + getCurrentMethodName(), Arrays.toString(objects.toArray())); - } else { - e(TAG, null); - } - } - - private static String getCurrentMethodName() { - try { - return Thread.currentThread().getStackTrace()[4].getMethodName() + "()"; - } catch (Exception ignored) {} - return TAG; - } - - private static String getCurrentClassName() { - try { - String className = Thread.currentThread().getStackTrace()[4].getClassName(); - String[] temp = className.split("[.]"); - className = temp[temp.length - 1]; - return className; - } catch (Exception ignored) {} - return TAG; - } -} diff --git a/app/src/main/java/com/fastaccess/helper/ObjectsCompat.java b/app/src/main/java/com/fastaccess/helper/ObjectsCompat.java deleted file mode 100644 index 34f709f27..000000000 --- a/app/src/main/java/com/fastaccess/helper/ObjectsCompat.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.helper; - -import android.support.annotation.Nullable; - -/** - * Created by Kosh on 18 Apr 2017, 10:57 PM - */ - -public class ObjectsCompat { - - public static boolean nonNull(@Nullable Object obj) { - return obj != null; - } -} diff --git a/app/src/main/java/com/fastaccess/helper/ParcelableHelper.kt b/app/src/main/java/com/fastaccess/helper/ParcelableHelper.kt deleted file mode 100644 index 224faeb59..000000000 --- a/app/src/main/java/com/fastaccess/helper/ParcelableHelper.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.fastaccess.helper - -import android.os.Parcel -import android.os.Parcelable - -interface KotlinParcelable : Parcelable { - override fun describeContents() = 0 - override fun writeToParcel(dest: Parcel, flags: Int) -} - -inline fun parcelableCreator(crossinline create: (Parcel) -> T) = object : Parcelable.Creator { - override fun createFromParcel(source: Parcel) = create(source) - override fun newArray(size: Int) = arrayOfNulls(size) -} - -fun Parcel.readBoolean() = readInt() != 0 - -fun Parcel.writeBoolean(value: Boolean) = writeInt(if (value) 1 else 0) diff --git a/app/src/main/java/com/fastaccess/helper/ParseDateFormat.java b/app/src/main/java/com/fastaccess/helper/ParseDateFormat.java deleted file mode 100644 index eba702cc5..000000000 --- a/app/src/main/java/com/fastaccess/helper/ParseDateFormat.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.fastaccess.helper; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.format.DateUtils; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; - -public class ParseDateFormat { - - private static final ParseDateFormat INSTANCE = new ParseDateFormat(); - - private final Object lock = new Object(); - - private final DateFormat dateFormat; - - private ParseDateFormat() { - dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); - dateFormat.setTimeZone(TimeZone.getDefault()); - } - - @NonNull public String format(Date date) { - synchronized (lock) { - return dateFormat.format(date); - } - } - - - @NonNull public static CharSequence getTimeAgo(@Nullable String toParse) { - try { - Date parsedDate = getInstance().dateFormat.parse(toParse); - long now = System.currentTimeMillis(); - return DateUtils.getRelativeTimeSpanString(parsedDate.getTime(), now, DateUtils.SECOND_IN_MILLIS); - } catch (Exception e) { - e.printStackTrace(); - } - return "N/A"; - } - - @NonNull public static CharSequence getTimeAgo(@Nullable Date parsedDate) { - if (parsedDate != null) { - long now = System.currentTimeMillis(); - return DateUtils.getRelativeTimeSpanString(parsedDate.getTime(), now, DateUtils.SECOND_IN_MILLIS); - } - return "N/A"; - } - - @NonNull public static String toGithubDate(@NonNull Date date) { - return getInstance().format(date); - } - - @NonNull public static String prettifyDate(long timestamp) { - return new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH).format(new Date(timestamp)); - } - - @Nullable public static Date getDateFromString(@NonNull String date) { - try { - return new SimpleDateFormat("dd-MM-yyyy", Locale.US).parse(date); - } catch (ParseException e) { - e.printStackTrace(); - } - return null; - } - - @NonNull private static ParseDateFormat getInstance() { - return INSTANCE; - } - - private static String getDateByDays(int days) { - Calendar cal = Calendar.getInstance(); - SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); - cal.add(Calendar.DAY_OF_YEAR, days); - return s.format(new Date(cal.getTimeInMillis())); - } - - public static String getLastWeekDate() { - return getDateByDays(-7); - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/helper/PrefGetter.java b/app/src/main/java/com/fastaccess/helper/PrefGetter.java deleted file mode 100644 index 5e72b8d30..000000000 --- a/app/src/main/java/com/fastaccess/helper/PrefGetter.java +++ /dev/null @@ -1,519 +0,0 @@ -package com.fastaccess.helper; - -import android.content.Context; -import android.content.res.Resources; -import android.media.RingtoneManager; -import android.net.Uri; -import android.support.annotation.IntDef; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.App; -import com.fastaccess.BuildConfig; -import com.fastaccess.R; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * Created by Kosh on 10 Nov 2016, 3:43 PM - */ - -public class PrefGetter { - - public static final int LIGHT = 1; - public static final int DARK = 2; - public static final int AMLOD = 3; - public static final int BLUISH = 4; - public static final int MID_NIGHT_BLUE = 5; - - public static final int RED = 1; - public static final int PINK = 2; - public static final int PURPLE = 3; - public static final int DEEP_PURPLE = 4; - public static final int INDIGO = 5; - public static final int BLUE = 6; - public static final int LIGHT_BLUE = 7; - public static final int CYAN = 8; - public static final int TEAL = 9; - public static final int GREEN = 10; - public static final int LIGHT_GREEN = 11; - public static final int LIME = 12; - public static final int YELLOW = 13; - public static final int AMBER = 14; - public static final int ORANGE = 15; - public static final int DEEP_ORANGE = 16; - - @IntDef({ - LIGHT, - DARK, - AMLOD, - MID_NIGHT_BLUE, - BLUISH - }) - @Retention(RetentionPolicy.SOURCE) public @interface ThemeType {} - - @IntDef({ - RED, - PINK, - PURPLE, - DEEP_PURPLE, - INDIGO, - BLUE, - LIGHT_BLUE, - CYAN, - TEAL, - GREEN, - LIGHT_GREEN, - LIME, - YELLOW, - AMBER, - ORANGE, - DEEP_ORANGE - }) - @Retention(RetentionPolicy.SOURCE) @interface ThemeColor {} - - - private static final String WHATS_NEW_VERSION = "whats_new"; - private static final String ADS = "enable_ads"; - private static final String TOKEN = "token"; - private static final String ENTERPRISE_TOKEN = "enterprise_token"; - private static final String USER_ICON_GUIDE = "user_icon_guide"; - private static final String RELEASE_GUIDE = "release_guide"; - private static final String FILE_OPTION_GUIDE = "file_option_guide"; - private static final String COMMENTS_GUIDE = "comments_guide"; - private static final String REPO_GUIDE = "repo_guide"; - private static final String MARKDOWNDOWN_GUIDE = "markdowndown_guide"; - private static final String HOME_BUTTON_GUIDE = "home_button_guide"; - private static final String NAV_DRAWER_GUIDE = "nav_drawer_guide"; - private static final String ACC_NAV_DRAWER_GUIDE = "acc_nav_drawer_guide"; - private static final String FAB_LONG_PRESS_REPO_GUIDE = "fab_long_press_repo_guide"; - private static final String WRAP_CODE = "wrap_code"; - private static final String OTP_CODE = "otp_code"; - private static final String ENTERPRISE_OTP_CODE = "enterprise_otp_code"; - private static final String APP_LANGUAGE = "app_language"; - private static final String SENT_VIA = "fasthub_signature"; - private static final String SENT_VIA_BOX = "sent_via_enabled"; - private static final String PROFILE_BACKGROUND_URL = "profile_background_url"; - private static final String AMLOD_THEME_ENABLED = "amlod_theme_enabled"; - private static final String MIDNIGHTBLUE_THEME_ENABLED = "midnightblue_theme_enabled"; - private static final String BLUISH_THEME_ENABLED = "bluish_theme_enabled"; - private static final String PRO_ITEMS = "fasth_pro_items"; - private static final String ENTERPRISE_ITEM = "enterprise_item"; - private static final String CODE_THEME = "code_theme"; - private static final String ENTERPRISE_URL = "enterprise_url"; - private static final String NOTIFICATION_SOUND_PATH = "notification_sound_path"; - private static final String DISABLE_AUTO_LOAD_IMAGE = "disable_auto_loading_image"; - private static final String PLAY_STORE_REVIEW_ACTIVITY = "play_store_review_activity"; - - public static void setToken(@Nullable String token) { - PrefHelper.set(TOKEN, token); - } - - public static void setTokenEnterprise(@Nullable String token) { - PrefHelper.set(ENTERPRISE_TOKEN, token); - } - - public static String getToken() { - return PrefHelper.getString(TOKEN); - } - - public static String getEnterpriseToken() { - return PrefHelper.getString(ENTERPRISE_TOKEN); - } - - public static String getEnterpriseOtpCode() { - return PrefHelper.getString(ENTERPRISE_OTP_CODE); - } - - public static void setEnterpriseOtpCode(@Nullable String otp) { - PrefHelper.set(ENTERPRISE_OTP_CODE, otp); - } - - public static String getOtpCode() { - return PrefHelper.getString(OTP_CODE); - } - - public static void setOtpCode(@Nullable String otp) { - PrefHelper.set(OTP_CODE, otp); - } - - public static boolean isAdsEnabled() { - return PrefHelper.getBoolean(ADS); - } - - public static void setAdsEnabled(boolean isEnabled) { - PrefHelper.set(ADS, isEnabled); - } - - public static void clear() { - PrefHelper.clearPrefs(); - } - - @SuppressWarnings("BooleanMethodIsAlwaysInverted") public static boolean isUserIconGuideShowed() { - boolean isShowed = PrefHelper.getBoolean(USER_ICON_GUIDE); - PrefHelper.set(USER_ICON_GUIDE, true); - return isShowed; - } - - public static boolean isReleaseHintShow() { - boolean isShowed = PrefHelper.getBoolean(RELEASE_GUIDE); - PrefHelper.set(RELEASE_GUIDE, true); - return isShowed; - } - - public static boolean isFileOptionHintShow() { - boolean isShowed = PrefHelper.getBoolean(FILE_OPTION_GUIDE); - PrefHelper.set(FILE_OPTION_GUIDE, true); - return isShowed; - } - - public static boolean isCommentHintShowed() { - boolean isShowed = PrefHelper.getBoolean(COMMENTS_GUIDE); - PrefHelper.set(COMMENTS_GUIDE, true); - return isShowed; - } - - public static boolean isHomeButoonHintShowed() { - boolean isShowed = PrefHelper.getBoolean(HOME_BUTTON_GUIDE); - PrefHelper.set(HOME_BUTTON_GUIDE, true); - return isShowed; - } - - public static boolean isRepoGuideShowed() { - boolean isShowed = PrefHelper.getBoolean(REPO_GUIDE); - PrefHelper.set(REPO_GUIDE, true); - return isShowed; - } - - public static boolean isEditorHintShowed() { - boolean isShowed = PrefHelper.getBoolean(MARKDOWNDOWN_GUIDE); - PrefHelper.set(MARKDOWNDOWN_GUIDE, true); - return isShowed; - } - - public static boolean isNavDrawerHintShowed() { - boolean isShowed = PrefHelper.getBoolean(NAV_DRAWER_GUIDE); - PrefHelper.set(NAV_DRAWER_GUIDE, true); - return isShowed; - } - - public static boolean isAccountNavDrawerHintShowed() { - boolean isShowed = PrefHelper.getBoolean(ACC_NAV_DRAWER_GUIDE); - PrefHelper.set(ACC_NAV_DRAWER_GUIDE, true); - return isShowed; - } - - public static boolean isRepoFabHintShowed() { - boolean isShowed = PrefHelper.getBoolean(FAB_LONG_PRESS_REPO_GUIDE); - PrefHelper.set(FAB_LONG_PRESS_REPO_GUIDE, true); - return isShowed; - } - - public static boolean isRVAnimationEnabled() { - return PrefHelper.getBoolean("recylerViewAnimation"); - } - - public static int getNotificationTaskDuration() { - if (PrefHelper.isExist("notificationEnabled") && PrefHelper.getBoolean("notificationEnabled")) { - String prefValue = PrefHelper.getString("notificationTime"); - if (prefValue != null) { - return notificationDurationMillis(prefValue); - } - } - return -1; - } - - public static int notificationDurationMillis(@NonNull String prefValue) { - if (!InputHelper.isEmpty(prefValue)) { - switch (prefValue) { - case "1": - return 60; - case "5": - return 5 * 60; - case "10": - return 10 * 60; - case "20": - return 20 * 60; - case "30": - return 30 * 60; - case "60": - return 60 * 60; // 1 hour - case "120": - return (60 * 2) * 60; // 2 hours - case "180": - return (60 * 3) * 60; // 3 hours - } - } - return -1; - } - - public static boolean isTwiceBackButtonDisabled() { - return PrefHelper.getBoolean("back_button"); - } - - public static boolean isRectAvatar() { - return PrefHelper.getBoolean("rect_avatar"); - } - - @SuppressWarnings("BooleanMethodIsAlwaysInverted") public static boolean isMarkAsReadEnabled() { - return PrefHelper.getBoolean("markNotificationAsRead"); - } - - public static boolean isWrapCode() { - return PrefHelper.getBoolean(WRAP_CODE); - } - - public static boolean isSentViaEnabled() { - return PrefHelper.getBoolean(SENT_VIA); - } - - public static boolean isSentViaBoxEnabled() { - return PrefHelper.getBoolean(SENT_VIA_BOX); - } - - @ThemeType public static int getThemeType(@NonNull Context context) { - return getThemeType(context.getResources()); - } - - @ThemeType public static int getThemeType() { - return getThemeType(App.getInstance().getResources()); - } - - @ThemeColor public static int getThemeColor(@NonNull Context context) { - return getThemeColor(context.getResources()); - } - - @ThemeType static int getThemeType(@NonNull Resources resources) { - String appTheme = PrefHelper.getString("appTheme"); - if (!InputHelper.isEmpty(appTheme)) { - if (appTheme.equalsIgnoreCase(resources.getString(R.string.dark_theme_mode))) { - return DARK; - } else if (appTheme.equalsIgnoreCase(resources.getString(R.string.light_theme_mode))) { - return LIGHT; - } else if (appTheme.equalsIgnoreCase(resources.getString(R.string.amlod_theme_mode))) { - return AMLOD; - } else if (appTheme.equalsIgnoreCase(resources.getString(R.string.mid_night_blue_theme_mode))) { - return MID_NIGHT_BLUE; - } else if (appTheme.equalsIgnoreCase(resources.getString(R.string.bluish_theme))) { - return BLUISH; - } - } - return LIGHT; - } - - @ThemeColor private static int getThemeColor(@NonNull Resources resources) { - String appColor = PrefHelper.getString("appColor"); - return getThemeColor(resources, appColor); - } - - // used for color picker to get the index of the color (enum) from the name of the color - public static int getThemeColor(@NonNull Resources resources, String appColor) { - if (!InputHelper.isEmpty(appColor)) { - if (appColor.equalsIgnoreCase(resources.getString(R.string.red_theme_mode))) - return RED; - if (appColor.equalsIgnoreCase(resources.getString(R.string.pink_theme_mode))) - return PINK; - if (appColor.equalsIgnoreCase(resources.getString(R.string.purple_theme_mode))) - return PURPLE; - if (appColor.equalsIgnoreCase(resources.getString(R.string.deep_purple_theme_mode))) - return DEEP_PURPLE; - if (appColor.equalsIgnoreCase(resources.getString(R.string.indigo_theme_mode))) - return INDIGO; - if (appColor.equalsIgnoreCase(resources.getString(R.string.blue_theme_mode))) - return BLUE; - if (appColor.equalsIgnoreCase(resources.getString(R.string.light_blue_theme_mode))) - return LIGHT_BLUE; - if (appColor.equalsIgnoreCase(resources.getString(R.string.cyan_theme_mode))) - return CYAN; - if (appColor.equalsIgnoreCase(resources.getString(R.string.teal_theme_mode))) - return TEAL; - if (appColor.equalsIgnoreCase(resources.getString(R.string.green_theme_mode))) - return GREEN; - if (appColor.equalsIgnoreCase(resources.getString(R.string.light_green_theme_mode))) - return LIGHT_GREEN; - if (appColor.equalsIgnoreCase(resources.getString(R.string.lime_theme_mode))) - return LIME; - if (appColor.equalsIgnoreCase(resources.getString(R.string.yellow_theme_mode))) - return YELLOW; - if (appColor.equalsIgnoreCase(resources.getString(R.string.amber_theme_mode))) - return AMBER; - if (appColor.equalsIgnoreCase(resources.getString(R.string.orange_theme_mode))) - return ORANGE; - if (appColor.equalsIgnoreCase(resources.getString(R.string.deep_orange_theme_mode))) - return DEEP_ORANGE; - } - return BLUE; - } - - @NonNull public static String getAppLanguage() { - String appLanguage = PrefHelper.getString(APP_LANGUAGE); - return appLanguage == null ? "en" : appLanguage; - } - - public static void setAppLangauge(@Nullable String language) { - PrefHelper.set(APP_LANGUAGE, language == null ? "en" : language); - } - - public static void setProfileBackgroundUrl(@Nullable String url) { - if (url == null) { - PrefHelper.clearKey(PROFILE_BACKGROUND_URL); - } else { - PrefHelper.set(PROFILE_BACKGROUND_URL, url); - } - } - - @Nullable public static String getProfileBackgroundUrl() { - return PrefHelper.getString(PROFILE_BACKGROUND_URL); - } - - public static void setWhatsNewVersion() { - PrefHelper.set(WHATS_NEW_VERSION, BuildConfig.VERSION_CODE); - } - - public static boolean showWhatsNew() { - return PrefHelper.getInt(WHATS_NEW_VERSION) != BuildConfig.VERSION_CODE; - } - - public static boolean isNotificationSoundEnabled() { - return PrefHelper.getBoolean("notificationSound"); - } - - public static void enableAmlodTheme() { - PrefHelper.set(AMLOD_THEME_ENABLED, true); - } - - public static boolean isAmlodEnabled() { - return PrefHelper.getBoolean(AMLOD_THEME_ENABLED); - } - - public static void enableMidNightBlueTheme() { - PrefHelper.set(MIDNIGHTBLUE_THEME_ENABLED, true); - } - - public static boolean isMidNightBlueThemeEnabled() { - return PrefHelper.getBoolean(MIDNIGHTBLUE_THEME_ENABLED); - } - - public static boolean isBluishEnabled() { - return PrefHelper.getBoolean(BLUISH_THEME_ENABLED); - } - - public static void enableBluishTheme() { - PrefHelper.set(BLUISH_THEME_ENABLED, true); - } - - public static void setProItems() { - PrefHelper.set(PRO_ITEMS, true); - enableAmlodTheme(); - enableBluishTheme(); - enableMidNightBlueTheme(); - } - - public static void setEnterpriseItem() { - PrefHelper.set(ENTERPRISE_ITEM, true); - } - - public static boolean isEnterpriseEnabled() { - return PrefHelper.getBoolean(ENTERPRISE_ITEM); - } - - public static boolean isAllFeaturesUnlocked() { - return isProEnabled() && isEnterprise(); - } - - public static boolean isProEnabled() { - return PrefHelper.getBoolean(PRO_ITEMS); - } - - public static boolean hasSupported() { - return isProEnabled() || isAmlodEnabled() || isBluishEnabled(); - } - - public static String getCodeTheme() { - return PrefHelper.getString(CODE_THEME); - } - - public static void setCodeTheme(@NonNull String theme) { - PrefHelper.set(CODE_THEME, theme); - } - - public static String getEnterpriseUrl() { - return PrefHelper.getString(ENTERPRISE_URL); - } - - public static void setEnterpriseUrl(@Nullable String value) { - PrefHelper.set(ENTERPRISE_URL, value); - } - - public static boolean isEnterprise() { - return !InputHelper.isEmpty(getEnterpriseUrl()); - } - - public static boolean isNavBarTintingDisabled() { - return PrefHelper.getBoolean("navigation_color"); - } - - public static void resetEnterprise() { - PrefGetter.setTokenEnterprise(null); - PrefGetter.setEnterpriseOtpCode(null); - PrefGetter.setEnterpriseUrl(null); - } - - @Nullable public static Uri getNotificationSound() { - String nsp = PrefHelper.getString(NOTIFICATION_SOUND_PATH); - return !InputHelper.isEmpty(nsp) ? Uri.parse(nsp) : RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); - } - - public static void setNotificationSound(@NonNull Uri uri) { - PrefHelper.set(NOTIFICATION_SOUND_PATH, uri.toString()); - } - - public static boolean isAutoImageDisabled() { - return PrefHelper.getBoolean(DISABLE_AUTO_LOAD_IMAGE) && AppHelper.isDataPlan(); - } - - public static boolean isAppAnimationDisabled() { - return PrefHelper.getBoolean("app_animation"); - } - - public static boolean isPlayStoreWarningShowed() { - return PrefHelper.getBoolean(PLAY_STORE_REVIEW_ACTIVITY); - } - - public static void setPlayStoreWarningShowed() { - PrefHelper.set(PLAY_STORE_REVIEW_ACTIVITY, true); - } - - public static void clearPurchases() { - PrefHelper.set(PRO_ITEMS, false); - PrefHelper.set(BLUISH_THEME_ENABLED, false); - PrefHelper.set(AMLOD_THEME_ENABLED, false); - setEnterpriseUrl(null); - } - - public static boolean isFeedsHintShowed() { - boolean isFeedsHitShowed = PrefHelper.getBoolean("feeds_hint"); - if (!isFeedsHitShowed) { - PrefHelper.set("feeds_hint", true); - } - return isFeedsHitShowed; - } - - public static boolean isIssuesLongPressHintShowed() { - boolean isIssuesLongPressHintShowed = PrefHelper.getBoolean("issues_long_press_hint"); - if (!isIssuesLongPressHintShowed) { - PrefHelper.set("issues_long_press_hint", true); - } - return isIssuesLongPressHintShowed; - } - - public static boolean isPRLongPressHintShowed() { - boolean isPRLongPressHintShowed = PrefHelper.getBoolean("pr_long_press_hint"); - if (!isPRLongPressHintShowed) { - PrefHelper.set("pr_long_press_hint", true); - } - return isPRLongPressHintShowed; - } - -} diff --git a/app/src/main/java/com/fastaccess/helper/PrefHelper.java b/app/src/main/java/com/fastaccess/helper/PrefHelper.java deleted file mode 100644 index 74eadf203..000000000 --- a/app/src/main/java/com/fastaccess/helper/PrefHelper.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.fastaccess.helper; - -import android.annotation.SuppressLint; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.App; - -import java.util.Map; - -/** - * Created by kosh20111 on 19 Feb 2017, 2:01 AM - */ -public class PrefHelper { - - /** - * @param key - * ( the Key to used to retrieve this data later ) - * @param value - * ( any kind of primitive values ) - *

    - * non can be null!!! - */ - @SuppressLint("ApplySharedPref") public static void set(@NonNull String key, @Nullable T value) { - if (InputHelper.isEmpty(key)) { - throw new NullPointerException("Key must not be null! (key = " + key + "), (value = " + value + ")"); - } - SharedPreferences.Editor edit = PreferenceManager.getDefaultSharedPreferences(App.getInstance()).edit(); - if (InputHelper.isEmpty(value)) { - clearKey(key); - return; - } - if (value instanceof String) { - edit.putString(key, (String) value); - } else if (value instanceof Integer) { - edit.putInt(key, (Integer) value); - } else if (value instanceof Long) { - edit.putLong(key, (Long) value); - } else if (value instanceof Boolean) { - edit.putBoolean(key, (Boolean) value); - } else if (value instanceof Float) { - edit.putFloat(key, (Float) value); - } else { - edit.putString(key, value.toString()); - } - edit.commit();//apply on UI - } - - @Nullable public static String getString(@NonNull String key) { - return PreferenceManager.getDefaultSharedPreferences(App.getInstance()).getString(key, null); - } - - public static boolean getBoolean(@NonNull String key) { - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(App.getInstance()); - return preferences.getAll().get(key) instanceof Boolean && preferences.getBoolean(key, false); - } - - public static int getInt(@NonNull String key) { - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(App.getInstance()); - return preferences.getAll().get(key) instanceof Integer ? preferences.getInt(key, 0) : -1; - } - - public static long getLong(@NonNull String key) { - return PreferenceManager.getDefaultSharedPreferences(App.getInstance()).getLong(key, 0); - } - - public static float getFloat(@NonNull String key) { - return PreferenceManager.getDefaultSharedPreferences(App.getInstance()).getFloat(key, 0); - } - - public static void clearKey(@NonNull String key) { - PreferenceManager.getDefaultSharedPreferences(App.getInstance()).edit().remove(key).apply(); - } - - public static boolean isExist(@NonNull String key) { - return PreferenceManager.getDefaultSharedPreferences(App.getInstance()).contains(key); - } - - public static void clearPrefs() { - PreferenceManager.getDefaultSharedPreferences(App.getInstance()).edit().clear().apply(); - } - - public static Map getAll() { - return PreferenceManager.getDefaultSharedPreferences(App.getInstance()).getAll(); - } -} diff --git a/app/src/main/java/com/fastaccess/helper/RxHelper.java b/app/src/main/java/com/fastaccess/helper/RxHelper.java deleted file mode 100644 index 1cd29bea2..000000000 --- a/app/src/main/java/com/fastaccess/helper/RxHelper.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.fastaccess.helper; - -import android.support.annotation.NonNull; - -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.schedulers.Schedulers; - - -/** - * Created by Kosh on 11 Nov 2016, 11:53 AM - */ - -public class RxHelper { - public static Observable getObservable(@NonNull Observable observable) { - return observable - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()); - } - - public static Observable safeObservable(@NonNull Observable observable) { - return getObservable(observable) - .doOnError(Throwable::printStackTrace); - } - - public static Single getSingle(@NonNull Single single) { - return single - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()); - } -} diff --git a/app/src/main/java/com/fastaccess/helper/TypeFaceHelper.java b/app/src/main/java/com/fastaccess/helper/TypeFaceHelper.java deleted file mode 100644 index 6cc413711..000000000 --- a/app/src/main/java/com/fastaccess/helper/TypeFaceHelper.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.fastaccess.helper; - -import android.content.Context; -import android.graphics.Typeface; -import android.widget.TextView; - -/** - * Created by Kosh on 17/12/15 10:25 PM - */ -public class TypeFaceHelper { - - private static Typeface typeFace; - - public static void generateTypeface(Context context) { - typeFace = Typeface.createFromAsset(context.getAssets(), "fonts/app_font.ttf"); - } - - public static void applyTypeface(TextView textView) { - textView.setTypeface(typeFace); - } - - public static Typeface getTypeface() { - return typeFace; - } -} diff --git a/app/src/main/java/com/fastaccess/helper/ViewHelper.java b/app/src/main/java/com/fastaccess/helper/ViewHelper.java deleted file mode 100644 index eabedf762..000000000 --- a/app/src/main/java/com/fastaccess/helper/ViewHelper.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.fastaccess.helper; - -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.Color; -import android.graphics.PorterDuff; -import android.graphics.Rect; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.RippleDrawable; -import android.graphics.drawable.ShapeDrawable; -import android.graphics.drawable.StateListDrawable; -import android.graphics.drawable.shapes.RoundRectShape; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; -import android.text.Layout; -import android.util.TypedValue; -import android.view.View; -import android.view.inputmethod.InputMethodManager; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.annimon.stream.IntStream; -import com.fastaccess.R; - -import java.util.Arrays; - - -/** - * Created by kosh20111 on 10/7/2015 10:42 PM - */ -public class ViewHelper { - - @ColorInt public static int getPrimaryDarkColor(@NonNull Context context) { - return getColorAttr(context, R.attr.colorPrimaryDark); - } - - @ColorInt public static int getPrimaryColor(@NonNull Context context) { - return getColorAttr(context, R.attr.colorPrimary); - } - - @ColorInt public static int getPrimaryTextColor(@NonNull Context context) { - return getColorAttr(context, android.R.attr.textColorPrimary); - } - - @ColorInt public static int getSecondaryTextColor(@NonNull Context context) { - return getColorAttr(context, android.R.attr.textColorSecondary); - } - - @ColorInt public static int getTertiaryTextColor(@NonNull Context context) { - return getColorAttr(context, android.R.attr.textColorTertiary); - } - - @ColorInt public static int getAccentColor(@NonNull Context context) { - return getColorAttr(context, R.attr.colorAccent); - } - - @ColorInt public static int getIconColor(@NonNull Context context) { - return getColorAttr(context, R.attr.icon_color); - } - - @ColorInt public static int getWindowBackground(@NonNull Context context) { - return getColorAttr(context, android.R.attr.windowBackground); - } - - @ColorInt public static int getListDivider(@NonNull Context context) { - return getColorAttr(context, R.attr.dividerColor); - } - - @ColorInt public static int getCardBackground(@NonNull Context context) { - return getColorAttr(context, R.attr.card_background); - } - - @ColorInt public static int getPatchAdditionColor(@NonNull Context context) { - return getColorAttr(context, R.attr.patch_addition); - } - - @ColorInt public static int getPatchDeletionColor(@NonNull Context context) { - return getColorAttr(context, R.attr.patch_deletion); - } - - @ColorInt public static int getPatchRefColor(@NonNull Context context) { - return getColorAttr(context, R.attr.patch_ref); - } - - @ColorInt private static int getColorAttr(@NonNull Context context, int attr) { - Resources.Theme theme = context.getTheme(); - TypedArray typedArray = theme.obtainStyledAttributes(new int[]{attr}); - final int color = typedArray.getColor(0, Color.LTGRAY); - typedArray.recycle(); - return color; - } - - public static int toPx(@NonNull Context context, int dp) { - return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, dp, context.getResources().getDisplayMetrics()); - } - - public static int dpToPx(Context context, float dp) { - return (int) (dp * context.getResources().getDisplayMetrics().density + 0.5f); - } - - public static void tintDrawable(@NonNull Drawable drawable, @ColorInt int color) { - drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN); - } - - public static Drawable getDrawableSelector(int normalColor, int pressedColor) { - return new RippleDrawable(ColorStateList.valueOf(pressedColor), getRippleMask(normalColor), getRippleMask(normalColor)); - } - - @NonNull private static Drawable getRippleMask(int color) { - float[] outerRadii = new float[8]; - Arrays.fill(outerRadii, 3); - RoundRectShape r = new RoundRectShape(outerRadii, null, null); - ShapeDrawable shapeDrawable = new ShapeDrawable(r); - shapeDrawable.getPaint().setColor(color); - return shapeDrawable; - } - - @NonNull private static StateListDrawable getStateListDrawable(int normalColor, int pressedColor) { - StateListDrawable states = new StateListDrawable(); - states.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(pressedColor)); - states.addState(new int[]{android.R.attr.state_focused}, new ColorDrawable(pressedColor)); - states.addState(new int[]{android.R.attr.state_activated}, new ColorDrawable(pressedColor)); - states.addState(new int[]{android.R.attr.state_selected}, new ColorDrawable(pressedColor)); - states.addState(new int[]{}, new ColorDrawable(normalColor)); - return states; - } - - public static ColorStateList textSelector(int normalColor, int pressedColor) { - return new ColorStateList( - new int[][]{ - new int[]{android.R.attr.state_pressed}, - new int[]{android.R.attr.state_focused}, - new int[]{android.R.attr.state_activated}, - new int[]{android.R.attr.state_selected}, - new int[]{} - }, - new int[]{ - pressedColor, - pressedColor, - pressedColor, - pressedColor, - normalColor - } - ); - } - - private static boolean isTablet(@NonNull Resources resources) { - return (resources.getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; - } - - @SuppressWarnings("ConstantConditions") public static boolean isTablet(@NonNull Context context) { - return context != null && isTablet(context.getResources()); - } - - public static boolean isLandscape(@NonNull Resources resources) { - return resources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; - } - - @NonNull @SuppressWarnings("WeakerAccess") public static Rect getLayoutPosition(@NonNull View view) { - Rect myViewRect = new Rect(); - view.getGlobalVisibleRect(myViewRect); - return myViewRect; - } - - @SuppressWarnings("WeakerAccess") @Nullable public static String getTransitionName(@NonNull View view) { - return !InputHelper.isEmpty(view.getTransitionName()) ? view.getTransitionName() : null; - } - - @SuppressWarnings("WeakerAccess") public static void showKeyboard(@NonNull View v, @NonNull Context activity) { - InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(v, 0); - } - - public static void showKeyboard(@NonNull View v) { - showKeyboard(v, v.getContext()); - } - - public static void hideKeyboard(@NonNull View view) { - InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - inputManager.hideSoftInputFromWindow(view.getWindowToken(), 0); - } - - @ColorInt public static int generateTextColor(int background) { - return getContrastColor(background); - } - - @ColorInt private static int getContrastColor(@ColorInt int color) { - double a = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255; - return a < 0.5 ? Color.BLACK : Color.WHITE; - } - - public static boolean isEllipsed(@NonNull TextView textView) { - Layout layout = textView.getLayout(); - if (layout != null) { - int lines = layout.getLineCount(); - if (lines > 0) { - return IntStream.range(0, lines).anyMatch(line -> layout.getEllipsisCount(line) > 0); - } - } - return false; - } - - @NonNull public static TextView getTabTextView(@NonNull TabLayout tabs, int tabIndex) { - return (TextView) (((LinearLayout) ((LinearLayout) tabs.getChildAt(0)).getChildAt(tabIndex)).getChildAt(1)); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/colors/ColorsProvider.java b/app/src/main/java/com/fastaccess/provider/colors/ColorsProvider.java deleted file mode 100644 index f21b16726..000000000 --- a/app/src/main/java/com/fastaccess/provider/colors/ColorsProvider.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.fastaccess.provider.colors; - -import android.content.Context; -import android.graphics.Color; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.fastaccess.App; -import com.fastaccess.data.dao.LanguageColorModel; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.ui.widgets.color.ColorGenerator; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.google.gson.stream.JsonReader; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 27 May 2017, 9:50 PM - */ - -public class ColorsProvider { - - private static List POPULAR_LANG = Stream.of("Java", "Kotlin", "JavaScript", "Python", "CSS", "PHP", - "Ruby", "C++", "C", "Go", "Swift").toList();//predefined languages. - - private static Map colors = new LinkedHashMap<>(); - - public static void load() { - if (colors.isEmpty()) { - RxHelper.safeObservable(Observable - .create(observableEmitter -> { - try { - Type type = new TypeToken>() {}.getType(); - try (InputStream stream = App.getInstance().getAssets().open("colors.json")) { - Gson gson = new Gson(); - try (JsonReader reader = new JsonReader(new InputStreamReader(stream))) { - colors.putAll(gson.fromJson(reader, type)); - observableEmitter.onNext(""); - } - } - } catch (IOException e) { - e.printStackTrace(); - observableEmitter.onError(e); - } - observableEmitter.onComplete(); - })) - .subscribe(s -> {/**/}, Throwable::printStackTrace); - } - } - - @NonNull public static ArrayList languages() { - ArrayList lang = new ArrayList<>(); - lang.addAll(Stream.of(colors) - .filter(value -> value != null && !InputHelper.isEmpty(value.getKey())) - .map(Map.Entry::getKey) - .collect(Collectors.toCollection(ArrayList::new))); - lang.add(0, "All Languages"); - lang.addAll(1, POPULAR_LANG); - return lang; - } - - @Nullable public static LanguageColorModel getColor(@NonNull String lang) { - return colors.get(lang); - } - - @ColorInt public static int getColorAsColor(@NonNull String lang, @NonNull Context context) { - LanguageColorModel color = getColor(lang); - int langColor = ColorGenerator.getColor(context, lang); - if (color != null && !InputHelper.isEmpty(color.getColor())) { - try {langColor = Color.parseColor(color.getColor());} catch (Exception ignored) {} - } - return langColor; - } -} diff --git a/app/src/main/java/com/fastaccess/provider/emoji/Emoji.java b/app/src/main/java/com/fastaccess/provider/emoji/Emoji.java deleted file mode 100644 index 8f46fdb8f..000000000 --- a/app/src/main/java/com/fastaccess/provider/emoji/Emoji.java +++ /dev/null @@ -1,217 +0,0 @@ -package com.fastaccess.provider.emoji; - -import java.io.UnsupportedEncodingException; -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -/** - * This class represents an emoji.
    - *
    - * This object is immutable so it can be used safely in a multithreaded context. - * - * @author Vincent DURMONT [vdurmont@gmail.com] - */ -public class Emoji { - private final String description; - private final boolean supportsFitzpatrick; - private final List aliases; - private final List tags; - private String unicode; - private String htmlDec; - private String htmlHex; - - /** - * Constructor for the Emoji. - * - * @param description - * The description of the emoji - * @param supportsFitzpatrick - * Whether the emoji supports Fitzpatrick modifiers - * @param aliases - * the aliases for this emoji - * @param tags - * the tags associated with this emoji - * @param bytes - * the bytes that represent the emoji - */ - protected Emoji( - String description, - boolean supportsFitzpatrick, - List aliases, - List tags, - byte... bytes - ) { - this.description = description; - this.supportsFitzpatrick = supportsFitzpatrick; - this.aliases = Collections.unmodifiableList(aliases); - this.tags = Collections.unmodifiableList(tags); - - int count = 0; - try { - this.unicode = new String(bytes, "UTF-8"); - int stringLength = getUnicode().length(); - String[] pointCodes = new String[stringLength]; - String[] pointCodesHex = new String[stringLength]; - for (int offset = 0; offset < stringLength; ) { - final int codePoint = getUnicode().codePointAt(offset); - pointCodes[count] = String.format(Locale.getDefault(), "&#%d;", codePoint); - pointCodesHex[count++] = String.format("&#x%x;", codePoint); - offset += Character.charCount(codePoint); - } - this.htmlDec = stringJoin(pointCodes, count); - this.htmlHex = stringJoin(pointCodesHex, count); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - - /** - * Method to replace String.join, since it was only introduced in java8 - * - * @param array - * the array to be concatenated - * @return concatenated String - */ - private String stringJoin(String[] array, int count) { - String joined = ""; - for (int i = 0; i < count; i++) - joined += array[i]; - return joined; - } - - /** - * Returns the description of the emoji - * - * @return the description - */ - public String getDescription() { - return this.description; - } - - /** - * Returns wether the emoji supports the Fitzpatrick modifiers or not - * - * @return true if the emoji supports the Fitzpatrick modifiers - */ - public boolean supportsFitzpatrick() { - return this.supportsFitzpatrick; - } - - /** - * Returns the aliases of the emoji - * - * @return the aliases (unmodifiable) - */ - public List getAliases() { - return this.aliases; - } - - /** - * Returns the tags of the emoji - * - * @return the tags (unmodifiable) - */ - public List getTags() { - return this.tags; - } - - /** - * Returns the unicode representation of the emoji - * - * @return the unicode representation - */ - public String getUnicode() { - return this.unicode; - } - - /** - * Returns the unicode representation of the emoji associated with the - * provided Fitzpatrick modifier.
    - * If the modifier is null, then the result is similar to - * {@link Emoji#getUnicode()} - * - * @param fitzpatrick - * the fitzpatrick modifier or null - * @return the unicode representation - * @throws UnsupportedOperationException - * if the emoji doesn't support the Fitzpatrick modifiers - */ - public String getUnicode(Fitzpatrick fitzpatrick) { - if (!this.supportsFitzpatrick()) { - throw new UnsupportedOperationException( - "Cannot get the unicode with a fitzpatrick modifier, " + - "the emoji doesn't support fitzpatrick." - ); - } else if (fitzpatrick == null) { - return this.getUnicode(); - } - return this.getUnicode() + fitzpatrick.unicode; - } - - /** - * Returns the HTML decimal representation of the emoji - * - * @return the HTML decimal representation - */ - public String getHtmlDecimal() { - return this.htmlDec; - } - - /** - * @return the HTML hexadecimal representation - * @deprecated identical to {@link #getHtmlHexadecimal()} for backwards-compatibility. Use that instead. - */ - public String getHtmlHexidecimal() { - return this.getHtmlHexadecimal(); - } - - /** - * Returns the HTML hexadecimal representation of the emoji - * - * @return the HTML hexadecimal representation - */ - public String getHtmlHexadecimal() { - return this.htmlHex; - } - - @Override - public boolean equals(Object other) { - return !(other == null || !(other instanceof Emoji)) && - ((Emoji) other).getUnicode().equals(getUnicode()); - } - - @Override - public int hashCode() { - return unicode.hashCode(); - } - - /** - * Returns the String representation of the Emoji object.
    - *
    - * Example:
    - * Emoji { - * description='smiling face with open mouth and smiling eyes', - * supportsFitzpatrick=false, - * aliases=[smile], - * tags=[happy, joy, pleased], - * unicode='😄', - * htmlDec='&#128516;', - * htmlHex='&#x1f604;' - * } - * - * @return the string representation - */ - @Override - public String toString() { - return "Emoji{" + - "description='" + description + '\'' + - ", supportsFitzpatrick=" + supportsFitzpatrick + - ", aliases=" + aliases + - ", tags=" + tags + - ", unicode='" + unicode + '\'' + - ", htmlDec='" + htmlDec + '\'' + - ", htmlHex='" + htmlHex + '\'' + - '}'; - } -} diff --git a/app/src/main/java/com/fastaccess/provider/emoji/EmojiLoader.java b/app/src/main/java/com/fastaccess/provider/emoji/EmojiLoader.java deleted file mode 100644 index 5dd884dff..000000000 --- a/app/src/main/java/com/fastaccess/provider/emoji/EmojiLoader.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.fastaccess.provider.emoji; - -import org.json.JSONArray; -import org.json.JSONObject; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Loads the emojis from a JSON database. - * - * @author Vincent DURMONT [vdurmont@gmail.com] - */ -class EmojiLoader { - private EmojiLoader() {} - - static List loadEmojis(InputStream stream) throws IOException { - try { - JSONArray emojisJSON = new JSONArray(inputStreamToString(stream)); - List emojis = new ArrayList(emojisJSON.length()); - for (int i = 0; i < emojisJSON.length(); i++) { - Emoji emoji = buildEmojiFromJSON(emojisJSON.getJSONObject(i)); - if (emoji != null) { - emojis.add(emoji); - } - } - return emojis; - } catch (Exception e) { - e.printStackTrace(); - } - return Collections.emptyList(); - } - - private static String inputStreamToString(InputStream stream) throws IOException { - StringBuilder sb = new StringBuilder(); - InputStreamReader isr = new InputStreamReader(stream, "UTF-8"); - BufferedReader br = new BufferedReader(isr); - String read; - while ((read = br.readLine()) != null) { - sb.append(read); - } - br.close(); - return sb.toString(); - } - - private static Emoji buildEmojiFromJSON(JSONObject json) throws Exception { - if (!json.has("emoji")) { - return null; - } - byte[] bytes = json.getString("emoji").getBytes("UTF-8"); - String description = null; - if (json.has("description")) { - description = json.getString("description"); - } - boolean supportsFitzpatrick = false; - if (json.has("supports_fitzpatrick")) { - supportsFitzpatrick = json.getBoolean("supports_fitzpatrick"); - } - List aliases = jsonArrayToStringList(json.getJSONArray("aliases")); - List tags = jsonArrayToStringList(json.getJSONArray("tags")); - return new Emoji(description, supportsFitzpatrick, aliases, tags, bytes); - } - - private static List jsonArrayToStringList(JSONArray array) { - List strings = new ArrayList(array.length()); - try { - for (int i = 0; i < array.length(); i++) { - strings.add(array.getString(i)); - } - } catch (Exception e) { - e.printStackTrace(); - } - return strings; - } -} diff --git a/app/src/main/java/com/fastaccess/provider/emoji/EmojiManager.java b/app/src/main/java/com/fastaccess/provider/emoji/EmojiManager.java deleted file mode 100644 index c8283bfc7..000000000 --- a/app/src/main/java/com/fastaccess/provider/emoji/EmojiManager.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.fastaccess.provider.emoji; - -import com.fastaccess.App; -import com.fastaccess.helper.RxHelper; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import io.reactivex.Observable; -import io.reactivex.schedulers.Schedulers; - -/** - * Holds the loaded emojis and provides search functions. - * - * @author Vincent DURMONT [vdurmont@gmail.com] - */ -public class EmojiManager { - private static final String PATH = "emojis.json"; - private static final Map EMOJIS_BY_ALIAS = new HashMap<>(); - private static final Map> EMOJIS_BY_TAG = new HashMap<>(); - private static List ALL_EMOJIS; - private static EmojiTrie EMOJI_TRIE; - - public static void load() { - RxHelper.safeObservable(Observable.fromCallable(() -> { - try { - InputStream stream = App.getInstance().getAssets().open(PATH); - List emojis = EmojiLoader.loadEmojis(stream); - ALL_EMOJIS = emojis; - for (Emoji emoji : emojis) { - for (String tag : emoji.getTags()) { - if (EMOJIS_BY_TAG.get(tag) == null) { - EMOJIS_BY_TAG.put(tag, new HashSet<>()); - } - EMOJIS_BY_TAG.get(tag).add(emoji); - } - for (String alias : emoji.getAliases()) { - EMOJIS_BY_ALIAS.put(alias, emoji); - } - } - EMOJI_TRIE = new EmojiTrie(emojis); - stream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - return ""; - })).subscribeOn(Schedulers.io()).subscribe(); - } - - private EmojiManager() {} - - public static Set getForTag(String tag) { - if (tag == null) { - return null; - } - return EMOJIS_BY_TAG.get(tag); - } - - public static Emoji getForAlias(String alias) { - if (alias == null) { - return null; - } - return EMOJIS_BY_ALIAS.get(trimAlias(alias)); - } - - private static String trimAlias(String alias) { - String result = alias; - if (result.startsWith(":")) { - result = result.substring(1, result.length()); - } - if (result.endsWith(":")) { - result = result.substring(0, result.length() - 1); - } - return result; - } - - public static Emoji getByUnicode(String unicode) { - if (unicode == null) { - return null; - } - return EMOJI_TRIE.getEmoji(unicode); - } - - public static List getAll() { - return ALL_EMOJIS; - } - - public static boolean isEmoji(String string) { - return string != null && - EMOJI_TRIE.isEmoji(string.toCharArray()).exactMatch(); - } - - public static boolean isOnlyEmojis(String string) { - return string != null && EmojiParser.removeAllEmojis(string).isEmpty(); - } - - public static EmojiTrie.Matches isEmoji(char[] sequence) { - return EMOJI_TRIE.isEmoji(sequence); - } - - public static Collection getAllTags() { - return EMOJIS_BY_TAG.keySet(); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/emoji/EmojiParser.java b/app/src/main/java/com/fastaccess/provider/emoji/EmojiParser.java deleted file mode 100644 index 934b0ef5f..000000000 --- a/app/src/main/java/com/fastaccess/provider/emoji/EmojiParser.java +++ /dev/null @@ -1,515 +0,0 @@ -package com.fastaccess.provider.emoji; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Provides methods to parse strings with emojis. - * - * @author Vincent DURMONT [vdurmont@gmail.com] - */ -public class EmojiParser { - private static final Pattern ALIAS_CANDIDATE_PATTERN = - Pattern.compile("(?<=:)\\+?(\\w|\\||\\-)+(?=:)"); - - /** - * See {@link #parseToAliases(String, FitzpatrickAction)} with the action - * "PARSE" - * - * @param input the string to parse - * - * @return the string with the emojis replaced by their alias. - */ - public static String parseToAliases(String input) { - return parseToAliases(input, FitzpatrickAction.PARSE); - } - - /** - * Replaces the emoji's unicode occurrences by one of their alias - * (between 2 ':').
    - * Example: 😄 will be replaced by :smile:
    - *
    - * When a fitzpatrick modifier is present with a PARSE action, a "|" will be - * appendend to the alias, with the fitzpatrick type.
    - * Example: 👦🏿 will be replaced by - * :boy|type_6:
    - * The fitzpatrick types are: type_1_2, type_3, type_4, type_5, type_6
    - *
    - * When a fitzpatrick modifier is present with a REMOVE action, the modifier - * will be deleted.
    - * Example: 👦🏿 will be replaced by :boy:
    - *
    - * When a fitzpatrick modifier is present with a IGNORE action, the modifier - * will be ignored.
    - * Example: 👦🏿 will be replaced by :boy:🏿
    - * - * @param input the string to parse - * @param fitzpatrickAction the action to apply for the fitzpatrick modifiers - * - * @return the string with the emojis replaced by their alias. - */ - private static String parseToAliases( - String input, - final FitzpatrickAction fitzpatrickAction - ) { - EmojiTransformer emojiTransformer = unicodeCandidate -> { - switch (fitzpatrickAction) { - default: - case PARSE: - if (unicodeCandidate.hasFitzpatrick()) { - return ":" + - unicodeCandidate.getEmoji().getAliases().get(0) + - "|" + - unicodeCandidate.getFitzpatrickType() + - ":"; - } - case REMOVE: - return ":" + - unicodeCandidate.getEmoji().getAliases().get(0) + - ":"; - case IGNORE: - return ":" + - unicodeCandidate.getEmoji().getAliases().get(0) + - ":" + - unicodeCandidate.getFitzpatrickUnicode(); - } - }; - - return parseFromUnicode(input, emojiTransformer); - } - - - /** - * Replaces the emoji's aliases (between 2 ':') occurrences and the html - * representations by their unicode.
    - * Examples:
    - * :smile: will be replaced by 😄
    - * &#128516; will be replaced by 😄
    - * :boy|type_6: will be replaced by 👦🏿 - * - * @param input the string to parse - * - * @return the string with the aliases and html representations replaced by - * their unicode. - */ - public static String parseToUnicode(String input) { - // Get all the potential aliases - List candidates = getAliasCandidates(input); - - // Replace the aliases by their unicode - String result = input; - for (AliasCandidate candidate : candidates) { - Emoji emoji = EmojiManager.getForAlias(candidate.alias); - if (emoji != null) { - if ( - emoji.supportsFitzpatrick() || - (!emoji.supportsFitzpatrick() && candidate.fitzpatrick == null) - ) { - String replacement = emoji.getUnicode(); - if (candidate.fitzpatrick != null) { - replacement += candidate.fitzpatrick.unicode; - } - result = result.replace( - ":" + candidate.fullString + ":", - replacement - ); - } - } - } - - // Replace the html - for (Emoji emoji : EmojiManager.getAll()) { - result = result.replace(emoji.getHtmlHexadecimal(), emoji.getUnicode()); - result = result.replace(emoji.getHtmlDecimal(), emoji.getUnicode()); - } - - return result; - } - - private static List getAliasCandidates(String input) { - List candidates = new ArrayList(); - - Matcher matcher = ALIAS_CANDIDATE_PATTERN.matcher(input); - matcher = matcher.useTransparentBounds(true); - while (matcher.find()) { - String match = matcher.group(); - if (!match.contains("|")) { - candidates.add(new AliasCandidate(match, match, null)); - } else { - String[] splitted = match.split("\\|"); - if (splitted.length == 2 || splitted.length > 2) { - candidates.add(new AliasCandidate(match, splitted[0], splitted[1])); - } else { - candidates.add(new AliasCandidate(match, match, null)); - } - } - } - return candidates; - } - - /** - * See {@link #parseToHtmlDecimal(String, FitzpatrickAction)} with the action - * "PARSE" - * - * @param input the string to parse - * - * @return the string with the emojis replaced by their html decimal - * representation. - */ - public static String parseToHtmlDecimal(String input) { - return parseToHtmlDecimal(input, FitzpatrickAction.PARSE); - } - - /** - * Replaces the emoji's unicode occurrences by their html representation.
    - * Example: 😄 will be replaced by &#128516;
    - *
    - * When a fitzpatrick modifier is present with a PARSE or REMOVE action, the - * modifier will be deleted from the string.
    - * Example: 👦🏿 will be replaced by - * &#128102;
    - *
    - * When a fitzpatrick modifier is present with a IGNORE action, the modifier - * will be ignored and will remain in the string.
    - * Example: 👦🏿 will be replaced by - * &#128102;🏿 - * - * @param input the string to parse - * @param fitzpatrickAction the action to apply for the fitzpatrick modifiers - * - * @return the string with the emojis replaced by their html decimal - * representation. - */ - private static String parseToHtmlDecimal( - String input, - final FitzpatrickAction fitzpatrickAction - ) { - EmojiTransformer emojiTransformer = unicodeCandidate -> { - switch (fitzpatrickAction) { - default: - case PARSE: - case REMOVE: - return unicodeCandidate.getEmoji().getHtmlDecimal(); - case IGNORE: - return unicodeCandidate.getEmoji().getHtmlDecimal() + - unicodeCandidate.getFitzpatrickUnicode(); - } - }; - - return parseFromUnicode(input, emojiTransformer); - } - - /** - * See {@link #parseToHtmlHexadecimal(String, FitzpatrickAction)} with the - * action "PARSE" - * - * @param input the string to parse - * - * @return the string with the emojis replaced by their html hex - * representation. - */ - public static String parseToHtmlHexadecimal(String input) { - return parseToHtmlHexadecimal(input, FitzpatrickAction.PARSE); - } - - /** - * Replaces the emoji's unicode occurrences by their html hex - * representation.
    - * Example: 👦 will be replaced by &#x1f466;
    - *
    - * When a fitzpatrick modifier is present with a PARSE or REMOVE action, the - * modifier will be deleted.
    - * Example: 👦🏿 will be replaced by - * &#x1f466;
    - *
    - * When a fitzpatrick modifier is present with a IGNORE action, the modifier - * will be ignored and will remain in the string.
    - * Example: 👦🏿 will be replaced by - * &#x1f466;🏿 - * - * @param input the string to parse - * @param fitzpatrickAction the action to apply for the fitzpatrick modifiers - * - * @return the string with the emojis replaced by their html hex - * representation. - */ - private static String parseToHtmlHexadecimal( - String input, - final FitzpatrickAction fitzpatrickAction - ) { - EmojiTransformer emojiTransformer = unicodeCandidate -> { - switch (fitzpatrickAction) { - default: - case PARSE: - case REMOVE: - return unicodeCandidate.getEmoji().getHtmlHexadecimal(); - case IGNORE: - return unicodeCandidate.getEmoji().getHtmlHexadecimal() + - unicodeCandidate.getFitzpatrickUnicode(); - } - }; - - return parseFromUnicode(input, emojiTransformer); - } - - /** - * Removes all emojis from a String - * - * @param str the string to process - * - * @return the string without any emoji - */ - public static String removeAllEmojis(String str) { - EmojiTransformer emojiTransformer = unicodeCandidate -> ""; - - return parseFromUnicode(str, emojiTransformer); - } - - - /** - * Removes a set of emojis from a String - * - * @param str the string to process - * @param emojisToRemove the emojis to remove from this string - * - * @return the string without the emojis that were removed - */ - public static String removeEmojis( - String str, - final Collection emojisToRemove - ) { - EmojiTransformer emojiTransformer = unicodeCandidate -> { - if (!emojisToRemove.contains(unicodeCandidate.getEmoji())) { - return unicodeCandidate.getEmoji().getUnicode() + - unicodeCandidate.getFitzpatrickUnicode(); - } - return ""; - }; - - return parseFromUnicode(str, emojiTransformer); - } - - /** - * Removes all the emojis in a String except a provided set - * - * @param str the string to process - * @param emojisToKeep the emojis to keep in this string - * - * @return the string without the emojis that were removed - */ - public static String removeAllEmojisExcept( - String str, - final Collection emojisToKeep - ) { - EmojiTransformer emojiTransformer = unicodeCandidate -> { - if (emojisToKeep.contains(unicodeCandidate.getEmoji())) { - return unicodeCandidate.getEmoji().getUnicode() + - unicodeCandidate.getFitzpatrickUnicode(); - } - return ""; - }; - - return parseFromUnicode(str, emojiTransformer); - } - - - /** - * Detects all unicode emojis in input string and replaces them with the - * return value of transformer.transform() - * - * @param input the string to process - * @param transformer emoji transformer to apply to each emoji - * - * @return input string with all emojis transformed - */ - private static String parseFromUnicode( - String input, - EmojiTransformer transformer - ) { - int prev = 0; - StringBuilder sb = new StringBuilder(); - List replacements = getUnicodeCandidates(input); - for (UnicodeCandidate candidate : replacements) { - sb.append(input.substring(prev, candidate.getEmojiStartIndex())); - - sb.append(transformer.transform(candidate)); - prev = candidate.getFitzpatrickEndIndex(); - } - - return sb.append(input.substring(prev)).toString(); - } - - public static List extractEmojis(String input) { - List emojis = getUnicodeCandidates(input); - List result = new ArrayList(); - for (UnicodeCandidate emoji : emojis) { - result.add(emoji.getEmoji().getUnicode()); - } - return result; - } - - - /** - * Generates a list UnicodeCandidates found in input string. A - * UnicodeCandidate is created for every unicode emoticon found in input - * string, additionally if Fitzpatrick modifier follows the emoji, it is - * included in UnicodeCandidate. Finally, it contains start and end index of - * unicode emoji itself (WITHOUT Fitzpatrick modifier whether it is there or - * not!). - * - * @param input String to find all unicode emojis in - * @return List of UnicodeCandidates for each unicode emote in text - */ - private static List getUnicodeCandidates(String input) { - char[] inputCharArray = input.toCharArray(); - List candidates = new ArrayList(); - for (int i = 0; i < input.length(); i++) { - int emojiEnd = getEmojiEndPos(inputCharArray, i); - - if (emojiEnd != -1) { - Emoji emoji = EmojiManager.getByUnicode(input.substring(i, emojiEnd)); - String fitzpatrickString = (emojiEnd + 2 <= input.length()) ? - new String(inputCharArray, emojiEnd, 2) : - null; - UnicodeCandidate candidate = new UnicodeCandidate( - emoji, - fitzpatrickString, - i - ); - candidates.add(candidate); - i = candidate.getFitzpatrickEndIndex() - 1; - } - } - - return candidates; - } - - - /** - * Returns end index of a unicode emoji if it is found in text starting at - * index startPos, -1 if not found. - * This returns the longest matching emoji, for example, in - * "\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC66" - * it will find alias:family_man_woman_boy, NOT alias:man - * - * @param text the current text where we are looking for an emoji - * @param startPos the position in the text where we should start looking for - * an emoji end - * - * @return the end index of the unicode emoji starting at startPos. -1 if not - * found - */ - private static int getEmojiEndPos(char[] text, int startPos) { - int best = -1; - for (int j = startPos + 1; j <= text.length; j++) { - EmojiTrie.Matches status = EmojiManager.isEmoji(Arrays.copyOfRange( - text, - startPos, - j - )); - - if (status.exactMatch()) { - best = j; - } else if (status.impossibleMatch()) { - return best; - } - } - - return best; - } - - - public static class UnicodeCandidate { - private final Emoji emoji; - private final Fitzpatrick fitzpatrick; - private final int startIndex; - - private UnicodeCandidate(Emoji emoji, String fitzpatrick, int startIndex) { - this.emoji = emoji; - this.fitzpatrick = Fitzpatrick.fitzpatrickFromUnicode(fitzpatrick); - this.startIndex = startIndex; - } - - public Emoji getEmoji() { - return emoji; - } - - public boolean hasFitzpatrick() { - return getFitzpatrick() != null; - } - - public Fitzpatrick getFitzpatrick() { - return fitzpatrick; - } - - public String getFitzpatrickType() { - return hasFitzpatrick() ? fitzpatrick.name().toLowerCase() : ""; - } - - public String getFitzpatrickUnicode() { - return hasFitzpatrick() ? fitzpatrick.unicode : ""; - } - - public int getEmojiStartIndex() { - return startIndex; - } - - public int getEmojiEndIndex() { - return startIndex + emoji.getUnicode().length(); - } - - public int getFitzpatrickEndIndex() { - return getEmojiEndIndex() + (fitzpatrick != null ? 2 : 0); - } - } - - - static class AliasCandidate { - public final String fullString; - public final String alias; - public final Fitzpatrick fitzpatrick; - - private AliasCandidate( - String fullString, - String alias, - String fitzpatrickString - ) { - this.fullString = fullString; - this.alias = alias; - if (fitzpatrickString == null) { - this.fitzpatrick = null; - } else { - this.fitzpatrick = Fitzpatrick.fitzpatrickFromType(fitzpatrickString); - } - } - } - - /** - * Enum used to indicate what should be done when a Fitzpatrick modifier is - * found. - */ - public enum FitzpatrickAction { - /** - * Tries to match the Fitzpatrick modifier with the previous emoji - */ - PARSE, - - /** - * Removes the Fitzpatrick modifier from the string - */ - REMOVE, - - /** - * Ignores the Fitzpatrick modifier (it will stay in the string) - */ - IGNORE - } - - public interface EmojiTransformer { - String transform(UnicodeCandidate unicodeCandidate); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/emoji/EmojiTrie.java b/app/src/main/java/com/fastaccess/provider/emoji/EmojiTrie.java deleted file mode 100644 index 29741953e..000000000 --- a/app/src/main/java/com/fastaccess/provider/emoji/EmojiTrie.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.fastaccess.provider.emoji; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -public class EmojiTrie { - private Node root = new Node(); - - public EmojiTrie(Collection emojis) { - for (Emoji emoji : emojis) { - Node tree = root; - for (char c : emoji.getUnicode().toCharArray()) { - if (!tree.hasChild(c)) { - tree.addChild(c); - } - tree = tree.getChild(c); - } - tree.setEmoji(emoji); - } - } - - - /** - * Checks if sequence of chars contain an emoji. - * - * @param sequence - * Sequence of char that may contain emoji in full or partially. - * @return <li> Matches.EXACTLY if char sequence in its entirety is an emoji </li> <li> Matches.POSSIBLY if char sequence - * matches prefix of an emoji </li> <li> Matches.IMPOSSIBLE if char sequence matches no emoji or prefix of an emoji </li> - */ - public Matches isEmoji(char[] sequence) { - if (sequence == null) { - return Matches.POSSIBLY; - } - - Node tree = root; - for (char c : sequence) { - if (!tree.hasChild(c)) { - return Matches.IMPOSSIBLE; - } - tree = tree.getChild(c); - } - - return tree.isEndOfEmoji() ? Matches.EXACTLY : Matches.POSSIBLY; - } - - - /** - * Finds Emoji instance from emoji unicode - * - * @param unicode - * unicode of emoji to get - * @return Emoji instance if unicode matches and emoji, null otherwise. - */ - public Emoji getEmoji(String unicode) { - Node tree = root; - for (char c : unicode.toCharArray()) { - if (!tree.hasChild(c)) { - return null; - } - tree = tree.getChild(c); - } - return tree.getEmoji(); - } - - public enum Matches { - EXACTLY, POSSIBLY, IMPOSSIBLE; - - public boolean exactMatch() { - return this == EXACTLY; - } - - public boolean impossibleMatch() { - return this == IMPOSSIBLE; - } - - public boolean possibleMatch() { - return this == POSSIBLY; - } - } - - private class Node { - private Map children = new HashMap(); - private Emoji emoji; - - private void setEmoji(Emoji emoji) { - this.emoji = emoji; - } - - private Emoji getEmoji() { - return emoji; - } - - private boolean hasChild(char child) { - return children.containsKey(child); - } - - private void addChild(char child) { - children.put(child, new Node()); - } - - private Node getChild(char child) { - return children.get(child); - } - - private boolean isEndOfEmoji() { - return emoji != null; - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/emoji/Fitzpatrick.java b/app/src/main/java/com/fastaccess/provider/emoji/Fitzpatrick.java deleted file mode 100644 index 484bcdb3c..000000000 --- a/app/src/main/java/com/fastaccess/provider/emoji/Fitzpatrick.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.fastaccess.provider.emoji; - -/** - * Enum that represents the Fitzpatrick modifiers supported by the emojis. - */ -public enum Fitzpatrick { - /** - * Fitzpatrick modifier of type 1/2 (pale white/white) - */ - TYPE_1_2("\uD83C\uDFFB"), - - /** - * Fitzpatrick modifier of type 3 (cream white) - */ - TYPE_3("\uD83C\uDFFC"), - - /** - * Fitzpatrick modifier of type 4 (moderate brown) - */ - TYPE_4("\uD83C\uDFFD"), - - /** - * Fitzpatrick modifier of type 5 (dark brown) - */ - TYPE_5("\uD83C\uDFFE"), - - /** - * Fitzpatrick modifier of type 6 (black) - */ - TYPE_6("\uD83C\uDFFF"); - - /** - * The unicode representation of the Fitzpatrick modifier - */ - public final String unicode; - - Fitzpatrick(String unicode) { - this.unicode = unicode; - } - - - public static Fitzpatrick fitzpatrickFromUnicode(String unicode) { - for (Fitzpatrick v : values()) { - if (v.unicode.equals(unicode)) { - return v; - } - } - return null; - } - - public static Fitzpatrick fitzpatrickFromType(String type) { - try { - return Fitzpatrick.valueOf(type.toUpperCase()); - } catch (IllegalArgumentException e) { - return null; - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/fcm/PushNotificationService.java b/app/src/main/java/com/fastaccess/provider/fcm/PushNotificationService.java deleted file mode 100644 index 64a3d8d82..000000000 --- a/app/src/main/java/com/fastaccess/provider/fcm/PushNotificationService.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.fastaccess.provider.fcm; - -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.support.v4.app.NotificationCompat; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.FastHubNotification; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.modules.main.MainActivity; -import com.google.firebase.messaging.FirebaseMessagingService; -import com.google.firebase.messaging.RemoteMessage; - -import org.json.JSONObject; - -import java.util.Date; - -/** - * Created by Kosh on 16 Apr 2017, 1:17 PM - */ - -public class PushNotificationService extends FirebaseMessagingService { - - @Override public void onMessageReceived(RemoteMessage remoteMessage) { - super.onMessageReceived(remoteMessage); - if (remoteMessage != null) { - if (remoteMessage.getData() != null && !remoteMessage.getData().isEmpty()) { - Date date = new Date(remoteMessage.getSentTime()); - FastHubNotification fastHubNotification = RestProvider.gson - .fromJson(new JSONObject(remoteMessage.getData()).toString(), FastHubNotification.class); - fastHubNotification.setDate(date); - FastHubNotification.save(fastHubNotification); - } else if (remoteMessage.getNotification() != null) { - String title = remoteMessage.getNotification().getTitle(); - String body = remoteMessage.getNotification().getBody(); - if (remoteMessage.getData() != null && !remoteMessage.getData().isEmpty()) { - title = title == null ? remoteMessage.getData().get("title") : title; - body = body == null ? remoteMessage.getData().get("message") : body; - } - Intent intent = new Intent(this, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); - NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "In App-Notifications") - .setSmallIcon(R.drawable.ic_notification) - .setContentTitle(title) - .setContentText(body) - .setAutoCancel(true) - .setContentIntent(pendingIntent); - NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - if (notificationManager != null) { - notificationManager.notify(1, notificationBuilder.build()); - } - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/gson/ToGsonProvider.java b/app/src/main/java/com/fastaccess/provider/gson/ToGsonProvider.java deleted file mode 100644 index 5f88e3e52..000000000 --- a/app/src/main/java/com/fastaccess/provider/gson/ToGsonProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.fastaccess.provider.gson; - -import android.content.Context; -import android.support.annotation.NonNull; - -import com.fastaccess.R; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 26 Mar 2017, 10:07 PM - */ - -public class ToGsonProvider { - - public static Observable getChangelog(@NonNull Context context) { - return Observable.fromCallable(() -> { - try (InputStream is = context.getResources().openRawResource(R.raw.changelog)) { - try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) { - byte[] buffer = new byte[is.available()]; - int read = is.read(buffer);//ignore lint - byteStream.write(buffer); - return byteStream.toString(); - } catch (IOException e) { - e.printStackTrace(); - } - } - return null; - }); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/markdown/CachedComments.kt b/app/src/main/java/com/fastaccess/provider/markdown/CachedComments.kt deleted file mode 100644 index 87a90ee19..000000000 --- a/app/src/main/java/com/fastaccess/provider/markdown/CachedComments.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.fastaccess.provider.markdown - -import java.util.* - -/** - * Created by kosh on 11/08/2017. - */ -class CachedComments private constructor() { - - val map = WeakHashMap() - - fun put(repo: String?, login: String?, number: Any?, comment: CharSequence) { - map.put("$repo/$login/$number", comment) - } - - fun get(repo: String?, login: String?, number: Any?): CharSequence? { - return map["$repo/$login/$number"] - } - - fun clear() = map.clear() - - private object Holder { - val INSTANCE = CachedComments() - } - - companion object { - val instance: CachedComments by lazy { Holder.INSTANCE } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/markdown/MarkDownProvider.java b/app/src/main/java/com/fastaccess/provider/markdown/MarkDownProvider.java deleted file mode 100644 index 70056f032..000000000 --- a/app/src/main/java/com/fastaccess/provider/markdown/MarkDownProvider.java +++ /dev/null @@ -1,339 +0,0 @@ -package com.fastaccess.provider.markdown; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.Html; -import android.view.ViewTreeObserver; -import android.webkit.MimeTypeMap; -import android.widget.EditText; -import android.widget.TextView; - -import com.annimon.stream.IntStream; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.provider.markdown.extension.emoji.EmojiExtension; -import com.fastaccess.provider.markdown.extension.mention.MentionExtension; -import com.fastaccess.provider.timeline.HtmlHelper; - -import org.commonmark.Extension; -import org.commonmark.ext.autolink.AutolinkExtension; -import org.commonmark.ext.front.matter.YamlFrontMatterExtension; -import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension; -import org.commonmark.ext.gfm.tables.TablesExtension; -import org.commonmark.ext.ins.InsExtension; -import org.commonmark.node.Node; -import org.commonmark.parser.Parser; -import org.commonmark.renderer.html.HtmlRenderer; - -import java.util.Arrays; -import java.util.List; - -/** - * Created by Kosh on 24 Nov 2016, 7:43 PM - */ - -public class MarkDownProvider { - - private static final String[] IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".gif", ".svg"}; - - private static final String[] MARKDOWN_EXTENSIONS = { - ".md", ".mkdn", ".mdwn", ".mdown", ".markdown", ".mkd", ".mkdown", ".ron", ".rst", "adoc" - }; - - private static final String[] ARCHIVE_EXTENSIONS = { - ".zip", ".7z", ".rar", ".tar.gz", ".tgz", ".tar.Z", ".tar.bz2", ".tbz2", ".tar.lzma", ".tlz", ".apk", ".jar", - ".dmg", ".pdf", ".ico", ".docx", ".doc", ".xlsx", ".hwp", ".pptx", ".show", ".mp3", ".ogg", ".ipynb" - }; - - private MarkDownProvider() {} - - public static void setMdText(@NonNull TextView textView, String markdown) { - if (!InputHelper.isEmpty(markdown)) { - int width = textView.getMeasuredWidth(); - if (width > 0) { - render(textView, markdown, width); - } else { - textView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override public boolean onPreDraw() { - textView.getViewTreeObserver().removeOnPreDrawListener(this); - render(textView, markdown, textView.getMeasuredWidth()); - return true; - } - }); - } - } - } - - public static void setMdText(@NonNull TextView textView, String markdown, int width) { - if (!InputHelper.isEmpty(markdown)) { - render(textView, markdown, width); - } - } - - protected static void render(@NonNull TextView textView, String markdown, int width) { - List extensions = Arrays.asList( - StrikethroughExtension.create(), - AutolinkExtension.create(), - TablesExtension.create(), - InsExtension.create(), - EmojiExtension.create(), - MentionExtension.create(), - YamlFrontMatterExtension.create()); - Parser parser = Parser.builder() - .extensions(extensions) - .build(); - try { - Node node = parser.parse(markdown); - String rendered = HtmlRenderer - .builder() - .extensions(extensions) - .build() - .render(node); - HtmlHelper.htmlIntoTextView(textView, rendered, (width - (textView.getPaddingStart() + textView.getPaddingEnd()))); - } catch (Exception ignored) { - HtmlHelper.htmlIntoTextView(textView, markdown, (width - (textView.getPaddingStart() + textView.getPaddingEnd()))); - } - } - - public static void stripMdText(@NonNull TextView textView, String markdown) { - if (!InputHelper.isEmpty(markdown)) { - Parser parser = Parser.builder().build(); - Node node = parser.parse(markdown); - textView.setText(stripHtml(HtmlRenderer.builder().build().render(node))); - } - } - - @NonNull public static String stripMdText(String markdown) { - if (!InputHelper.isEmpty(markdown)) { - Parser parser = Parser.builder().build(); - Node node = parser.parse(markdown); - return stripHtml(HtmlRenderer.builder().build().render(node)); - } - return ""; - } - - public static String stripHtml(String html) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { - return Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY).toString(); - } else { - return Html.fromHtml(html).toString(); - } - } - - public static void addList(@NonNull EditText editText, @NonNull String list) { - String tag = list + " "; - String source = editText.getText().toString(); - int selectionStart = editText.getSelectionStart(); - int selectionEnd = editText.getSelectionEnd(); - String substring = source.substring(0, selectionStart); - int line = substring.lastIndexOf(10); - if (line != -1) { - selectionStart = line + 1; - } else { - selectionStart = 0; - } - substring = source.substring(selectionStart, selectionEnd); - String[] split = substring.split("\n"); - StringBuilder stringBuffer = new StringBuilder(); - if (split.length > 0) - for (String s : split) { - if (s.length() == 0 && stringBuffer.length() != 0) { - stringBuffer.append("\n"); - continue; - } - if (!s.trim().startsWith(tag)) { - if (stringBuffer.length() > 0) stringBuffer.append("\n"); - stringBuffer.append(tag).append(s); - } else { - if (stringBuffer.length() > 0) stringBuffer.append("\n"); - stringBuffer.append(s); - } - } - - if (stringBuffer.length() == 0) { - stringBuffer.append(tag); - } - editText.getText().replace(selectionStart, selectionEnd, stringBuffer.toString()); - editText.setSelection(stringBuffer.length() + selectionStart); - } - - public static void addHeader(@NonNull EditText editText, int level) { - String source = editText.getText().toString(); - int selectionStart = editText.getSelectionStart(); - int selectionEnd = editText.getSelectionEnd(); - StringBuilder result = new StringBuilder(); - String substring = source.substring(selectionStart, selectionEnd); - if (!hasNewLine(source, selectionStart)) - result.append("\n"); - IntStream.range(0, level).forEach(integer -> result.append("#")); - result.append(" ").append(substring); - editText.getText().replace(selectionStart, selectionEnd, result.toString()); - editText.setSelection(selectionStart + result.length()); - - } - - public static void addItalic(@NonNull EditText editText) { - String source = editText.getText().toString(); - int selectionStart = editText.getSelectionStart(); - int selectionEnd = editText.getSelectionEnd(); - String substring = source.substring(selectionStart, selectionEnd); - String result = "_" + substring + "_ "; - editText.getText().replace(selectionStart, selectionEnd, result); - editText.setSelection(result.length() + selectionStart - 2); - - } - - public static void addBold(@NonNull EditText editText) { - String source = editText.getText().toString(); - int selectionStart = editText.getSelectionStart(); - int selectionEnd = editText.getSelectionEnd(); - String substring = source.substring(selectionStart, selectionEnd); - String result = "**" + substring + "** "; - editText.getText().replace(selectionStart, selectionEnd, result); - editText.setSelection(result.length() + selectionStart - 3); - - } - - public static void addCode(@NonNull EditText editText) { - try { - String source = editText.getText().toString(); - int selectionStart = editText.getSelectionStart(); - int selectionEnd = editText.getSelectionEnd(); - String substring = source.substring(selectionStart, selectionEnd); - String result; - if (hasNewLine(source, selectionStart)) - result = "```\n" + substring + "\n```\n"; - else - result = "\n```\n" + substring + "\n```\n"; - - editText.getText().replace(selectionStart, selectionEnd, result); - editText.setSelection(result.length() + selectionStart - 5); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static void addInlinleCode(@NonNull EditText editText) { - String source = editText.getText().toString(); - int selectionStart = editText.getSelectionStart(); - int selectionEnd = editText.getSelectionEnd(); - String substring = source.substring(selectionStart, selectionEnd); - String result = "`" + substring + "` "; - editText.getText().replace(selectionStart, selectionEnd, result); - editText.setSelection(result.length() + selectionStart - 2); - - } - - public static void addStrikeThrough(@NonNull EditText editText) { - String source = editText.getText().toString(); - int selectionStart = editText.getSelectionStart(); - int selectionEnd = editText.getSelectionEnd(); - String substring = source.substring(selectionStart, selectionEnd); - String result = "~~" + substring + "~~ "; - editText.getText().replace(selectionStart, selectionEnd, result); - editText.setSelection(result.length() + selectionStart - 3); - - } - - public static void addQuote(@NonNull EditText editText) { - String source = editText.getText().toString(); - int selectionStart = editText.getSelectionStart(); - int selectionEnd = editText.getSelectionEnd(); - String substring = source.substring(selectionStart, selectionEnd); - String result; - if (hasNewLine(source, selectionStart)) { - result = "> " + substring; - } else { - result = "\n> " + substring; - - } - editText.getText().replace(selectionStart, selectionEnd, result); - editText.setSelection(result.length() + selectionStart); - - } - - public static void addDivider(@NonNull EditText editText) { - String source = editText.getText().toString(); - int selectionStart = editText.getSelectionStart(); - String result; - if (hasNewLine(source, selectionStart)) { - result = "-------\n"; - } else { - result = "\n-------\n"; - } - editText.getText().replace(selectionStart, selectionStart, result); - editText.setSelection(result.length() + selectionStart); - - } - - public static void addPhoto(@NonNull EditText editText, @NonNull String title, @NonNull String link) { - String result = "![" + InputHelper.toString(title) + "](" + InputHelper.toString(link) + ")"; - insertAtCursor(editText, result); - } - - public static void addLink(@NonNull EditText editText, @NonNull String title, @NonNull String link) { - String result = "[" + InputHelper.toString(title) + "](" + InputHelper.toString(link) + ")"; - insertAtCursor(editText, result); - } - - private static boolean hasNewLine(@NonNull String source, int selectionStart) { - try { - if (source.isEmpty()) return true; - source = source.substring(0, selectionStart); - return source.charAt(source.length() - 1) == 10; - } catch (StringIndexOutOfBoundsException e) { - return false; - } - } - - public static boolean isImage(@Nullable String name) { - if (InputHelper.isEmpty(name)) return false; - name = name.toLowerCase(); - for (String value : IMAGE_EXTENSIONS) { - String extension = MimeTypeMap.getFileExtensionFromUrl(name); - if ((extension != null && value.replace(".", "").equals(extension)) || name.endsWith(value)) return true; - } - return false; - } - - public static boolean isMarkdown(@Nullable String name) { - if (InputHelper.isEmpty(name)) return false; - name = name.toLowerCase(); - for (String value : MARKDOWN_EXTENSIONS) { - String extension = MimeTypeMap.getFileExtensionFromUrl(name); - if ((extension != null && value.replace(".", "").equals(extension)) || - name.equalsIgnoreCase("README") || name.endsWith(value)) - return true; - } - return false; - } - - public static boolean isArchive(@Nullable String name) { - if (InputHelper.isEmpty(name)) return false; - name = name.toLowerCase(); - for (String value : ARCHIVE_EXTENSIONS) { - String extension = MimeTypeMap.getFileExtensionFromUrl(name); - if ((extension != null && value.replace(".", "").equals(extension)) || name.endsWith(value)) return true; - } - - return false; - } - - public static void insertAtCursor(@NonNull EditText editText, @NonNull String text) { - String oriContent = editText.getText().toString(); - int start = editText.getSelectionStart(); - int end = editText.getSelectionEnd(); - Logger.e(start, end); - if (start >= 0 && end > 0 && start != end) { - editText.setText(editText.getText().replace(start, end, text)); - } else { - int index = editText.getSelectionStart() >= 0 ? editText.getSelectionStart() : 0; - Logger.e(start, end, index); - StringBuilder builder = new StringBuilder(oriContent); - builder.insert(index, text); - editText.setText(builder.toString()); - editText.setSelection(index + text.length()); - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/Emoji.java b/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/Emoji.java deleted file mode 100644 index 7af55f486..000000000 --- a/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/Emoji.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.provider.markdown.extension.emoji; - -import org.commonmark.node.CustomNode; -import org.commonmark.node.Delimited; - -/** - * Created by kosh on 20/08/2017. - */ - -public class Emoji extends CustomNode implements Delimited { - - private static final String DELIMITER = ":"; - - @Override public String getOpeningDelimiter() { - return DELIMITER; - } - - @Override public String getClosingDelimiter() { - return DELIMITER; - } -} diff --git a/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/EmojiExtension.java b/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/EmojiExtension.java deleted file mode 100644 index 1414f486f..000000000 --- a/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/EmojiExtension.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.fastaccess.provider.markdown.extension.emoji; - -import com.fastaccess.provider.markdown.extension.emoji.internal.EmojiDelimiterProcessor; -import com.fastaccess.provider.markdown.extension.emoji.internal.EmojiNodeRenderer; - -import org.commonmark.Extension; -import org.commonmark.parser.Parser; -import org.commonmark.renderer.html.HtmlRenderer; - -/** - * Created by kosh on 20/08/2017. - */ - -public class EmojiExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension { - private EmojiExtension() {} - - public static Extension create() { - return new EmojiExtension(); - } - - @Override public void extend(Parser.Builder parserBuilder) { - parserBuilder.customDelimiterProcessor(new EmojiDelimiterProcessor()); - } - - @Override public void extend(HtmlRenderer.Builder rendererBuilder) { - rendererBuilder.nodeRendererFactory(EmojiNodeRenderer::new); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/internal/EmojiDelimiterProcessor.java b/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/internal/EmojiDelimiterProcessor.java deleted file mode 100644 index 2a80257d7..000000000 --- a/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/internal/EmojiDelimiterProcessor.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.fastaccess.provider.markdown.extension.emoji.internal; - -import com.fastaccess.provider.markdown.extension.emoji.Emoji; - -import org.commonmark.node.Node; -import org.commonmark.node.Text; -import org.commonmark.parser.delimiter.DelimiterProcessor; -import org.commonmark.parser.delimiter.DelimiterRun; - -public class EmojiDelimiterProcessor implements DelimiterProcessor { - - @Override public char getOpeningCharacter() { - return ':'; - } - - @Override public char getClosingCharacter() { - return ':'; - } - - @Override public int getMinLength() { - return 1; - } - - @Override public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) { - if (opener.length() >= 1 && closer.length() >= 1) { - return 1; - } else { - return 0; - } - } - - @Override public void process(Text opener, Text closer, int delimiterCount) { - Node emoji = new Emoji(); - Node tmp = opener.getNext(); - while (tmp != null && tmp != closer) { - Node next = tmp.getNext(); - emoji.appendChild(tmp); - tmp = next; - } - opener.insertAfter(emoji); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/internal/EmojiNodeRenderer.java b/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/internal/EmojiNodeRenderer.java deleted file mode 100644 index bbef8b818..000000000 --- a/app/src/main/java/com/fastaccess/provider/markdown/extension/emoji/internal/EmojiNodeRenderer.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.fastaccess.provider.markdown.extension.emoji.internal; - -import org.commonmark.node.Node; -import org.commonmark.renderer.NodeRenderer; -import org.commonmark.renderer.html.HtmlNodeRendererContext; -import org.commonmark.renderer.html.HtmlWriter; - -import java.util.Collections; -import java.util.Map; -import java.util.Set; - -public class EmojiNodeRenderer implements NodeRenderer { - - private final HtmlNodeRendererContext context; - private final HtmlWriter html; - - public EmojiNodeRenderer(HtmlNodeRendererContext context) { - this.context = context; - this.html = context.getWriter(); - } - - @Override public Set> getNodeTypes() { - return Collections.singleton(com.fastaccess.provider.markdown.extension.emoji.Emoji.class); - } - - @Override public void render(Node node) { - Map attributes = context.extendAttributes(node, "emoji", Collections.emptyMap()); - html.tag("emoji", attributes); - renderChildren(node); - html.tag("/emoji"); - } - - private void renderChildren(Node parent) { - Node node = parent.getFirstChild(); - while (node != null) { - Node next = node.getNext(); - context.render(node); - node = next; - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/Mention.java b/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/Mention.java deleted file mode 100644 index c2d148c72..000000000 --- a/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/Mention.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.provider.markdown.extension.mention; - -import org.commonmark.node.CustomNode; -import org.commonmark.node.Delimited; - -/** - * Created by kosh on 20/08/2017. - */ - -public class Mention extends CustomNode implements Delimited { - - private static final String DELIMITER = "@"; - - @Override public String getOpeningDelimiter() { - return DELIMITER; - } - - @Override public String getClosingDelimiter() { - return " "; - } -} diff --git a/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/MentionExtension.java b/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/MentionExtension.java deleted file mode 100644 index 5a8fa103b..000000000 --- a/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/MentionExtension.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.fastaccess.provider.markdown.extension.mention; - -import com.fastaccess.provider.markdown.extension.mention.internal.MentionDelimiterProcessor; -import com.fastaccess.provider.markdown.extension.mention.internal.MentionNodeRenderer; - -import org.commonmark.Extension; -import org.commonmark.parser.Parser; -import org.commonmark.renderer.html.HtmlRenderer; - -/** - * Created by kosh on 20/08/2017. - */ - -public class MentionExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension { - private MentionExtension() {} - - public static Extension create() { - return new MentionExtension(); - } - - @Override public void extend(Parser.Builder parserBuilder) { - parserBuilder.customDelimiterProcessor(new MentionDelimiterProcessor()); - } - - @Override public void extend(HtmlRenderer.Builder rendererBuilder) { - rendererBuilder.nodeRendererFactory(MentionNodeRenderer::new); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/internal/MentionDelimiterProcessor.java b/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/internal/MentionDelimiterProcessor.java deleted file mode 100644 index 5b3f6d0da..000000000 --- a/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/internal/MentionDelimiterProcessor.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.fastaccess.provider.markdown.extension.mention.internal; - -import com.fastaccess.provider.markdown.extension.mention.Mention; - -import org.commonmark.node.Node; -import org.commonmark.node.Text; -import org.commonmark.parser.delimiter.DelimiterProcessor; -import org.commonmark.parser.delimiter.DelimiterRun; - -public class MentionDelimiterProcessor implements DelimiterProcessor { - - @Override public char getOpeningCharacter() { - return '@'; - } - - @Override public char getClosingCharacter() { - return ' '; - } - - @Override public int getMinLength() { - return 1; - } - - @Override public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) { - if (opener.length() >= 1 && closer.length() >= 1) { - return 1; - } else { - return 0; - } - } - - @Override public void process(Text opener, Text closer, int delimiterCount) { - Node mention = new Mention(); - Node tmp = opener.getNext(); - while (tmp != null && tmp != closer) { - Node next = tmp.getNext(); - mention.appendChild(tmp); - tmp = next; - } - opener.insertAfter(mention); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/internal/MentionNodeRenderer.java b/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/internal/MentionNodeRenderer.java deleted file mode 100644 index c09fe0fd1..000000000 --- a/app/src/main/java/com/fastaccess/provider/markdown/extension/mention/internal/MentionNodeRenderer.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.fastaccess.provider.markdown.extension.mention.internal; - -import com.fastaccess.provider.markdown.extension.mention.Mention; - -import org.commonmark.node.Node; -import org.commonmark.renderer.NodeRenderer; -import org.commonmark.renderer.html.HtmlNodeRendererContext; -import org.commonmark.renderer.html.HtmlWriter; - -import java.util.Collections; -import java.util.Map; -import java.util.Set; - -public class MentionNodeRenderer implements NodeRenderer { - - private final HtmlNodeRendererContext context; - private final HtmlWriter html; - - public MentionNodeRenderer(HtmlNodeRendererContext context) { - this.context = context; - this.html = context.getWriter(); - } - - @Override public Set> getNodeTypes() { - return Collections.singleton(Mention.class); - } - - @Override public void render(Node node) { - Map attributes = context.extendAttributes(node, "mention", Collections.emptyMap()); - html.tag("mention", attributes); - renderChildren(node); - html.tag("/mention"); - } - - private void renderChildren(Node parent) { - Node node = parent.getFirstChild(); - while (node != null) { - Node next = node.getNext(); - context.render(node); - node = next; - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/rest/ApolloProdivder.kt b/app/src/main/java/com/fastaccess/provider/rest/ApolloProdivder.kt deleted file mode 100644 index 230843348..000000000 --- a/app/src/main/java/com/fastaccess/provider/rest/ApolloProdivder.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.fastaccess.provider.rest - -import com.apollographql.apollo.ApolloClient -import com.fastaccess.BuildConfig -import com.fastaccess.helper.PrefGetter -import com.fastaccess.provider.scheme.LinkParserHelper - -/** - * Created by Hashemsergani on 12.09.17. - */ - -object ApolloProdivder { - - fun getApollo(enterprise: Boolean) = ApolloClient.builder() - .serverUrl("${if (enterprise && PrefGetter.isEnterprise()) { - "${LinkParserHelper.getEndpoint(PrefGetter.getEnterpriseUrl())}/" - } else { - BuildConfig.REST_URL - }}graphql") - .okHttpClient(RestProvider.provideOkHttpClient()) - .build() - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/rest/ImgurProvider.java b/app/src/main/java/com/fastaccess/provider/rest/ImgurProvider.java deleted file mode 100644 index cfabe1116..000000000 --- a/app/src/main/java/com/fastaccess/provider/rest/ImgurProvider.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.fastaccess.provider.rest; - -import android.support.annotation.NonNull; - -import com.fastaccess.BuildConfig; -import com.fastaccess.data.service.ImgurService; -import com.fastaccess.provider.rest.converters.GithubResponseConverter; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import java.lang.reflect.Modifier; - -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.logging.HttpLoggingInterceptor; -import retrofit2.Retrofit; -import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; - -/** - * Created by Kosh on 15 Apr 2017, 7:59 PM - */ - -public class ImgurProvider { - - public final static Gson gson = new GsonBuilder() - .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC) - .setPrettyPrinting() - .create(); - - private ImgurProvider() {} - - private static OkHttpClient provideOkHttpClient() { - OkHttpClient.Builder client = new OkHttpClient.Builder(); - if (BuildConfig.DEBUG) { - client.addInterceptor(new HttpLoggingInterceptor() - .setLevel(HttpLoggingInterceptor.Level.BODY)); - } - client.addInterceptor(chain -> { - Request original = chain.request(); - Request.Builder requestBuilder = original.newBuilder(); - requestBuilder.header("Authorization", "Client-ID " + BuildConfig.IMGUR_CLIENT_ID); - requestBuilder.method(original.method(), original.body()); - Request request = requestBuilder.build(); - return chain.proceed(request); - }); - return client.build(); - } - - private static Retrofit provideRetrofit() { - return new Retrofit.Builder() - .baseUrl(BuildConfig.IMGUR_URL) - .client(provideOkHttpClient()) - .addConverterFactory(new GithubResponseConverter(gson)) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .build(); - } - - @NonNull public static ImgurService getImgurService() { - return provideRetrofit().create(ImgurService.class); - } - -} diff --git a/app/src/main/java/com/fastaccess/provider/rest/LoginProvider.java b/app/src/main/java/com/fastaccess/provider/rest/LoginProvider.java deleted file mode 100644 index 383825f1b..000000000 --- a/app/src/main/java/com/fastaccess/provider/rest/LoginProvider.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.fastaccess.provider.rest; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.BuildConfig; -import com.fastaccess.data.service.LoginRestService; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.converters.GithubResponseConverter; -import com.fastaccess.provider.rest.interceptors.AuthenticationInterceptor; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.google.gson.FieldNamingPolicy; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import java.lang.reflect.Modifier; - -import okhttp3.OkHttpClient; -import okhttp3.logging.HttpLoggingInterceptor; -import retrofit2.Retrofit; -import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; - -/** - * Created by Kosh on 08 Feb 2017, 8:37 PM - */ - -public class LoginProvider { - - private final static Gson gson = new GsonBuilder() - .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) - .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC) - .setDateFormat("yyyy-MM-dd HH:mm:ss") - .setPrettyPrinting() - .create(); - - private static OkHttpClient provideOkHttpClient(@Nullable String authToken, @Nullable String otp) { - OkHttpClient.Builder client = new OkHttpClient.Builder(); - if (BuildConfig.DEBUG) { - client.addInterceptor(new HttpLoggingInterceptor() - .setLevel(HttpLoggingInterceptor.Level.BODY)); - } - client.addInterceptor(new AuthenticationInterceptor(authToken, otp)); - return client.build(); - } - - private static Retrofit provideRetrofit(@Nullable String authToken, @Nullable String otp, @Nullable String enterpriseUrl) { - return new Retrofit.Builder() - .baseUrl(InputHelper.isEmpty(enterpriseUrl) ? BuildConfig.REST_URL : LinkParserHelper.getEndpoint(enterpriseUrl)) - .client(provideOkHttpClient(authToken, otp)) - .addConverterFactory(new GithubResponseConverter(gson)) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .build(); - } - - public static LoginRestService getLoginRestService() { - return new Retrofit.Builder() - .baseUrl("https://github.com/login/oauth/") - .client(provideOkHttpClient(null, null)) - .addConverterFactory(new GithubResponseConverter(gson)) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .build() - .create(LoginRestService.class); - } - - @NonNull public static LoginRestService getLoginRestService(@NonNull String authToken, @Nullable String otp, - @Nullable String endpoint) { - return provideRetrofit(authToken, otp, endpoint).create(LoginRestService.class); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/rest/RepoQueryProvider.java b/app/src/main/java/com/fastaccess/provider/rest/RepoQueryProvider.java deleted file mode 100644 index 65adb2ae8..000000000 --- a/app/src/main/java/com/fastaccess/provider/rest/RepoQueryProvider.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.fastaccess.provider.rest; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.types.IssueState; - -/** - * Created by Kosh on 23 Mar 2017, 7:26 PM - */ - -public class RepoQueryProvider { - @NonNull public static String getIssuesPullRequestQuery(@NonNull String owner, @NonNull String repo, - @NonNull IssueState issueState, boolean isPr) { - return "+" + "type:" + (isPr ? "pr" : "issue") + - "+" + "repo:" + owner + "/" + - repo + "+" + "is:" + issueState.name(); - } - - @NonNull public static String getMyIssuesPullRequestQuery(@NonNull String username, @NonNull IssueState issueState, boolean isPr) { - return "type:" + (isPr ? "pr" : "issue") + - "+" + "author:" + username + - "+is:" + issueState.name(); - } - - @NonNull public static String getAssigned(@NonNull String username, @NonNull IssueState issueState, boolean isPr) { - return "type:" + (isPr ? "pr" : "issue") + - "+" + "assignee:" + username + - "+is:" + issueState.name(); - } - - @NonNull public static String getMentioned(@NonNull String username, @NonNull IssueState issueState, boolean isPr) { - return "type:" + (isPr ? "pr" : "issue") + - "+" + "mentions:" + username + - "+is:" + issueState.name(); - } - - @NonNull public static String getReviewRequests(@NonNull String username, @NonNull IssueState issueState) { - return "type:pr" + - "+" + "review-requested:" + username + - "+is:" + issueState.name(); - } - - public static String getParticipated(@NonNull String username, @NonNull IssueState issueState, boolean isPr) { - return "type:" + (isPr ? "pr" : "issue") + - "+" + "involves:" + username + - "+is:" + issueState.name(); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/rest/RestProvider.java b/app/src/main/java/com/fastaccess/provider/rest/RestProvider.java deleted file mode 100644 index 6fb75871d..000000000 --- a/app/src/main/java/com/fastaccess/provider/rest/RestProvider.java +++ /dev/null @@ -1,224 +0,0 @@ -package com.fastaccess.provider.rest; - -import android.app.DownloadManager; -import android.content.Context; -import android.net.Uri; -import android.os.Environment; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import android.widget.Toast; - -import com.fastaccess.App; -import com.fastaccess.BuildConfig; -import com.fastaccess.R; -import com.fastaccess.data.dao.GitHubErrorResponse; -import com.fastaccess.data.dao.GitHubStatusModel; -import com.fastaccess.data.service.ContentService; -import com.fastaccess.data.service.GistService; -import com.fastaccess.data.service.IssueService; -import com.fastaccess.data.service.NotificationService; -import com.fastaccess.data.service.OrganizationService; -import com.fastaccess.data.service.ProjectsService; -import com.fastaccess.data.service.PullRequestService; -import com.fastaccess.data.service.ReactionsService; -import com.fastaccess.data.service.RepoService; -import com.fastaccess.data.service.ReviewService; -import com.fastaccess.data.service.SearchService; -import com.fastaccess.data.service.SlackService; -import com.fastaccess.data.service.UserRestService; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.rest.converters.GithubResponseConverter; -import com.fastaccess.provider.rest.interceptors.AuthenticationInterceptor; -import com.fastaccess.provider.rest.interceptors.ContentTypeInterceptor; -import com.fastaccess.provider.rest.interceptors.PaginationInterceptor; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.google.gson.FieldNamingPolicy; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import java.io.File; -import java.lang.reflect.Modifier; - -import io.reactivex.Observable; -import okhttp3.OkHttpClient; -import okhttp3.ResponseBody; -import okhttp3.logging.HttpLoggingInterceptor; -import retrofit2.HttpException; -import retrofit2.Retrofit; -import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; - -/** - * Created by Kosh on 08 Feb 2017, 8:37 PM - */ - -public class RestProvider { - - public static final int PAGE_SIZE = 30; - - private static OkHttpClient okHttpClient; - public final static Gson gson = new GsonBuilder() - .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) - .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC) - .setDateFormat("yyyy-MM-dd HH:mm:ss") - .disableHtmlEscaping() - .setPrettyPrinting() - .create(); - - public static OkHttpClient provideOkHttpClient() { - if (okHttpClient == null) { - OkHttpClient.Builder client = new OkHttpClient.Builder(); - if (BuildConfig.DEBUG) { - client.addInterceptor(new HttpLoggingInterceptor() - .setLevel(HttpLoggingInterceptor.Level.BODY)); - } - client.addInterceptor(new AuthenticationInterceptor()); - client.addInterceptor(new PaginationInterceptor()); - client.addInterceptor(new ContentTypeInterceptor()); - okHttpClient = client.build(); - } - return okHttpClient; - } - - private static Retrofit provideRetrofit(boolean enterprise) { - return new Retrofit.Builder() - .baseUrl(enterprise && PrefGetter.isEnterprise() ? LinkParserHelper.getEndpoint(PrefGetter.getEnterpriseUrl()) : BuildConfig.REST_URL) - .client(provideOkHttpClient()) - .addConverterFactory(new GithubResponseConverter(gson)) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .build(); - } - - public static void downloadFile(@NonNull Context context, @NonNull String url) { - if (InputHelper.isEmpty(url)) return; - boolean isEnterprise = LinkParserHelper.isEnterprise(url); - Uri uri = Uri.parse(url); - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - DownloadManager.Request request = new DownloadManager.Request(uri); - String authToken = isEnterprise ? PrefGetter.getEnterpriseToken() : PrefGetter.getToken(); - if (!TextUtils.isEmpty(authToken)) { - request.addRequestHeader("Authorization", authToken.startsWith("Basic") ? authToken : "token " + authToken); - } - File direct = new File(Environment.getExternalStorageDirectory() + File.separator + context.getString(R.string.app_name)); - if (!direct.isDirectory() || !direct.exists()) { - boolean isCreated = direct.mkdirs(); - if (!isCreated) { - Toast.makeText(App.getInstance(), "Unable to create directory to download file", Toast.LENGTH_SHORT).show(); - return; - } - } - String fileName = new File(url).getName(); - request.setDestinationInExternalPublicDir(context.getString(R.string.app_name), fileName); - request.setTitle(fileName); - request.setDescription(context.getString(R.string.downloading_file)); - request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI); - request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); - if (downloadManager != null) { - downloadManager.enqueue(request); - } - } - - public static int getErrorCode(Throwable throwable) { - if (throwable instanceof HttpException) { - return ((HttpException) throwable).code(); - - } - return -1; - } - - @NonNull public static UserRestService getUserService(boolean enterprise) { - return provideRetrofit(enterprise).create(UserRestService.class); - } - - @NonNull public static GistService getGistService(boolean enterprise) { - return provideRetrofit(enterprise).create(GistService.class); - } - - @NonNull public static RepoService getRepoService(boolean enterprise) { - return provideRetrofit(enterprise).create(RepoService.class); - } - - @NonNull public static IssueService getIssueService(boolean enterprise) { - return provideRetrofit(enterprise).create(IssueService.class); - } - - @NonNull public static PullRequestService getPullRequestService(boolean enterprise) { - return provideRetrofit(enterprise).create(PullRequestService.class); - } - - @NonNull public static NotificationService getNotificationService(boolean enterprise) { - return provideRetrofit(enterprise).create(NotificationService.class); - } - - @NonNull public static ReactionsService getReactionsService(boolean enterprise) { - return provideRetrofit(enterprise).create(ReactionsService.class); - } - - @NonNull public static OrganizationService getOrgService(boolean enterprise) { - return provideRetrofit(enterprise).create(OrganizationService.class); - } - - @NonNull public static ReviewService getReviewService(boolean enterprise) { - return provideRetrofit(enterprise).create(ReviewService.class); - } - - @NonNull public static UserRestService getContribution() { - return new Retrofit.Builder() - .baseUrl(BuildConfig.REST_URL) - .addConverterFactory(new GithubResponseConverter(gson)) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .build() - .create(UserRestService.class); - } - - @NonNull public static SearchService getSearchService(boolean enterprise) { - return provideRetrofit(enterprise).create(SearchService.class); - } - - @NonNull public static SlackService getSlackService() { - return new Retrofit.Builder() - .baseUrl("https://ok13pknpj4.execute-api.eu-central-1.amazonaws.com/prod/") - .addConverterFactory(new GithubResponseConverter(gson)) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .build() - .create(SlackService.class); - } - - @NonNull public static ContentService getContentService(boolean enterprise) { - return provideRetrofit(enterprise).create(ContentService.class); - } - - @NonNull public static ProjectsService getProjectsService(boolean enterprise) { - return provideRetrofit(enterprise).create(ProjectsService.class); - } - - @Nullable public static GitHubErrorResponse getErrorResponse(@NonNull Throwable throwable) { - ResponseBody body = null; - if (throwable instanceof HttpException) { - body = ((HttpException) throwable).response().errorBody(); - } - if (body != null) { - try { - return gson.fromJson(body.string(), GitHubErrorResponse.class); - } catch (Exception ignored) {} - } - return null; - } - - @NonNull public static Observable gitHubStatus() { - return new Retrofit.Builder() - .baseUrl("https://status.github.com/") - .client(provideOkHttpClient()) - .addConverterFactory(new GithubResponseConverter(gson)) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .build() - .create(ContentService.class) - .checkStatus(); - } - - public static void clearHttpClient() { - okHttpClient = null; - } - -} diff --git a/app/src/main/java/com/fastaccess/provider/rest/converters/GithubResponseConverter.java b/app/src/main/java/com/fastaccess/provider/rest/converters/GithubResponseConverter.java deleted file mode 100644 index 630f6e777..000000000 --- a/app/src/main/java/com/fastaccess/provider/rest/converters/GithubResponseConverter.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.fastaccess.provider.rest.converters; - -import android.support.annotation.NonNull; - -import com.google.gson.Gson; - -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; - -import lombok.AllArgsConstructor; -import okhttp3.RequestBody; -import okhttp3.ResponseBody; -import retrofit2.Converter; -import retrofit2.Retrofit; -import retrofit2.converter.gson.GsonConverterFactory; - - -/** - * call that supports String & Gson and always uses json as its request body - */ -@AllArgsConstructor -public class GithubResponseConverter extends Converter.Factory { - private Gson gson; - - @Override public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { - try { - if (type == String.class) { - return new StringResponseConverter(); - } - return GsonConverterFactory.create(gson).responseBodyConverter(type, annotations, retrofit); - } catch (OutOfMemoryError ignored) { - return null; - } - } - - @Override public Converter requestBodyConverter(Type type, Annotation[] parameterAnnotations, - Annotation[] methodAnnotations, Retrofit retrofit) { - return GsonConverterFactory.create(gson).requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit); - } - - private static class StringResponseConverter implements Converter { - @Override public String convert(@NonNull ResponseBody value) throws IOException { - return value.string(); - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/rest/interceptors/AuthenticationInterceptor.kt b/app/src/main/java/com/fastaccess/provider/rest/interceptors/AuthenticationInterceptor.kt deleted file mode 100644 index 5e381a549..000000000 --- a/app/src/main/java/com/fastaccess/provider/rest/interceptors/AuthenticationInterceptor.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.fastaccess.provider.rest.interceptors - -import com.fastaccess.helper.Logger -import com.fastaccess.helper.PrefGetter -import com.fastaccess.provider.scheme.LinkParserHelper -import okhttp3.Interceptor -import okhttp3.Response -import java.io.IOException - -class AuthenticationInterceptor : Interceptor { - private var isScrapping: Boolean = false - private var token: String? = null - private var otp: String? = null - - constructor(token: String? = null, otp: String? = null) { - this.token = token - this.otp = otp - } - - @JvmOverloads constructor(isScrapping: Boolean = false) { - this.isScrapping = isScrapping - } - - @Throws(IOException::class) override fun intercept(chain: Interceptor.Chain): Response { - val original = chain.request() - val builder = original.newBuilder() - val isEnterprise = LinkParserHelper.isEnterprise(original.url().host()) - val authToken = if (token.isNullOrBlank()) if (isEnterprise) PrefGetter.getEnterpriseToken() else PrefGetter.getToken() else token - val otpCode = if (otp.isNullOrBlank()) if (isEnterprise) PrefGetter.getEnterpriseOtpCode() else PrefGetter.getOtpCode() else otp - if (!authToken.isNullOrBlank()) { - builder.header("Authorization", if (authToken!!.startsWith("Basic")) authToken else "token " + authToken) - } - if (!otpCode.isNullOrBlank()) { - builder.addHeader("X-GitHub-OTP", otpCode!!.trim()) - } - if (!isScrapping) builder.addHeader("User-Agent", "FastHub") - val request = builder.build() - return chain.proceed(request) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/rest/interceptors/ContentTypeInterceptor.kt b/app/src/main/java/com/fastaccess/provider/rest/interceptors/ContentTypeInterceptor.kt deleted file mode 100644 index 263c378b0..000000000 --- a/app/src/main/java/com/fastaccess/provider/rest/interceptors/ContentTypeInterceptor.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.fastaccess.provider.rest.interceptors - -import okhttp3.Interceptor -import okhttp3.Response - -/** - * Created by Kosh on 05 Jul 2017, 8:14 PM - */ - -class ContentTypeInterceptor : Interceptor { - override fun intercept(chain: Interceptor.Chain): Response { - val request = chain.request() - return chain.proceed(request.newBuilder() - .addHeader("Accept", "application/vnd.github.v3+json") - .addHeader("Content-type", "application/vnd.github.v3+json") - .method(request.method(), request.body()) - .build()) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/rest/interceptors/PaginationInterceptor.java b/app/src/main/java/com/fastaccess/provider/rest/interceptors/PaginationInterceptor.java deleted file mode 100644 index 4875f0c84..000000000 --- a/app/src/main/java/com/fastaccess/provider/rest/interceptors/PaginationInterceptor.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.fastaccess.provider.rest.interceptors; - -import android.net.Uri; -import android.support.annotation.NonNull; - -import com.fastaccess.helper.InputHelper; - -import java.io.IOException; - -import okhttp3.Headers; -import okhttp3.Interceptor; -import okhttp3.Request; -import okhttp3.Response; -import okhttp3.ResponseBody; - -public class PaginationInterceptor implements Interceptor { - - @Override public Response intercept(@NonNull Chain chain) throws IOException { - Request request = chain.request(); - Response response = chain.proceed(request); - Headers headers = chain.request().headers(); - if (headers != null) { - if ((headers.values("Accept").contains("application/vnd.github.html") || - headers.values("Accept").contains("application/vnd.github.VERSION.raw"))) { - return response;//return them as they are. - } - } - if (response.isSuccessful()) { - if (response.peekBody(1).string().equals("[")) { - String json = "{"; - String link = response.header("link"); - if (link != null) { - String[] links = link.split(","); - for (String link1 : links) { - String[] pageLink = link1.split(";"); - String page = Uri.parse(pageLink[0].replaceAll("[<>]", "")).getQueryParameter("page"); - String rel = pageLink[1].replaceAll("\"", "").replace("rel=", ""); - if (page != null) json += String.format("\"%s\":\"%s\",", rel.trim(), page); - } - } - json += String.format("\"items\":%s}", response.body().string()); - return response.newBuilder().body(ResponseBody.create(response.body().contentType(), json)).build(); - } else if (response.header("link") != null) { - String link = response.header("link"); - String pagination = ""; - String[] links = link.split(","); - for (String link1 : links) { - String[] pageLink = link1.split(";"); - String page = Uri.parse(pageLink[0].replaceAll("[<>]", "")).getQueryParameter("page"); - String rel = pageLink[1].replaceAll("\"", "").replace("rel=", ""); - if (page != null) pagination += String.format("\"%s\":\"%s\",", rel.trim(), page); - } - if (!InputHelper.isEmpty(pagination)) {//hacking for search pagination. - String body = response.body().string(); - return response.newBuilder().body(ResponseBody.create(response.body().contentType(), - "{" + pagination + body.substring(1, body.length()))).build(); - } - } - } - return response; - } - -} diff --git a/app/src/main/java/com/fastaccess/provider/rest/jsoup/JsoupProvider.java b/app/src/main/java/com/fastaccess/provider/rest/jsoup/JsoupProvider.java deleted file mode 100644 index c95d4be40..000000000 --- a/app/src/main/java/com/fastaccess/provider/rest/jsoup/JsoupProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.fastaccess.provider.rest.jsoup; - -import com.fastaccess.BuildConfig; -import com.fastaccess.data.service.ScrapService; -import com.fastaccess.provider.rest.converters.GithubResponseConverter; -import com.fastaccess.provider.rest.interceptors.AuthenticationInterceptor; -import com.google.gson.Gson; - -import okhttp3.OkHttpClient; -import okhttp3.logging.HttpLoggingInterceptor; -import retrofit2.Retrofit; -import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; - -/** - * Created by Kosh on 02 Jun 2017, 12:47 PM - */ - -public class JsoupProvider { - - private static OkHttpClient okHttpClient; - - private static OkHttpClient provideOkHttpClient() { - if (okHttpClient == null) { - OkHttpClient.Builder client = new OkHttpClient.Builder(); - if (BuildConfig.DEBUG) { - client.addInterceptor(new HttpLoggingInterceptor() - .setLevel(HttpLoggingInterceptor.Level.BODY)); - } - client.addInterceptor(new AuthenticationInterceptor(true)); - okHttpClient = client.build(); - } - return okHttpClient; - } - - public static ScrapService getTrendingService() { - return new Retrofit.Builder() - .baseUrl("https://github.com/trending/") - .client(provideOkHttpClient()) - .addConverterFactory(new GithubResponseConverter(new Gson())) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .build() - .create(ScrapService.class); - } - - public static ScrapService getWiki() { - return new Retrofit.Builder() - .baseUrl("https://github.com/") - .client(provideOkHttpClient()) - .addConverterFactory(new GithubResponseConverter(new Gson())) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .build() - .create(ScrapService.class); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/rest/loadmore/OnLoadMore.java b/app/src/main/java/com/fastaccess/provider/rest/loadmore/OnLoadMore.java deleted file mode 100644 index f0d77da74..000000000 --- a/app/src/main/java/com/fastaccess/provider/rest/loadmore/OnLoadMore.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fastaccess.provider.rest.loadmore; - -import android.support.annotation.Nullable; - -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.scroll.InfiniteScroll; - -public class OnLoadMore

    extends InfiniteScroll { - - private BaseMvp.PaginationListener

    presenter; - @Nullable private P parameter; - - public OnLoadMore(BaseMvp.PaginationListener

    presenter) { - this(presenter, null); - } - - public OnLoadMore(BaseMvp.PaginationListener

    presenter, @Nullable P parameter) { - super(); - this.presenter = presenter; - this.parameter = parameter; - } - - - public void setParameter(@Nullable P parameter) { - this.parameter = parameter; - } - - @Nullable public P getParameter() { - return parameter; - } - - @Override public boolean onLoadMore(int page, int totalItemsCount) { - if (presenter != null) { - presenter.setPreviousTotal(totalItemsCount); - return presenter.onCallApi(page + 1, parameter); - } - return false; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/scheme/LinkParserHelper.java b/app/src/main/java/com/fastaccess/provider/scheme/LinkParserHelper.java deleted file mode 100644 index 5a0bfab6d..000000000 --- a/app/src/main/java/com/fastaccess/provider/scheme/LinkParserHelper.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.fastaccess.provider.scheme; - -import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import android.webkit.MimeTypeMap; - -import com.annimon.stream.Optional; -import com.annimon.stream.Stream; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ObjectsCompat; -import com.fastaccess.helper.PrefGetter; - -import java.util.Arrays; -import java.util.List; - -/** - * Created by Kosh on 11 Apr 2017, 10:02 PM - */ - -public class LinkParserHelper { - public static final String HOST_DEFAULT = "github.com"; - public static final String PROTOCOL_HTTPS = "https"; - static final String HOST_GISTS = "gist.github.com"; - static final String HOST_GISTS_RAW = "gist.githubusercontent.com"; - static final String RAW_AUTHORITY = "raw.githubusercontent.com"; - static final String API_AUTHORITY = "api.github.com"; - static final List IGNORED_LIST = Arrays.asList("notifications", "settings", "blog", - "explore", "dashboard", "repositories", "logout", "sessions", "site", "security", - "contact", "about", "logos", "login", "pricing", ""); - - @SafeVarargs static Optional returnNonNull(@NonNull T... t) { - return Stream.of(t).filter(ObjectsCompat::nonNull).findFirst(); - } - - @NonNull static Uri getBlobBuilder(@NonNull Uri uri) { - boolean isSvg = "svg".equalsIgnoreCase(MimeTypeMap.getFileExtensionFromUrl(uri.toString())); - List segments = uri.getPathSegments(); - if (isSvg) { - Uri svgBlob = Uri.parse(uri.toString().replace("blob/", "")); - return svgBlob.buildUpon().authority(RAW_AUTHORITY).build(); - } - Uri.Builder urlBuilder = new Uri.Builder(); - String owner = segments.get(0); - String repo = segments.get(1); - String branch = segments.get(3); - urlBuilder.scheme("https") - .authority(API_AUTHORITY) - .appendPath("repos") - .appendPath(owner) - .appendPath(repo) - .appendPath("contents"); - for (int i = 4; i < segments.size(); i++) { - urlBuilder.appendPath(segments.get(i)); - } - if (uri.getQueryParameterNames() != null) { - for (String query : uri.getQueryParameterNames()) { - urlBuilder.appendQueryParameter(query, uri.getQueryParameter(query)); - } - } - if (uri.getEncodedFragment() != null) { - urlBuilder.encodedFragment(uri.getEncodedFragment()); - } - urlBuilder.appendQueryParameter("ref", branch); - return urlBuilder.build(); - } - - public static boolean isEnterprise(@Nullable String url) { - if (InputHelper.isEmpty(url) || !PrefGetter.isEnterprise()) return false; - String enterpriseUrl = PrefGetter.getEnterpriseUrl().toLowerCase(); - url = url.toLowerCase(); - return url.equalsIgnoreCase(enterpriseUrl) || url.startsWith(enterpriseUrl) || url.startsWith(getEndpoint(enterpriseUrl)) - || url.contains(enterpriseUrl) || enterpriseUrl.contains(url); - } - - public static String stripScheme(@NonNull String url) { - try { - Uri uri = Uri.parse(url); - return !InputHelper.isEmpty(uri.getAuthority()) ? uri.getAuthority() : url; - } catch (Exception ignored) {} - return url; - } - - @NonNull public static String getEndpoint(@NonNull String url) { - if (url.startsWith("http://")) { - url = url.replace("http://", "https://"); - } - if (!url.startsWith("https://")) { - url = "https://" + url; - } - return getEnterpriseUrl(url); - } - - @NonNull private static String getEnterpriseUrl(@NonNull String url) { - if (url.endsWith("/api/v3/")) { - return url; - } else if (url.endsWith("/api/")) { - return url + "v3/"; - } else if (url.endsWith("/api")) { - return url + "/v3/"; - } else if (url.endsWith("/api/v3")) { - return url + "/"; - } else if (!url.endsWith("/")) { - return url + "/api/v3/"; - } else if (url.endsWith("/")) { - return url + "api/v3/"; - } - return url; - } - - public static String getEnterpriseGistUrl(@NonNull String url, boolean isEnterprise) { - if (isEnterprise) { - Uri uri = Uri.parse(url); - boolean isGist = uri == null || uri.getPathSegments() == null ? url.contains("gist/") : uri.getPathSegments().get(0).equals("gist"); - if (isGist) { - String enterpriseUrl = PrefGetter.getEnterpriseUrl(); - if (!url.contains(enterpriseUrl + "/raw/")) { - url = url.replace(enterpriseUrl, enterpriseUrl + "/raw"); - } - } - } - return url; - } - - @Nullable public static String getGistId(@NonNull Uri uri) { - String gistId = null; - if (uri.toString().contains("raw/gist")) { - if (uri.getPathSegments().size() > 5) { - gistId = uri.getPathSegments().get(5); - } - } else if (uri.getPathSegments() != null) { - if (TextUtils.equals(LinkParserHelper.HOST_GISTS_RAW, uri.getAuthority())) { - if (uri.getPathSegments().size() > 1) { - gistId = uri.getPathSegments().get(1); - } - } - } - return gistId; - } -} diff --git a/app/src/main/java/com/fastaccess/provider/scheme/SchemeParser.java b/app/src/main/java/com/fastaccess/provider/scheme/SchemeParser.java deleted file mode 100644 index 250131a0b..000000000 --- a/app/src/main/java/com/fastaccess/provider/scheme/SchemeParser.java +++ /dev/null @@ -1,578 +0,0 @@ -package com.fastaccess.provider.scheme; - -import android.app.Activity; -import android.app.Application; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import android.webkit.MimeTypeMap; - -import com.annimon.stream.Optional; -import com.annimon.stream.Stream; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.markdown.MarkDownProvider; -import com.fastaccess.ui.modules.code.CodeViewerActivity; -import com.fastaccess.ui.modules.filter.issues.FilterIssuesActivity; -import com.fastaccess.ui.modules.gists.gist.GistActivity; -import com.fastaccess.ui.modules.repos.RepoPagerActivity; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.code.commit.details.CommitPagerActivity; -import com.fastaccess.ui.modules.repos.code.files.activity.RepoFilesActivity; -import com.fastaccess.ui.modules.repos.code.releases.ReleasesListActivity; -import com.fastaccess.ui.modules.repos.issues.create.CreateIssueActivity; -import com.fastaccess.ui.modules.repos.issues.issue.details.IssuePagerActivity; -import com.fastaccess.ui.modules.repos.projects.details.ProjectPagerActivity; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.PullRequestPagerActivity; -import com.fastaccess.ui.modules.repos.wiki.WikiActivity; -import com.fastaccess.ui.modules.search.SearchActivity; -import com.fastaccess.ui.modules.trending.TrendingActivity; -import com.fastaccess.ui.modules.user.UserPagerActivity; - -import java.util.List; - -import static com.fastaccess.provider.scheme.LinkParserHelper.API_AUTHORITY; -import static com.fastaccess.provider.scheme.LinkParserHelper.HOST_DEFAULT; -import static com.fastaccess.provider.scheme.LinkParserHelper.HOST_GISTS; -import static com.fastaccess.provider.scheme.LinkParserHelper.HOST_GISTS_RAW; -import static com.fastaccess.provider.scheme.LinkParserHelper.IGNORED_LIST; -import static com.fastaccess.provider.scheme.LinkParserHelper.PROTOCOL_HTTPS; -import static com.fastaccess.provider.scheme.LinkParserHelper.RAW_AUTHORITY; -import static com.fastaccess.provider.scheme.LinkParserHelper.getBlobBuilder; -import static com.fastaccess.provider.scheme.LinkParserHelper.returnNonNull; - -/** - * Created by Kosh on 09 Dec 2016, 4:44 PM - */ - -public class SchemeParser { - - public static void launchUri(@NonNull Context context, @NonNull String url) { - launchUri(context, Uri.parse(url), false); - } - - public static void launchUri(@NonNull Context context, @NonNull Uri data) { - launchUri(context, data, false); - } - - public static void launchUri(@NonNull Context context, @NonNull Uri data, boolean showRepoBtn) { - launchUri(context, data, showRepoBtn, false); - } - - public static void launchUri(@NonNull Context context, @NonNull Uri data, boolean showRepoBtn, boolean newDocument) { - Logger.e(data); - Intent intent = convert(context, data, showRepoBtn); - if (intent != null) { - intent.putExtra(BundleConstant.SCHEME_URL, data.toString()); - if (newDocument) { - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); - } - if (context instanceof Service || context instanceof Application) { - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } - context.startActivity(intent); - } else { - Activity activity = ActivityHelper.getActivity(context); - if (activity != null) { - ActivityHelper.startCustomTab(activity, data); - } else { - ActivityHelper.openChooser(context, data); - } - } - } - - @Nullable private static Intent convert(@NonNull Context context, Uri data, boolean showRepoBtn) { - if (data == null) return null; - if (InputHelper.isEmpty(data.getHost()) || InputHelper.isEmpty(data.getScheme())) { - String host = data.getHost(); - if (InputHelper.isEmpty(host)) host = HOST_DEFAULT; - String scheme = data.getScheme(); - if (InputHelper.isEmpty(scheme)) scheme = PROTOCOL_HTTPS; - String prefix = scheme + "://" + host; - String path = data.getPath(); - if (!InputHelper.isEmpty(path)) { - if (path.charAt(0) == '/') { - data = Uri.parse(prefix + path); - } else { - data = Uri.parse(prefix + '/' + path); - } - } else { - data = Uri.parse(prefix); - } - } - if (data.getPathSegments() != null && !data.getPathSegments().isEmpty()) { - if (IGNORED_LIST.contains(data.getPathSegments().get(0))) return null; - return getIntentForURI(context, data, showRepoBtn); - } - return null; - } - - @Nullable private static Intent getIntentForURI(@NonNull Context context, @NonNull Uri data, boolean showRepoBtn) { - String authority = data.getAuthority(); - boolean isEnterprise = PrefGetter.isEnterprise() && LinkParserHelper.isEnterprise(authority == null ? data.toString() : authority); - if (HOST_GISTS.equals(data.getHost()) || "gist".equalsIgnoreCase(data.getPathSegments().get(0))) { - String extension = MimeTypeMap.getFileExtensionFromUrl(data.toString()); - if (!InputHelper.isEmpty(extension) && !MarkDownProvider.isArchive(data.getLastPathSegment())) { - String url = data.toString(); - return CodeViewerActivity.createIntent(context, url, url); - } - String gist = getGistId(data); - if (gist != null) { - return GistActivity.createIntent(context, gist, isEnterprise); - } - } else if (HOST_GISTS_RAW.equalsIgnoreCase(data.getHost())) { - return getGistFile(context, data); - } else { - if (MarkDownProvider.isArchive(data.toString())) return null; - if (TextUtils.equals(authority, HOST_DEFAULT) || TextUtils.equals(authority, RAW_AUTHORITY) || - TextUtils.equals(authority, API_AUTHORITY) || isEnterprise) { - Intent trending = getTrending(context, data); - Intent projects = getRepoProject(context, data); - Intent userIntent = getUser(context, data); - Intent repoIssues = getRepoIssueIntent(context, data); - Intent repoPulls = getRepoPullRequestIntent(context, data); - Intent createIssueIntent = getCreateIssueIntent(context, data); - Intent pullRequestIntent = getPullRequestIntent(context, data, showRepoBtn); - Intent issueIntent = getIssueIntent(context, data, showRepoBtn); - Intent releasesIntent = getReleases(context, data, isEnterprise); - Intent repoIntent = getRepo(context, data); - Intent repoWikiIntent = getWiki(context, data); - Intent commit = getCommit(context, data, showRepoBtn); - Intent commits = getCommits(context, data, showRepoBtn); - Intent blob = getBlob(context, data); - Intent label = getLabel(context, data); - Intent search = getSearchIntent(context, data); - Optional intentOptional = returnNonNull(trending, projects, search, userIntent, repoIssues, repoPulls, - pullRequestIntent, label, commit, commits, createIssueIntent, issueIntent, releasesIntent, repoIntent, - repoWikiIntent, blob); - Optional empty = Optional.empty(); - if (intentOptional != null && intentOptional.isPresent() && intentOptional != empty) { - Intent intent = intentOptional.get(); - if (isEnterprise) { - if (intent.getExtras() != null) { - Bundle bundle = intent.getExtras(); - bundle.putBoolean(BundleConstant.IS_ENTERPRISE, true); - intent.putExtras(bundle); - } else { - intent.putExtra(BundleConstant.IS_ENTERPRISE, true); - } - } - return intent; - } else { - Intent intent = getGeneralRepo(context, data); - if (isEnterprise) { - if (intent != null && intent.getExtras() != null) { - Bundle bundle = intent.getExtras(); - bundle.putBoolean(BundleConstant.IS_ENTERPRISE, true); - intent.putExtras(bundle); - } else if (intent != null) { - intent.putExtra(BundleConstant.IS_ENTERPRISE, true); - } - } - return intent; - } - } - } - return null; - } - - private static boolean getInvitationIntent(@NonNull Uri uri) { - List segments = uri.getPathSegments(); - return (segments != null && segments.size() == 3) && "invitations".equalsIgnoreCase(uri.getLastPathSegment()); - } - - @Nullable private static Intent getPullRequestIntent(@NonNull Context context, @NonNull Uri uri, boolean showRepoBtn) { - List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 3) return null; - String owner = null; - String repo = null; - String number = null; - String fragment = uri.getEncodedFragment();//#issuecomment-332236665 - Long commentId = null; - if (!InputHelper.isEmpty(fragment) && fragment.split("-").length > 1) { - fragment = fragment.split("-")[1]; - if (!InputHelper.isEmpty(fragment)) { - try { - commentId = Long.parseLong(fragment); - } catch (Exception ignored) {} - } - } - if (segments.size() > 3) { - if (("pull".equals(segments.get(2)) || "pulls".equals(segments.get(2)))) { - owner = segments.get(0); - repo = segments.get(1); - number = segments.get(3); - } else if (("pull".equals(segments.get(3)) || "pulls".equals(segments.get(3))) && segments.size() > 4) { - owner = segments.get(1); - repo = segments.get(2); - number = segments.get(4); - } else { - return null; - } - } - if (InputHelper.isEmpty(number)) return null; - int issueNumber; - try { - issueNumber = Integer.parseInt(number); - } catch (NumberFormatException nfe) { - return null; - } - if (issueNumber < 1) return null; - return PullRequestPagerActivity.createIntent(context, repo, owner, issueNumber, showRepoBtn, - LinkParserHelper.isEnterprise(uri.toString()), commentId == null ? 0 : commentId); - } - - @Nullable private static Intent getIssueIntent(@NonNull Context context, @NonNull Uri uri, boolean showRepoBtn) { - List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 3) return null; - String owner = null; - String repo = null; - String number = null; - String fragment = uri.getEncodedFragment();//#issuecomment-332236665 - Long commentId = null; - if (!InputHelper.isEmpty(fragment) && fragment.split("-").length > 1) { - fragment = fragment.split("-")[1]; - if (!InputHelper.isEmpty(fragment)) { - try { - commentId = Long.parseLong(fragment); - } catch (Exception ignored) {} - } - } - if (segments.size() > 3) { - if (segments.get(2).equalsIgnoreCase("issues")) { - owner = segments.get(0); - repo = segments.get(1); - number = segments.get(3); - } else if (segments.get(3).equalsIgnoreCase("issues") && segments.size() > 4) { - owner = segments.get(1); - repo = segments.get(2); - number = segments.get(4); - } else { - return null; - } - } - if (InputHelper.isEmpty(number)) - return null; - int issueNumber; - try { - issueNumber = Integer.parseInt(number); - } catch (NumberFormatException nfe) { - return null; - } - if (issueNumber < 1) return null; - return IssuePagerActivity.createIntent(context, repo, owner, issueNumber, showRepoBtn, - LinkParserHelper.isEnterprise(uri.toString()), commentId == null ? 0 : commentId); - } - - @Nullable private static Intent getLabel(@NonNull Context context, @NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 3) return null; - String owner = segments.get(0); - String repoName = segments.get(1); - String lastPath = segments.get(2); - if ("labels".equalsIgnoreCase(lastPath)) { - return FilterIssuesActivity.getIntent(context, owner, repoName, "label:\"" + segments.get(3) + "\""); - } - return null; - } - - @Nullable private static Intent getRepo(@NonNull Context context, @NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 2 || segments.size() > 3) return null; - String owner = segments.get(0); - String repoName = segments.get(1); - if (!InputHelper.isEmpty(repoName)) { - if (repoName.endsWith(".git")) repoName = repoName.replace(".git", ""); - } - if (segments.size() == 3) { - String lastPath = uri.getLastPathSegment(); - if ("milestones".equalsIgnoreCase(lastPath)) { - return RepoPagerActivity.createIntent(context, repoName, owner, RepoPagerMvp.CODE, 4); - } else if ("network".equalsIgnoreCase(lastPath)) { - return RepoPagerActivity.createIntent(context, repoName, owner, RepoPagerMvp.CODE, 3); - } else if ("stargazers".equalsIgnoreCase(lastPath)) { - return RepoPagerActivity.createIntent(context, repoName, owner, RepoPagerMvp.CODE, 2); - } else if ("watchers".equalsIgnoreCase(lastPath)) { - return RepoPagerActivity.createIntent(context, repoName, owner, RepoPagerMvp.CODE, 1); - } else if ("labels".equalsIgnoreCase(lastPath)) { - return RepoPagerActivity.createIntent(context, repoName, owner, RepoPagerMvp.CODE, 5); - } else { - return null; - } - } else { - return RepoPagerActivity.createIntent(context, repoName, owner); - } - } - - @Nullable private static Intent getRepoProject(@NonNull Context context, @NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 3) return null; - String owner = segments.get(0); - String repoName = segments.get(1); - if (segments.size() == 3 && "projects".equalsIgnoreCase(segments.get(2))) { - return RepoPagerActivity.createIntent(context, repoName, owner, RepoPagerMvp.PROJECTS); - } else if (segments.size() == 4 && "projects".equalsIgnoreCase(segments.get(2))) { - try { - int projectId = Integer.parseInt(segments.get(segments.size() - 1)); - if (projectId > 0) { - return ProjectPagerActivity.Companion.getIntent(context, owner, repoName, projectId, - LinkParserHelper.isEnterprise(uri.toString())); - } - } catch (Exception ignored) {} - } - return null; - } - - @Nullable private static Intent getWiki(@NonNull Context context, @NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 3) return null; - if ("wiki".equalsIgnoreCase(segments.get(2))) { - String owner = segments.get(0); - String repoName = segments.get(1); - return WikiActivity.Companion.getWiki(context, repoName, owner, - "wiki".equalsIgnoreCase(uri.getLastPathSegment()) ? null : uri.getLastPathSegment()); - } - return null; - } - - /** - * [[k0shk0sh, FastHub, issues], k0shk0sh/fastHub/(issues,pulls,commits, etc)] - */ - @Nullable private static Intent getGeneralRepo(@NonNull Context context, @NonNull Uri uri) { - //TODO parse deeper links to their associate views. meantime fallback to repoPage - if (getInvitationIntent(uri)) { - return null; - } - boolean isEnterprise = PrefGetter.isEnterprise() && Uri.parse(LinkParserHelper.getEndpoint(PrefGetter.getEnterpriseUrl())).getAuthority() - .equalsIgnoreCase(uri.getAuthority()); - if (uri.getAuthority().equals(HOST_DEFAULT) || uri.getAuthority().equals(API_AUTHORITY) || isEnterprise) { - List segments = uri.getPathSegments(); - if (segments == null || segments.isEmpty()) return null; - if (segments.size() == 1) { - return getUser(context, uri); - } else if (segments.size() > 1) { - if (segments.get(0).equalsIgnoreCase("repos") && segments.size() >= 2) { - String owner = segments.get(1); - String repoName = segments.get(2); - return RepoPagerActivity.createIntent(context, repoName, owner); - } else if ("orgs".equalsIgnoreCase(segments.get(0))) { - return null; - } else { - String owner = segments.get(0); - String repoName = segments.get(1); - return RepoPagerActivity.createIntent(context, repoName, owner); - } - } - } - return null; - } - - @Nullable private static Intent getCommits(@NonNull Context context, @NonNull Uri uri, boolean showRepoBtn) { - List segments = Stream.of(uri.getPathSegments()) - .filter(value -> !value.equalsIgnoreCase("api") || !value.equalsIgnoreCase("v3")) - .toList(); - if (segments == null || segments.isEmpty() || segments.size() < 3) return null; - String login = null; - String repoId = null; - String sha = null; - if (segments.size() > 3 && segments.get(3).equals("commits")) { - login = segments.get(1); - repoId = segments.get(2); - sha = segments.get(4); - } else if (segments.size() > 2 && segments.get(2).equals("commits")) { - login = segments.get(0); - repoId = segments.get(1); - sha = uri.getLastPathSegment(); - } - if (login != null && sha != null && repoId != null) { - return CommitPagerActivity.createIntent(context, repoId, login, sha, showRepoBtn); - } - return null; - } - - @Nullable private static Intent getCommit(@NonNull Context context, @NonNull Uri uri, boolean showRepoBtn) { - List segments = Stream.of(uri.getPathSegments()) - .filter(value -> !value.equalsIgnoreCase("api") || !value.equalsIgnoreCase("v3")) - .toList(); - if (segments.size() < 3 || !"commit".equals(segments.get(2))) return null; - String login = segments.get(0); - String repoId = segments.get(1); - String sha = segments.get(3); - return CommitPagerActivity.createIntent(context, repoId, login, sha, showRepoBtn); - } - - @Nullable private static String getGistId(@NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (segments.size() != 1 && segments.size() != 2) return null; - String gistId = segments.get(segments.size() - 1); - if (InputHelper.isEmpty(gistId)) return null; - if (TextUtils.isDigitsOnly(gistId)) return gistId; - else if (gistId.matches("[a-fA-F0-9]+")) return gistId; - else return null; - } - - @Nullable private static Intent getUser(@NonNull Context context, @NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (segments != null && !segments.isEmpty() && segments.size() == 1) { - return UserPagerActivity.createIntent(context, segments.get(0)); - } else if (segments != null && !segments.isEmpty() && segments.size() > 1 && segments.get(0).equalsIgnoreCase("orgs")) { - if ("invitation".equalsIgnoreCase(uri.getLastPathSegment())) { - return null; - } else if ("search".equalsIgnoreCase(uri.getLastPathSegment())) { - String query = uri.getQueryParameter("q"); - return SearchActivity.getIntent(context, query); - } else { - return UserPagerActivity.createIntent(context, segments.get(1), true); - } - } - return null; - } - - @Nullable private static Intent getBlob(@NonNull Context context, @NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (segments == null || segments.size() < 4) return null; - String segmentTwo = segments.get(2); - String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString()); - if (InputHelper.isEmpty(extension) || TextUtils.isDigitsOnly(extension)) { - Uri urlBuilder = LinkParserHelper.getBlobBuilder(uri); - return RepoFilesActivity.getIntent(context, urlBuilder.toString()); - } - if (segmentTwo.equals("blob") || segmentTwo.equals("tree")) { - Uri urlBuilder = getBlobBuilder(uri); - Logger.e(urlBuilder); - return CodeViewerActivity.createIntent(context, urlBuilder.toString(), uri.toString()); - } else { - String authority = uri.getAuthority(); - if (TextUtils.equals(authority, RAW_AUTHORITY)) { - return CodeViewerActivity.createIntent(context, uri.toString(), uri.toString()); - } - } - return null; - } - - @Nullable private static Intent getRepoIssueIntent(@NonNull Context context, @NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (segments != null && segments.size() == 3 && uri.getLastPathSegment().equalsIgnoreCase("issues")) { - String owner = segments.get(0); - String repo = segments.get(1); - Uri encoded = Uri.parse(uri.toString().replace("utf8=%E2%9C%93&", "")); - if (encoded.getQueryParameter("q") != null) { - String query = encoded.getQueryParameter("q"); - return FilterIssuesActivity.getIntent(context, owner, repo, query); - } - return RepoPagerActivity.createIntent(context, repo, owner, RepoPagerMvp.ISSUES); - } - return null; - } - - @Nullable private static Intent getRepoPullRequestIntent(@NonNull Context context, @NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (segments != null && segments.size() == 3 && uri.getLastPathSegment().equalsIgnoreCase("pulls")) { - String owner = segments.get(0); - String repo = segments.get(1); - Uri encoded = Uri.parse(uri.toString().replace("utf8=%E2%9C%93&", "")); - if (encoded.getQueryParameter("q") != null) { - String query = encoded.getQueryParameter("q"); - return FilterIssuesActivity.getIntent(context, owner, repo, query); - } - return RepoPagerActivity.createIntent(context, repo, owner, RepoPagerMvp.PULL_REQUEST); - } - return null; - } - - @Nullable private static Intent getReleases(@NonNull Context context, @NonNull Uri uri, boolean isEnterprise) { - List segments = uri.getPathSegments(); - if (segments != null && segments.size() > 2) { - if (uri.getPathSegments().get(2).equals("releases")) { - String owner = segments.get(0); - String repo = segments.get(1); - String tag = uri.getLastPathSegment(); - if (tag != null && !repo.equalsIgnoreCase(tag)) { - if (TextUtils.isDigitsOnly(tag)) { - return ReleasesListActivity.getIntent(context, owner, repo, InputHelper.toLong(tag), isEnterprise); - } else { - return ReleasesListActivity.getIntent(context, owner, repo, tag, isEnterprise); - } - } - return ReleasesListActivity.getIntent(context, owner, repo); - } else if (segments.size() > 3 && segments.get(3).equalsIgnoreCase("releases")) { - String owner = segments.get(1); - String repo = segments.get(2); - String tag = uri.getLastPathSegment(); - if (tag != null && !repo.equalsIgnoreCase(tag)) { - if (TextUtils.isDigitsOnly(tag)) { - return ReleasesListActivity.getIntent(context, owner, repo, InputHelper.toLong(tag), isEnterprise); - } else { - return ReleasesListActivity.getIntent(context, owner, repo, tag, isEnterprise); - } - } - return ReleasesListActivity.getIntent(context, owner, repo); - } - return null; - } - return null; - } - - @Nullable private static Intent getTrending(@NonNull Context context, @NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (segments != null && !segments.isEmpty()) { - if (uri.getPathSegments().get(0).equals("trending")) { - String query = ""; - String lang = ""; - if (uri.getPathSegments().size() > 1) { - lang = uri.getPathSegments().get(1); - } - if (uri.getQueryParameterNames() != null && !uri.getQueryParameterNames().isEmpty()) { - query = uri.getQueryParameter("since"); - } - return TrendingActivity.Companion.getTrendingIntent(context, lang, query); - } - return null; - } - return null; - } - - /** - * https://github.com/owner/repo/issues/new - */ - @Nullable private static Intent getCreateIssueIntent(@NonNull Context context, @NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (uri.getLastPathSegment() == null) return null; - if (segments == null || segments.size() < 3 || !uri.getLastPathSegment().equalsIgnoreCase("new")) return null; - if ("issues".equals(segments.get(2))) { - String owner = segments.get(0); - String repo = segments.get(1); - boolean isFeedback = "k0shk0sh/FastHub".equalsIgnoreCase(owner + "/" + repo); - return CreateIssueActivity.getIntent(context, owner, repo, isFeedback); - } - return null; - } - - @Nullable private static Intent getGistFile(@NonNull Context context, @NonNull Uri uri) { - if (HOST_GISTS_RAW.equalsIgnoreCase(uri.getHost())) { - return CodeViewerActivity.createIntent(context, uri.toString(), uri.toString()); - } - return null; - } - - @Nullable private static Intent getSearchIntent(@NonNull Context context, @NonNull Uri uri) { - List segments = uri.getPathSegments(); - if (segments == null || segments.size() > 1) return null; - String search = segments.get(0); - if ("search".equalsIgnoreCase(search)) { - Uri encoded = Uri.parse(uri.toString().replace("utf8=%E2%9C%93&", "")); - String query = encoded.getQueryParameter("q"); - Logger.e(encoded, query); - return SearchActivity.getIntent(context, query); - } - return null; - } -} diff --git a/app/src/main/java/com/fastaccess/provider/tasks/git/GithubActionService.java b/app/src/main/java/com/fastaccess/provider/tasks/git/GithubActionService.java deleted file mode 100644 index 57fe9ed66..000000000 --- a/app/src/main/java/com/fastaccess/provider/tasks/git/GithubActionService.java +++ /dev/null @@ -1,235 +0,0 @@ -package com.fastaccess.provider.tasks.git; - -import android.app.IntentService; -import android.app.NotificationManager; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.IntDef; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.NotificationCompat; - -import com.fastaccess.R; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.RestProvider; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import io.reactivex.schedulers.Schedulers; - - -/** - * Created by Kosh on 12 Mar 2017, 2:25 PM - */ - -public class GithubActionService extends IntentService { - - public static final int STAR_REPO = 1; - public static final int UNSTAR_REPO = 2; - public static final int FORK_REPO = 3; - public static final int WATCH_REPO = 4; - public static final int UNWATCH_REPO = 5; - public static final int STAR_GIST = 6; - public static final int UNSTAR_GIST = 7; - public static final int FORK_GIST = 8; - private NotificationCompat.Builder notification; - private NotificationManager notificationManager; - - @IntDef({ - STAR_REPO, - UNSTAR_REPO, - FORK_REPO, - WATCH_REPO, - UNWATCH_REPO, - STAR_GIST, - UNSTAR_GIST, - FORK_GIST, - }) - @Retention(RetentionPolicy.SOURCE) @interface GitActionType {} - - public static void startForRepo(@NonNull Context context, @NonNull String login, @NonNull String repo, - @GitActionType int type, boolean isEnterprise) { - Intent intent = new Intent(context.getApplicationContext(), GithubActionService.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.ID, repo) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TYPE, type) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - context.startService(intent); - } - - public static void startForGist(@NonNull Context context, @NonNull String id, @GitActionType int type, boolean isEnterprise) { - Intent intent = new Intent(context.getApplicationContext(), GithubActionService.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.ID, id) - .put(BundleConstant.EXTRA_TYPE, type) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - context.startService(intent); - } - - public GithubActionService() { - super(GithubActionService.class.getName()); - } - - @Override protected void onHandleIntent(@Nullable Intent intent) { - if (intent != null && intent.getExtras() != null) { - Bundle bundle = intent.getExtras(); - @GitActionType int type = bundle.getInt(BundleConstant.EXTRA_TYPE); - String id = bundle.getString(BundleConstant.ID); - String login = bundle.getString(BundleConstant.EXTRA); - boolean isEnterprise = bundle.getBoolean(BundleConstant.IS_ENTERPRISE); - switch (type) { - case FORK_GIST: - forkGist(id, isEnterprise); - break; - case FORK_REPO: - forkRepo(id, login, isEnterprise); - break; - case STAR_GIST: - starGist(id, isEnterprise); - break; - case STAR_REPO: - starRepo(id, login, isEnterprise); - break; - case UNSTAR_GIST: - unStarGist(id, isEnterprise); - break; - case UNSTAR_REPO: - unStarRepo(id, login, isEnterprise); - break; - case UNWATCH_REPO: - unWatchRepo(id, login, isEnterprise); - break; - case WATCH_REPO: - watchRepo(id, login, isEnterprise); - break; - } - } - } - - private void forkGist(@Nullable String id, boolean isEnterprise) { - if (id != null) { - String msg = getString(R.string.forking, getString(R.string.gist)); - RestProvider.getGistService(isEnterprise) - .forkGist(id) - .doOnSubscribe(disposable -> showNotification(msg)) - .subscribeOn(Schedulers.io()) - .subscribe(response -> { - }, throwable -> hideNotification(msg), () -> hideNotification(msg)); - } - } - - private void forkRepo(@Nullable String id, @Nullable String login, boolean isEnterprise) { - if (id != null && login != null) { - String msg = getString(R.string.forking, id); - RestProvider.getRepoService(isEnterprise) - .forkRepo(login, id) - .doOnSubscribe(disposable -> showNotification(msg)) - .subscribeOn(Schedulers.io()) - .subscribe(response -> { - }, throwable -> hideNotification(msg), () -> hideNotification(msg)); - } - } - - private void starGist(@Nullable String id, boolean isEnterprise) { - if (id != null) { - String msg = getString(R.string.starring, getString(R.string.gist)); - RestProvider.getGistService(isEnterprise) - .starGist(id) - .doOnSubscribe(disposable -> showNotification(msg)) - .subscribeOn(Schedulers.io()) - .subscribe(response -> { - }, throwable -> hideNotification(msg), () -> hideNotification(msg)); - } - } - - private void starRepo(@Nullable String id, @Nullable String login, boolean isEnterprise) { - if (id != null && login != null) { - String msg = getString(R.string.starring, id); - RestProvider.getRepoService(isEnterprise) - .starRepo(login, id) - .doOnSubscribe(disposable -> showNotification(msg)) - .subscribeOn(Schedulers.io()) - .subscribe(response -> { - }, throwable -> hideNotification(msg), () -> hideNotification(msg)); - } - } - - private void unStarGist(@Nullable String id, boolean isEnterprise) { - if (id != null) { - String msg = getString(R.string.un_starring, getString(R.string.gist)); - RestProvider.getGistService(isEnterprise) - .unStarGist(id) - .doOnSubscribe(disposable -> showNotification(msg)) - .subscribeOn(Schedulers.io()) - .subscribe(response -> { - }, throwable -> hideNotification(msg), () -> hideNotification(msg)); - } - } - - private void unStarRepo(@Nullable String id, @Nullable String login, boolean isEnterprise) { - if (id != null && login != null) { - String msg = getString(R.string.un_starring, id); - RestProvider.getRepoService(isEnterprise) - .unstarRepo(login, id) - .doOnSubscribe(disposable -> showNotification(msg)) - .subscribeOn(Schedulers.io()) - .subscribe(response -> { - }, throwable -> hideNotification(msg), () -> hideNotification(msg)); - } - } - - private void unWatchRepo(@Nullable String id, @Nullable String login, boolean isEnterprise) { - if (id != null && login != null) { - String msg = getString(R.string.un_watching, id); - RestProvider.getRepoService(isEnterprise) - .unwatchRepo(login, id) - .doOnSubscribe(disposable -> showNotification(msg)) - .subscribeOn(Schedulers.io()) - .subscribe(response -> { - }, throwable -> hideNotification(msg), () -> hideNotification(msg)); - } - } - - private void watchRepo(@Nullable String id, @Nullable String login, boolean isEnterprise) { - if (id != null && login != null) { - String msg = getString(R.string.watching, id); - RestProvider.getRepoService(isEnterprise) - .watchRepo(login, id) - .doOnSubscribe(disposable -> showNotification(msg)) - .subscribeOn(Schedulers.io()) - .subscribe(response -> { - }, throwable -> hideNotification(msg), () -> hideNotification(msg)); - } - } - - private NotificationCompat.Builder getNotification(@NonNull String title) { - if (notification == null) { - notification = new NotificationCompat.Builder(this, title) - .setSmallIcon(R.drawable.ic_sync) - .setProgress(0, 100, true); - } - notification.setContentTitle(title); - return notification; - } - - private NotificationManager getNotificationManager() { - if (notificationManager == null) { - notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - } - return notificationManager; - } - - private void showNotification(@NonNull String msg) { - getNotificationManager().notify(msg.hashCode(), getNotification(msg).build()); - } - - private void hideNotification(@NonNull String msg) { - getNotificationManager().cancel(msg.hashCode()); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/tasks/git/ReactionService.java b/app/src/main/java/com/fastaccess/provider/tasks/git/ReactionService.java deleted file mode 100644 index 63d9a3bcb..000000000 --- a/app/src/main/java/com/fastaccess/provider/tasks/git/ReactionService.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.fastaccess.provider.tasks.git; - -import android.app.IntentService; -import android.app.NotificationManager; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.NotificationCompat; - -import com.fastaccess.R; -import com.fastaccess.data.dao.PostReactionModel; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; - -/** - * Created by Kosh on 29 Mar 2017, 9:59 PM - */ - -public class ReactionService extends IntentService { - - private NotificationCompat.Builder notification; - private NotificationManager notificationManager; - - public static void start(@NonNull Context context, @NonNull String login, @NonNull String repo, - long commentId, ReactionTypes reactionType, boolean isCommit, boolean isDelete, - boolean isEnterprise) { - Intent intent = new Intent(context, ReactionService.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, isCommit) - .put(BundleConstant.EXTRA_TWO, login) - .put(BundleConstant.EXTRA_THREE, repo) - .put(BundleConstant.EXTRA_FOUR, isDelete) - .put(BundleConstant.ID, commentId) - .put(BundleConstant.EXTRA_TYPE, reactionType) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - context.startService(intent); - } - - public ReactionService() { - super(ReactionService.class.getSimpleName()); - } - - @Override protected void onHandleIntent(@Nullable Intent intent) { - if (intent != null && intent.getExtras() != null) { - Bundle bundle = intent.getExtras(); - ReactionTypes reactionType = (ReactionTypes) bundle.getSerializable(BundleConstant.EXTRA_TYPE); - boolean isCommit = bundle.getBoolean(BundleConstant.EXTRA); - String login = bundle.getString(BundleConstant.EXTRA_TWO); - String repo = bundle.getString(BundleConstant.EXTRA_THREE); - long commentId = bundle.getLong(BundleConstant.ID); - boolean isEnterprise = bundle.getBoolean(BundleConstant.IS_ENTERPRISE); - if (InputHelper.isEmpty(login) || InputHelper.isEmpty(repo) || reactionType == null) { - stopSelf(); - return; - } - if (isCommit) { - postCommit(reactionType, login, repo, commentId, isEnterprise); - } else { - post(reactionType, login, repo, commentId, isEnterprise); - } - } - } - - private void post(@NonNull ReactionTypes reactionType, @NonNull String login, @NonNull String repo, long commentId, boolean isEnterprise) { - RxHelper.safeObservable(RestProvider.getReactionsService(isEnterprise) - .postIssueCommentReaction(new PostReactionModel(reactionType.getContent()), login, repo, commentId)) - .doOnSubscribe(disposable -> showNotification(getNotification(reactionType), (int) commentId)) - .subscribe(response -> hideNotification((int) commentId), throwable -> hideNotification((int) commentId)); - } - - private void postCommit(@NonNull ReactionTypes reactionType, @NonNull String login, @NonNull String repo, long commentId, boolean isEnterprise) { - RxHelper.safeObservable(RestProvider.getReactionsService(isEnterprise) - .postCommitReaction(new PostReactionModel(reactionType.getContent()), login, repo, commentId)) - .doOnSubscribe(disposable -> showNotification(getNotification(reactionType), (int) commentId)) - .subscribe(response -> hideNotification((int) commentId), throwable -> hideNotification((int) commentId)); - } - - public NotificationCompat.Builder getNotification(@NonNull ReactionTypes reactionTypes) { - if (notification == null) { - notification = new NotificationCompat.Builder(this, "reaction") - .setSmallIcon(R.drawable.ic_sync) - .setProgress(0, 100, true); - } - notification.setContentTitle(getString(R.string.posting_reaction, reactionTypes.getContent())); - return notification; - } - - public NotificationManager getNotificationManager() { - if (notificationManager == null) { - notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - } - return notificationManager; - } - - private void showNotification(@NonNull NotificationCompat.Builder builder, int id) { - getNotificationManager().notify(id, builder.build()); - } - - private void hideNotification(int id) { - getNotificationManager().cancel(id); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/tasks/notification/NotificationSchedulerJobTask.java b/app/src/main/java/com/fastaccess/provider/tasks/notification/NotificationSchedulerJobTask.java deleted file mode 100644 index 3f6f4d57c..000000000 --- a/app/src/main/java/com/fastaccess/provider/tasks/notification/NotificationSchedulerJobTask.java +++ /dev/null @@ -1,305 +0,0 @@ - -package com.fastaccess.provider.tasks.notification; - -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.graphics.BitmapFactory; -import android.media.AudioManager; -import android.os.Build; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.NotificationCompat; -import android.support.v4.content.ContextCompat; - -import com.annimon.stream.Stream; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.Notification; -import com.fastaccess.data.dao.model.NotificationQueue; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.markdown.MarkDownProvider; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.modules.notification.NotificationActivity; -import com.firebase.jobdispatcher.Constraint; -import com.firebase.jobdispatcher.FirebaseJobDispatcher; -import com.firebase.jobdispatcher.GooglePlayDriver; -import com.firebase.jobdispatcher.Job; -import com.firebase.jobdispatcher.JobParameters; -import com.firebase.jobdispatcher.JobService; -import com.firebase.jobdispatcher.Lifetime; -import com.firebase.jobdispatcher.RetryStrategy; -import com.firebase.jobdispatcher.Trigger; - -import java.util.List; - -import io.reactivex.Observable; -import io.reactivex.schedulers.Schedulers; - -/** - * Created by Kosh on 19 Feb 2017, 6:32 PM - */ - -public class NotificationSchedulerJobTask extends JobService { - private final static String JOB_ID = "fasthub_notification"; - private final static String SINGLE_JOB_ID = "single_fasthub_notification"; - - private final static int THIRTY_MINUTES = 30 * 60; - private static final String NOTIFICATION_GROUP_ID = "FastHub"; - - @Override public boolean onStartJob(JobParameters job) { - if (!SINGLE_JOB_ID.equalsIgnoreCase(job.getTag())) { - if (PrefGetter.getNotificationTaskDuration() == -1) { - scheduleJob(this, -1, false); - finishJob(job); - return true; - } - } - Login login = null; - try { - login = Login.getUser(); - } catch (Exception ignored) {} - if (login != null) { - RestProvider.getNotificationService(PrefGetter.isEnterprise()) - .getNotifications(ParseDateFormat.getLastWeekDate()) - .subscribeOn(Schedulers.io()) - .subscribe(item -> { - AppHelper.cancelAllNotifications(getApplicationContext()); - if (item != null) { - onSave(item.getItems(), job); - } else { - finishJob(job); - } - }, throwable -> jobFinished(job, true)); - } - return true; - } - - @Override public boolean onStopJob(JobParameters jobParameters) { - return false; - } - - public static void scheduleJob(@NonNull Context context) { - int duration = PrefGetter.getNotificationTaskDuration(); - scheduleJob(context, duration, false); - } - - public static void scheduleJob(@NonNull Context context, int duration, boolean cancel) { - if (AppHelper.isGoogleAvailable(context)) { - FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context)); - dispatcher.cancel(SINGLE_JOB_ID); - if (cancel) dispatcher.cancel(JOB_ID); - if (duration == -1) { - dispatcher.cancel(JOB_ID); - return; - } - duration = duration <= 0 ? THIRTY_MINUTES : duration; - Job.Builder builder = dispatcher - .newJobBuilder() - .setTag(JOB_ID) - .setRetryStrategy(RetryStrategy.DEFAULT_LINEAR) - .setLifetime(Lifetime.FOREVER) - .setRecurring(true) - .setConstraints(Constraint.ON_ANY_NETWORK) - .setTrigger(Trigger.executionWindow(duration / 2, duration)) - .setService(NotificationSchedulerJobTask.class); - dispatcher.mustSchedule(builder.build()); - } - } - - public static void scheduleOneTimeJob(@NonNull Context context) { - if (AppHelper.isGoogleAvailable(context)) { - FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context)); - Job.Builder builder = dispatcher - .newJobBuilder() - .setTag(SINGLE_JOB_ID) - .setReplaceCurrent(true) - .setRecurring(false) - .setTrigger(Trigger.executionWindow(30, 60)) - .setConstraints(Constraint.ON_ANY_NETWORK) - .setService(NotificationSchedulerJobTask.class); - dispatcher.mustSchedule(builder.build()); - } - } - - private void onSave(@Nullable List notificationThreadModels, JobParameters job) { - if (notificationThreadModels != null) { - Notification.save(notificationThreadModels); - onNotifyUser(notificationThreadModels, job); - } - } - - private void onNotifyUser(@NonNull List notificationThreadModels, JobParameters job) { - long count = Stream.of(notificationThreadModels) - .filter(Notification::isUnread) - .count(); - if (count == 0) { - AppHelper.cancelAllNotifications(getApplicationContext()); - finishJob(job); - return; - } - Context context = getApplicationContext(); - int accentColor = ContextCompat.getColor(this, R.color.material_blue_700); - Notification first = notificationThreadModels.get(0); - Observable.fromIterable(notificationThreadModels) - .subscribeOn(Schedulers.io()) - .filter(notification -> notification.isUnread() && first.getId() != notification.getId() - && !NotificationQueue.exists(notification.getId())) - .take(10) - .flatMap(notification -> { - if (notification.getSubject() != null && notification.getSubject().getLatestCommentUrl() != null) { - return RestProvider.getNotificationService(PrefGetter.isEnterprise()) - .getComment(notification.getSubject().getLatestCommentUrl()) - .subscribeOn(Schedulers.io()); - } else { - return Observable.empty(); - } - }, (thread, comment) -> { - CustomNotificationModel customNotificationModel = new CustomNotificationModel(); - String url; - if (comment != null && comment.getUser() != null) { - url = comment.getUser().getAvatarUrl(); - if (!InputHelper.isEmpty(thread.getSubject().getLatestCommentUrl())) { - customNotificationModel.comment = comment; - customNotificationModel.url = url; - } - } - customNotificationModel.notification = thread; - return customNotificationModel; - }) - .subscribeOn(Schedulers.io()) - .subscribe(custom -> { - if (custom.comment != null) { - getNotificationWithComment(context, accentColor, custom.notification, custom.comment, custom.url); - } else { - showNotificationWithoutComment(context, accentColor, custom.notification, custom.url); - } - - }, throwable -> finishJob(job), () -> { - if (!NotificationQueue.exists(first.getId())) { - android.app.Notification grouped = getSummaryGroupNotification(first, accentColor, notificationThreadModels.size() > 1); - showNotification(first.getId(), grouped); - } - NotificationQueue.put(notificationThreadModels) - .subscribe(aBoolean -> {/*do nothing*/}, Throwable::printStackTrace, () -> finishJob(job)); - }); - } - - private void finishJob(JobParameters job) { - jobFinished(job, false); - } - - private void showNotificationWithoutComment(Context context, int accentColor, Notification thread, String iconUrl) { - withoutComments(thread, context, accentColor); - } - - private void withoutComments(Notification thread, Context context, int accentColor) { - android.app.Notification toAdd = getNotification(thread.getSubject().getTitle(), thread.getRepository().getFullName(), - thread.getRepository() != null ? thread.getRepository().getFullName() : "general") - .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) - .setContentIntent(getPendingIntent(thread.getId(), thread.getSubject().getUrl())) - .addAction(R.drawable.ic_github, context.getString(R.string.open), getPendingIntent(thread.getId(), thread - .getSubject().getUrl())) - .addAction(R.drawable.ic_eye_off, context.getString(R.string.mark_as_read), getReadOnlyPendingIntent(thread.getId(), thread - .getSubject().getUrl())) - .setWhen(thread.getUpdatedAt() != null ? thread.getUpdatedAt().getTime() : System.currentTimeMillis()) - .setShowWhen(true) - .setColor(accentColor) - .setGroup(NOTIFICATION_GROUP_ID) - .build(); - showNotification(thread.getId(), toAdd); - } - - private void getNotificationWithComment(Context context, int accentColor, Notification thread, Comment comment, String url) { - withComments(comment, context, thread, accentColor); - } - - private void withComments(Comment comment, Context context, Notification thread, int accentColor) { - android.app.Notification toAdd = getNotification(comment.getUser() != null ? comment.getUser().getLogin() : "", - MarkDownProvider.stripMdText(comment.getBody()), - thread.getRepository() != null ? thread.getRepository().getFullName() : "general") - .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) - .setSmallIcon(R.drawable.ic_notification) - .setStyle(new NotificationCompat.BigTextStyle() - .setBigContentTitle(comment.getUser() != null ? comment.getUser().getLogin() : "") - .bigText(MarkDownProvider.stripMdText(comment.getBody()))) - .setWhen(comment.getCreatedAt().getTime()) - .setShowWhen(true) - .addAction(R.drawable.ic_github, context.getString(R.string.open), getPendingIntent(thread.getId(), - thread.getSubject().getUrl())) - .addAction(R.drawable.ic_eye_off, context.getString(R.string.mark_as_read), getReadOnlyPendingIntent(thread.getId(), - thread.getSubject().getUrl())) - .setContentIntent(getPendingIntent(thread.getId(), thread.getSubject().getUrl())) - .setColor(accentColor) - .setGroup(NOTIFICATION_GROUP_ID) - .build(); - showNotification(thread.getId(), toAdd); - } - - private android.app.Notification getSummaryGroupNotification(@NonNull Notification thread, int accentColor, boolean toNotificationActivity) { - PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, - new Intent(getApplicationContext(), NotificationActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); - NotificationCompat.Builder builder = getNotification(thread.getSubject().getTitle(), thread.getRepository().getFullName(), - thread.getRepository() != null ? thread.getRepository().getFullName() : "general") - .setContentIntent(toNotificationActivity ? pendingIntent : getPendingIntent(thread.getId(), thread.getSubject().getUrl())) - .addAction(R.drawable.ic_github, getString(R.string.open), getPendingIntent(thread.getId(), thread - .getSubject().getUrl())) - .addAction(R.drawable.ic_eye_off, getString(R.string.mark_as_read), getReadOnlyPendingIntent(thread.getId(), thread - .getSubject().getUrl())) - .setWhen(thread.getUpdatedAt() != null ? thread.getUpdatedAt().getTime() : System.currentTimeMillis()) - .setShowWhen(true) - .setSmallIcon(R.drawable.ic_notification) - .setColor(accentColor) - .setGroup(NOTIFICATION_GROUP_ID) - .setGroupSummary(true); - if (PrefGetter.isNotificationSoundEnabled()) { - builder.setDefaults(NotificationCompat.DEFAULT_ALL) - .setSound(PrefGetter.getNotificationSound(), AudioManager.STREAM_NOTIFICATION); - } - return builder.build(); - } - - private NotificationCompat.Builder getNotification(@NonNull String title, @NonNull String message, @NonNull String channelName) { - return new NotificationCompat.Builder(this, channelName) - .setContentTitle(title) - .setContentText(message) - .setAutoCancel(true); - } - - private void showNotification(long id, android.app.Notification notification) { - NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - if (notificationManager != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - NotificationChannel notificationChannel = new NotificationChannel(notification.getChannelId(), - notification.getChannelId(), NotificationManager.IMPORTANCE_DEFAULT); - notificationChannel.setShowBadge(true); - notificationManager.createNotificationChannel(notificationChannel); - } - notificationManager.notify(InputHelper.getSafeIntId(id), notification); - } - } - - private PendingIntent getReadOnlyPendingIntent(long id, @NonNull String url) { - Intent intent = ReadNotificationService.start(getApplicationContext(), id, url, true); - return PendingIntent.getService(getApplicationContext(), InputHelper.getSafeIntId(id) / 2, intent, - PendingIntent.FLAG_UPDATE_CURRENT); - } - - private PendingIntent getPendingIntent(long id, @NonNull String url) { - Intent intent = ReadNotificationService.start(getApplicationContext(), id, url); - return PendingIntent.getService(getApplicationContext(), InputHelper.getSafeIntId(id), intent, - PendingIntent.FLAG_UPDATE_CURRENT); - } - - private static class CustomNotificationModel { - public String url; - public Notification notification; - public Comment comment; - } -} diff --git a/app/src/main/java/com/fastaccess/provider/tasks/notification/ReadNotificationService.java b/app/src/main/java/com/fastaccess/provider/tasks/notification/ReadNotificationService.java deleted file mode 100644 index 764359939..000000000 --- a/app/src/main/java/com/fastaccess/provider/tasks/notification/ReadNotificationService.java +++ /dev/null @@ -1,163 +0,0 @@ -package com.fastaccess.provider.tasks.notification; - -import android.app.IntentService; -import android.app.Notification; -import android.app.NotificationManager; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.NotificationCompat; - -import com.annimon.stream.LongStream; -import com.fastaccess.R; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; - -import io.reactivex.Observable; -import io.reactivex.schedulers.Schedulers; - -/** - * Created by Kosh on 11 Mar 2017, 12:13 AM - */ - -public class ReadNotificationService extends IntentService { - - public static final int READ_SINGLE = 1; - public static final int READ_ALL = 2; - public static final int OPEN_NOTIFICATION = 3; - public static final int UN_SUBSCRIBE = 4; - private NotificationCompat.Builder notification; - private NotificationManager notificationManager; - - public static void start(@NonNull Context context, long id) { - Intent intent = new Intent(context.getApplicationContext(), ReadNotificationService.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA_TYPE, READ_SINGLE) - .put(BundleConstant.ID, id) - .end()); - context.startService(intent); - } - - public static Intent start(@NonNull Context context, long id, @NonNull String url) { - return start(context, id, url, false); - } - - public static Intent start(@NonNull Context context, long id, @NonNull String url, boolean onlyRead) { - Intent intent = new Intent(context.getApplicationContext(), ReadNotificationService.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA_TYPE, OPEN_NOTIFICATION) - .put(BundleConstant.EXTRA, url) - .put(BundleConstant.ID, id) - .put(BundleConstant.YES_NO_EXTRA, onlyRead) - .end()); - return intent; - } - - public static void unSubscribe(@NonNull Context context, long id) { - Intent intent = new Intent(context.getApplicationContext(), ReadNotificationService.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA_TYPE, UN_SUBSCRIBE) - .put(BundleConstant.ID, id) - .end()); - context.startService(intent); - } - - public static void start(@NonNull Context context, @NonNull long[] ids) { - Intent intent = new Intent(context.getApplicationContext(), ReadNotificationService.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA_TYPE, READ_ALL) - .put(BundleConstant.ID, ids) - .end()); - context.startService(intent); - } - - public ReadNotificationService() { - super(ReadNotificationService.class.getSimpleName()); - } - - @Override public void onCreate() { - super.onCreate(); - notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - } - - @Override protected void onHandleIntent(@Nullable Intent intent) { - if (intent != null && intent.getExtras() != null) { - Bundle bundle = intent.getExtras(); - int type = bundle.getInt(BundleConstant.EXTRA_TYPE); - if (type == READ_SINGLE) { - markSingleAsRead(bundle.getLong(BundleConstant.ID)); - } else if (type == READ_ALL) { - markMultiAsRead(bundle.getLongArray(BundleConstant.ID)); - } else if (type == OPEN_NOTIFICATION) { - openNotification(bundle.getLong(BundleConstant.ID), bundle.getString(BundleConstant.EXTRA), - bundle.getBoolean(BundleConstant.YES_NO_EXTRA)); - } else if (type == UN_SUBSCRIBE) { - unSubscribeFromThread(bundle.getLong(BundleConstant.ID)); - } - } - } - - private void unSubscribeFromThread(long id) { - RestProvider.getNotificationService(PrefGetter.isEnterprise()) - .unSubscribe(id) - .doOnSubscribe(disposable -> notify(id, getNotification().build())) - .subscribeOn(Schedulers.io()) - .flatMap(notification1 -> Observable.create(subscriber -> markSingleAsRead(id))) - .subscribe(booleanResponse -> cancel(id), throwable -> cancel(id)); - } - - private void openNotification(long id, @Nullable String url, boolean readOnly) { - if (id > 0 && url != null) { - AppHelper.cancelNotification(this, InputHelper.getSafeIntId(id)); - if (readOnly) { - markSingleAsRead(id); - } else if (!PrefGetter.isMarkAsReadEnabled()) { - markSingleAsRead(id); - } - if (!readOnly) { - SchemeParser.launchUri(getApplicationContext(), Uri.parse(url), true, true); - } - } - } - - private void markMultiAsRead(@Nullable long[] ids) { - if (ids != null && ids.length > 0) { - LongStream.of(ids).forEach(this::markSingleAsRead); - } - } - - private void markSingleAsRead(long id) { - com.fastaccess.data.dao.model.Notification.markAsRead(id); - RestProvider.getNotificationService(PrefGetter.isEnterprise()) - .markAsRead(String.valueOf(id)) - .doOnSubscribe(disposable -> notify(id, getNotification().build())) - .subscribeOn(Schedulers.io()) - .subscribe(booleanResponse -> cancel(id), throwable -> cancel(id)); - } - - private NotificationCompat.Builder getNotification() { - if (notification == null) { - notification = new NotificationCompat.Builder(this, "read-notification") - .setContentTitle(getString(R.string.marking_as_read)) - .setSmallIcon(R.drawable.ic_sync) - .setProgress(0, 100, true); - } - return notification; - } - - private void notify(long id, Notification notification) { - notificationManager.notify(InputHelper.getSafeIntId(id), notification); - } - - private void cancel(long id) { - notificationManager.cancel(InputHelper.getSafeIntId(id)); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/tasks/slack/SlackInvitationService.java b/app/src/main/java/com/fastaccess/provider/tasks/slack/SlackInvitationService.java deleted file mode 100644 index d8c0ed14a..000000000 --- a/app/src/main/java/com/fastaccess/provider/tasks/slack/SlackInvitationService.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.fastaccess.provider.tasks.slack; - -import android.app.IntentService; -import android.content.Intent; -import android.support.annotation.Nullable; - -import com.fastaccess.App; -import com.fastaccess.R; -import com.fastaccess.data.dao.SlackInvitePostModel; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; - -import es.dmoral.toasty.Toasty; - -/** - * Created by Kosh on 01 May 2017, 1:09 AM - */ - -public class SlackInvitationService extends IntentService { - - public SlackInvitationService() { - super(SlackInvitationService.class.getName()); - } - - @Override protected void onHandleIntent(@Nullable Intent intent) { - Login login = Login.getUser(); - if (login != null) { - SlackInvitePostModel body = new SlackInvitePostModel(); - body.setEmail(login.getEmail()); - body.setFirst_name(login.getName()); - body.setLast_name(login.getLogin()); - RxHelper.getObservable(RestProvider.getSlackService() - .invite(body)) - .subscribe(response -> { - if (response != null) { - if (response.isOk()) { - Toasty.success(App.getInstance(), getString(R.string.successfully_invited)).show(); - } else { - Toasty.info(App.getInstance(), response.getError().replaceAll("_", " ")).show(); - } - } - }, Throwable::printStackTrace); - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/tasks/version/CheckVersionService.kt b/app/src/main/java/com/fastaccess/provider/tasks/version/CheckVersionService.kt deleted file mode 100644 index a40a753bc..000000000 --- a/app/src/main/java/com/fastaccess/provider/tasks/version/CheckVersionService.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.fastaccess.provider.tasks.version - -import android.app.IntentService -import android.content.Intent -import android.widget.Toast -import com.fastaccess.App -import com.fastaccess.BuildConfig -import com.fastaccess.R -import com.fastaccess.data.dao.model.Release -import com.fastaccess.helper.RxHelper -import com.fastaccess.provider.rest.RestProvider - -/** - * Created by Kosh on 09 Jun 2017, 9:02 PM - */ -class CheckVersionService : IntentService("CheckVersionService") { - - override fun onHandleIntent(p0: Intent?) { - RxHelper.getObservable(RestProvider.getRepoService(false) - .getLatestRelease("k0shk0sh", "FastHub")) - .subscribe({ t: Release? -> - t?.let { - Toast.makeText(App.getInstance(), if (BuildConfig.VERSION_NAME.contains(it.tagName)) - R.string.up_to_date else R.string.new_version, Toast.LENGTH_LONG).show() - } - }, { throwable -> throwable.printStackTrace() }) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/theme/ThemeEngine.kt b/app/src/main/java/com/fastaccess/provider/theme/ThemeEngine.kt deleted file mode 100644 index 74d303294..000000000 --- a/app/src/main/java/com/fastaccess/provider/theme/ThemeEngine.kt +++ /dev/null @@ -1,270 +0,0 @@ -package com.fastaccess.provider.theme - -import android.app.Activity -import android.app.ActivityManager -import android.graphics.BitmapFactory -import android.support.annotation.StyleRes -import com.danielstone.materialaboutlibrary.MaterialAboutActivity -import com.fastaccess.R -import com.fastaccess.helper.Logger -import com.fastaccess.helper.PrefGetter -import com.fastaccess.helper.ViewHelper -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.modules.login.LoginActivity -import com.fastaccess.ui.modules.login.chooser.LoginChooserActivity -import com.fastaccess.ui.modules.main.donation.DonateActivity - -/** - * Created by Kosh on 07 Jun 2017, 6:52 PM - */ - -object ThemeEngine { - - fun apply(activity: BaseActivity<*, *>) { - if (hasTheme(activity)) { - return - } - val themeMode = PrefGetter.getThemeType(activity) - val themeColor = PrefGetter.getThemeColor(activity) - activity.setTheme(getTheme(themeMode, themeColor)) - setTaskDescription(activity) - applyNavBarColor(activity) - } - - private fun applyNavBarColor(activity: Activity) { - if (!PrefGetter.isNavBarTintingDisabled() && PrefGetter.getThemeType() != PrefGetter.LIGHT) { - activity.window.navigationBarColor = ViewHelper.getPrimaryColor(activity) - } - } - - fun applyForAbout(activity: MaterialAboutActivity) { - val themeMode = PrefGetter.getThemeType(activity) - when (themeMode) { - PrefGetter.LIGHT -> activity.setTheme(R.style.AppTheme_AboutActivity_Light) - PrefGetter.DARK -> activity.setTheme(R.style.AppTheme_AboutActivity_Dark) - PrefGetter.AMLOD -> activity.setTheme(R.style.AppTheme_AboutActivity_Amlod) - PrefGetter.MID_NIGHT_BLUE -> activity.setTheme(R.style.AppTheme_AboutActivity_Midnight) - PrefGetter.BLUISH -> activity.setTheme(R.style.AppTheme_AboutActivity_Bluish) - } - setTaskDescription(activity) - } - - fun applyDialogTheme(activity: BaseActivity<*, *>) { - val themeMode = PrefGetter.getThemeType(activity) - val themeColor = PrefGetter.getThemeColor(activity) - activity.setTheme(getDialogTheme(themeMode, themeColor)) - setTaskDescription(activity) - } - - @StyleRes private fun getTheme(themeMode: Int, themeColor: Int): Int { - Logger.e(themeMode, themeColor) - // I wish if I could simplify this :'( too many cases for the love of god. - when (themeMode) { - PrefGetter.LIGHT -> when (themeColor) { - PrefGetter.RED -> return R.style.ThemeLight_Red - PrefGetter.PINK -> return R.style.ThemeLight_Pink - PrefGetter.PURPLE -> return R.style.ThemeLight_Purple - PrefGetter.DEEP_PURPLE -> return R.style.ThemeLight_DeepPurple - PrefGetter.INDIGO -> return R.style.ThemeLight_Indigo - PrefGetter.BLUE -> return R.style.ThemeLight - PrefGetter.LIGHT_BLUE -> return R.style.ThemeLight_LightBlue - PrefGetter.CYAN -> return R.style.ThemeLight_Cyan - PrefGetter.TEAL -> return R.style.ThemeLight_Teal - PrefGetter.GREEN -> return R.style.ThemeLight_Green - PrefGetter.LIGHT_GREEN -> return R.style.ThemeLight_LightGreen - PrefGetter.LIME -> return R.style.ThemeLight_Lime - PrefGetter.YELLOW -> return R.style.ThemeLight_Yellow - PrefGetter.AMBER -> return R.style.ThemeLight_Amber - PrefGetter.ORANGE -> return R.style.ThemeLight_Orange - PrefGetter.DEEP_ORANGE -> return R.style.ThemeLight_DeepOrange - else -> return R.style.ThemeLight - } - PrefGetter.DARK -> when (themeColor) { - PrefGetter.RED -> return R.style.ThemeDark_Red - PrefGetter.PINK -> return R.style.ThemeDark_Pink - PrefGetter.PURPLE -> return R.style.ThemeDark_Purple - PrefGetter.DEEP_PURPLE -> return R.style.ThemeDark_DeepPurple - PrefGetter.INDIGO -> return R.style.ThemeDark_Indigo - PrefGetter.BLUE -> return R.style.ThemeDark - PrefGetter.LIGHT_BLUE -> return R.style.ThemeDark_LightBlue - PrefGetter.CYAN -> return R.style.ThemeDark_Cyan - PrefGetter.GREEN -> return R.style.ThemeDark_Green - PrefGetter.TEAL -> return R.style.ThemeDark_Teal - PrefGetter.LIGHT_GREEN -> return R.style.ThemeDark_LightGreen - PrefGetter.LIME -> return R.style.ThemeDark_Lime - PrefGetter.YELLOW -> return R.style.ThemeDark_Yellow - PrefGetter.AMBER -> return R.style.ThemeDark_Amber - PrefGetter.ORANGE -> return R.style.ThemeDark_Orange - PrefGetter.DEEP_ORANGE -> return R.style.ThemeDark_DeepOrange - else -> return R.style.ThemeDark - } - PrefGetter.AMLOD -> when (themeColor) { - PrefGetter.RED -> return R.style.ThemeAmlod_Red - PrefGetter.PINK -> return R.style.ThemeAmlod_Pink - PrefGetter.PURPLE -> return R.style.ThemeAmlod_Purple - PrefGetter.DEEP_PURPLE -> return R.style.ThemeAmlod_DeepPurple - PrefGetter.INDIGO -> return R.style.ThemeAmlod_Indigo - PrefGetter.BLUE -> return R.style.ThemeAmlod - PrefGetter.LIGHT_BLUE -> return R.style.ThemeAmlod_LightBlue - PrefGetter.CYAN -> return R.style.ThemeAmlod_Cyan - PrefGetter.TEAL -> return R.style.ThemeAmlod_Teal - PrefGetter.GREEN -> return R.style.ThemeAmlod_Green - PrefGetter.LIGHT_GREEN -> return R.style.ThemeAmlod_LightGreen - PrefGetter.LIME -> return R.style.ThemeAmlod_Lime - PrefGetter.YELLOW -> return R.style.ThemeAmlod_Yellow - PrefGetter.AMBER -> return R.style.ThemeAmlod_Amber - PrefGetter.ORANGE -> return R.style.ThemeAmlod_Orange - PrefGetter.DEEP_ORANGE -> return R.style.ThemeAmlod_DeepOrange - else -> return R.style.ThemeAmlod - } - PrefGetter.MID_NIGHT_BLUE -> when (themeColor) { - PrefGetter.RED -> return R.style.ThemeMidnight_Red - PrefGetter.PINK -> return R.style.ThemeMidnight_Pink - PrefGetter.PURPLE -> return R.style.ThemeMidnight_Purple - PrefGetter.DEEP_PURPLE -> return R.style.ThemeMidnight_DeepPurple - PrefGetter.INDIGO -> return R.style.ThemeMidnight_Indigo - PrefGetter.BLUE -> return R.style.ThemeMidnight - PrefGetter.LIGHT_BLUE -> return R.style.ThemeMidnight_LightBlue - PrefGetter.CYAN -> return R.style.ThemeMidnight_Cyan - PrefGetter.TEAL -> return R.style.ThemeMidnight_Teal - PrefGetter.GREEN -> return R.style.ThemeMidnight_Green - PrefGetter.LIGHT_GREEN -> return R.style.ThemeMidnight_LightGreen - PrefGetter.LIME -> return R.style.ThemeMidnight_Lime - PrefGetter.YELLOW -> return R.style.ThemeMidnight_Yellow - PrefGetter.AMBER -> return R.style.ThemeMidnight_Amber - PrefGetter.ORANGE -> return R.style.ThemeMidnight_Orange - PrefGetter.DEEP_ORANGE -> return R.style.ThemeMidnight_DeepOrange - else -> return R.style.ThemeMidnight - } - PrefGetter.BLUISH -> when (themeColor) { - PrefGetter.RED -> return R.style.ThemeBluish_Red - PrefGetter.PINK -> return R.style.ThemeBluish_Pink - PrefGetter.PURPLE -> return R.style.ThemeBluish_Purple - PrefGetter.DEEP_PURPLE -> return R.style.ThemeBluish_DeepPurple - PrefGetter.INDIGO -> return R.style.ThemeBluish_Indigo - PrefGetter.BLUE -> return R.style.ThemeBluish - PrefGetter.LIGHT_BLUE -> return R.style.ThemeBluish_LightBlue - PrefGetter.CYAN -> return R.style.ThemeBluish_Cyan - PrefGetter.TEAL -> return R.style.ThemeBluish_Teal - PrefGetter.GREEN -> return R.style.ThemeBluish_Green - PrefGetter.LIGHT_GREEN -> return R.style.ThemeBluish_LightGreen - PrefGetter.LIME -> return R.style.ThemeBluish_Lime - PrefGetter.YELLOW -> return R.style.ThemeBluish_Yellow - PrefGetter.AMBER -> return R.style.ThemeBluish_Amber - PrefGetter.ORANGE -> return R.style.ThemeBluish_Orange - PrefGetter.DEEP_ORANGE -> return R.style.ThemeBluish_DeepOrange - else -> return R.style.ThemeBluish - } - } - return R.style.ThemeLight - } - - @StyleRes private fun getDialogTheme(themeMode: Int, themeColor: Int): Int { - when (themeMode) { - PrefGetter.LIGHT -> when (themeColor) { - PrefGetter.RED -> return R.style.DialogThemeLight_Red - PrefGetter.PINK -> return R.style.DialogThemeLight_Pink - PrefGetter.PURPLE -> return R.style.DialogThemeLight_Purple - PrefGetter.DEEP_PURPLE -> return R.style.DialogThemeLight_DeepPurple - PrefGetter.INDIGO -> return R.style.DialogThemeLight_Indigo - PrefGetter.BLUE -> return R.style.DialogThemeLight - PrefGetter.LIGHT_BLUE -> return R.style.DialogThemeLight_LightBlue - PrefGetter.CYAN -> return R.style.DialogThemeLight_Cyan - PrefGetter.TEAL -> return R.style.DialogThemeLight_Teal - PrefGetter.GREEN -> return R.style.DialogThemeLight_Green - PrefGetter.LIGHT_GREEN -> return R.style.DialogThemeLight_LightGreen - PrefGetter.LIME -> return R.style.DialogThemeLight_Lime - PrefGetter.YELLOW -> return R.style.DialogThemeLight_Yellow - PrefGetter.AMBER -> return R.style.DialogThemeLight_Amber - PrefGetter.ORANGE -> return R.style.DialogThemeLight_Orange - PrefGetter.DEEP_ORANGE -> return R.style.DialogThemeLight_DeepOrange - else -> return R.style.DialogThemeLight - } - PrefGetter.DARK -> when (themeColor) { - PrefGetter.RED -> return R.style.DialogThemeDark_Red - PrefGetter.PINK -> return R.style.DialogThemeDark_Pink - PrefGetter.PURPLE -> return R.style.DialogThemeDark_Purple - PrefGetter.DEEP_PURPLE -> return R.style.DialogThemeDark_DeepPurple - PrefGetter.INDIGO -> return R.style.DialogThemeDark_Indigo - PrefGetter.BLUE -> return R.style.DialogThemeDark - PrefGetter.LIGHT_BLUE -> return R.style.DialogThemeDark_LightBlue - PrefGetter.CYAN -> return R.style.DialogThemeDark_Cyan - PrefGetter.TEAL -> return R.style.DialogThemeDark_Teal - PrefGetter.GREEN -> return R.style.DialogThemeDark_Green - PrefGetter.LIGHT_GREEN -> return R.style.DialogThemeDark_LightGreen - PrefGetter.LIME -> return R.style.DialogThemeDark_Lime - PrefGetter.YELLOW -> return R.style.DialogThemeDark_Yellow - PrefGetter.AMBER -> return R.style.DialogThemeDark_Amber - PrefGetter.ORANGE -> return R.style.DialogThemeDark_Orange - PrefGetter.DEEP_ORANGE -> return R.style.DialogThemeDark_DeepOrange - else -> return R.style.DialogThemeDark - } - PrefGetter.AMLOD -> when (themeColor) { - PrefGetter.RED -> return R.style.DialogThemeAmlod_Red - PrefGetter.PINK -> return R.style.DialogThemeAmlod_Pink - PrefGetter.PURPLE -> return R.style.DialogThemeAmlod_Purple - PrefGetter.DEEP_PURPLE -> return R.style.DialogThemeAmlod_DeepPurple - PrefGetter.INDIGO -> return R.style.DialogThemeAmlod_Indigo - PrefGetter.BLUE -> return R.style.DialogThemeAmlod - PrefGetter.LIGHT_BLUE -> return R.style.DialogThemeAmlod_LightBlue - PrefGetter.CYAN -> return R.style.DialogThemeAmlod_Cyan - PrefGetter.TEAL -> return R.style.DialogThemeAmlod_Teal - PrefGetter.GREEN -> return R.style.DialogThemeAmlod_Green - PrefGetter.LIGHT_GREEN -> return R.style.DialogThemeAmlod_LightGreen - PrefGetter.LIME -> return R.style.DialogThemeAmlod_Lime - PrefGetter.YELLOW -> return R.style.DialogThemeAmlod_Yellow - PrefGetter.AMBER -> return R.style.DialogThemeAmlod_Amber - PrefGetter.ORANGE -> return R.style.DialogThemeAmlod_Orange - PrefGetter.DEEP_ORANGE -> return R.style.DialogThemeAmlod_DeepOrange - else -> return R.style.DialogThemeAmlod - } - PrefGetter.MID_NIGHT_BLUE -> when (themeColor) { - PrefGetter.RED -> return R.style.DialogThemeMidnight_Red - PrefGetter.PINK -> return R.style.DialogThemeMidnight_Pink - PrefGetter.PURPLE -> return R.style.DialogThemeMidnight_Purple - PrefGetter.DEEP_PURPLE -> return R.style.DialogThemeMidnight_DeepPurple - PrefGetter.INDIGO -> return R.style.DialogThemeMidnight_Indigo - PrefGetter.BLUE -> return R.style.DialogThemeMidnight - PrefGetter.LIGHT_BLUE -> return R.style.DialogThemeMidnight_LightBlue - PrefGetter.CYAN -> return R.style.DialogThemeMidnight_Cyan - PrefGetter.TEAL -> return R.style.DialogThemeMidnight_Teal - PrefGetter.GREEN -> return R.style.DialogThemeMidnight_Green - PrefGetter.LIGHT_GREEN -> return R.style.DialogThemeMidnight_LightGreen - PrefGetter.LIME -> return R.style.DialogThemeMidnight_Lime - PrefGetter.YELLOW -> return R.style.DialogThemeMidnight_Yellow - PrefGetter.AMBER -> return R.style.DialogThemeMidnight_Amber - PrefGetter.ORANGE -> return R.style.DialogThemeMidnight_Orange - PrefGetter.DEEP_ORANGE -> return R.style.DialogThemeMidnight_DeepOrange - else -> return R.style.DialogThemeLight - } - PrefGetter.BLUISH -> when (themeColor) { - PrefGetter.RED -> return R.style.DialogThemeBluish_Red - PrefGetter.PINK -> return R.style.DialogThemeBluish_Pink - PrefGetter.PURPLE -> return R.style.DialogThemeBluish_Purple - PrefGetter.DEEP_PURPLE -> return R.style.DialogThemeBluish_DeepPurple - PrefGetter.INDIGO -> return R.style.DialogThemeBluish_Indigo - PrefGetter.BLUE -> return R.style.DialogThemeBluish - PrefGetter.LIGHT_BLUE -> return R.style.DialogThemeBluish_LightBlue - PrefGetter.CYAN -> return R.style.DialogThemeBluish_Cyan - PrefGetter.TEAL -> return R.style.DialogThemeBluish_Teal - PrefGetter.GREEN -> return R.style.DialogThemeBluish_Green - PrefGetter.LIGHT_GREEN -> return R.style.DialogThemeBluish_LightGreen - PrefGetter.LIME -> return R.style.DialogThemeBluish_Lime - PrefGetter.YELLOW -> return R.style.DialogThemeBluish_Yellow - PrefGetter.AMBER -> return R.style.DialogThemeBluish_Amber - PrefGetter.ORANGE -> return R.style.DialogThemeBluish_Orange - PrefGetter.DEEP_ORANGE -> return R.style.DialogThemeBluish_DeepOrange - else -> return R.style.DialogThemeBluish - } - } - return R.style.DialogThemeLight - } - - private fun setTaskDescription(activity: Activity) { - activity.setTaskDescription(ActivityManager.TaskDescription(activity.getString(R.string.app_name), - BitmapFactory.decodeResource(activity.resources, R.mipmap.ic_launcher), ViewHelper.getPrimaryColor(activity))) - } - - private fun hasTheme(activity: BaseActivity<*, *>) = (activity is LoginChooserActivity || activity is LoginActivity || - activity is DonateActivity) -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/timeline/CommentsHelper.java b/app/src/main/java/com/fastaccess/provider/timeline/CommentsHelper.java deleted file mode 100644 index 8114ae478..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/CommentsHelper.java +++ /dev/null @@ -1,191 +0,0 @@ -package com.fastaccess.provider.timeline; - -import android.content.Context; -import android.support.annotation.IdRes; -import android.support.annotation.NonNull; -import android.view.View; -import android.widget.TextView; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.fastaccess.R; -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.provider.tasks.git.ReactionService; -import com.fastaccess.ui.widgets.SpannableBuilder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 30 Mar 2017, 6:44 PM - */ - -public class CommentsHelper { - - private static final int LAUGH = 0x1F601; - private static final int SAD = 0x1F615; - private static final int THUMBS_UP = 0x1f44d; - private static final int THUMBS_DOWN = 0x1f44e; - private static final int HOORAY = 0x1f389; - private static final int HEART = 0x2764; - - - public static boolean isOwner(@NonNull String currentLogin, @NonNull String repoOwner, @NonNull String commentUser) { - return currentLogin.equalsIgnoreCase(repoOwner) || currentLogin.equalsIgnoreCase(commentUser); - } - - public static void handleReactions(@NonNull Context context, @NonNull String login, @NonNull String repoId, - @IdRes int id, long commentId, boolean commit, boolean isDelete, - boolean isEnterprise) { - ReactionTypes type = null; - switch (id) { - case R.id.heart: - type = ReactionTypes.HEART; - break; - case R.id.sad: - type = ReactionTypes.CONFUSED; - break; - case R.id.thumbsDown: - type = ReactionTypes.MINUS_ONE; - break; - case R.id.thumbsUp: - type = ReactionTypes.PLUS_ONE; - break; - case R.id.laugh: - type = ReactionTypes.LAUGH; - break; - case R.id.hurray: - type = ReactionTypes.HOORAY; - break; - } - if (type != null) { - ReactionService.start(context, login, repoId, commentId, type, commit, isDelete, isEnterprise); - } - } - - private static String getEmojiByUnicode(int unicode) { - return new String(Character.toChars(unicode)); - } - - public static String getEmoji(@NonNull ReactionTypes reactionTypes) { - switch (reactionTypes) { - case HEART: - return getHeart(); - case HOORAY: - return getHooray(); - case PLUS_ONE: - return getThumbsUp(); - case MINUS_ONE: - return getThumbsDown(); - case CONFUSED: - return getSad(); - case LAUGH: - return getLaugh(); - default: - return getThumbsUp(); - } - } - - public static String getLaugh() { - return getEmojiByUnicode(LAUGH); - } - - public static String getSad() { - return getEmojiByUnicode(SAD); - } - - public static String getThumbsUp() { - return getEmojiByUnicode(THUMBS_UP); - } - - public static String getThumbsDown() { - return getEmojiByUnicode(THUMBS_DOWN); - } - - public static String getHooray() { - return getEmojiByUnicode(HOORAY); - } - - public static String getHeart() { - return getEmojiByUnicode(HEART); - } - - @NonNull public static ArrayList getUsers(@NonNull List comments) { - return Stream.of(comments) - .map(comment -> comment.getUser().getLogin()) - .distinct() - .collect(Collectors.toCollection(ArrayList::new)); - } - - @NonNull public static ArrayList getUsersByTimeline(@NonNull List comments) { - return Stream.of(comments) - .filter(timelineModel -> timelineModel.getComment() != null && timelineModel.getComment().getUser() != null) - .map(comment -> comment.getComment().getUser().getLogin()) - .distinct() - .collect(Collectors.toCollection(ArrayList::new)); - } - - public static void appendEmojies(@NonNull ReactionsModel reaction, @NonNull TextView thumbsUp, - @NonNull TextView thumbsUpReaction, @NonNull TextView thumbsDown, - @NonNull TextView thumbsDownReaction, @NonNull TextView hurray, - @NonNull TextView hurrayReaction, @NonNull TextView sad, - @NonNull TextView sadReaction, @NonNull TextView laugh, - @NonNull TextView laughReaction, @NonNull TextView heart, - @NonNull TextView heartReaction, @NonNull View reactionsList) { - SpannableBuilder spannableBuilder = SpannableBuilder.builder() - .append(CommentsHelper.getThumbsUp()).append(" ") - .append(String.valueOf(reaction.getPlusOne())) - .append(" "); - thumbsUp.setText(spannableBuilder); - thumbsUpReaction.setText(spannableBuilder); - thumbsUpReaction.setVisibility(reaction.getPlusOne() > 0 ? View.VISIBLE : View.GONE); - spannableBuilder = SpannableBuilder.builder() - .append(CommentsHelper.getThumbsDown()).append(" ") - .append(String.valueOf(reaction.getMinusOne())) - .append(" "); - thumbsDown.setText(spannableBuilder); - thumbsDownReaction.setText(spannableBuilder); - thumbsDownReaction.setVisibility(reaction.getMinusOne() > 0 ? View.VISIBLE : View.GONE); - spannableBuilder = SpannableBuilder.builder() - .append(CommentsHelper.getHooray()).append(" ") - .append(String.valueOf(reaction.getHooray())) - .append(" "); - hurray.setText(spannableBuilder); - hurrayReaction.setText(spannableBuilder); - hurrayReaction.setVisibility(reaction.getHooray() > 0 ? View.VISIBLE : View.GONE); - spannableBuilder = SpannableBuilder.builder() - .append(CommentsHelper.getSad()).append(" ") - .append(String.valueOf(reaction.getConfused())) - .append(" "); - sad.setText(spannableBuilder); - sadReaction.setText(spannableBuilder); - sadReaction.setVisibility(reaction.getConfused() > 0 ? View.VISIBLE : View.GONE); - spannableBuilder = SpannableBuilder.builder() - .append(CommentsHelper.getLaugh()).append(" ") - .append(String.valueOf(reaction.getLaugh())) - .append(" "); - laugh.setText(spannableBuilder); - laughReaction.setText(spannableBuilder); - laughReaction.setVisibility(reaction.getLaugh() > 0 ? View.VISIBLE : View.GONE); - spannableBuilder = SpannableBuilder.builder() - .append(CommentsHelper.getHeart()).append(" ") - .append(String.valueOf(reaction.getHeart())); - heart.setText(spannableBuilder); - heartReaction.setText(spannableBuilder); - heartReaction.setVisibility(reaction.getHeart() > 0 ? View.VISIBLE : View.GONE); - if (reaction.getPlusOne() > 0 || reaction.getMinusOne() > 0 - || reaction.getLaugh() > 0 || reaction.getHooray() > 0 - || reaction.getConfused() > 0 || reaction.getHeart() > 0) { - reactionsList.setVisibility(View.VISIBLE); - reactionsList.setTag(true); - } else { - reactionsList.setVisibility(View.GONE); - reactionsList.setTag(false); - } - } - - -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/HtmlHelper.java b/app/src/main/java/com/fastaccess/provider/timeline/HtmlHelper.java deleted file mode 100644 index 68b8e9bb4..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/HtmlHelper.java +++ /dev/null @@ -1,207 +0,0 @@ -package com.fastaccess.provider.timeline; - - -import android.graphics.Color; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.v4.content.ContextCompat; -import android.view.HapticFeedbackConstants; -import android.widget.PopupMenu; -import android.widget.TextView; - -import com.fastaccess.R; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.provider.timeline.handler.BetterLinkMovementExtended; -import com.fastaccess.provider.timeline.handler.DrawableHandler; -import com.fastaccess.provider.timeline.handler.EmojiHandler; -import com.fastaccess.provider.timeline.handler.HeaderHandler; -import com.fastaccess.provider.timeline.handler.HrHandler; -import com.fastaccess.provider.timeline.handler.ItalicHandler; -import com.fastaccess.provider.timeline.handler.LinkHandler; -import com.fastaccess.provider.timeline.handler.ListsHandler; -import com.fastaccess.provider.timeline.handler.MarginHandler; -import com.fastaccess.provider.timeline.handler.PreTagHandler; -import com.fastaccess.provider.timeline.handler.QuoteHandler; -import com.fastaccess.provider.timeline.handler.StrikethroughHandler; -import com.fastaccess.provider.timeline.handler.SubScriptHandler; -import com.fastaccess.provider.timeline.handler.SuperScriptHandler; -import com.fastaccess.provider.timeline.handler.TableHandler; -import com.fastaccess.provider.timeline.handler.UnderlineHandler; - -import net.nightwhistler.htmlspanner.HtmlSpanner; -import net.nightwhistler.htmlspanner.handlers.BoldHandler; - - -/** - * Created by Kosh on 21 Apr 2017, 11:24 PM - */ - -public class HtmlHelper { - - public static void htmlIntoTextView(@NonNull TextView textView, @NonNull String html, int width) { - registerClickEvent(textView); - textView.setText(initHtml(textView, width).fromHtml(format(html).toString())); - } - - private static void registerClickEvent(@NonNull TextView textView) { - BetterLinkMovementExtended betterLinkMovementMethod = BetterLinkMovementExtended.linkifyHtml(textView); - betterLinkMovementMethod.setOnLinkClickListener((view, url) -> { - SchemeParser.launchUri(view.getContext(), Uri.parse(url)); - return true; - }); - betterLinkMovementMethod.setOnLinkLongClickListener((view, url) -> { - view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - PopupMenu menu = new PopupMenu(view.getContext(), view); - menu.setOnMenuItemClickListener(menuItem -> { - switch (menuItem.getItemId()) { - case R.id.copy: - AppHelper.copyToClipboard(view.getContext(), url); - return true; - case R.id.open: - SchemeParser.launchUri(view.getContext(), Uri.parse(url)); - return true; - case R.id.open_new_window: - SchemeParser.launchUri(view.getContext(), Uri.parse(url), false, true); - return true; - default: - return false; - } - }); - menu.inflate(R.menu.link_popup_menu); - menu.show(); - return true; - }); - } - - private static HtmlSpanner initHtml(@NonNull TextView textView, int width) { - @PrefGetter.ThemeType int theme = PrefGetter.getThemeType(); - @ColorInt int windowBackground = getWindowBackground(theme); - Drawable checked = ContextCompat.getDrawable(textView.getContext(), R.drawable.ic_checkbox_small); - Drawable unchecked = ContextCompat.getDrawable(textView.getContext(), R.drawable.ic_checkbox_empty_small); - HtmlSpanner mySpanner = new HtmlSpanner(); - mySpanner.setStripExtraWhiteSpace(true); - mySpanner.registerHandler("pre", new PreTagHandler(windowBackground, true, theme)); - mySpanner.registerHandler("code", new PreTagHandler(windowBackground, false, theme)); - mySpanner.registerHandler("img", new DrawableHandler(textView, width)); - mySpanner.registerHandler("g-emoji", new EmojiHandler()); - mySpanner.registerHandler("blockquote", new QuoteHandler(windowBackground)); - mySpanner.registerHandler("b", new BoldHandler()); - mySpanner.registerHandler("strong", new BoldHandler()); - mySpanner.registerHandler("i", new ItalicHandler()); - mySpanner.registerHandler("em", new ItalicHandler()); - mySpanner.registerHandler("ul", new MarginHandler()); - mySpanner.registerHandler("ol", new MarginHandler()); - mySpanner.registerHandler("li", new ListsHandler(checked, unchecked)); - mySpanner.registerHandler("u", new UnderlineHandler()); - mySpanner.registerHandler("strike", new StrikethroughHandler()); - mySpanner.registerHandler("ins", new UnderlineHandler()); - mySpanner.registerHandler("del", new StrikethroughHandler()); - mySpanner.registerHandler("sub", new SubScriptHandler()); - mySpanner.registerHandler("sup", new SuperScriptHandler()); - mySpanner.registerHandler("a", new LinkHandler()); - mySpanner.registerHandler("hr", new HrHandler(windowBackground, width, false)); - mySpanner.registerHandler("emoji", new EmojiHandler()); - mySpanner.registerHandler("mention", new LinkHandler()); - mySpanner.registerHandler("h1", new HeaderHandler(1.5F)); - mySpanner.registerHandler("h2", new HeaderHandler(1.4F)); - mySpanner.registerHandler("h3", new HeaderHandler(1.3F)); - mySpanner.registerHandler("h4", new HeaderHandler(1.2F)); - mySpanner.registerHandler("h5", new HeaderHandler(1.1F)); - mySpanner.registerHandler("h6", new HeaderHandler(1.0F)); - if (width > 0) { - TableHandler tableHandler = new TableHandler(); - tableHandler.setTextColor(ViewHelper.generateTextColor(windowBackground)); - tableHandler.setTableWidth(width); - mySpanner.registerHandler("table", tableHandler); - } - return mySpanner; - } - - @ColorInt public static int getWindowBackground(@PrefGetter.ThemeType int theme) { - if (theme == PrefGetter.AMLOD) { - return Color.parseColor("#0B162A"); - } else if (theme == PrefGetter.BLUISH) { - return Color.parseColor("#111C2C"); - } else if (theme == PrefGetter.DARK) { - return Color.parseColor("#22252A"); - } else { - return Color.parseColor("#EEEEEE"); - } - } - - private static final String TOGGLE_START = ""; - - private static final String TOGGLE_END = ""; - - private static final String REPLY_START = "

    "; - - private static final String REPLY_END = "
    "; - - private static final String SIGNATURE_START = "
    "; - - private static final String SIGNATURE_END = "
    "; - - private static final String HIDDEN_REPLY_START = "
    "; - - private static final String HIDDEN_REPLY_END = "
    "; - - private static final String BREAK = "
    "; - - private static final String PARAGRAPH_START = "

    "; - - private static final String PARAGRAPH_END = "

    "; - - //https://github.com/k0shk0sh/GitHubSdk/blob/master/library/src/main/java/com/meisolsson/githubsdk/core/HtmlUtils.java - @NonNull public static CharSequence format(final String html) { - if (html == null || html.length() == 0) return ""; - StringBuilder formatted = new StringBuilder(html); - strip(formatted, TOGGLE_START, TOGGLE_END); - strip(formatted, SIGNATURE_START, SIGNATURE_END); - strip(formatted, REPLY_START, REPLY_END); - strip(formatted, HIDDEN_REPLY_START, HIDDEN_REPLY_END); - if (replace(formatted, PARAGRAPH_START, BREAK)) replace(formatted, PARAGRAPH_END, BREAK); - trim(formatted); - return formatted; - } - - private static void strip(final StringBuilder input, final String prefix, final String suffix) { - int start = input.indexOf(prefix); - while (start != -1) { - int end = input.indexOf(suffix, start + prefix.length()); - if (end == -1) - end = input.length(); - input.delete(start, end + suffix.length()); - start = input.indexOf(prefix, start); - } - } - - private static boolean replace(final StringBuilder input, final String from, final String to) { - int start = input.indexOf(from); - if (start == -1) return false; - final int fromLength = from.length(); - final int toLength = to.length(); - while (start != -1) { - input.replace(start, start + fromLength, to); - start = input.indexOf(from, start + toLength); - } - return true; - } - - private static void trim(final StringBuilder input) { - int length = input.length(); - int breakLength = BREAK.length(); - while (length > 0) { - if (input.indexOf(BREAK) == 0) input.delete(0, breakLength); - else if (length >= breakLength && input.lastIndexOf(BREAK) == length - breakLength) input.delete(length - breakLength, length); - else if (Character.isWhitespace(input.charAt(0))) input.deleteCharAt(0); - else if (Character.isWhitespace(input.charAt(length - 1))) input.deleteCharAt(length - 1); - else break; - length = input.length(); - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/ReactionsProvider.java b/app/src/main/java/com/fastaccess/provider/timeline/ReactionsProvider.java deleted file mode 100644 index cd64cb375..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/ReactionsProvider.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.fastaccess.provider.timeline; - -import android.support.annotation.IdRes; -import android.support.annotation.IntDef; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.PostReactionModel; -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.LinkedHashMap; -import java.util.Map; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 09 Apr 2017, 10:40 AM - */ - -public class ReactionsProvider { - - public static final int HEADER = 0; - public static final int COMMENT = 1; - public static final int REVIEW_COMMENT = 2; - public static final int COMMIT = 3; - - @IntDef({ - HEADER, - COMMENT, - REVIEW_COMMENT, - COMMIT - }) - @Retention(RetentionPolicy.SOURCE) public @interface ReactionType {} - - private Map reactionsMap = new LinkedHashMap<>(); - - @Nullable public Observable onHandleReaction(@IdRes int viewId, long idOrNumber, @Nullable String login, - @Nullable String repoId, @ReactionType int reactionType, boolean isEnterprise) { - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - if (!isPreviouslyReacted(idOrNumber, viewId)) { - ReactionTypes reactionTypes = ReactionTypes.get(viewId); - if (reactionTypes != null) { - Observable observable = null; - switch (reactionType) { - case COMMENT: - observable = RestProvider.getReactionsService(isEnterprise) - .postIssueCommentReaction(new PostReactionModel(reactionTypes.getContent()), login, repoId, idOrNumber); - break; - case HEADER: - observable = RestProvider.getReactionsService(isEnterprise) - .postIssueReaction(new PostReactionModel(reactionTypes.getContent()), login, repoId, idOrNumber); - break; - case REVIEW_COMMENT: - observable = RestProvider.getReactionsService(isEnterprise) - .postCommentReviewReaction(new PostReactionModel(reactionTypes.getContent()), login, repoId, idOrNumber); - break; - case COMMIT: - observable = RestProvider.getReactionsService(isEnterprise) - .postCommitReaction(new PostReactionModel(reactionTypes.getContent()), login, repoId, idOrNumber); - break; - } - if (observable == null) return null; - return RxHelper.safeObservable(observable) - .doOnNext(response -> getReactionsMap().put(idOrNumber, response)); - } - } else { - ReactionsModel reactionsModel = getReactionsMap().get(idOrNumber); - if (reactionsModel != null) { - return RxHelper.safeObservable(RestProvider.getReactionsService(isEnterprise).delete(reactionsModel.getId())) - .doOnNext(booleanResponse -> { - if (booleanResponse.code() == 204) { - getReactionsMap().remove(idOrNumber); - } - }); - } - } - } - return null; - } - - - public boolean isPreviouslyReacted(long idOrNumber, @IdRes int vId) { - ReactionsModel reactionsModel = getReactionsMap().get(idOrNumber); - if (reactionsModel == null || InputHelper.isEmpty(reactionsModel.getContent())) { - return false; - } - ReactionTypes type = ReactionTypes.get(vId); - return type != null && type.getContent().equals(reactionsModel.getContent()); - } - - public boolean isCallingApi(long id, int vId) { - ReactionsModel reactionsModel = getReactionsMap().get(id); - if (reactionsModel == null || InputHelper.isEmpty(reactionsModel.getContent())) { - return false; - } - ReactionTypes type = ReactionTypes.get(vId); - return type != null && type.getContent().equals(reactionsModel.getContent()) && reactionsModel.isCallingApi(); - } - - @NonNull private Map getReactionsMap() { - return reactionsMap; - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/TimelineConverter.kt b/app/src/main/java/com/fastaccess/provider/timeline/TimelineConverter.kt deleted file mode 100644 index f6bed9074..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/TimelineConverter.kt +++ /dev/null @@ -1,133 +0,0 @@ -package com.fastaccess.provider.timeline - -import com.fastaccess.data.dao.* -import com.fastaccess.data.dao.model.Comment -import com.fastaccess.data.dao.timeline.GenericEvent -import com.fastaccess.data.dao.timeline.PullRequestCommitModel -import com.fastaccess.data.dao.types.IssueEventType -import com.fastaccess.helper.InputHelper -import com.fastaccess.provider.rest.RestProvider -import com.google.gson.Gson -import com.google.gson.JsonObject -import io.reactivex.Observable - -/** - * Created by kosh on 26/07/2017. - */ - -object TimelineConverter { - - fun convert(jsonObjects: List?): Observable { - if (jsonObjects == null) return Observable.empty() - val gson = RestProvider.gson - return Observable.fromIterable(jsonObjects) - .map { jsonObject -> - val event = jsonObject.get("event").asString - val timeline = TimelineModel() - if (!InputHelper.isEmpty(event)) { - val type = IssueEventType.getType(event) - timeline.event = type - if (type != null) { - if (type == IssueEventType.commented) { - timeline.comment = getComment(jsonObject, gson) - } else { - timeline.genericEvent = getGenericEvent(jsonObject, gson) - } - } - } else { - timeline.genericEvent = getGenericEvent(jsonObject, gson) - } - timeline - } - .filter { filterEvents(it.event) } - } - - fun convert(jsonObjects: List?, comments: Pageable?): List { - val list = arrayListOf() - if (jsonObjects == null) return list - val gson = RestProvider.gson - jsonObjects.onEach { jsonObject -> - val event = jsonObject.get("event").asString - val timeline = TimelineModel() - if (!InputHelper.isEmpty(event)) { - val type = IssueEventType.getType(event) - timeline.event = type - if (type != null) { - if (type == IssueEventType.commented) { - timeline.comment = getComment(jsonObject, gson) - list.add(timeline) - } else if (type == IssueEventType.commit_commented) { - val commit = getCommit(jsonObject, gson) - if (commit != null) { - val comment = commit.comments?.firstOrNull() - comment?.let { - commit.path = it.path - commit.position = it.position - commit.line = it.line - commit.login = it.user?.login - } - timeline.commit = commit - list.add(timeline) - } - } else if (type == IssueEventType.reviewed || type == IssueEventType - .changes_requested) { - val review = getReview(jsonObject, gson) - if (review != null) { - timeline.review = review - list.add(timeline) - val reviewsList = arrayListOf() - comments?.items?.filter { it.pullRequestReviewId == review.id } - ?.onEach { - val grouped = GroupedReviewModel() - grouped.diffText = it.diffHunk - grouped.path = it.path - grouped.position = it.position - grouped.comments = arrayListOf(it) - grouped.id = it.id - val groupTimeline = TimelineModel() - groupTimeline.event = IssueEventType.GROUPED - groupTimeline.groupedReviewModel = grouped - reviewsList.add(groupTimeline) - } - comments?.items?.filter { it.pullRequestReviewId != review.id }?.onEach { - reviewsList.onEach { reviews -> - if (it.path == reviews.groupedReviewModel.path && it.position == reviews.groupedReviewModel.position) { - reviews.groupedReviewModel.comments.add(it) - } - } - } - list.addAll(reviewsList) - } - } else { - timeline.genericEvent = getGenericEvent(jsonObject, gson) - list.add(timeline) - } - } - } else { - timeline.genericEvent = getGenericEvent(jsonObject, gson) - list.add(timeline) - } - } - return list.filter({filterEvents(it.event)}) - } - - private fun getCommit(jsonObject: JsonObject, gson: Gson): PullRequestCommitModel? { - return gson.fromJson(jsonObject, PullRequestCommitModel::class.java) - } - - private fun getGenericEvent(jsonObject: JsonObject, gson: Gson): GenericEvent { - return gson.fromJson(jsonObject, GenericEvent::class.java) - } - - private fun getComment(jsonObject: JsonObject, gson: Gson): Comment { - return gson.fromJson(jsonObject, Comment::class.java) - } - - private fun filterEvents(type: IssueEventType?): Boolean { - return type != null && type != IssueEventType.subscribed && type != IssueEventType.unsubscribed && type != IssueEventType.mentioned - } - - private fun getReview(jsonObject: JsonObject, gson: Gson): ReviewModel? { - return gson.fromJson(jsonObject, ReviewModel::class.java) - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/TimelineProvider.java b/app/src/main/java/com/fastaccess/provider/timeline/TimelineProvider.java deleted file mode 100644 index 54f04a3b9..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/TimelineProvider.java +++ /dev/null @@ -1,208 +0,0 @@ -package com.fastaccess.provider.timeline; - -import android.content.Context; -import android.graphics.Color; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.style.BackgroundColorSpan; - -import com.fastaccess.R; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.timeline.GenericEvent; -import com.fastaccess.data.dao.timeline.SourceModel; -import com.fastaccess.data.dao.types.IssueEventType; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.zzhoujay.markdown.style.CodeSpan; - -import java.util.Date; - -/** - * Created by Kosh on 20 Apr 2017, 7:18 PM - */ - -public class TimelineProvider { - - @NonNull public static SpannableBuilder getStyledEvents(@NonNull GenericEvent issueEventModel, - @NonNull Context context, boolean isMerged) { - IssueEventType event = issueEventModel.getEvent(); - SpannableBuilder spannableBuilder = SpannableBuilder.builder(); - Date date = issueEventModel.getCreatedAt() != null - ? issueEventModel.getCreatedAt() - : issueEventModel.getAuthor() != null - ? issueEventModel.getAuthor().getDate() : null; - if (event != null) { - String to = context.getString(R.string.to); - String from = context.getString(R.string.from); - String thisString = context.getString(R.string.this_value); - String in = context.getString(R.string.in_value); - if (event == IssueEventType.labeled || event == IssueEventType.unlabeled) { - spannableBuilder.bold(issueEventModel.getActor() != null ? issueEventModel.getActor().getLogin() : "anonymous"); - spannableBuilder.append(" ").append(event.name().replaceAll("_", " ")); - LabelModel labelModel = issueEventModel.getLabel(); - int color = Color.parseColor("#" + labelModel.getColor()); - spannableBuilder.append(" ").append(" " + labelModel.getName() + " ", new CodeSpan(color, ViewHelper.generateTextColor(color), 5)); - spannableBuilder.append(" ").append(getDate(issueEventModel.getCreatedAt())); - } else if (event == IssueEventType.committed) { - spannableBuilder.append(issueEventModel.getMessage().replaceAll("\n", " ")) - .append(" ") - .url(substring(issueEventModel.getSha())); - } else { - User user = null; - if (issueEventModel.getAssignee() != null && issueEventModel.getAssigner() != null) { - user = issueEventModel.getAssigner(); - } else if (issueEventModel.getActor() != null) { - user = issueEventModel.getActor(); - } else if (issueEventModel.getAuthor() != null) { - user = issueEventModel.getAuthor(); - } - if (user != null) { - spannableBuilder.bold(user.getLogin()); - } - if ((event == IssueEventType.review_requested || (event == IssueEventType.review_dismissed || - event == IssueEventType.review_request_removed)) && user != null) { - appendReviews(issueEventModel, event, spannableBuilder, from, issueEventModel.getReviewRequester()); - } else if (event == IssueEventType.closed || event == IssueEventType.reopened) { - if (isMerged) { - spannableBuilder.append(" ").append(IssueEventType.merged.name()); - } else { - spannableBuilder - .append(" ") - .append(event.name().replaceAll("_", " ")) - .append(" ") - .append(thisString); - } - if (issueEventModel.getCommitId() != null) { - spannableBuilder - .append(" ") - .append(in) - .append(" ") - .url(substring(issueEventModel.getCommitId())); - } - } else if (event == IssueEventType.assigned || event == IssueEventType.unassigned) { - spannableBuilder - .append(" "); - if ((user != null && issueEventModel.getAssignee() != null) && user.getLogin() - .equalsIgnoreCase(issueEventModel.getAssignee().getLogin())) { - spannableBuilder - .append(event == IssueEventType.assigned ? "self-assigned this" : "removed their assignment"); - } else { - spannableBuilder - .append(event == IssueEventType.assigned ? "assigned" : "unassigned"); - spannableBuilder - .append(" ") - .bold(issueEventModel.getAssignee() != null ? issueEventModel.getAssignee().getLogin() : ""); - } - } else if (event == IssueEventType.locked || event == IssueEventType.unlocked) { - spannableBuilder - .append(" ") - .append(event == IssueEventType.locked ? "locked and limited conversation to collaborators" : "unlocked this " + - "conversation"); - } else if (event == IssueEventType.head_ref_deleted || event == IssueEventType.head_ref_restored) { - spannableBuilder.append(" ").append(event.name().replaceAll("_", " "), - new BackgroundColorSpan(HtmlHelper.getWindowBackground(PrefGetter.getThemeType()))); - } else if (event == IssueEventType.milestoned || event == IssueEventType.demilestoned) { - spannableBuilder.append(" ") - .append(event == IssueEventType.milestoned ? "added this to the" : "removed this from the") - .append(" ") - .bold(issueEventModel.getMilestone().getTitle()) - .append(" ") - .append("milestone"); - } else if (event == IssueEventType.deployed) { - spannableBuilder.append(" ") - .bold("deployed"); - } else { - spannableBuilder.append(" ").append(event.name().replaceAll("_", " ")); - } - if (event == IssueEventType.renamed) { - spannableBuilder - .append(" ") - .append(from) - .append(" ") - .bold(issueEventModel.getRename().getFromValue()) - .append(" ") - .append(to) - .append(" ") - .bold(issueEventModel.getRename().getToValue()); - } else if (event == IssueEventType.referenced || event == IssueEventType.merged) { - spannableBuilder - .append(" ") - .append("commit") - .append(" ") - .url(substring(issueEventModel.getCommitId())); - } else if (event == IssueEventType.cross_referenced) { - SourceModel sourceModel = issueEventModel.getSource(); - if (sourceModel != null) { - String type = sourceModel.getType(); - SpannableBuilder title = SpannableBuilder.builder(); - if (sourceModel.getPullRequest() != null) { - if (sourceModel.getIssue() != null) title.url("#" + sourceModel.getIssue().getNumber()); - type = "pull request"; - } else if (sourceModel.getIssue() != null) { - title.url("#" + sourceModel.getIssue().getNumber()); - } else if (sourceModel.getCommit() != null) { - title.url(substring(sourceModel.getCommit().getSha())); - } else if (sourceModel.getRepository() != null) { - title.url(sourceModel.getRepository().getName()); - } - if (!InputHelper.isEmpty(title)) { - spannableBuilder.append(" ") - .append(thisString) - .append(" in ") - .append(type) - .append(" ") - .append(title); - } - } - } - spannableBuilder.append(" ").append(getDate(date)); - } - } - return spannableBuilder; - } - - private static void appendReviews(@NonNull GenericEvent issueEventModel, @NonNull IssueEventType event, - @NonNull SpannableBuilder spannableBuilder, @NonNull String from, - @NonNull User user) { - spannableBuilder.append(" "); - User reviewer = issueEventModel.getRequestedReviewer(); - if (reviewer != null && user.getLogin().equalsIgnoreCase(reviewer.getLogin())) { - spannableBuilder - .append(event == IssueEventType.review_requested - ? "self-requested a review" : "removed their request for review"); - } else { - spannableBuilder - .append(event == IssueEventType.review_requested ? "Requested a review" : "dismissed the review") - .append(" ") - .append(reviewer != null && !reviewer.getLogin().equalsIgnoreCase(user.getLogin()) ? from : " ") - .append(reviewer != null && !reviewer.getLogin().equalsIgnoreCase(user.getLogin()) ? " " : ""); - } - if (issueEventModel.getRequestedTeam() != null) { - String name = !InputHelper.isEmpty(issueEventModel.getRequestedTeam().getName()) - ? issueEventModel.getRequestedTeam().getName() : issueEventModel.getRequestedTeam().getSlug(); - spannableBuilder - .bold(name) - .append(" ") - .append("team"); - } else if (reviewer != null && !user.getLogin().equalsIgnoreCase(reviewer.getLogin())) { - spannableBuilder.bold(issueEventModel.getRequestedReviewer().getLogin()); - } - } - - @NonNull private static CharSequence getDate(@Nullable Date date) { - return ParseDateFormat.getTimeAgo(date); - } - - @NonNull private static String substring(@Nullable String value) { - if (value == null) { - return ""; - } - if (value.length() <= 7) return value; - else return value.substring(0, 7); - } - -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/BetterLinkMovementExtended.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/BetterLinkMovementExtended.java deleted file mode 100644 index 3d64b5766..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/BetterLinkMovementExtended.java +++ /dev/null @@ -1,267 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.content.Context; -import android.graphics.RectF; -import android.text.Layout; -import android.text.Selection; -import android.text.Spannable; -import android.text.Spanned; -import android.text.method.LinkMovementMethod; -import android.text.style.BackgroundColorSpan; -import android.text.style.ClickableSpan; -import android.text.style.URLSpan; -import android.text.util.Linkify; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - - -/** - * Created by Kosh on 23 Apr 2017, 12:09 PM - *

    - * credit to to https://github.com/Saketme/Better-Link-Movement-Method - */ - -public class BetterLinkMovementExtended extends LinkMovementMethod { - private static final Class SPAN_CLASS = ClickableSpan.class; - private static final int LINKIFY_NONE = -2; - private BetterLinkMovementExtended.OnLinkClickListener onLinkClickListener; - private BetterLinkMovementExtended.OnLinkLongClickListener onLinkLongClickListener; - private final RectF touchedLineBounds = new RectF(); - private boolean isUrlHighlighted; - private boolean touchStartedOverLink; - private int activeTextViewHashcode; - - private final GestureDetector gestureDetector; - private final LinkClickGestureListener clickGestureListener = new LinkClickGestureListener(); - - private BetterLinkMovementExtended(Context context) { - gestureDetector = new GestureDetector(context, clickGestureListener); - } - - private final class LinkClickGestureListener extends GestureDetector.SimpleOnGestureListener { - private GestureDetector.SimpleOnGestureListener listener = null; - - @Override public boolean onDown(MotionEvent e) { - if(listener != null) listener.onDown(e); - return true; - } - - @Override public boolean onSingleTapUp(MotionEvent e) { - return listener == null || listener.onSingleTapUp(e); - } - - @Override public void onLongPress(MotionEvent e) { - if(listener != null) listener.onLongPress(e); - } - } - - private static BetterLinkMovementExtended linkify(int linkifyMask, TextView textView) { - BetterLinkMovementExtended movementMethod = new BetterLinkMovementExtended(textView.getContext()); - addLinks(linkifyMask, movementMethod, textView); - return movementMethod; - } - - public static BetterLinkMovementExtended linkifyHtml(TextView textView) { - return linkify(LINKIFY_NONE, textView); - } - - private static BetterLinkMovementExtended linkify(int linkifyMask, ViewGroup viewGroup) { - BetterLinkMovementExtended movementMethod = new BetterLinkMovementExtended(viewGroup.getContext()); - rAddLinks(linkifyMask, viewGroup, movementMethod); - return movementMethod; - } - - public static BetterLinkMovementExtended linkifyHtml(ViewGroup viewGroup) { - return linkify(LINKIFY_NONE, viewGroup); - } - - public void setOnLinkClickListener(OnLinkClickListener onLinkClickListener) { - this.onLinkClickListener = onLinkClickListener; - } - - public void setOnLinkLongClickListener(OnLinkLongClickListener onLinkLongClickListener) { - this.onLinkLongClickListener = onLinkLongClickListener; - } - - private static void rAddLinks(int linkifyMask, ViewGroup viewGroup, BetterLinkMovementExtended movementMethod) { - for (int i = 0; i < viewGroup.getChildCount(); ++i) { - View child = viewGroup.getChildAt(i); - if (child instanceof ViewGroup) { - rAddLinks(linkifyMask, (ViewGroup) child, movementMethod); - } else if (child instanceof TextView) { - TextView textView = (TextView) child; - addLinks(linkifyMask, movementMethod, textView); - } - } - - } - - private static void addLinks(int linkifyMask, BetterLinkMovementExtended movementMethod, TextView textView) { - textView.setMovementMethod(movementMethod); - if (linkifyMask != LINKIFY_NONE) { - Linkify.addLinks(textView, linkifyMask); - } - - } - - public boolean onTouchEvent(TextView view, Spannable text, MotionEvent event) { - if (this.activeTextViewHashcode != view.hashCode()) { - this.activeTextViewHashcode = view.hashCode(); - view.setAutoLinkMask(0); - } - - BetterLinkMovementExtended.ClickableSpanWithText touchedClickableSpan = this.findClickableSpanUnderTouch(view, text, event); - if (touchedClickableSpan != null) { - this.highlightUrl(view, touchedClickableSpan, text); - } else { - this.removeUrlHighlightColor(view); - } - - clickGestureListener.listener = new GestureDetector.SimpleOnGestureListener() { - @Override public boolean onDown(MotionEvent e) { - touchStartedOverLink = touchedClickableSpan != null; - return true; - } - - @Override public boolean onSingleTapUp(MotionEvent e) { - if (touchedClickableSpan != null && touchStartedOverLink) { - dispatchUrlClick(view, touchedClickableSpan); - removeUrlHighlightColor(view); - } - - touchStartedOverLink = false; - return true; - } - - @Override public void onLongPress(MotionEvent e) { - if (touchedClickableSpan != null && touchStartedOverLink) { - dispatchUrlLongClick(view, touchedClickableSpan); - removeUrlHighlightColor(view); - } - - touchStartedOverLink = false; - } - }; - - boolean ret = gestureDetector.onTouchEvent(event); - - if(!ret && event.getAction() == MotionEvent.ACTION_UP) { - clickGestureListener.listener = null; - removeUrlHighlightColor(view); - this.touchStartedOverLink = false; - ret = true; - } - - return ret; - } - - private BetterLinkMovementExtended.ClickableSpanWithText findClickableSpanUnderTouch(TextView textView, Spannable text, MotionEvent event) { - int touchX = (int) event.getX(); - int touchY = (int) event.getY(); - touchX -= textView.getTotalPaddingLeft(); - touchY -= textView.getTotalPaddingTop(); - touchX += textView.getScrollX(); - touchY += textView.getScrollY(); - Layout layout = textView.getLayout(); - int touchedLine = layout.getLineForVertical(touchY); - int touchOffset = layout.getOffsetForHorizontal(touchedLine, (float) touchX); - this.touchedLineBounds.left = layout.getLineLeft(touchedLine); - this.touchedLineBounds.top = (float) layout.getLineTop(touchedLine); - this.touchedLineBounds.right = layout.getLineWidth(touchedLine) + this.touchedLineBounds.left; - this.touchedLineBounds.bottom = (float) layout.getLineBottom(touchedLine); - if (this.touchedLineBounds.contains((float) touchX, (float) touchY)) { - Object[] spans = text.getSpans(touchOffset, touchOffset, SPAN_CLASS); - for (Object span : spans) { - if (span instanceof ClickableSpan) { - return ClickableSpanWithText.ofSpan(textView, (ClickableSpan) span); - } - } - return null; - } else { - return null; - } - } - - private void highlightUrl(TextView textView, BetterLinkMovementExtended.ClickableSpanWithText spanWithText, Spannable text) { - if (!this.isUrlHighlighted) { - this.isUrlHighlighted = true; - int spanStart = text.getSpanStart(spanWithText.span()); - int spanEnd = text.getSpanEnd(spanWithText.span()); - Selection.removeSelection(text); - text.setSpan(new BackgroundColorSpan(textView.getHighlightColor()), spanStart, spanEnd, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - textView.setText(text); - Selection.setSelection(text, spanStart, spanEnd); - } - } - - private void removeUrlHighlightColor(TextView textView) { - if (this.isUrlHighlighted) { - this.isUrlHighlighted = false; - Spannable text = (Spannable) textView.getText(); - BackgroundColorSpan[] highlightSpans = text.getSpans(0, text.length(), BackgroundColorSpan.class); - for (BackgroundColorSpan highlightSpan : highlightSpans) { - text.removeSpan(highlightSpan); - } - try { - textView.setText(text); - Selection.removeSelection(text); - } catch (Exception ignored) {} - } - } - - private void dispatchUrlClick(TextView textView, BetterLinkMovementExtended.ClickableSpanWithText spanWithText) { - String spanUrl = spanWithText.text(); - boolean handled = this.onLinkClickListener != null && this.onLinkClickListener.onClick(textView, spanUrl); - if (!handled) { - spanWithText.span().onClick(textView); - } - - } - - private void dispatchUrlLongClick(TextView textView, BetterLinkMovementExtended.ClickableSpanWithText spanWithText) { - String spanUrl = spanWithText.text(); - if(onLinkLongClickListener != null) onLinkLongClickListener.onLongClick(textView, spanUrl); - } - - static class ClickableSpanWithText { - private ClickableSpan span; - private String text; - - static BetterLinkMovementExtended.ClickableSpanWithText ofSpan(TextView textView, ClickableSpan span) { - Spanned s = (Spanned) textView.getText(); - String text; - if (span instanceof URLSpan) { - text = ((URLSpan) span).getURL(); - } else { - int start = s.getSpanStart(span); - int end = s.getSpanEnd(span); - text = s.subSequence(start, end).toString(); - } - return new BetterLinkMovementExtended.ClickableSpanWithText(span, text); - } - - private ClickableSpanWithText(ClickableSpan span, String text) { - this.span = span; - this.text = text; - } - - ClickableSpan span() { - return this.span; - } - - String text() { - return this.text; - } - } - - public interface OnLinkClickListener { - boolean onClick(TextView view, String link); - } - - public interface OnLinkLongClickListener { - boolean onLongClick(TextView view, String link); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/CodeBackgroundRoundedSpan.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/CodeBackgroundRoundedSpan.java deleted file mode 100644 index 4a7a0e1cd..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/CodeBackgroundRoundedSpan.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.RectF; -import android.graphics.Typeface; -import android.text.Layout; -import android.text.TextPaint; -import android.text.style.LeadingMarginSpan; -import android.text.style.LineBackgroundSpan; -import android.text.style.MetricAffectingSpan; - -public class CodeBackgroundRoundedSpan extends MetricAffectingSpan implements LeadingMarginSpan, LineBackgroundSpan { - private final int color; - - private final RectF rect = new RectF(); - - CodeBackgroundRoundedSpan(int color) { - this.color = color; - } - - @Override public void updateMeasureState(TextPaint paint) { - apply(paint); - } - - @Override public void updateDrawState(TextPaint paint) { - apply(paint); - } - - private void apply(TextPaint paint) { - paint.setTypeface(Typeface.MONOSPACE); - } - - @Override public void drawBackground(Canvas c, Paint p, int left, int right, int top, int baseline, int bottom, - CharSequence text, int start, int end, int lnum) { - Paint.Style style = p.getStyle(); - int color = p.getColor(); - p.setStyle(Paint.Style.FILL); - p.setColor(this.color); - rect.set(left, top, right, bottom); - c.drawRect(rect, p); - p.setColor(color); - p.setStyle(style); - } - - @Override public int getLeadingMargin(boolean first) { - return 30; - } - - @Override public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, - CharSequence text, int start, int end, boolean first, Layout layout) {} -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/DrawableHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/DrawableHandler.java deleted file mode 100644 index fe6517dbf..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/DrawableHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.text.SpannableStringBuilder; -import android.text.style.ImageSpan; -import android.widget.TextView; - -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.provider.timeline.handler.drawable.DrawableGetter; -import com.fastaccess.ui.widgets.SpannableBuilder; - -import net.nightwhistler.htmlspanner.TagNodeHandler; -import net.nightwhistler.htmlspanner.spans.CenterSpan; - -import org.htmlcleaner.TagNode; - -import lombok.AllArgsConstructor; - -import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE; - -/** - * Created by Kosh on 22 Apr 2017, 1:09 PM - */ - -@AllArgsConstructor public class DrawableHandler extends TagNodeHandler { - - private TextView textView; - private int width; - - @SuppressWarnings("ConstantConditions") private boolean isNull() { - return textView == null; - } - - @Override public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) { - String src = node.getAttributeByName("src"); - if (!InputHelper.isEmpty(src)) { - if (!PrefGetter.isAutoImageDisabled()) { - builder.append(""); - if (isNull()) return; - builder.append("\n"); - DrawableGetter imageGetter = new DrawableGetter(textView, width); - builder.setSpan(new ImageSpan(imageGetter.getDrawable(src)), start, builder.length(), SPAN_EXCLUSIVE_EXCLUSIVE); - builder.setSpan(new CenterSpan(), start, builder.length(), SPAN_EXCLUSIVE_EXCLUSIVE); - builder.append("\n"); - } else { - builder.append(SpannableBuilder.builder().clickable("Image", v -> SchemeParser.launchUri(v.getContext(), src))); - builder.append("\n"); - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/EmojiHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/EmojiHandler.java deleted file mode 100644 index 8960fd22b..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/EmojiHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.text.SpannableStringBuilder; - -import com.fastaccess.helper.Logger; -import com.fastaccess.provider.emoji.Emoji; -import com.fastaccess.provider.emoji.EmojiManager; - -import net.nightwhistler.htmlspanner.TagNodeHandler; - -import org.htmlcleaner.TagNode; - -/** - * Created by Kosh on 27 May 2017, 4:54 PM - */ - -public class EmojiHandler extends TagNodeHandler { - - @Override public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) { - String emoji = node.getAttributeByName("alias"); - if (emoji != null) { - Emoji unicode = EmojiManager.getForAlias(emoji); - if (unicode != null && unicode.getUnicode() != null) { - builder.replace(start, end, " " + unicode.getUnicode() + " "); - } - } else if (node.getText() != null) { - Logger.e(node.getText()); - Emoji unicode = EmojiManager.getForAlias(node.getText().toString()); - if (unicode != null && unicode.getUnicode() != null) { - builder.replace(start, end, " " + unicode.getUnicode() + " "); - } - } - } - - @Override public void beforeChildren(TagNode node, SpannableStringBuilder builder) { - super.beforeChildren(node, builder); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/HeaderHandler.kt b/app/src/main/java/com/fastaccess/provider/timeline/handler/HeaderHandler.kt deleted file mode 100644 index 32c61f8ee..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/HeaderHandler.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.fastaccess.provider.timeline.handler - -import android.text.SpannableStringBuilder -import android.text.style.RelativeSizeSpan -import net.nightwhistler.htmlspanner.TagNodeHandler -import net.nightwhistler.htmlspanner.spans.FontFamilySpan -import org.htmlcleaner.TagNode - -/** - * Created by Kosh on 29.09.17. - */ -class HeaderHandler(val size: Float) : TagNodeHandler() { - - override fun beforeChildren(node: TagNode?, builder: SpannableStringBuilder?) { - appendNewLine(builder) - } - - override fun handleTagNode(node: TagNode, builder: SpannableStringBuilder, start: Int, end: Int) { - builder.setSpan(RelativeSizeSpan(this.size), start, end, 33) - val originalSpan = this.getFontFamilySpan(builder, start, end) - val boldSpan: FontFamilySpan - if (originalSpan == null) { - boldSpan = FontFamilySpan(this.spanner.defaultFont) - } else { - boldSpan = FontFamilySpan(originalSpan.fontFamily) - boldSpan.isItalic = originalSpan.isItalic - } - - boldSpan.isBold = true - builder.setSpan(boldSpan, start, end, 33) - appendNewLine(builder) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/HrHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/HrHandler.java deleted file mode 100644 index 21a75d3b0..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/HrHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.text.SpannableStringBuilder; -import android.text.Spanned; - -import net.nightwhistler.htmlspanner.TagNodeHandler; -import net.nightwhistler.htmlspanner.spans.CenterSpan; - -import org.htmlcleaner.TagNode; - -import lombok.AllArgsConstructor; - -/** - * Created by kosh on 30/07/2017. - */ - -@AllArgsConstructor public class HrHandler extends TagNodeHandler { - - private final int color; - private final int width; - private final boolean isHeader; - - @Override public void handleTagNode(TagNode tagNode, SpannableStringBuilder spannableStringBuilder, int i, int i1) { - spannableStringBuilder.append("\n"); - SpannableStringBuilder builder = new SpannableStringBuilder("$"); - HrSpan hrSpan = new HrSpan(color, width); - builder.setSpan(hrSpan, 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - builder.setSpan(new CenterSpan(), 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - builder.append("\n"); - spannableStringBuilder.append(builder); - } - -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/HrSpan.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/HrSpan.java deleted file mode 100644 index 176612d2f..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/HrSpan.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.text.style.LineHeightSpan; -import android.text.style.ReplacementSpan; - -public class HrSpan extends ReplacementSpan implements LineHeightSpan { - - private final int width; - private final int color; - - HrSpan(int color, int width) { - this.color = color; - this.width = width; - Drawable drawable = new ColorDrawable(color); - } - - @Override public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { - return (int) paint.measureText(text, start, end); - } - - @Override public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, - int y, int bottom, @NonNull Paint paint) { - final int currentColor = paint.getColor(); - paint.setColor(color); - paint.setStyle(Paint.Style.FILL); - int height = 10; - canvas.drawRect(new Rect(0, bottom - height, (int) x + width, bottom), paint); - paint.setColor(currentColor); - } - - @Override public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int v, Paint.FontMetricsInt fm) { - fm.top /= 3; - fm.ascent /= 3; - fm.bottom /= 3; - fm.descent /= 3; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/ItalicHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/ItalicHandler.java deleted file mode 100644 index a1c625511..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/ItalicHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.graphics.Typeface; -import android.text.SpannableStringBuilder; - -import com.zzhoujay.markdown.style.FontSpan; - -import net.nightwhistler.htmlspanner.TagNodeHandler; - -import org.htmlcleaner.TagNode; - -/** - * Created by Kosh on 06 May 2017, 11:02 AM - */ - -public class ItalicHandler extends TagNodeHandler { - - public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) { - builder.setSpan(new FontSpan(1, Typeface.ITALIC), start, builder.length(), 33); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/LinkHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/LinkHandler.java deleted file mode 100644 index 5cd9de55e..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/LinkHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.graphics.Color; -import android.text.SpannableStringBuilder; - -import com.zzhoujay.markdown.style.LinkSpan; - -import net.nightwhistler.htmlspanner.TagNodeHandler; - -import org.htmlcleaner.TagNode; - -/** - * Created by Kosh on 10 May 2017, 8:46 PM - */ - -public class LinkHandler extends TagNodeHandler { - private final static int linkColor = Color.parseColor("#4078C0"); - - @Override public void handleTagNode(TagNode node, SpannableStringBuilder spannableStringBuilder, int start, int end) { - String href = node.getAttributeByName("href"); - if (href != null) { - spannableStringBuilder.setSpan(new LinkSpan(href, linkColor), start, end, 33); - } else if (node.getText() != null) { - spannableStringBuilder.setSpan(new LinkSpan("https://github.com/" + node.getText().toString(), linkColor), start, end, 33); - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/ListsHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/ListsHandler.java deleted file mode 100644 index 6e5d01de3..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/ListsHandler.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.graphics.drawable.Drawable; -import android.support.annotation.Nullable; -import android.text.SpannableStringBuilder; - -import com.fastaccess.helper.Logger; -import com.fastaccess.ui.widgets.SpannableBuilder; - -import net.nightwhistler.htmlspanner.TagNodeHandler; - -import org.htmlcleaner.TagNode; - -import lombok.AllArgsConstructor; -import lombok.NoArgsConstructor; - -@NoArgsConstructor @AllArgsConstructor public class ListsHandler extends TagNodeHandler { - - @Nullable private Drawable checked; - @Nullable private Drawable unchecked; - - private int getMyIndex(TagNode node) { - if (node.getParent() == null) { - return -1; - } else { - int i = 1; - for (Object child : node.getParent().getChildren()) { - if (child == node) { - return i; - } - if (child instanceof TagNode) { - TagNode childNode = (TagNode) child; - if ("li".equals(childNode.getName())) { - ++i; - } - } - } - return -1; - } - } - - private String getParentName(TagNode node) { - return node.getParent() == null ? null : node.getParent().getName(); - } - - @Override public void beforeChildren(TagNode node, SpannableStringBuilder builder) { - TodoItems todoItem = null; - if (node.getChildTags() != null && node.getChildTags().length > 0) { - for (TagNode tagNode : node.getChildTags()) { - Logger.e(tagNode.getName(), tagNode.getText()); - if (tagNode.getName() != null && tagNode.getName().equals("input")) { - todoItem = new TodoItems(); - todoItem.isChecked = tagNode.getAttributeByName("checked") != null; - break; - } - } - } - if ("ol".equals(getParentName(node))) { - builder.append(String.valueOf(getMyIndex(node))).append(". "); - } else if ("ul".equals(getParentName(node))) { - if (todoItem != null) { - if (checked == null || unchecked == null) { - builder.append(todoItem.isChecked ? "☑" : "☐"); - } else { - builder.append(SpannableBuilder.builder() - .append(todoItem.isChecked ? checked : unchecked)) - .append(" "); - } - } else { - builder.append("\u2022 "); - } - } - } - - @Override public void handleTagNode(TagNode tagNode, SpannableStringBuilder spannableStringBuilder, int i, int i1) { - appendNewLine(spannableStringBuilder); - } - - static class TodoItems { - boolean isChecked; - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/MarginHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/MarginHandler.java deleted file mode 100644 index 3fec4aa40..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/MarginHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.text.Spannable; -import android.text.SpannableStringBuilder; -import android.text.style.LeadingMarginSpan; - -import net.nightwhistler.htmlspanner.TagNodeHandler; - -import org.htmlcleaner.TagNode; - -/** - * Created by Kosh on 29 Apr 2017, 11:59 PM - */ - -public class MarginHandler extends TagNodeHandler { - - public void beforeChildren(TagNode node, SpannableStringBuilder builder) { - if (builder.length() > 0 && builder.charAt(builder.length() - 1) != 10) { //'10 = \n' - this.appendNewLine(builder); - } - } - - public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) { - builder.setSpan(new LeadingMarginSpan.Standard(30), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - this.appendNewLine(builder); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/PreTagHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/PreTagHandler.java deleted file mode 100644 index e1f40a747..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/PreTagHandler.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.graphics.Color; -import android.support.annotation.ColorInt; -import android.text.SpannableStringBuilder; -import android.text.style.BackgroundColorSpan; -import android.text.style.ForegroundColorSpan; -import android.text.style.TypefaceSpan; - -import com.fastaccess.helper.PrefGetter; - -import net.nightwhistler.htmlspanner.handlers.PreHandler; - -import org.htmlcleaner.ContentNode; -import org.htmlcleaner.TagNode; - -import lombok.AllArgsConstructor; - -import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE; - -/** - * Created by Kosh on 22 Apr 2017, 1:07 PM - */ - -@AllArgsConstructor public class PreTagHandler extends PreHandler { - - @ColorInt private final int color; - private final boolean isPre; - @PrefGetter.ThemeType private int theme; - - private void getPlainText(StringBuffer buffer, Object node) { - if (node instanceof ContentNode) { - ContentNode contentNode = (ContentNode) node; - String text = contentNode.getContent().toString(); - buffer.append(text); - } else if (node instanceof TagNode) { - TagNode tagNode = (TagNode) node; - for (Object child : tagNode.getChildren()) { - this.getPlainText(buffer, child); - } - } - } - - private String replace(String text) { - return text.replaceAll(" ", "\u00A0") - .replaceAll("&", "&") - .replaceAll(""", "\"") - .replaceAll("¢", "¢") - .replaceAll("<", "<") - .replaceAll(">", ">") - .replaceAll("§", "§") - .replaceAll("“", "“") - .replaceAll("”", "”") - .replaceAll("‘", "‘") - .replaceAll("’", "’") - .replaceAll("–", "\u2013") - .replaceAll("—", "\u2014") - .replaceAll("―", "\u2015"); - } - - @Override public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) { - if (isPre) { - StringBuffer buffer = new StringBuffer(); - buffer.append("\n");//fake padding top + make sure, pre is always by itself - getPlainText(buffer, node); - buffer.append("\n");//fake padding bottom + make sure, pre is always by itself - builder.append(replace(buffer.toString())); - builder.append("\n"); - builder.setSpan(new CodeBackgroundRoundedSpan(color), start, builder.length(), SPAN_EXCLUSIVE_EXCLUSIVE); - builder.append("\n"); - this.appendNewLine(builder); - this.appendNewLine(builder); - } else { - StringBuffer text = node.getText(); - builder.append(" "); - builder.append(replace(text.toString())); - builder.append(" "); - final int stringStart = start + 1; - final int stringEnd = builder.length() - 1; - builder.setSpan(new BackgroundColorSpan(color), stringStart, stringEnd, SPAN_EXCLUSIVE_EXCLUSIVE); - if (theme == PrefGetter.LIGHT) { - builder.setSpan(new ForegroundColorSpan(Color.RED), stringStart, stringEnd, SPAN_EXCLUSIVE_EXCLUSIVE); - } - builder.setSpan(new TypefaceSpan("monospace"), stringStart, stringEnd, SPAN_EXCLUSIVE_EXCLUSIVE); - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/QuoteHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/QuoteHandler.java deleted file mode 100644 index d44a49f99..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/QuoteHandler.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.support.annotation.ColorInt; -import android.text.SpannableStringBuilder; - -import com.zzhoujay.markdown.style.MarkDownQuoteSpan; - -import net.nightwhistler.htmlspanner.TagNodeHandler; - -import org.htmlcleaner.TagNode; - -import lombok.AllArgsConstructor; - -/** - * Created by Kosh on 23 Apr 2017, 11:30 AM - */ - -@AllArgsConstructor public class QuoteHandler extends TagNodeHandler { - - @ColorInt private int color; - - @Override - public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) { - builder.setSpan(new MarkDownQuoteSpan(color), start + 1, builder.length(), 33); - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/StrikethroughHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/StrikethroughHandler.java deleted file mode 100644 index 51eb388ab..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/StrikethroughHandler.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.text.SpannableStringBuilder; -import android.text.style.StrikethroughSpan; - -import net.nightwhistler.htmlspanner.TagNodeHandler; - -import org.htmlcleaner.TagNode; - -public class StrikethroughHandler extends TagNodeHandler { - - @Override public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) { - builder.setSpan(new StrikethroughSpan(), start, end, 33); - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/SubScriptHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/SubScriptHandler.java deleted file mode 100644 index 4b252c2e4..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/SubScriptHandler.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.text.SpannableStringBuilder; -import android.text.style.RelativeSizeSpan; -import android.text.style.SubscriptSpan; - -import net.nightwhistler.htmlspanner.TagNodeHandler; - -import org.htmlcleaner.TagNode; - -public class SubScriptHandler extends TagNodeHandler { - - @Override public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) { - builder.setSpan(new SubscriptSpan(), start, end, 33); - builder.setSpan(new RelativeSizeSpan(0.8f), start, end, 33); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/SuperScriptHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/SuperScriptHandler.java deleted file mode 100644 index 1900bdf4b..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/SuperScriptHandler.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.text.SpannableStringBuilder; -import android.text.style.RelativeSizeSpan; -import android.text.style.SuperscriptSpan; - -import net.nightwhistler.htmlspanner.TagNodeHandler; - -import org.htmlcleaner.TagNode; - -public class SuperScriptHandler extends TagNodeHandler { - - @Override public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) { - builder.setSpan(new SuperscriptSpan(), start, end, 33); - builder.setSpan(new RelativeSizeSpan(0.8f), start, end, 33); - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/TableHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/TableHandler.java deleted file mode 100644 index 141946f4e..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/TableHandler.java +++ /dev/null @@ -1,252 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.PixelFormat; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.text.Layout.Alignment; -import android.text.Spannable; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.StaticLayout; -import android.text.TextPaint; -import android.text.style.AlignmentSpan; -import android.text.style.ImageSpan; - -import net.nightwhistler.htmlspanner.TagNodeHandler; - -import org.htmlcleaner.TagNode; - -import java.util.ArrayList; -import java.util.List; - -/** - * Handles simple HTML tables. - *

    - * Since it renders these tables itself, it needs to know things like font size - * and text colour to use. - * - * @author Alex Kuiper - */ -public class TableHandler extends TagNodeHandler { - - private int tableWidth = 500; - private Typeface typeFace = Typeface.DEFAULT; - private float textSize = 28f; - private int textColor = Color.BLACK; - private static final int PADDING = 20; - - @Override public boolean rendersContent() { - return true; - } - - @Override public void handleTagNode(TagNode node, SpannableStringBuilder builder, int start, int end) { - Table table = getTable(node); - for (int i = 0; i < table.getRows().size(); i++) { - List row = table.getRows().get(i); - builder.append("\uFFFC"); - TableRowDrawable drawable = new TableRowDrawable(row, table.isDrawBorder()); - drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), - drawable.getIntrinsicHeight()); - builder.setSpan(new ImageSpan(drawable), start + i, builder.length(), 33); - - } - builder.append("\uFFFC"); - Drawable drawable = new TableRowDrawable(new ArrayList(), table.isDrawBorder()); - drawable.setBounds(0, 0, tableWidth, 1); - builder.setSpan(new ImageSpan(drawable), builder.length() - 1, builder.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - builder.setSpan((AlignmentSpan) () -> Alignment.ALIGN_CENTER, start, builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - builder.append("\n"); - } - - public void setTableWidth(int tableWidth) { - this.tableWidth = tableWidth; - } - - public void setTextColor(int textColor) { - this.textColor = textColor; - } - - private void readNode(Object node, Table table) { - if (node instanceof TagNode) { - TagNode tagNode = (TagNode) node; - if (tagNode.getName().equals("td") || tagNode.getName().equals("th")) { - Spanned result = this.getSpanner().fromTagNode(tagNode); - table.addCell(result); - return; - } - if (tagNode.getName().equals("tr")) { - table.addRow(); - } - for (Object child : tagNode.getChildTags()) { - readNode(child, table); - } - } - - } - - private Table getTable(TagNode node) { - - String border = node.getAttributeByName("border"); - - boolean drawBorder = !"0".equals(border); - - Table result = new Table(drawBorder); - - readNode(node, result); - - return result; - } - - private TextPaint getTextPaint() { - TextPaint textPaint = new TextPaint(); - textPaint.setColor(this.textColor); - textPaint.linkColor = this.textColor; - textPaint.setAntiAlias(true); - textPaint.setTextSize(this.textSize); - textPaint.setTypeface(this.typeFace); - - return textPaint; - } - - private int calculateRowHeight(List row) { - - if (row.size() == 0) { - return 0; - } - - TextPaint textPaint = getTextPaint(); - - int columnWidth = tableWidth / row.size(); - - int rowHeight = 0; - - for (Spanned cell : row) { - - StaticLayout layout = new StaticLayout(cell, textPaint, columnWidth - - 2 * PADDING, Alignment.ALIGN_NORMAL, 1.5f, 0.5f, true); - - if (layout.getHeight() > rowHeight) { - rowHeight = layout.getHeight(); - } - } - - return rowHeight; - } - - private class TableRowDrawable extends Drawable { - - private List tableRow; - - private int rowHeight; - private boolean paintBorder; - - TableRowDrawable(List tableRow, boolean paintBorder) { - this.tableRow = tableRow; - this.rowHeight = calculateRowHeight(tableRow); - this.paintBorder = paintBorder; - } - - @Override public void draw(@NonNull Canvas canvas) { - Paint paint = new Paint(); - paint.setColor(textColor); - paint.setStyle(Style.STROKE); - - int numberOfColumns = tableRow.size(); - - if (numberOfColumns == 0) { - return; - } - - int columnWidth = tableWidth / numberOfColumns; - - int offset; - - for (int i = 0; i < numberOfColumns; i++) { - - offset = i * columnWidth; - - if (paintBorder) { - // The rect is open at the bottom, so there's a single line - // between rows. - canvas.drawRect(offset, 0, offset + columnWidth, rowHeight, paint); - } - - StaticLayout layout = new StaticLayout(tableRow.get(i), - getTextPaint(), (columnWidth - 2 * PADDING), - Alignment.ALIGN_NORMAL, 1.5f, 0.5f, true); - - canvas.translate(offset + PADDING, 0); - layout.draw(canvas); - canvas.translate(-1 * (offset + PADDING), 0); - - } - } - - @Override - public int getIntrinsicHeight() { - return rowHeight; - } - - @Override - public int getIntrinsicWidth() { - return tableWidth; - } - - @Override - public int getOpacity() { - return PixelFormat.OPAQUE; - } - - @Override - public void setAlpha(int alpha) { - - } - - @Override - public void setColorFilter(ColorFilter cf) { - - } - } - - private class Table { - - private boolean drawBorder; - private List> content = new ArrayList<>(); - - private Table(boolean drawBorder) { - this.drawBorder = drawBorder; - } - - boolean isDrawBorder() { - return drawBorder; - } - - void addRow() { - content.add(new ArrayList<>()); - } - - List getBottomRow() { - return content.get(content.size() - 1); - } - - List> getRows() { - return content; - } - - void addCell(Spanned text) { - if (content.isEmpty()) { - throw new IllegalStateException("No rows added yet"); - } - - getBottomRow().add(text); - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/UnderlineHandler.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/UnderlineHandler.java deleted file mode 100644 index 1f7ab595a..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/UnderlineHandler.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.fastaccess.provider.timeline.handler; - -import android.text.SpannableStringBuilder; -import android.text.style.UnderlineSpan; - -import net.nightwhistler.htmlspanner.TagNodeHandler; - -import org.htmlcleaner.TagNode; - -public class UnderlineHandler extends TagNodeHandler { - - @Override public void handleTagNode(TagNode tagNode, SpannableStringBuilder spannableStringBuilder, int start, int end) { - spannableStringBuilder.setSpan(new UnderlineSpan(), start, end, 33); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/DrawableGetter.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/DrawableGetter.java deleted file mode 100644 index 12c78e0e7..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/DrawableGetter.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.fastaccess.provider.timeline.handler.drawable; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.v4.content.ContextCompat; -import android.text.Html; -import android.widget.TextView; - -import com.bumptech.glide.GenericRequestBuilder; -import com.bumptech.glide.Glide; -import com.fastaccess.R; - -import java.lang.ref.WeakReference; -import java.util.HashSet; -import java.util.Set; - -/** - * Created by Kosh on 22 Apr 2017, 7:44 PM - */ - -public class DrawableGetter implements Html.ImageGetter, Drawable.Callback { - private WeakReference container; - private final Set cachedTargets; - private final int width; - - public DrawableGetter(TextView tv, int width) { - tv.setTag(R.id.drawable_callback, this); - this.container = new WeakReference<>(tv); - this.cachedTargets = new HashSet<>(); - this.width = width; - } - - @Override public Drawable getDrawable(@NonNull String url) { - final UrlDrawable urlDrawable = new UrlDrawable(); - if (container != null && container.get() != null) { - Context context = container.get().getContext(); - final GenericRequestBuilder load = Glide.with(context) - .load(url) - .placeholder(ContextCompat.getDrawable(context, R.drawable.ic_image)) - .dontAnimate(); - final GlideDrawableTarget target = new GlideDrawableTarget(urlDrawable, container, width); - load.override(width, width / 2); - load.into(target); - cachedTargets.add(target); - } - return urlDrawable; - } - - @Override public void invalidateDrawable(@NonNull Drawable drawable) { - if (container != null && container.get() != null) { - container.get().invalidate(); - } - } - - @Override public void scheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable, long l) {} - - @Override public void unscheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable) {} - - public void clear(@NonNull DrawableGetter drawableGetter) { - if (drawableGetter.cachedTargets != null) { - for (GlideDrawableTarget target : drawableGetter.cachedTargets) { - Glide.clear(target); - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/GlideDrawableTarget.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/GlideDrawableTarget.java deleted file mode 100644 index f9ffaf050..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/GlideDrawableTarget.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.fastaccess.provider.timeline.handler.drawable; - -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.widget.TextView; - -import com.bumptech.glide.load.resource.drawable.GlideDrawable; -import com.bumptech.glide.request.animation.GlideAnimation; -import com.bumptech.glide.request.target.SimpleTarget; -import com.fastaccess.R; - -import java.lang.ref.WeakReference; - -class GlideDrawableTarget extends SimpleTarget { - private final UrlDrawable urlDrawable; - private final WeakReference container; - private final int width; - - GlideDrawableTarget(UrlDrawable urlDrawable, WeakReference container, int width) { - this.urlDrawable = urlDrawable; - this.container = container; - this.width = width; - } - - @Override public void onResourceReady(GlideDrawable resource, GlideAnimation glideAnimation) { - if (container != null && container.get() != null) { - TextView textView = container.get(); - textView.post(() -> { - float width; - float height; - if (resource.getIntrinsicWidth() >= this.width) { - float downScale = (float) resource.getIntrinsicWidth() / this.width; - width = (float) (resource.getIntrinsicWidth() / downScale / 1.3); - height = (float) (resource.getIntrinsicHeight() / downScale / 1.3); - } else { - float multiplier = (float) this.width / resource.getIntrinsicWidth(); - width = (float) resource.getIntrinsicWidth() * multiplier; - height = (float) resource.getIntrinsicHeight() * multiplier; - } - Rect rect = new Rect(0, 0, Math.round(width), Math.round(height)); - resource.setBounds(rect); - urlDrawable.setBounds(rect); - urlDrawable.setDrawable(resource); - if (resource.isAnimated()) { - urlDrawable.setCallback((Drawable.Callback) textView.getTag(R.id.drawable_callback)); - resource.setLoopCount(GlideDrawable.LOOP_FOREVER); - resource.start(); - } - textView.setText(textView.getText()); - textView.invalidate(); - }); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/UrlDrawable.java b/app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/UrlDrawable.java deleted file mode 100644 index 3478859ec..000000000 --- a/app/src/main/java/com/fastaccess/provider/timeline/handler/drawable/UrlDrawable.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.fastaccess.provider.timeline.handler.drawable; - -import android.graphics.Canvas; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; - -import com.bumptech.glide.load.resource.gif.GifDrawable; - -class UrlDrawable extends BitmapDrawable implements Drawable.Callback { - private Drawable drawable; - - @SuppressWarnings("deprecation") UrlDrawable() {} - - @Override public void draw(Canvas canvas) { - if (drawable != null) { - drawable.draw(canvas); - if (drawable instanceof GifDrawable) { - if (!((GifDrawable) drawable).isRunning()) { - ((GifDrawable) drawable).start(); - } - } - } - } - - public Drawable getDrawable() { - return drawable; - } - - public void setDrawable(Drawable drawable) { - if (this.drawable != null) { - this.drawable.setCallback(null); - } - drawable.setCallback(this); - this.drawable = drawable; - } - - @Override public void invalidateDrawable(@NonNull Drawable who) { - if (getCallback() != null) { - getCallback().invalidateDrawable(who); - } - } - - @Override public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { - if (getCallback() != null) { - getCallback().scheduleDrawable(who, what, when); - } - } - - @Override public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { - if (getCallback() != null) { - getCallback().unscheduleDrawable(who, what); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/AssigneesAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/AssigneesAdapter.java deleted file mode 100644 index 6398da337..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/AssigneesAdapter.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.ui.adapter.viewholder.AssigneesViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class AssigneesAdapter extends BaseRecyclerAdapter> { - - public interface OnSelectAssignee { - boolean isAssigneeSelected(int position); - - void onToggleSelection(int position, boolean select); - } - - private final OnSelectAssignee onSelectAssignee; - - public AssigneesAdapter(@NonNull List data, @Nullable OnSelectAssignee onSelectAssignee) { - super(data); - this.onSelectAssignee = onSelectAssignee; - } - - @Override protected AssigneesViewHolder viewHolder(ViewGroup parent, int viewType) { - return AssigneesViewHolder.newInstance(parent, onSelectAssignee, this); - } - - @Override protected void onBindView(AssigneesViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/BranchesAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/BranchesAdapter.java deleted file mode 100644 index d9dd9a91a..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/BranchesAdapter.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatImageView; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.fastaccess.R; -import com.fastaccess.data.dao.BranchesModel; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 09 Apr 2017, 10:55 AM - */ - -public class BranchesAdapter extends BaseRecyclerAdapter> { - - public BranchesAdapter(@NonNull List data, @Nullable BaseViewHolder.OnItemClickListener listener) { - super(data, listener); - } - - @Override protected BranchesViewHolder viewHolder(ViewGroup parent, int viewType) { - return new BranchesViewHolder(BaseViewHolder.getView(parent, R.layout.branches_row_item), this); - } - - @Override protected void onBindView(BranchesViewHolder holder, int position) { - holder.bind(getItem(position)); - } - - - static class BranchesViewHolder extends BaseViewHolder { - @Nullable @BindView(R.id.image) AppCompatImageView image; - @BindView(android.R.id.text1) TextView title; - - BranchesViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - } - - @Override public void bind(@NonNull BranchesModel branchesModel) { - if (image != null) { - image.setImageResource(branchesModel.isTag() ? R.drawable.ic_label : R.drawable.ic_branch); - image.setContentDescription(branchesModel.getName()); - } - title.setText(branchesModel.getName()); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/ColumnCardAdapter.kt b/app/src/main/java/com/fastaccess/ui/adapter/ColumnCardAdapter.kt deleted file mode 100644 index 25d939472..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/ColumnCardAdapter.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.ui.adapter - -import android.view.ViewGroup -import com.fastaccess.data.dao.ProjectCardModel -import com.fastaccess.ui.adapter.viewholder.ColumnCardViewHolder -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Hashemsergani on 11.09.17. - */ -class ColumnCardAdapter(date: ArrayList, val isOwner: Boolean) : BaseRecyclerAdapter>(date) { - - override fun viewHolder(parent: ViewGroup, viewType: Int): ColumnCardViewHolder = ColumnCardViewHolder.newInstance(parent, this, isOwner) - - override fun onBindView(holder: ColumnCardViewHolder?, position: Int) { - holder?.bind(data[position]) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/CommentsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/CommentsAdapter.java deleted file mode 100644 index c51c06455..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/CommentsAdapter.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.ui.adapter.viewholder.CommentsViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class CommentsAdapter extends BaseRecyclerAdapter> { - - public CommentsAdapter(@NonNull ArrayList eventsModels) { - super(eventsModels); - } - - @Override protected CommentsViewHolder viewHolder(ViewGroup parent, int viewType) { - return CommentsViewHolder.newInstance(parent, this); - } - - @Override protected void onBindView(CommentsViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/CommitCommentsAdapter.kt b/app/src/main/java/com/fastaccess/ui/adapter/CommitCommentsAdapter.kt deleted file mode 100644 index 1b470b0f5..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/CommitCommentsAdapter.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.fastaccess.ui.adapter - -import android.view.ViewGroup -import com.fastaccess.data.dao.model.Comment -import com.fastaccess.ui.adapter.callback.OnToggleView -import com.fastaccess.ui.adapter.viewholder.CommitCommentsViewHolder -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by kosh on 15/08/2017. - */ -class CommitCommentsAdapter(data: List, - listener: BaseViewHolder.OnItemClickListener, - var onToggleView: OnToggleView) - : BaseRecyclerAdapter>(data, listener) { - - override fun viewHolder(parent: ViewGroup, viewType: Int): CommitCommentsViewHolder { - return CommitCommentsViewHolder.newInstance(parent, this, onToggleView) - } - - override fun onBindView(holder: CommitCommentsViewHolder, position: Int) { - holder.bind(data[position]) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/CommitFilesAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/CommitFilesAdapter.java deleted file mode 100644 index 15d40b9c1..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/CommitFilesAdapter.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.CommitFileChanges; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.adapter.viewholder.PullRequestFilesViewHolder; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files.PullRequestFilesMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class CommitFilesAdapter extends BaseRecyclerAdapter> { - - - @NonNull private OnToggleView onToggleView; - @Nullable private PullRequestFilesMvp.OnPatchClickListener onPatchClickListener; - - public CommitFilesAdapter(@NonNull ArrayList eventsModels, - @NonNull OnToggleView onToggleView, - @Nullable PullRequestFilesMvp.OnPatchClickListener onPatchClickListener) { - super(eventsModels); - this.onToggleView = onToggleView; - this.onPatchClickListener = onPatchClickListener; - } - - @Override protected PullRequestFilesViewHolder viewHolder(ViewGroup parent, int viewType) { - return PullRequestFilesViewHolder.newInstance(parent, this, onToggleView, onPatchClickListener); - } - - @Override protected void onBindView(PullRequestFilesViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/CommitLinesAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/CommitLinesAdapter.java deleted file mode 100644 index a2348d09e..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/CommitLinesAdapter.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.CommitLinesModel; -import com.fastaccess.ui.adapter.viewholder.CommitLinesViewHolder; -import com.fastaccess.ui.adapter.viewholder.SimpleViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; - -import java.util.List; - -public class CommitLinesAdapter extends BaseRecyclerAdapter> { - - public CommitLinesAdapter(@NonNull List data, @Nullable CommitLinesViewHolder.OnItemClickListener listener) { - super(data, listener); - } - - @Override protected CommitLinesViewHolder viewHolder(ViewGroup parent, int viewType) { - return CommitLinesViewHolder.newInstance(parent, this); - } - - @Override protected void onBindView(CommitLinesViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/CommitsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/CommitsAdapter.java deleted file mode 100644 index 2a7ec7211..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/CommitsAdapter.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.ui.adapter.viewholder.CommitsViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class CommitsAdapter extends BaseRecyclerAdapter> { - - public CommitsAdapter(@NonNull List data) { - super(data); - } - - @Override protected CommitsViewHolder viewHolder(ViewGroup parent, int viewType) { - return CommitsViewHolder.newInstance(parent, this); - } - - @Override protected void onBindView(CommitsViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/EmojiAdapter.kt b/app/src/main/java/com/fastaccess/ui/adapter/EmojiAdapter.kt deleted file mode 100644 index debe140ef..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/EmojiAdapter.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.fastaccess.ui.adapter - -import android.view.ViewGroup -import android.widget.Filter -import android.widget.Filterable -import com.fastaccess.provider.emoji.Emoji -import com.fastaccess.ui.adapter.viewholder.EmojiViewHolder -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by kosh on 17/08/2017. - */ -class EmojiAdapter(listener: BaseViewHolder.OnItemClickListener) - : BaseRecyclerAdapter>(listener), Filterable { - - var copiedList = mutableListOf() - - override fun viewHolder(parent: ViewGroup, viewType: Int): EmojiViewHolder { - return EmojiViewHolder.newInstance(parent, this) - } - - override fun onBindView(holder: EmojiViewHolder, position: Int) { - holder.bind(data[position]) - } - - override fun getFilter(): Filter { - return object : Filter() { - override fun performFiltering(constraint: CharSequence): Filter.FilterResults { - if (copiedList.isEmpty()) { - copiedList.addAll(data) - } - val text = constraint.toString().toLowerCase() - val filteredResults: List = if (text.isNotBlank()) { - val data = data.filter { - text in it.tags || it.description.contains(text) || - it.unicode.contains(text) || text in it.aliases - } - if (data.isNotEmpty()) data - else copiedList - } else { - copiedList - } - val results = FilterResults() - results.values = filteredResults - results.count = filteredResults.size - return results - } - - @Suppress("UNCHECKED_CAST") - override fun publishResults(var1: CharSequence, results: Filter.FilterResults) { - results.values?.let { - insertItems(it as List) - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/FastHubNotificationsAdapter.kt b/app/src/main/java/com/fastaccess/ui/adapter/FastHubNotificationsAdapter.kt deleted file mode 100644 index bf29a4994..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/FastHubNotificationsAdapter.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.fastaccess.ui.adapter - -import android.view.ViewGroup -import com.fastaccess.R -import com.fastaccess.data.dao.model.FastHubNotification -import com.fastaccess.ui.adapter.viewholder.FastHubNotificationViewHolder -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Kosh on 02 Jun 2017, 1:36 PM - */ - -class FastHubNotificationsAdapter(data: List) : BaseRecyclerAdapter>(data) { - - override fun viewHolder(parent: ViewGroup?, viewType: Int): FastHubNotificationViewHolder { - return FastHubNotificationViewHolder(BaseViewHolder.getView(parent!!, R.layout.fasthub_notification_row_item), this) - } - - override fun onBindView(holder: FastHubNotificationViewHolder?, position: Int) { - holder?.bind(getItem(position)) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/FeedsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/FeedsAdapter.java deleted file mode 100644 index 43cf047ef..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/FeedsAdapter.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.Event; -import com.fastaccess.ui.adapter.viewholder.FeedsViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class FeedsAdapter extends BaseRecyclerAdapter> { - - private boolean noImage; - - public FeedsAdapter(@NonNull ArrayList events) { - this(events, false); - } - - public FeedsAdapter(@NonNull ArrayList events, boolean noImage) { - super(events); - this.noImage = noImage; - } - - @Override protected FeedsViewHolder viewHolder(ViewGroup parent, int viewType) { - return new FeedsViewHolder(FeedsViewHolder.getView(parent, noImage), this); - } - - @Override protected void onBindView(FeedsViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/FragmentsPagerAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/FragmentsPagerAdapter.java deleted file mode 100644 index 18595d228..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/FragmentsPagerAdapter.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentStatePagerAdapter; - -import com.fastaccess.data.dao.FragmentPagerAdapterModel; - -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 9:25 AM - */ - -public class FragmentsPagerAdapter extends FragmentStatePagerAdapter { - - private List fragments; - - public FragmentsPagerAdapter(FragmentManager fm, List fragments) { - super(fm); - this.fragments = fragments; - } - - @Override public Fragment getItem(int position) { - return fragments.get(position).getFragment(); - } - - @Override public int getCount() { - return fragments.size(); - } - - @Override public CharSequence getPageTitle(int position) { - return fragments.get(position).getTitle(); - } - - @Override public float getPageWidth(int position) { - return super.getPageWidth(position); - } - - public void remove(FragmentPagerAdapterModel model) { - if (fragments != null) { - fragments.remove(model); - notifyDataSetChanged(); - } - } - - public void remove(int position) { - if (fragments != null) { - fragments.remove(position); - notifyDataSetChanged(); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/GistFilesAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/GistFilesAdapter.java deleted file mode 100644 index e7899d7dd..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/GistFilesAdapter.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.FilesListModel; -import com.fastaccess.ui.adapter.viewholder.GistFilesViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class GistFilesAdapter extends BaseRecyclerAdapter> { - private boolean isOwner; - - public GistFilesAdapter(@NonNull List data, - @Nullable BaseViewHolder.OnItemClickListener listener, boolean isOwner) { - super(data, listener); - this.isOwner = isOwner; - } - - public void setOwner(boolean owner) { - isOwner = owner; - } - - @Override protected GistFilesViewHolder viewHolder(ViewGroup parent, int viewType) { - return GistFilesViewHolder.newInstance(parent, this, isOwner); - } - - @Override protected void onBindView(GistFilesViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/GistsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/GistsAdapter.java deleted file mode 100644 index 4d5ab031b..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/GistsAdapter.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.ui.adapter.viewholder.GistsViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class GistsAdapter extends BaseRecyclerAdapter> { - - private boolean isForProfile; - - public GistsAdapter(@NonNull ArrayList gistModels) { - this(gistModels, false); - } - - public GistsAdapter(@NonNull ArrayList gistsModels, boolean isForProfile) { - super(gistsModels); - this.isForProfile = isForProfile; - } - - @Override protected GistsViewHolder viewHolder(ViewGroup parent, int viewType) { - return GistsViewHolder.newInstance(parent, this, isForProfile); - } - - @Override protected void onBindView(GistsViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/IssuesAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/IssuesAdapter.java deleted file mode 100644 index 12655b481..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/IssuesAdapter.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.ui.adapter.viewholder.IssuesViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class IssuesAdapter extends BaseRecyclerAdapter> { - - private boolean withAvatar; - private boolean showRepoName; - private boolean showState; - - public IssuesAdapter(@NonNull List data) { - this(data, false); - } - - public IssuesAdapter(@NonNull List data, boolean withAvatar) { - super(data); - this.withAvatar = withAvatar; - } - - public IssuesAdapter(@NonNull List data, boolean withAvatar, boolean showRepoName) { - super(data); - this.withAvatar = withAvatar; - this.showRepoName = showRepoName; - } - - public IssuesAdapter(@NonNull List data, boolean withAvatar, boolean showRepoName, boolean showState) { - super(data); - this.withAvatar = withAvatar; - this.showRepoName = showRepoName; - this.showState = showState; - } - - @Override protected IssuesViewHolder viewHolder(ViewGroup parent, int viewType) { - return IssuesViewHolder.newInstance(parent, this, withAvatar, showRepoName, showState); - } - - @Override protected void onBindView(IssuesViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/IssuesTimelineAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/IssuesTimelineAdapter.java deleted file mode 100644 index 6e507bf01..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/IssuesTimelineAdapter.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.v7.widget.StaggeredGridLayoutManager; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.adapter.callback.ReactionsCallback; -import com.fastaccess.ui.adapter.viewholder.CommitThreadViewHolder; -import com.fastaccess.ui.adapter.viewholder.GroupedReviewsViewHolder; -import com.fastaccess.ui.adapter.viewholder.IssueDetailsViewHolder; -import com.fastaccess.ui.adapter.viewholder.IssueTimelineViewHolder; -import com.fastaccess.ui.adapter.viewholder.PullStatusViewHolder; -import com.fastaccess.ui.adapter.viewholder.ReviewsViewHolder; -import com.fastaccess.ui.adapter.viewholder.TimelineCommentsViewHolder; -import com.fastaccess.ui.adapter.viewholder.UnknownTypeViewHolder; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.timeline.timeline.PullRequestTimelineMvp.ReviewCommentCallback; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 13 Dec 2016, 1:44 AM - */ - -public class IssuesTimelineAdapter extends BaseRecyclerAdapter> { - - private final OnToggleView onToggleView; - private final boolean showEmojies; - private final ReactionsCallback reactionsCallback; - private final boolean isMerged; - private final ReviewCommentCallback reviewCommentCallback; - private final String repoOwner; - private final String poster; - - public IssuesTimelineAdapter(@NonNull List data, OnToggleView onToggleView, boolean showEmojies, - ReactionsCallback reactionsCallback, boolean isMerged, - ReviewCommentCallback reviewCommentCallback, String repoOwner, String poster) { - super(data); - this.onToggleView = onToggleView; - this.showEmojies = showEmojies; - this.reactionsCallback = reactionsCallback; - this.isMerged = isMerged; - this.reviewCommentCallback = reviewCommentCallback; - this.repoOwner = repoOwner; - this.poster = poster; - } - - public IssuesTimelineAdapter(@NonNull List data, OnToggleView onToggleView, boolean showEmojies, - ReactionsCallback reactionsCallback, String repoOwner, String poster) { - this(data, onToggleView, showEmojies, reactionsCallback, false, null, repoOwner, poster); - } - - @Override protected BaseViewHolder viewHolder(ViewGroup parent, int viewType) { - if (viewType == 0) { - return new UnknownTypeViewHolder(BaseViewHolder.getView(parent, R.layout.unknown_row_item)); - } else if (viewType == TimelineModel.HEADER) { - return IssueDetailsViewHolder.newInstance(parent, this, onToggleView, reactionsCallback, repoOwner, poster); - } else if (viewType == TimelineModel.EVENT) { - return IssueTimelineViewHolder.newInstance(parent, this, isMerged); - } else if (viewType == TimelineModel.REVIEW) { - return ReviewsViewHolder.Companion.newInstance(parent, this); - } else if (viewType == TimelineModel.GROUP) { - return GroupedReviewsViewHolder.newInstance(parent, this, onToggleView, reactionsCallback, - reviewCommentCallback, repoOwner, poster); - } else if (viewType == TimelineModel.COMMIT_COMMENTS) { - return CommitThreadViewHolder.Companion.newInstance(parent, this, onToggleView); - } else if (viewType == TimelineModel.STATUS) { - return PullStatusViewHolder.newInstance(parent); - } - return TimelineCommentsViewHolder.newInstance(parent, this, onToggleView, showEmojies, - reactionsCallback, repoOwner, poster); - } - - @Override protected void onBindView(BaseViewHolder holder, int position) { - TimelineModel model = getItem(position); - if (model.getType() == TimelineModel.HEADER) { - ((IssueDetailsViewHolder) holder).bind(model); - } else if (model.getType() == TimelineModel.EVENT) { - ((IssueTimelineViewHolder) holder).bind(model); - } else if (model.getType() == TimelineModel.COMMENT) { - ((TimelineCommentsViewHolder) holder).bind(model); - } else if (model.getType() == TimelineModel.GROUP) { - ((GroupedReviewsViewHolder) holder).bind(model); - } else if (model.getType() == TimelineModel.REVIEW) { - ((ReviewsViewHolder) holder).bind(model); - } else if (model.getType() == TimelineModel.COMMIT_COMMENTS) { - ((CommitThreadViewHolder) holder).bind(model); - } else if (model.getType() == TimelineModel.STATUS && model.getStatus() != null) { - ((PullStatusViewHolder) holder).bind(model.getStatus()); - } - if (model.getType() != TimelineModel.COMMENT) { - StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams(); - layoutParams.setFullSpan(true); - } - } - - @Override public int getItemViewType(int position) { - TimelineModel timelineModel = getData().get(position); - return timelineModel != null ? timelineModel.getType() : super.getItemViewType(position); - } - - -} - diff --git a/app/src/main/java/com/fastaccess/ui/adapter/LabelColorsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/LabelColorsAdapter.java deleted file mode 100644 index 325fd0513..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/LabelColorsAdapter.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.ViewGroup; - -import com.fastaccess.ui.adapter.viewholder.LabelColorsViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 02 Apr 2017, 5:19 PM - */ - -public class LabelColorsAdapter extends BaseRecyclerAdapter> { - - public LabelColorsAdapter(@NonNull List data, @Nullable BaseViewHolder.OnItemClickListener listener) { - super(data, listener); - } - - @Override protected LabelColorsViewHolder viewHolder(ViewGroup parent, int viewType) { - return LabelColorsViewHolder.newInstance(parent, this); - } - - @Override protected void onBindView(LabelColorsViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/LabelsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/LabelsAdapter.java deleted file mode 100644 index 1463f91fb..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/LabelsAdapter.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.ui.adapter.viewholder.LabelsViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class LabelsAdapter extends BaseRecyclerAdapter> { - - public interface OnSelectLabel { - boolean isLabelSelected(LabelModel labelModel); - - void onToggleSelection(LabelModel labelModel, boolean select); - } - - @Nullable private OnSelectLabel onSelectLabel; - - public LabelsAdapter(@NonNull List eventsModels, @Nullable OnSelectLabel onSelectLabel) { - super(eventsModels); - this.onSelectLabel = onSelectLabel; - } - - @Override protected LabelsViewHolder viewHolder(ViewGroup parent, int viewType) { - return LabelsViewHolder.newInstance(parent, onSelectLabel, this); - } - - @Override protected void onBindView(LabelsViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/LoginAdapter.kt b/app/src/main/java/com/fastaccess/ui/adapter/LoginAdapter.kt deleted file mode 100644 index df05ca4c9..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/LoginAdapter.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.fastaccess.ui.adapter - -import android.view.ViewGroup -import com.fastaccess.data.dao.model.Login -import com.fastaccess.ui.adapter.viewholder.LoginViewHolder -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Kosh on 09 Jul 2017, 5:00 PM - */ -class LoginAdapter constructor(private val small: Boolean = false) - : BaseRecyclerAdapter>() { - - override fun onBindView(holder: LoginViewHolder, position: Int) { - holder.bind(getItem(position)) - } - - override fun viewHolder(parent: ViewGroup, viewType: Int): LoginViewHolder { - return LoginViewHolder.Companion.newInstance(parent, this, small) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/MilestonesAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/MilestonesAdapter.java deleted file mode 100644 index 142be747d..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/MilestonesAdapter.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.ui.adapter.viewholder.MilestonesViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class MilestonesAdapter extends BaseRecyclerAdapter> { - - public MilestonesAdapter(@NonNull ArrayList eventsModels) { - super(eventsModels); - } - - @Override protected MilestonesViewHolder viewHolder(ViewGroup parent, int viewType) { - return MilestonesViewHolder.newInstance(parent, this); - } - - @Override protected void onBindView(MilestonesViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/NotificationsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/NotificationsAdapter.java deleted file mode 100644 index dc06bd8bc..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/NotificationsAdapter.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.v7.widget.StaggeredGridLayoutManager; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.GroupedNotificationModel; -import com.fastaccess.ui.adapter.viewholder.NotificationsHeaderViewHolder; -import com.fastaccess.ui.adapter.viewholder.NotificationsViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class NotificationsAdapter extends BaseRecyclerAdapter> { - private boolean showUnreadState; - private boolean hideClear; - - public NotificationsAdapter(@NonNull ArrayList eventsModels, boolean showUnreadState) { - super(eventsModels); - this.showUnreadState = showUnreadState; - } - - public NotificationsAdapter(@NonNull ArrayList eventsModels, boolean showUnreadState, boolean hideClear) { - super(eventsModels); - this.showUnreadState = showUnreadState; - this.hideClear = hideClear; - } - - @Override protected BaseViewHolder viewHolder(ViewGroup parent, int viewType) { - if (viewType == GroupedNotificationModel.HEADER) { - return NotificationsHeaderViewHolder.newInstance(parent, this); - } else { - return NotificationsViewHolder.newInstance(parent, this, showUnreadState); - } - } - - @Override protected void onBindView(BaseViewHolder holder, int position) { - if (getItemViewType(position) == GroupedNotificationModel.HEADER) { - ((NotificationsHeaderViewHolder) holder).bind(getItem(position)); - if (hideClear) - if (getItem(Math.min(position + 1, getItemCount() - 1)).getNotification().isUnread()) { - (((NotificationsHeaderViewHolder) holder).itemView).findViewById(R.id.markAsRead).setVisibility(View.VISIBLE); - } - } else { - ((NotificationsViewHolder) holder).bind(getItem(position)); - } - if (getItem(position).getType() == GroupedNotificationModel.HEADER) { - StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams(); - layoutParams.setFullSpan(true); - } - } - - @Override public int getItemViewType(int position) { - return getItem(position).getType(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/PinnedReposAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/PinnedReposAdapter.java deleted file mode 100644 index dd1157aa2..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/PinnedReposAdapter.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.PinnedRepos; -import com.fastaccess.ui.adapter.viewholder.PinnedReposViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class PinnedReposAdapter extends BaseRecyclerAdapter> { - - private boolean singleLine; - - public PinnedReposAdapter(boolean singleLine) { - this.singleLine = singleLine; - } - - public PinnedReposAdapter(@NonNull List data, @Nullable BaseViewHolder.OnItemClickListener listener) { - super(data, listener); - } - - @Override protected PinnedReposViewHolder viewHolder(ViewGroup parent, int viewType) { - return PinnedReposViewHolder.newInstance(parent, this, singleLine); - } - - @Override protected void onBindView(PinnedReposViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/ProfileOrgsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/ProfileOrgsAdapter.java deleted file mode 100644 index 5d956bfac..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/ProfileOrgsAdapter.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.ui.adapter.viewholder.ProfileOrgsViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -/** - * Created by Kosh on 21 May 2017, 12:30 PM - */ - -public class ProfileOrgsAdapter extends BaseRecyclerAdapter> { - - @Override protected ProfileOrgsViewHolder viewHolder(ViewGroup parent, int viewType) { - return ProfileOrgsViewHolder.newInstance(parent); - } - - @Override protected void onBindView(ProfileOrgsViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/ProfilePinnedReposAdapter.kt b/app/src/main/java/com/fastaccess/ui/adapter/ProfilePinnedReposAdapter.kt deleted file mode 100644 index de64981ff..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/ProfilePinnedReposAdapter.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.fastaccess.ui.adapter - -import android.view.ViewGroup -import com.fastaccess.ui.adapter.viewholder.ProfilePinnedReposViewHolder -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder -import github.GetPinnedReposQuery -import java.text.NumberFormat - -/** - * Created by kosh on 09/08/2017. - */ - -class ProfilePinnedReposAdapter(data: List) : BaseRecyclerAdapter>(data) { - - private val numberFormat = NumberFormat.getNumberInstance()!! - - override fun viewHolder(parent: ViewGroup, viewType: Int): ProfilePinnedReposViewHolder { - return ProfilePinnedReposViewHolder.newInstance(parent, this) - } - - override fun onBindView(holder: ProfilePinnedReposViewHolder, position: Int) { - holder.bind(data[position], numberFormat) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/ProjectsAdapter.kt b/app/src/main/java/com/fastaccess/ui/adapter/ProjectsAdapter.kt deleted file mode 100644 index b56807ddf..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/ProjectsAdapter.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.fastaccess.ui.adapter - -import android.view.ViewGroup -import com.fastaccess.ui.adapter.viewholder.ProjectViewHolder -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder -import github.RepoProjectsOpenQuery - -/** - * Created by kosh on 09/09/2017. - */ -class ProjectsAdapter(data: ArrayList) : - BaseRecyclerAdapter>(data) { - - override fun viewHolder(parent: ViewGroup, viewType: Int): ProjectViewHolder = ProjectViewHolder.newInstance(parent, this) - - override fun onBindView(holder: ProjectViewHolder?, position: Int) { - holder?.bind(data[position]) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/PullRequestAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/PullRequestAdapter.java deleted file mode 100644 index 962271b4d..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/PullRequestAdapter.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.ui.adapter.viewholder.PullRequestViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class PullRequestAdapter extends BaseRecyclerAdapter> { - - private boolean showRepoName; - private boolean withAvatar; - - public PullRequestAdapter(@NonNull List data) { - this(data, false); - } - - public PullRequestAdapter(@NonNull List data, boolean withAvatar) { - super(data); - this.withAvatar = withAvatar; - } - - public PullRequestAdapter(@NonNull List data, boolean withAvatar, boolean showRepoName) { - super(data); - this.withAvatar = withAvatar; - this.showRepoName = showRepoName; - } - - @Override protected PullRequestViewHolder viewHolder(ViewGroup parent, int viewType) { - return PullRequestViewHolder.newInstance(parent, this, withAvatar, showRepoName); - } - - @Override protected void onBindView(PullRequestViewHolder holder, int position) { - holder.bind(getItem(position)); - } - - -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/ReleasesAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/ReleasesAdapter.java deleted file mode 100644 index 288219a8a..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/ReleasesAdapter.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.Release; -import com.fastaccess.ui.adapter.viewholder.ReleasesViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class ReleasesAdapter extends BaseRecyclerAdapter> { - - public ReleasesAdapter(@NonNull List data) { - super(data); - } - - @Override protected ReleasesViewHolder viewHolder(ViewGroup parent, int viewType) { - return ReleasesViewHolder.newInstance(parent, this); - } - - @Override protected void onBindView(ReleasesViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/RepoFilePathsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/RepoFilePathsAdapter.java deleted file mode 100644 index 58d3f94c0..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/RepoFilePathsAdapter.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.RepoFile; -import com.fastaccess.ui.adapter.viewholder.RepoFilePathsViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class RepoFilePathsAdapter extends BaseRecyclerAdapter> { - - - public RepoFilePathsAdapter(@NonNull ArrayList eventsModels) { - super(eventsModels); - } - - @Override protected RepoFilePathsViewHolder viewHolder(ViewGroup parent, int viewType) { - return RepoFilePathsViewHolder.newInstance(parent, this); - } - - @Override protected void onBindView(RepoFilePathsViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/RepoFilesAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/RepoFilesAdapter.java deleted file mode 100644 index c60a328fc..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/RepoFilesAdapter.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.RepoFile; -import com.fastaccess.ui.adapter.viewholder.RepoFilesViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class RepoFilesAdapter extends BaseRecyclerAdapter> { - - - public RepoFilesAdapter(@NonNull ArrayList eventsModels) { - super(eventsModels); - } - - @Override protected RepoFilesViewHolder viewHolder(ViewGroup parent, int viewType) { - return RepoFilesViewHolder.newInstance(parent, this); - } - - @Override protected void onBindView(RepoFilesViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/ReposAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/ReposAdapter.java deleted file mode 100644 index 169763074..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/ReposAdapter.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.ui.adapter.viewholder.ReposViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class ReposAdapter extends BaseRecyclerAdapter> { - private boolean isStarred; - private boolean withImage; - - public ReposAdapter(@NonNull List data, boolean isStarred) { - this(data, isStarred, false); - } - - public ReposAdapter(@NonNull List data, boolean isStarred, boolean withImage) { - super(data); - this.isStarred = isStarred; - this.withImage = withImage; - } - - @Override protected ReposViewHolder viewHolder(ViewGroup parent, int viewType) { - return ReposViewHolder.newInstance(parent, this, isStarred, withImage); - } - - @Override protected void onBindView(ReposViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/ReviewCommentsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/ReviewCommentsAdapter.java deleted file mode 100644 index 9b42ca6b3..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/ReviewCommentsAdapter.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.ReviewCommentModel; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.adapter.callback.ReactionsCallback; -import com.fastaccess.ui.adapter.viewholder.ReviewCommentsViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class ReviewCommentsAdapter extends BaseRecyclerAdapter> { - - private final OnToggleView onToggleView; - private final ReactionsCallback reactionsCallback; - private final String repoOwner; - private final String poster; - - public ReviewCommentsAdapter(@NonNull List data, - @Nullable BaseViewHolder.OnItemClickListener listener, - OnToggleView onToggleView, ReactionsCallback reactionsCallback, String repoOwner, String poster) { - super(data, listener); - this.onToggleView = onToggleView; - this.reactionsCallback = reactionsCallback; - this.repoOwner = repoOwner; - this.poster = poster; - } - - - @Override protected ReviewCommentsViewHolder viewHolder(ViewGroup parent, int viewType) { - return ReviewCommentsViewHolder.newInstance(parent, this, onToggleView, - reactionsCallback, repoOwner, poster); - } - - @Override protected void onBindView(ReviewCommentsViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/SearchCodeAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/SearchCodeAdapter.java deleted file mode 100644 index 07091d369..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/SearchCodeAdapter.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.SearchCodeModel; -import com.fastaccess.ui.adapter.viewholder.SearchCodeViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class SearchCodeAdapter extends BaseRecyclerAdapter> { - - private boolean showRepoName; - - public SearchCodeAdapter(@NonNull List data) { - super(data); - this.showRepoName = showRepoName; - } - - @Override protected SearchCodeViewHolder viewHolder(ViewGroup parent, int viewType) { - return SearchCodeViewHolder.newInstance(parent, this); - } - - @Override protected void onBindView(SearchCodeViewHolder holder, int position) { - holder.bind(getItem(position), showRepoName); - } - - public void showRepoName(boolean showRepoName) { - this.showRepoName = showRepoName; - notifyDataSetChanged(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/SettingsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/SettingsAdapter.java deleted file mode 100644 index 0d2fb6e45..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/SettingsAdapter.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; - -import com.fastaccess.R; -import com.fastaccess.data.dao.SettingsModel; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; - -import java.util.ArrayList; - -import butterknife.BindView; -import butterknife.ButterKnife; - -/** - * Created by JediB on 5/12/2017. - */ - -public class SettingsAdapter extends BaseAdapter { - - private ArrayList settings; - private final LayoutInflater inflater; - - public SettingsAdapter(@NonNull Context context, @NonNull ArrayList settings) { - this.settings = settings; - this.inflater = LayoutInflater.from(context); - } - - @Override public int getCount() { - return settings.size(); - } - - @Override public SettingsModel getItem(int position) { - return settings.get(position); - } - - @Override public long getItemId(int position) { - return position; - } - - @Override public View getView(int position, View convertView, ViewGroup parent) { - ViewHolder viewHolder; - View row = convertView; - if (row == null) { - row = inflater.inflate(R.layout.icon_row_item, parent, false); - viewHolder = new ViewHolder(row); - row.setTag(viewHolder); - } else { - viewHolder = (ViewHolder) row.getTag(); - } - SettingsModel model = getItem(position); - viewHolder.title.setText(model.getTitle()); - viewHolder.image.setImageResource(model.getImage()); - viewHolder.summary.setVisibility(View.GONE); - return row; - } - - static class ViewHolder { - @BindView(R.id.iconItemImage) ForegroundImageView image; - @BindView(R.id.iconItemTitle) FontTextView title; - @BindView(R.id.iconItemSummary) FontTextView summary; - - ViewHolder(View view) {ButterKnife.bind(this, view);} - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/SimpleListAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/SimpleListAdapter.java deleted file mode 100644 index 066f39ae0..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/SimpleListAdapter.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.ui.adapter.viewholder.SimpleViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -public class SimpleListAdapter extends BaseRecyclerAdapter, - SimpleViewHolder.OnItemClickListener> { - public SimpleListAdapter(@NonNull List data, @Nullable SimpleViewHolder.OnItemClickListener listener) { - super(data, listener); - } - - @Override protected SimpleViewHolder viewHolder(ViewGroup parent, int viewType) { - return new SimpleViewHolder<>(BaseViewHolder.getView(parent, R.layout.simple_row_item), this); - } - - @Override protected void onBindView(SimpleViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/SpinnerAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/SpinnerAdapter.java deleted file mode 100644 index 46b727ba8..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/SpinnerAdapter.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.TextView; - -import java.util.List; - -import butterknife.BindView; -import butterknife.ButterKnife; - -/** - * Created by Kosh on 09 Apr 2017, 10:55 AM - */ - -public class SpinnerAdapter extends BaseAdapter { - - private List data; - private Context context; - - public SpinnerAdapter(@NonNull Context context, @NonNull List branches) { - this.data = branches; - this.context = context; - } - - @Override public int getCount() { - return data.size(); - } - - @Override public O getItem(int position) { - return data.get(position); - } - - @Override public long getItemId(int position) { - return position; - } - - @Override public View getView(int position, View convertView, ViewGroup parent) { - return getRowView(position, convertView, parent, false); - } - - @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { - return getRowView(position, convertView, parent, true); - } - - @NonNull private View getRowView(int position, View convertView, ViewGroup parent, boolean isDropDown) { - ViewHolder viewHolder; - if (convertView == null) { - if (!isDropDown) { - convertView = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false); - } else { - convertView = LayoutInflater.from(context).inflate(android.R.layout.simple_dropdown_item_1line, parent, false); - } - viewHolder = new ViewHolder(convertView); - convertView.setTag(viewHolder); - } else { - viewHolder = (ViewHolder) convertView.getTag(); - } - viewHolder.title.setText(getItem(position).toString()); - return convertView; - } - - static class ViewHolder { - @BindView(android.R.id.text1) TextView title; - - ViewHolder(View view) { - ButterKnife.bind(this, view); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/TeamsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/TeamsAdapter.java deleted file mode 100644 index 54706d8fd..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/TeamsAdapter.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.TeamsModel; -import com.fastaccess.ui.adapter.viewholder.TeamsViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; - -import java.util.List; - -/** - * Created by Kosh on 03 Apr 2017, 7:52 PM - */ - -public class TeamsAdapter extends BaseRecyclerAdapter> { - - public TeamsAdapter(@NonNull List data) { - super(data); - } - - @Override protected TeamsViewHolder viewHolder(ViewGroup parent, int viewType) { - return TeamsViewHolder.newInstance(parent, this); - } - - @Override protected void onBindView(TeamsViewHolder holder, int position) { - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/TopicsAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/TopicsAdapter.java deleted file mode 100644 index 3936a1714..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/TopicsAdapter.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.content.Intent; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.App; -import com.fastaccess.R; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.adapter.viewholder.SimpleViewHolder; -import com.fastaccess.ui.modules.search.SearchActivity; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 11 May 2017, 6:58 PM - */ - -public class TopicsAdapter extends BaseRecyclerAdapter, BaseViewHolder.OnItemClickListener> { - private boolean isLightTheme = true; - @ColorInt private int cardBackground; - - public TopicsAdapter(@NonNull List data) { - super(data); - } - - @Override protected SimpleViewHolder viewHolder(ViewGroup parent, int viewType) { - isLightTheme = !AppHelper.isNightMode(parent.getResources()); - cardBackground = ViewHelper.getCardBackground(parent.getContext()); - return new SimpleViewHolder<>(BaseViewHolder.getView(parent, R.layout.topics_row_item), null); - } - - @Override protected void onBindView(SimpleViewHolder holder, int position) { - if (isLightTheme) { - holder.itemView.setBackgroundColor(cardBackground); - } - String item = getItem(position); - holder.itemView.setOnClickListener((view) -> { - Intent intent = new Intent(new Intent(App.getInstance().getApplicationContext(), SearchActivity.class)); - intent.putExtra("search", "topic:\"" + item + "\""); - view.getContext().startActivity(intent); - }); - holder.bind(getItem(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/TrendingAdapter.kt b/app/src/main/java/com/fastaccess/ui/adapter/TrendingAdapter.kt deleted file mode 100644 index 252ab5c99..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/TrendingAdapter.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.fastaccess.ui.adapter - -import android.view.ViewGroup -import com.fastaccess.R -import com.fastaccess.data.dao.TrendingModel -import com.fastaccess.ui.adapter.viewholder.TrendingViewHolder -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Kosh on 02 Jun 2017, 1:36 PM - */ - -class TrendingAdapter(data: MutableList) : BaseRecyclerAdapter>(data) { - - override fun viewHolder(parent: ViewGroup?, viewType: Int): TrendingViewHolder { - return TrendingViewHolder(BaseViewHolder.getView(parent!!, R.layout.trending_row_item), this) - } - - override fun onBindView(holder: TrendingViewHolder?, position: Int) { - holder?.bind(getItem(position)) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/UsersAdapter.java b/app/src/main/java/com/fastaccess/ui/adapter/UsersAdapter.java deleted file mode 100644 index 42d9ac083..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/UsersAdapter.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.fastaccess.ui.adapter; - -import android.support.annotation.NonNull; -import android.view.ViewGroup; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.ui.adapter.viewholder.UsersViewHolder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 2:07 PM - */ - -public class UsersAdapter extends BaseRecyclerAdapter> { - - private boolean isContributor; - private boolean isFilter; - - public UsersAdapter(@NonNull ArrayList list) { - this(list, false); - } - - public UsersAdapter(@NonNull ArrayList list, boolean isContributor) { - this(list, isContributor, false); - } - - public UsersAdapter(@NonNull ArrayList list, boolean isContributor, boolean isFilter) { - super(list); - this.isContributor = isContributor; - this.isFilter = isFilter; - } - - @Override protected UsersViewHolder viewHolder(ViewGroup parent, int viewType) { - return UsersViewHolder.newInstance(parent, this, isFilter); - } - - @Override protected void onBindView(UsersViewHolder holder, int position) { - holder.bind(getItem(position), isContributor); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/callback/OnToggleView.java b/app/src/main/java/com/fastaccess/ui/adapter/callback/OnToggleView.java deleted file mode 100644 index 36c52fe88..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/callback/OnToggleView.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.fastaccess.ui.adapter.callback; - -public interface OnToggleView { - void onToggle(long id, boolean isCollapsed); - - boolean isCollapsed(long id); -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/callback/ReactionsCallback.java b/app/src/main/java/com/fastaccess/ui/adapter/callback/ReactionsCallback.java deleted file mode 100644 index d02aa2729..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/callback/ReactionsCallback.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.fastaccess.ui.adapter.callback; - -/** - * Created by Kosh on 03 Apr 2017, 2:52 PM - */ - -public interface ReactionsCallback { - boolean isPreviouslyReacted(long id, int vId); - - boolean isCallingApi(long id, int vId); -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/AssigneesViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/AssigneesViewHolder.java deleted file mode 100644 index 7027707b1..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/AssigneesViewHolder.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.adapter.AssigneesAdapter; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindColor; -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class AssigneesViewHolder extends BaseViewHolder { - - @BindView(R.id.avatarLayout) AvatarLayout avatar; - @BindView(R.id.title) FontTextView title; - @BindView(R.id.date) FontTextView date; - @BindColor(R.color.light_gray) int lightGray; - private final AssigneesAdapter.OnSelectAssignee onSelectAssignee; - - @Override public void onClick(View v) { - if (onSelectAssignee != null) { - int position = getAdapterPosition(); - onSelectAssignee.onToggleSelection(position, !onSelectAssignee.isAssigneeSelected(position)); - } else { - super.onClick(v); - } - } - - private AssigneesViewHolder(@NonNull View itemView, @Nullable AssigneesAdapter.OnSelectAssignee onSelectAssignee, - @NonNull BaseRecyclerAdapter adapter) { - super(itemView, adapter); - this.onSelectAssignee = onSelectAssignee; - } - - public static AssigneesViewHolder newInstance(@NonNull ViewGroup viewGroup, @Nullable AssigneesAdapter.OnSelectAssignee onSelectAssignee, - @NonNull BaseRecyclerAdapter adapter) { - return new AssigneesViewHolder(getView(viewGroup, R.layout.feeds_row_item), onSelectAssignee, adapter); - } - - @Override public void bind(@NonNull User user) { - avatar.setUrl(user.getAvatarUrl(), user.getLogin(), user.isOrganizationType(), LinkParserHelper.isEnterprise(user.getHtmlUrl())); - title.setText(user.getLogin()); - date.setVisibility(View.GONE); - if (onSelectAssignee != null) { - itemView.setBackgroundColor(onSelectAssignee.isAssigneeSelected(getAdapterPosition()) - ? lightGray : ViewHelper.getWindowBackground(itemView.getContext())); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ColumnCardViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ColumnCardViewHolder.kt deleted file mode 100644 index 6ea18f174..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ColumnCardViewHolder.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.ProjectCardModel -import com.fastaccess.data.dao.PullsIssuesParser -import com.fastaccess.helper.ParseDateFormat -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Hashemsergani on 11.09.17. - */ -class ColumnCardViewHolder private constructor(item: View, adapter: BaseRecyclerAdapter<*, *, *>, val isOwner: Boolean) - : BaseViewHolder(item, adapter) { - - @BindView(R.id.title) lateinit var title: TextView - @BindView(R.id.addedBy) lateinit var addedBy: TextView - @BindView(R.id.editCard) lateinit var editCard: View - - init { - editCard.setOnClickListener(this) - } - - override fun bind(t: ProjectCardModel) { - title.text = if (t.note.isNullOrBlank()) { - val issue = PullsIssuesParser.getForIssue(t.contentUrl) - if (issue != null) { - "${issue.login}/${issue.repoId}/${issue.number}" - } else { - val pr = PullsIssuesParser.getForPullRequest(t.contentUrl) - if (pr != null) { - "${pr.login}/${pr.repoId}/${pr.number}" - } else { - "(FastHub) - to be fixed by GitHub! Sorry!" - } - } - } else { - t.note - } - addedBy.text = itemView.context.getString(R.string.card_added_by, t.creator?.login, ParseDateFormat.getTimeAgo(t.createdAt)) - } - - companion object { - fun newInstance(parent: ViewGroup, adapter: BaseRecyclerAdapter<*, *, *>, isOwner: Boolean): ColumnCardViewHolder { - return ColumnCardViewHolder(getView(parent, R.layout.column_card_row_layout), adapter, isOwner) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommentsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommentsViewHolder.java deleted file mode 100644 index de2545be5..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommentsViewHolder.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatImageView; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.provider.timeline.HtmlHelper; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class CommentsViewHolder extends BaseViewHolder { - - @BindView(R.id.avatarView) AvatarLayout avatar; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.name) FontTextView name; - @BindView(R.id.comment) FontTextView comment; - @BindView(R.id.toggleHolder) View toggleHolder; - @BindView(R.id.toggle) AppCompatImageView toggle; - private final ViewGroup viewGroup; - - @Override public void onClick(View v) { - if (v.getId() == R.id.toggleHolder) { - toggle.callOnClick(); - } else { - super.onClick(v); - } - } - - private CommentsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter, @NonNull ViewGroup viewGroup) { - super(itemView, adapter); - if (adapter != null && adapter.getRowWidth() == 0) { - itemView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override public boolean onPreDraw() { - itemView.getViewTreeObserver().removeOnPreDrawListener(this); - adapter.setRowWidth(itemView.getWidth() - ViewHelper.dpToPx(itemView.getContext(), 48)); - return false; - } - }); - } - itemView.setOnClickListener(null); - itemView.setOnLongClickListener(null); - toggleHolder.setOnClickListener(this); - toggle.setOnClickListener(this); - toggle.setOnLongClickListener(this); - this.viewGroup = viewGroup; - } - - public static CommentsViewHolder newInstance(@NonNull ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter) { - return new CommentsViewHolder(getView(viewGroup, R.layout.no_emojies_comments_row_item), adapter, viewGroup); - } - - @Override public void bind(@NonNull Comment commentsModel) { - if (commentsModel.getUser() != null) { - avatar.setUrl(commentsModel.getUser().getAvatarUrl(), commentsModel.getUser().getLogin(), - commentsModel.getUser().isOrganizationType(), LinkParserHelper.isEnterprise(commentsModel.getUser().getHtmlUrl())); - } else { - avatar.setUrl(null, null, false, false); - } - if (!InputHelper.isEmpty(commentsModel.getBodyHtml())) { - int width = adapter != null ? adapter.getRowWidth() : 0; - HtmlHelper.htmlIntoTextView(comment, commentsModel.getBodyHtml(), width > 0 ? width : viewGroup.getWidth()); - } else { - comment.setText(""); - } - name.setText(commentsModel.getUser() != null ? commentsModel.getUser().getLogin() : "Anonymous"); - if (commentsModel.getCreatedAt().before(commentsModel.getUpdatedAt())) { - date.setText(String.format("%s %s", ParseDateFormat.getTimeAgo(commentsModel.getCreatedAt()), - date.getResources().getString(R.string.edited))); - } else { - date.setText(ParseDateFormat.getTimeAgo(commentsModel.getCreatedAt())); - } - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitCommentsViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitCommentsViewHolder.kt deleted file mode 100644 index c80bbd9d0..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitCommentsViewHolder.kt +++ /dev/null @@ -1,121 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.support.transition.ChangeBounds -import android.support.transition.TransitionManager -import android.view.View -import android.view.ViewGroup -import android.view.ViewTreeObserver -import android.widget.TextView -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.model.Comment -import com.fastaccess.helper.InputHelper -import com.fastaccess.helper.ParseDateFormat -import com.fastaccess.helper.ViewHelper -import com.fastaccess.provider.markdown.MarkDownProvider -import com.fastaccess.provider.scheme.LinkParserHelper -import com.fastaccess.provider.timeline.handler.drawable.DrawableGetter -import com.fastaccess.ui.adapter.callback.OnToggleView -import com.fastaccess.ui.widgets.AvatarLayout -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.ForegroundImageView -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by kosh on 15/08/2017. - */ -class CommitCommentsViewHolder private constructor(view: View, adapter: BaseRecyclerAdapter<*, *, *>, - val viewGroup: ViewGroup, val onToggleView: OnToggleView) - : BaseViewHolder(view, adapter) { - - init { - if (adapter.getRowWidth() == 0) { - itemView.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { - override fun onPreDraw(): Boolean { - itemView.viewTreeObserver.removeOnPreDrawListener(this) - adapter.setRowWidth(itemView.width - ViewHelper.dpToPx(itemView.context, 48f)) - return false - } - }) - } - itemView.setOnClickListener(null) - itemView.setOnLongClickListener(null) - commentMenu.setOnClickListener(this) - commentMenu.setOnLongClickListener(this) - toggle.visibility = View.GONE - commentMenu.visibility = View.GONE - commentOptions.visibility = View.GONE - } - - @BindView(R.id.avatarView) lateinit var avatar: AvatarLayout - @BindView(R.id.name) lateinit var name: FontTextView - @BindView(R.id.date) lateinit var date: FontTextView - @BindView(R.id.toggle) lateinit var toggle: ForegroundImageView - @BindView(R.id.commentMenu) lateinit var commentMenu: ForegroundImageView - @BindView(R.id.comment) lateinit var comment: FontTextView - @BindView(R.id.commentOptions) lateinit var commentOptions: View - @BindView(R.id.owner) lateinit var owner: TextView - - override fun onClick(v: View) { - if (v.id == R.id.toggle || v.id == R.id.toggleHolder) { - val position = adapterPosition - onToggleView.onToggle(position.toLong(), !onToggleView.isCollapsed(position.toLong())) - onToggle(onToggleView.isCollapsed(position.toLong()), true) - } else { - super.onClick(v) - } - } - - override fun bind(t: Comment) { - val author3 = t.user - if (author3 != null) { - avatar.setUrl(author3.avatarUrl, author3.login, false, LinkParserHelper.isEnterprise(author3.url)) - name.text = author3.login - } else { - avatar.setUrl(null, null, false, false) - name.text = "" - } - if (!InputHelper.isEmpty(t.body)) { - val width = adapter?.getRowWidth() ?: 0 - if (width > 0) { - MarkDownProvider.setMdText(comment, t.body, width) - } else { - MarkDownProvider.setMdText(comment, t.body) - } - } else { - comment.text = "" - } - if (t.authorAssociation != null && !"none".equals(t.authorAssociation, ignoreCase = true)) { - owner.text = t.authorAssociation.toLowerCase() - owner.visibility = View.VISIBLE - } else { - owner.visibility = View.GONE - } - if (t.createdAt == t.updatedAt) { - date.text = String.format("%s %s", ParseDateFormat.getTimeAgo(t.updatedAt), itemView - .resources.getString(R.string.edited)) - } else { - date.text = ParseDateFormat.getTimeAgo(t.createdAt) - } - onToggle(onToggleView.isCollapsed(adapterPosition.toLong()), false) - } - - private fun onToggle(expanded: Boolean, animate: Boolean) { - if (animate) { - TransitionManager.beginDelayedTransition(viewGroup, ChangeBounds()) - } - toggle.rotation = if (!expanded) 0.0f else 180f - } - - override fun onViewIsDetaching() { - val drawableGetter = comment.getTag(R.id.drawable_callback) as DrawableGetter? - drawableGetter?.clear(drawableGetter) - } - - companion object { - fun newInstance(parent: ViewGroup, adapter: BaseRecyclerAdapter<*, *, *>, onToggleView: OnToggleView): CommitCommentsViewHolder { - return CommitCommentsViewHolder(getView(parent, R.layout.comments_row_item), adapter, parent, onToggleView) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitLinesViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitLinesViewHolder.java deleted file mode 100644 index 8492d9016..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitLinesViewHolder.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.graphics.Color; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.AppCompatTextView; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.CommitLinesModel; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 31 Dec 2016, 3:12 PM - */ - -public class CommitLinesViewHolder extends BaseViewHolder { - - @BindView(R.id.textView) AppCompatTextView textView; - @BindView(R.id.leftLinNo) AppCompatTextView leftLinNo; - @BindView(R.id.rightLinNo) AppCompatTextView rightLinNo; - @BindView(R.id.hasComment) View hasComment; - private final int patchAdditionColor; - private final int patchDeletionColor; - private final int patchRefColor; - - private CommitLinesViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - patchAdditionColor = ViewHelper.getPatchAdditionColor(itemView.getContext()); - patchDeletionColor = ViewHelper.getPatchDeletionColor(itemView.getContext()); - patchRefColor = ViewHelper.getPatchRefColor(itemView.getContext()); - textView.setOnLongClickListener(this); - } - - public static CommitLinesViewHolder newInstance(@NonNull ViewGroup viewGroup, @NonNull BaseRecyclerAdapter adapter) { - return new CommitLinesViewHolder(getView(viewGroup, R.layout.commit_line_row_item), adapter); - } - - @Override public void bind(@NonNull CommitLinesModel item) { - leftLinNo.setText(item.getLeftLineNo() > 0 ? String.valueOf(item.getLeftLineNo()) : " "); - rightLinNo.setText(item.getRightLineNo() > 0 ? String.valueOf(item.getRightLineNo()) : " "); - hasComment.setVisibility(item.isHasCommentedOn() ? View.VISIBLE : View.GONE); - switch (item.getColor()) { - case CommitLinesModel.ADDITION: - textView.setBackgroundColor(patchAdditionColor); - break; - case CommitLinesModel.DELETION: - textView.setBackgroundColor(patchDeletionColor); - break; - case CommitLinesModel.PATCH: - leftLinNo.setVisibility(View.GONE); - rightLinNo.setVisibility(View.GONE); - textView.setBackgroundColor(patchRefColor); - break; - default: - textView.setBackgroundColor(Color.TRANSPARENT); - } - if (item.isNoNewLine()) { - textView.setText(SpannableBuilder.builder().append(item.getText()).append(" ") - .append(ContextCompat.getDrawable(textView.getContext(), R.drawable.ic_newline))); - } else { - textView.setText(item.getText()); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitThreadViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitThreadViewHolder.kt deleted file mode 100644 index 8fcbdac05..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitThreadViewHolder.kt +++ /dev/null @@ -1,83 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.annotation.SuppressLint -import android.view.View -import android.view.ViewGroup -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.TimelineModel -import com.fastaccess.data.dao.model.Comment -import com.fastaccess.ui.adapter.CommitCommentsAdapter -import com.fastaccess.ui.adapter.callback.OnToggleView -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.SpannableBuilder -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView - -/** - * Created by kosh on 15/08/2017. - */ -class CommitThreadViewHolder private constructor(view: View, - adapter: BaseRecyclerAdapter<*, *, *>, - val onToggleView: OnToggleView) - : BaseViewHolder(view, adapter), BaseViewHolder.OnItemClickListener { - - @BindView(R.id.pathText) lateinit var pathText: FontTextView - @BindView(R.id.toggle) lateinit var toggle: View - @BindView(R.id.toggleHolder) lateinit var toggleHolder: View - @BindView(R.id.commitComments) lateinit var commitComments: DynamicRecyclerView - - init { - toggleHolder.setOnClickListener(this) - toggle.setOnClickListener(this) - itemView.setOnClickListener(null) - itemView.setOnLongClickListener(null) - } - - override fun onClick(v: View) { - if (v.id == R.id.toggle || v.id == R.id.toggleHolder) { - val position = adapterPosition - onToggleView.onToggle(position.toLong(), !onToggleView.isCollapsed(position.toLong())) - onToggle(onToggleView.isCollapsed(position.toLong())) - } - } - - @SuppressLint("SetTextI18n") - override fun bind(model: TimelineModel) { - val t = model.commit - t?.let { - val builder = SpannableBuilder.builder() - pathText.text = builder.append("${if (!it.login.isNullOrBlank()) it.login else ""} commented on") - .append(if (!it.path.isNullOrEmpty()) { - " ${it.path}#L${it.position} in " - } else { - " " - }) - .url(it.commitId.substring(0, 7)) - it.comments?.let { - if (!it.isEmpty()) commitComments.adapter = CommitCommentsAdapter(it, this, onToggleView) - } - } - onToggle(onToggleView.isCollapsed(adapterPosition.toLong())) - } - - - private fun onToggle(expanded: Boolean) { - toggle.rotation = if (!expanded) 0.0f else 180f - commitComments.visibility = if (!expanded) View.GONE - else if (commitComments.adapter != null) View.VISIBLE - else View.GONE - } - - override fun onItemClick(position: Int, v: View?, item: Comment) {} - - override fun onItemLongClick(position: Int, v: View?, item: Comment) {} - - companion object { - fun newInstance(parent: ViewGroup, adapter: BaseRecyclerAdapter<*, *, *>, - onToggleView: OnToggleView): CommitThreadViewHolder { - return CommitThreadViewHolder(getView(parent, R.layout.grouped_commit_comment_row), adapter, onToggleView) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitsViewHolder.java deleted file mode 100644 index d66e5a946..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/CommitsViewHolder.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.Date; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class CommitsViewHolder extends BaseViewHolder { - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.details) FontTextView details; - @BindView(R.id.commentsNo) FontTextView commentsNo; - - private CommitsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - } - - public static CommitsViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter) { - return new CommitsViewHolder(getView(viewGroup, R.layout.issue_row_item), adapter); - } - - @Override public void bind(@NonNull Commit commit) { - title.setText(commit.getGitCommit().getMessage()); - String login = commit.getAuthor() != null ? commit.getAuthor().getLogin() : commit.getGitCommit().getAuthor().getLogin(); - String avatar = commit.getAuthor() != null ? commit.getAuthor().getAvatarUrl() : null; - Date date = commit.getGitCommit().getAuthor().getDate(); - details.setText(SpannableBuilder.builder() - .bold(InputHelper.toNA(login)) - .append(" ") - .append(ParseDateFormat.getTimeAgo(date))); - avatarLayout.setUrl(avatar, login, false, LinkParserHelper - .isEnterprise(commit.getAuthor() != null ? commit.getAuthor().getUrl() : commit.getGitCommit().getAuthor().getHtmlUrl())); - avatarLayout.setVisibility(View.VISIBLE); - if (commit.getGitCommit() != null && commit.getGitCommit().getCommentCount() > 0) { - commentsNo.setText(String.valueOf(commit.getGitCommit() != null ? commit.getGitCommit().getCommentCount() : 0)); - commentsNo.setVisibility(View.VISIBLE); - } else { - commentsNo.setVisibility(View.GONE); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/EmojiViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/EmojiViewHolder.kt deleted file mode 100644 index c26bb6e2f..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/EmojiViewHolder.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.view.View -import android.view.ViewGroup -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.provider.emoji.Emoji -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by kosh on 17/08/2017. - */ -class EmojiViewHolder private constructor(view: View, adapter: BaseRecyclerAdapter<*, *, *>) - : BaseViewHolder(view, adapter) { - - @BindView(R.id.emoji) lateinit var emojiTextView: FontTextView - - override fun bind(t: Emoji) { - emojiTextView.text = t.unicode - } - - companion object { - fun newInstance(parent: ViewGroup, adapter: BaseRecyclerAdapter<*, *, *>): EmojiViewHolder { - return EmojiViewHolder(getView(parent, R.layout.emoji_row_item), adapter) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FastHubNotificationViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FastHubNotificationViewHolder.kt deleted file mode 100644 index 8be74ceb2..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FastHubNotificationViewHolder.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.view.View -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.model.FastHubNotification -import com.fastaccess.helper.ParseDateFormat -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created: by Kosh on 02 Jun 2017, 1:27 PM - */ - -open class FastHubNotificationViewHolder(itemView: View, adapter: BaseRecyclerAdapter>) : BaseViewHolder(itemView, adapter) { - - @BindView(R.id.title) lateinit var title: FontTextView - @BindView(R.id.date) lateinit var date: FontTextView - @BindView(R.id.type) lateinit var type: FontTextView - - - override fun bind(t: FastHubNotification) { - title.text = t.title - if (t.date != null) { - date.text = ParseDateFormat.getTimeAgo(t.date) - } - type.text = t.type.name.replace("_", " ") - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FeedsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FeedsViewHolder.java deleted file mode 100644 index 67eb3ffd4..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/FeedsViewHolder.java +++ /dev/null @@ -1,469 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.content.res.Resources; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.GitCommitModel; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.PayloadModel; -import com.fastaccess.data.dao.TeamsModel; -import com.fastaccess.data.dao.WikiModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Event; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.Release; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.EventsType; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.provider.markdown.MarkDownProvider; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class FeedsViewHolder extends BaseViewHolder { - - @Nullable @BindView(R.id.avatarLayout) AvatarLayout avatar; - @BindView(R.id.description) FontTextView description; - @BindView(R.id.title) FontTextView title; - @BindView(R.id.date) FontTextView date; - private Resources resources; - - public FeedsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - this.resources = itemView.getResources(); - } - - public static View getView(@NonNull ViewGroup viewGroup, boolean noImage) { - if (noImage) { - return getView(viewGroup, R.layout.feeds_row_no_image_item); - } else { - return getView(viewGroup, R.layout.feeds_row_item); - } - } - - @Override public void bind(@NonNull Event eventsModel) { - appendAvatar(eventsModel); - SpannableBuilder spannableBuilder = SpannableBuilder.builder(); - appendActor(eventsModel, spannableBuilder); - description.setMaxLines(2); - description.setText(""); - description.setVisibility(View.GONE); - if (eventsModel.getType() != null) { - EventsType type = eventsModel.getType(); - if (type == EventsType.WatchEvent) { - appendWatch(spannableBuilder, type, eventsModel); - } else if (type == EventsType.CreateEvent) { - appendCreateEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.CommitCommentEvent) { - appendCommitComment(spannableBuilder, eventsModel); - } else if (type == EventsType.DownloadEvent) { - appendDownloadEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.FollowEvent) { - appendFollowEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.ForkEvent) { - appendForkEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.GistEvent) { - appendGistEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.GollumEvent) { - appendGollumEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.IssueCommentEvent) { - appendIssueCommentEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.IssuesEvent) { - appendIssueEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.MemberEvent) { - appendMemberEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.PublicEvent) { - appendPublicEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.PullRequestEvent) { - appendPullRequestEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.PullRequestReviewCommentEvent) { - appendPullRequestReviewCommentEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.PullRequestReviewEvent) { - appendPullRequestReviewCommentEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.RepositoryEvent) { - appendPublicEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.PushEvent) { - appendPushEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.TeamAddEvent) { - appendTeamEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.DeleteEvent) { - appendDeleteEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.ReleaseEvent) { - appendReleaseEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.ForkApplyEvent) { - appendForkApplyEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.OrgBlockEvent) { - appendOrgBlockEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.ProjectCardEvent) { - appendProjectCardEvent(spannableBuilder, eventsModel, false); - } else if (type == EventsType.ProjectColumnEvent) { - appendProjectCardEvent(spannableBuilder, eventsModel, true); - } else if (type == EventsType.OrganizationEvent) { - appendOrganizationEvent(spannableBuilder, eventsModel); - } else if (type == EventsType.ProjectEvent) { - appendProjectCardEvent(spannableBuilder, eventsModel, false); - } - date.setGravity(Gravity.CENTER); - date.setEventsIcon(type.getDrawableRes()); - } - title.setText(spannableBuilder); - date.setText(ParseDateFormat.getTimeAgo(eventsModel.getCreatedAt())); - } - - private void appendOrganizationEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - spannableBuilder.bold(eventsModel.getPayload().getAction().replaceAll("_", "")) - .append(" ") - .append(eventsModel.getPayload().getInvitation() != null ? eventsModel.getPayload().getInvitation().getLogin() + " " : "") - .append(eventsModel.getPayload().getOrganization().getLogin()); - } - - private void appendProjectCardEvent(SpannableBuilder spannableBuilder, Event eventsModel, boolean isColumn) { - spannableBuilder.bold(eventsModel.getPayload().getAction()) - .append(" ") - .append(!isColumn ? "project" : "column") - .append(" ") - .append(eventsModel.getRepo().getName()); - } - - private void appendOrgBlockEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - spannableBuilder.bold(eventsModel.getPayload().getAction()) - .append(" ") - .append(eventsModel.getPayload().getBlockedUser().getLogin()) - .append(" ") - .append(eventsModel.getPayload().getOrganization().getLogin()); - } - - private void appendForkApplyEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - spannableBuilder.bold(eventsModel.getPayload().getHead()) - .append(" ") - .append(eventsModel.getPayload().getBefore()) - .append(" ") - .append(eventsModel.getRepo() != null ? "in " + eventsModel.getRepo().getName() : ""); - } - - private void appendReleaseEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - Release release = eventsModel.getPayload().getRelease(); - spannableBuilder.bold("released") - .append(" ") - .append(release.getName()) - .append(" ") - .append(eventsModel.getRepo().getName()); - } - - private void appendDeleteEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - spannableBuilder.bold("deleted") - .append(" ") - .append(eventsModel.getPayload().getRefType()) - .append(" ") - .append(eventsModel.getPayload().getRef()) - .append(" ") - .bold("at") - .append(" ") - .append(eventsModel.getRepo().getName()); - } - - private void appendTeamEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - TeamsModel teamsModel = eventsModel.getPayload().getTeam(); - User user = eventsModel.getPayload().getUser(); - spannableBuilder.bold("added") - .append(" ") - .append(user != null ? user.getLogin() : eventsModel.getRepo().getName()) - .append(" ") - .bold("in") - .append(" ") - .append(teamsModel.getName() != null ? teamsModel.getName() : teamsModel.getSlug()); - } - - private void appendPushEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - String ref = eventsModel.getPayload().getRef(); - if (ref.startsWith("refs/heads/")) { - ref = ref.substring(11); - } - spannableBuilder.bold("pushed to") - .append(" ") - .append(ref) - .append(" ") - .bold("at") - .append(" ") - .append(eventsModel.getRepo().getName()); - final List commits = eventsModel.getPayload().getCommits(); - int size = commits != null ? commits.size() : -1; - SpannableBuilder spanCommits = SpannableBuilder.builder(); - if (size > 0) { - if (size != 1) spanCommits.append(String.valueOf(eventsModel.getPayload().getSize())).append(" new commits").append("\n"); - else spanCommits.append("1 new commit").append("\n"); - int max = 5; - int appended = 0; - for (GitCommitModel commit : commits) { - if (commit == null) continue; - String sha = commit.getSha(); - if (TextUtils.isEmpty(sha)) continue; - sha = sha.length() > 7 ? sha.substring(0, 7) : sha; - spanCommits.url(sha).append(" ") - .append(commit.getMessage() != null ? commit.getMessage().replaceAll("\\r?\\n|\\r", " ") : "") - .append("\n"); - appended++; - if (appended == max) break; - } - } - if (spanCommits.length() > 0) { - int last = spanCommits.length(); - description.setMaxLines(5); - description.setText(spanCommits.delete(last - 1, last)); - description.setVisibility(View.VISIBLE); - } else { - description.setText(""); - description.setMaxLines(2); - description.setVisibility(View.GONE); - } - } - - private void appendPullRequestReviewCommentEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - PullRequest pullRequest = eventsModel.getPayload().getPullRequest(); - Comment comment = eventsModel.getPayload().getComment(); - spannableBuilder.bold("reviewed") - .append(" ") - .bold("pull request") - .append(" ") - .bold("in") - .append(" ") - .append(eventsModel.getRepo().getName()) - .bold("#") - .bold(String.valueOf(pullRequest.getNumber())); - if (comment.getBody() != null) { - MarkDownProvider.stripMdText(description, comment.getBody().replaceAll("\\r?\\n|\\r", " ")); - description.setVisibility(View.VISIBLE); - } else { - description.setText(""); - description.setVisibility(View.GONE); - } - } - - private void appendPullRequestEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - PullRequest issue = eventsModel.getPayload().getPullRequest(); - String action = eventsModel.getPayload().getAction(); - if ("synchronize".equals(action)) { - action = "updated"; - } - if (eventsModel.getPayload().getPullRequest().isMerged()) { - action = "merged"; - } - spannableBuilder.bold(action) - .append(" ") - .bold("pull request") - .append(" ") - .append(eventsModel.getRepo().getName()) - .bold("#") - .bold(String.valueOf(issue.getNumber())); - if ("opened".equals(action) || "closed".equals(action)) { - if (issue.getTitle() != null) { - MarkDownProvider.stripMdText(description, issue.getTitle().replaceAll("\\r?\\n|\\r", " ")); - description.setVisibility(View.VISIBLE); - } else { - description.setText(""); - description.setVisibility(View.GONE); - } - } - } - - private void appendPublicEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - String action = "public"; - if (eventsModel.getPayload() != null && "privatized".equalsIgnoreCase(eventsModel.getPayload().getAction())) { - action = "private"; - } - spannableBuilder.append("made") - .append(" ") - .append(eventsModel.getRepo().getName()) - .append(" ") - .append(action); - } - - private void appendMemberEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - User user = eventsModel.getPayload().getMember(); - spannableBuilder.bold("added") - .append(" ") - .append(user != null ? user.getLogin() + " " : "") - .append("as a collaborator") - .append(" ") - .append("to") - .append(" ") - .append(eventsModel.getRepo().getName()); - } - - private void appendIssueEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - Issue issue = eventsModel.getPayload().getIssue(); - boolean isLabel = "label".equals(eventsModel.getPayload().getAction()); - LabelModel label = isLabel ? issue.getLabels() != null && !issue.getLabels().isEmpty() - ? issue.getLabels().get(issue.getLabels().size() - 1) : null : null; - spannableBuilder.bold(isLabel && label != null ? ("Labeled " + label.getName()) : eventsModel.getPayload().getAction()) - .append(" ") - .bold("issue") - .append(" ") - .append(eventsModel.getRepo().getName()) - .bold("#") - .bold(String.valueOf(issue.getNumber())); - if (issue.getTitle() != null) { - MarkDownProvider.stripMdText(description, issue.getTitle().replaceAll("\\r?\\n|\\r", " ")); - description.setVisibility(View.VISIBLE); - } else { - description.setText(""); - description.setVisibility(View.GONE); - } - } - - private void appendIssueCommentEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - Comment comment = eventsModel.getPayload().getComment(); - Issue issue = eventsModel.getPayload().getIssue(); - spannableBuilder.bold("commented") - .append(" ") - .bold("on") - .append(" ") - .bold(issue.getPullRequest() != null ? "pull request" : "issue") - .append(" ") - .append(eventsModel.getRepo().getName()) - .bold("#") - .bold(String.valueOf(issue.getNumber())); - if (comment.getBody() != null) { - MarkDownProvider.stripMdText(description, comment.getBody().replaceAll("\\r?\\n|\\r", " ")); - description.setVisibility(View.VISIBLE); - } else { - description.setText(""); - description.setVisibility(View.GONE); - } - } - - private void appendGollumEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - List wiki = eventsModel.getPayload().getPages(); - if (wiki != null && !wiki.isEmpty()) { - for (WikiModel wikiModel : wiki) { - spannableBuilder.bold(wikiModel.getAction()) - .append(" ") - .append(wikiModel.getPageName()) - .append(" "); - } - } else { - spannableBuilder.bold(resources.getString(R.string.gollum)) - .append(" "); - } - spannableBuilder - .append(eventsModel.getRepo().getName()); - - } - - private void appendGistEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - String action = eventsModel.getPayload().getAction(); - action = "create".equals(action) ? "created" : "update".equals(action) ? "updated" : action; - spannableBuilder.bold(action) - .append(" ") - .append(itemView.getResources().getString(R.string.gist)) - .append(" ") - .append(eventsModel.getPayload().getGist().getGistId()); - } - - private void appendForkEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - spannableBuilder.bold("forked") - .append(" ") - .append(eventsModel.getRepo().getName()); - } - - private void appendFollowEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - spannableBuilder.bold("started following") - .append(" ") - .bold(eventsModel.getPayload().getTarget().getLogin()); - } - - private void appendDownloadEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - spannableBuilder.bold("uploaded a file") - .append(" ") - .append(eventsModel.getPayload().getDownload() != null ? eventsModel.getPayload().getDownload().getName() : "") - .append(" ") - .append("to") - .append(" ") - .append(eventsModel.getRepo().getName()); - } - - private void appendCreateEvent(SpannableBuilder spannableBuilder, Event eventsModel) { - PayloadModel payloadModel = eventsModel.getPayload(); - String refType = payloadModel.getRefType(); - spannableBuilder - .bold("created") - .append(" ") - .append(refType) - .append(" ") - .append(!"repository".equalsIgnoreCase(refType) ? payloadModel.getRef() + " " : "") - .bold("at") - .append(" ") - .append(eventsModel.getRepo().getName()); - if (payloadModel.getDescription() != null) { - MarkDownProvider.stripMdText(description, payloadModel.getDescription().replaceAll("\\r?\\n|\\r", " ")); - description.setVisibility(View.VISIBLE); - } else { - description.setText(""); - description.setVisibility(View.GONE); - } - } - - private void appendWatch(SpannableBuilder spannableBuilder, EventsType type, Event eventsModel) { - spannableBuilder.bold(resources.getString(type.getType()).toLowerCase()) - .append(" ") - .append(eventsModel.getRepo().getName()); - } - - private void appendCommitComment(SpannableBuilder spannableBuilder, Event eventsModel) { - Comment comment = eventsModel.getPayload().getCommitComment() == null ? eventsModel.getPayload().getComment() : eventsModel.getPayload() - .getCommitComment(); - String commitId = comment != null && comment.getCommitId() != null && comment.getCommitId().length() > 10 ? - comment.getCommitId().substring(0, 10) : null; - spannableBuilder.bold("commented") - .append(" ") - .bold("on") - .append(" ") - .bold("commit") - .append(" ") - .append(eventsModel.getRepo().getName()) - .url(commitId != null ? "@" + commitId : ""); - if (comment != null && comment.getBody() != null) { - MarkDownProvider.stripMdText(description, comment.getBody().replaceAll("\\r?\\n|\\r", " ")); - description.setVisibility(View.VISIBLE); - } else { - description.setText(""); - description.setVisibility(View.GONE); - } - } - - private void appendActor(@NonNull Event eventsModel, SpannableBuilder spannableBuilder) { - if (eventsModel.getActor() != null) { - spannableBuilder.append(eventsModel.getActor().getLogin()).append(" "); - } - } - - private void appendAvatar(@NonNull Event eventsModel) { - if (avatar != null) { - if (eventsModel.getActor() != null) { - avatar.setUrl(eventsModel.getActor().getAvatarUrl(), eventsModel.getActor().getLogin(), - eventsModel.getActor().isOrganizationType(), - LinkParserHelper.isEnterprise(eventsModel.getActor().getHtmlUrl())); - } else { - avatar.setUrl(null, null, false, false); - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/GistFilesViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/GistFilesViewHolder.java deleted file mode 100644 index 344942968..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/GistFilesViewHolder.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.text.format.Formatter; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.FilesListModel; -import com.fastaccess.ui.adapter.GistFilesAdapter; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 12 Nov 2016, 3:44 PM - */ - -public class GistFilesViewHolder extends BaseViewHolder { - - @BindView(R.id.fileName) FontTextView fileName; - @BindView(R.id.language) FontTextView language; - @BindView(R.id.size) FontTextView size; - @BindView(R.id.delete) ForegroundImageView delete; - @BindView(R.id.edit) ForegroundImageView edit; - private boolean isOwner; - - private GistFilesViewHolder(@NonNull View itemView, GistFilesAdapter adapter, boolean isOwner) { - super(itemView, adapter); - this.isOwner = isOwner; - if (isOwner) { - delete.setOnClickListener(this); - edit.setOnClickListener(this); - } - } - - public static GistFilesViewHolder newInstance(@NonNull ViewGroup parent, GistFilesAdapter adapter, boolean isOwner) { - return new GistFilesViewHolder(getView(parent, R.layout.gist_files_row_item), adapter, isOwner); - } - - @Override public void bind(@NonNull FilesListModel filesListModel) { - fileName.setText(filesListModel.getFilename()); - language.setText(SpannableBuilder.builder().bold(filesListModel.getType())); - size.setText(Formatter.formatFileSize(size.getContext(), filesListModel.getSize())); - delete.setVisibility(isOwner ? View.VISIBLE : View.GONE); - edit.setVisibility(isOwner ? View.VISIBLE : View.GONE); - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/GistsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/GistsViewHolder.java deleted file mode 100644 index 2fc2e36f7..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/GistsViewHolder.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class GistsViewHolder extends BaseViewHolder { - - @Nullable @BindView(R.id.avatarLayout) AvatarLayout avatar; - @BindView(R.id.title) FontTextView title; - @BindView(R.id.date) FontTextView date; - private boolean isFromProfile; - - - private GistsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter, boolean isFromProfile) { - super(itemView, adapter); - title.setMaxLines(2); - this.isFromProfile = isFromProfile; - } - - public static GistsViewHolder newInstance(@NonNull ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter, boolean isFromProfile) { - if (!isFromProfile) { - return new GistsViewHolder(getView(viewGroup, R.layout.feeds_row_item), adapter, false); - } else { - return new GistsViewHolder(getView(viewGroup, R.layout.feeds_row_no_image_item), adapter, true); - } - } - - @Override public void bind(@NonNull Gist item) { - if (!isFromProfile) { - if (avatar != null) { - String url = item.getOwner() != null ? item.getOwner().getAvatarUrl() : item.getUser() != null ? item.getUser().getAvatarUrl() : null; - String login = item.getOwner() != null ? item.getOwner().getLogin() : item.getUser() != null ? item.getUser().getLogin() : null; - avatar.setUrl(url, login, false, LinkParserHelper.isEnterprise( - item.getOwner() != null ? item.getOwner().getHtmlUrl() : item.getUser() != null ? item.getUser().getHtmlUrl() : null)); - } - } - title.setText(item.getDisplayTitle(isFromProfile)); - date.setText(ParseDateFormat.getTimeAgo(item.getCreatedAt())); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/GroupedReviewsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/GroupedReviewsViewHolder.java deleted file mode 100644 index cc4f3b26a..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/GroupedReviewsViewHolder.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; - -import com.fastaccess.R; -import com.fastaccess.data.dao.GroupedReviewModel; -import com.fastaccess.data.dao.ReviewCommentModel; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.adapter.ReviewCommentsAdapter; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.adapter.callback.ReactionsCallback; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.timeline.timeline.PullRequestTimelineMvp; -import com.fastaccess.ui.widgets.DiffLineSpan; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; - -import butterknife.BindView; - -/** - * Created by Kosh on 13 Dec 2016, 1:42 AM - */ - -public class GroupedReviewsViewHolder extends BaseViewHolder implements BaseViewHolder.OnItemClickListener { - - @BindView(R.id.stateImage) ForegroundImageView stateImage; - @BindView(R.id.nestedRecyclerView) DynamicRecyclerView nestedRecyclerView; - @BindView(R.id.name) FontTextView name; - @BindView(R.id.toggle) ForegroundImageView toggle; - @BindView(R.id.patch) FontTextView patch; - @BindView(R.id.minimized) View minimized; - @BindView(R.id.addCommentPreview) View addCommentPreview; - @BindView(R.id.toggleHolder) LinearLayout toggleHolder; - @BindView(R.id.bottomToggle) View bottomToggle; - - private final int patchAdditionColor; - private final int patchDeletionColor; - private final int patchRefColor; - private OnToggleView onToggleView; - private ReactionsCallback reactionsCallback; - private String pathText; - private PullRequestTimelineMvp.ReviewCommentCallback reviewCommentCallback; - private ViewGroup viewGroup; - private String repoOwner; - private String poster; - - @Override public void onClick(View v) { - if (v.getId() == R.id.toggle || v.getId() == R.id.toggleHolder || v.getId() == R.id.bottomToggle) { - long position = getId(); - onToggleView.onToggle(position, !onToggleView.isCollapsed(position)); - onToggle(onToggleView.isCollapsed(position), true); - } else { - super.onClick(v); - } - } - - private GroupedReviewsViewHolder(@NonNull View itemView, ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter, - @NonNull OnToggleView onToggleView, - @NonNull ReactionsCallback reactionsCallback, - @NonNull PullRequestTimelineMvp.ReviewCommentCallback reviewCommentCallback, - String repoOwner, String poster) { - super(itemView, adapter); - this.onToggleView = onToggleView; - this.viewGroup = viewGroup; - this.reactionsCallback = reactionsCallback; - this.reviewCommentCallback = reviewCommentCallback; - patchAdditionColor = ViewHelper.getPatchAdditionColor(itemView.getContext()); - patchDeletionColor = ViewHelper.getPatchDeletionColor(itemView.getContext()); - patchRefColor = ViewHelper.getPatchRefColor(itemView.getContext()); - this.onToggleView = onToggleView; - this.repoOwner = repoOwner; - this.poster = poster; - bottomToggle.setOnClickListener(this); - nestedRecyclerView.setNestedScrollingEnabled(false); - addCommentPreview.setOnClickListener(this); - toggle.setOnClickListener(this); - toggleHolder.setOnClickListener(this); - itemView.setOnClickListener(null); - itemView.setOnLongClickListener(null); - } - - public static GroupedReviewsViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter, - @NonNull OnToggleView onToggleView, - @NonNull ReactionsCallback reactionsCallback, - @NonNull PullRequestTimelineMvp.ReviewCommentCallback reviewCommentCallback, - String repoOwner, String poster) { - return new GroupedReviewsViewHolder(getView(viewGroup, R.layout.grouped_review_timeline_row_item), viewGroup, adapter, - onToggleView, reactionsCallback, reviewCommentCallback, repoOwner, poster); - } - - @Override public void bind(@NonNull TimelineModel model) { - GroupedReviewModel groupedReviewModel = model.getGroupedReviewModel(); - this.pathText = groupedReviewModel.getDiffText(); - name.setText(groupedReviewModel.getPath()); - stateImage.setImageResource(R.drawable.ic_eye); - if (groupedReviewModel.getComments() == null || groupedReviewModel.getComments().isEmpty()) { - nestedRecyclerView.setVisibility(View.GONE); - nestedRecyclerView.setAdapter(null); - } else { - nestedRecyclerView.setVisibility(View.VISIBLE); - nestedRecyclerView.setAdapter(new ReviewCommentsAdapter(groupedReviewModel.getComments(), this, - onToggleView, reactionsCallback, repoOwner, poster)); - nestedRecyclerView.addDivider(); - } - onToggle(onToggleView.isCollapsed(getId()), false); - } - - - @Override public void onItemClick(int position, View v, ReviewCommentModel item) { - if (reviewCommentCallback != null) { - reviewCommentCallback.onClick(getAdapterPosition(), position, v, item); - } - } - - @Override public void onItemLongClick(int position, View v, ReviewCommentModel item) { - if (reviewCommentCallback != null) { - reviewCommentCallback.onLongClick(getAdapterPosition(), position, v, item); - } - } - - private void onToggle(boolean expanded, boolean animate) { - if (!expanded) { - minimized.setVisibility(View.GONE); - patch.setText(""); - name.setMaxLines(2); - toggle.setRotation(0.0f); - } else { - minimized.setVisibility(View.VISIBLE); - name.setMaxLines(5); - setPatchText(pathText); - toggle.setRotation(180f); - } - } - - private long getId() { - return getAdapterPosition(); - } - - private void setPatchText(@NonNull String text) { - patch.setText(DiffLineSpan.getSpannable(text, patchAdditionColor, patchDeletionColor, patchRefColor, true)); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssueDetailsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssueDetailsViewHolder.java deleted file mode 100644 index 8bd68e0d1..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssueDetailsViewHolder.java +++ /dev/null @@ -1,276 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.graphics.Color; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.transition.ChangeBounds; -import android.support.transition.TransitionManager; -import android.text.TextUtils; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.fastaccess.R; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.provider.timeline.HtmlHelper; -import com.fastaccess.provider.timeline.handler.drawable.DrawableGetter; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.adapter.callback.ReactionsCallback; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.LabelSpan; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.Date; -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 13 Dec 2016, 1:03 AM - */ - -public class IssueDetailsViewHolder extends BaseViewHolder { - - @BindView(R.id.avatarView) AvatarLayout avatar; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.name) FontTextView name; - @BindView(R.id.comment) FontTextView comment; - @BindView(R.id.thumbsUp) FontTextView thumbsUp; - @BindView(R.id.thumbsDown) FontTextView thumbsDown; - @BindView(R.id.laugh) FontTextView laugh; - @BindView(R.id.sad) FontTextView sad; - @BindView(R.id.hurray) FontTextView hooray; - @BindView(R.id.heart) FontTextView heart; - @BindView(R.id.toggle) View toggle; - @BindView(R.id.commentMenu) View commentMenu; - @BindView(R.id.commentOptions) View commentOptions; - @BindView(R.id.toggleHolder) View toggleHolder; - @BindView(R.id.emojiesList) View emojiesList; - @BindView(R.id.owner) TextView owner; - @BindView(R.id.labels) TextView labels; - @BindView(R.id.labelsHolder) View labelsHolder; - @BindView(R.id.reactionsList) View reactionsList; - @BindView(R.id.thumbsUpReaction) FontTextView thumbsUpReaction; - @BindView(R.id.thumbsDownReaction) FontTextView thumbsDownReaction; - @BindView(R.id.laughReaction) FontTextView laughReaction; - @BindView(R.id.hurrayReaction) FontTextView hurrayReaction; - @BindView(R.id.sadReaction) FontTextView sadReaction; - @BindView(R.id.heartReaction) FontTextView heartReaction; - private OnToggleView onToggleView; - private ReactionsCallback reactionsCallback; - private ViewGroup viewGroup; - private String repoOwner; - private String poster; - - private IssueDetailsViewHolder(@NonNull View itemView, @NonNull ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter, - @NonNull OnToggleView onToggleView, @NonNull ReactionsCallback reactionsCallback, - String repoOwner, String poster) { - super(itemView, adapter); - this.onToggleView = onToggleView; - this.viewGroup = viewGroup; - this.reactionsCallback = reactionsCallback; - this.repoOwner = repoOwner; - this.poster = poster; - itemView.setOnClickListener(null); - itemView.setOnLongClickListener(null); - commentMenu.setOnClickListener(this); - toggle.setOnClickListener(this); - toggleHolder.setOnClickListener(this); - laugh.setOnClickListener(this); - sad.setOnClickListener(this); - thumbsDown.setOnClickListener(this); - thumbsUp.setOnClickListener(this); - hooray.setOnClickListener(this); - laugh.setOnLongClickListener(this); - sad.setOnLongClickListener(this); - thumbsDown.setOnLongClickListener(this); - thumbsUp.setOnLongClickListener(this); - hooray.setOnLongClickListener(this); - heart.setOnLongClickListener(this); - heart.setOnClickListener(this); - laughReaction.setOnClickListener(this); - sadReaction.setOnClickListener(this); - thumbsDownReaction.setOnClickListener(this); - thumbsUpReaction.setOnClickListener(this); - hurrayReaction.setOnClickListener(this); - heartReaction.setOnClickListener(this); - laughReaction.setOnLongClickListener(this); - sadReaction.setOnLongClickListener(this); - thumbsDownReaction.setOnLongClickListener(this); - thumbsUpReaction.setOnLongClickListener(this); - hurrayReaction.setOnLongClickListener(this); - heartReaction.setOnLongClickListener(this); - } - - public static IssueDetailsViewHolder newInstance(@NonNull ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter, - @NonNull OnToggleView onToggleView, @NonNull ReactionsCallback reactionsCallback, - @NonNull String repoOwner, @NonNull String poster) { - return new IssueDetailsViewHolder(getView(viewGroup, R.layout.issue_detail_header_row_item), viewGroup, - adapter, onToggleView, reactionsCallback, repoOwner, poster); - } - - @Override public void bind(@NonNull TimelineModel timelineModel) { - if (timelineModel.getIssue() != null) { - bind(timelineModel.getIssue()); - } else if (timelineModel.getPullRequest() != null) { - bind(timelineModel.getPullRequest()); - } - if (onToggleView != null) onToggle(onToggleView.isCollapsed(getAdapterPosition()), false); - } - - @Override public void onClick(View v) { - if (v.getId() == R.id.toggle || v.getId() == R.id.toggleHolder) { - if (onToggleView != null) { - int position = getAdapterPosition(); - onToggleView.onToggle(position, !onToggleView.isCollapsed(position)); - onToggle(onToggleView.isCollapsed(position), true); - } - } else { - addReactionCount(v); - super.onClick(v); - } - } - - private void addReactionCount(View v) { - if (adapter != null) { - TimelineModel timelineModel = (TimelineModel) adapter.getItem(getAdapterPosition()); - if (timelineModel == null) return; - ReactionsModel reactionsModel = null; - PullRequest pullRequest = timelineModel.getPullRequest(); - Issue issue = timelineModel.getIssue(); - int number = 0; - if (pullRequest != null) { - reactionsModel = pullRequest.getReactions(); - number = pullRequest.getNumber(); - } else if (issue != null) { - reactionsModel = issue.getReactions(); - number = issue.getNumber(); - } - if (reactionsModel == null) reactionsModel = new ReactionsModel(); - boolean isReacted = reactionsCallback == null || reactionsCallback.isPreviouslyReacted(number, v.getId()); - boolean isCallingApi = reactionsCallback != null && reactionsCallback.isCallingApi(number, v.getId()); - switch (v.getId()) { - case R.id.heart: - case R.id.heartReaction: - reactionsModel.setHeart(!isReacted ? reactionsModel.getHeart() + 1 : reactionsModel.getHeart() - 1); - break; - case R.id.sad: - case R.id.sadReaction: - reactionsModel.setConfused(!isReacted ? reactionsModel.getConfused() + 1 : reactionsModel.getConfused() - 1); - break; - case R.id.thumbsDown: - case R.id.thumbsDownReaction: - reactionsModel.setMinusOne(!isReacted ? reactionsModel.getMinusOne() + 1 : reactionsModel.getMinusOne() - 1); - break; - case R.id.thumbsUp: - case R.id.thumbsUpReaction: - reactionsModel.setPlusOne(!isReacted ? reactionsModel.getPlusOne() + 1 : reactionsModel.getPlusOne() - 1); - break; - case R.id.laugh: - case R.id.laughReaction: - reactionsModel.setLaugh(!isReacted ? reactionsModel.getLaugh() + 1 : reactionsModel.getLaugh() - 1); - break; - case R.id.hurray: - case R.id.hurrayReaction: - reactionsModel.setHooray(!isReacted ? reactionsModel.getHooray() + 1 : reactionsModel.getHooray() - 1); - break; - } - if (pullRequest != null) { - pullRequest.setReactions(reactionsModel); - appendEmojies(reactionsModel); - timelineModel.setPullRequest(pullRequest); - } else if (issue != null) { - issue.setReactions(reactionsModel); - appendEmojies(reactionsModel); - timelineModel.setIssue(issue); - } - } - } - - private void bind(@NonNull Issue issueModel) { - setup(issueModel.getUser(), issueModel.getBodyHtml(), issueModel.getReactions()); - setupDate(issueModel.getCreatedAt(), issueModel.getUpdatedAt()); - setupLabels(issueModel.getLabels()); - } - - private void bind(@NonNull PullRequest pullRequest) { - setup(pullRequest.getUser(), pullRequest.getBodyHtml(), pullRequest.getReactions()); - setupDate(pullRequest.getCreatedAt(), pullRequest.getUpdatedAt()); - setupLabels(pullRequest.getLabels()); - } - - private void setup(User user, String description, ReactionsModel reactionsModel) { - avatar.setUrl(user.getAvatarUrl(), user.getLogin(), user.isOrganizationType(), LinkParserHelper.isEnterprise(user.getHtmlUrl())); - name.setText(user.getLogin()); - boolean isOwner = TextUtils.equals(repoOwner, user.getLogin()); - if (isOwner) { - owner.setVisibility(View.VISIBLE); - owner.setText(R.string.owner); - } else { - owner.setText(""); - owner.setVisibility(View.GONE); - } - if (reactionsModel != null) { - appendEmojies(reactionsModel); - } - if (!InputHelper.isEmpty(description)) { - HtmlHelper.htmlIntoTextView(comment, description, viewGroup.getWidth() - ViewHelper.dpToPx(itemView.getContext(), 24)); - } else { - comment.setText(R.string.no_description_provided); - } - } - - private void setupDate(@NonNull Date createdDate, @NonNull Date updated) { - date.setText(ParseDateFormat.getTimeAgo(createdDate)); - } - - private void setupLabels(@Nullable List labelList) { - if (labelList != null && !labelList.isEmpty()) { - SpannableBuilder builder = SpannableBuilder.builder(); - for (LabelModel labelModel : labelList) { - int color = Color.parseColor("#" + labelModel.getColor()); - builder.append(" ").append(" " + labelModel.getName() + " ", new LabelSpan(color)); - } - labels.setText(builder); - labelsHolder.setVisibility(View.VISIBLE); - } else { - labels.setText(""); - labelsHolder.setVisibility(View.GONE); - } - } - - private void appendEmojies(ReactionsModel reaction) { - CommentsHelper.appendEmojies(reaction, thumbsUp, thumbsUpReaction, thumbsDown, thumbsDownReaction, hooray, hurrayReaction, sad, - sadReaction, laugh, laughReaction, heart, heartReaction, reactionsList); - } - - private void onToggle(boolean expanded, boolean animate) { - if (animate) { - TransitionManager.beginDelayedTransition(viewGroup, new ChangeBounds()); - } - toggle.setRotation(!expanded ? 0.0F : 180F); - commentOptions.setVisibility(!expanded ? View.GONE : View.VISIBLE); - reactionsList.setVisibility(expanded ? View.GONE : reactionsList.getTag() == null || (!((Boolean) reactionsList.getTag())) - ? View.GONE : View.VISIBLE); - } - - @Override protected void onViewIsDetaching() { - DrawableGetter drawableGetter = (DrawableGetter) comment.getTag(R.id.drawable_callback); - if (drawableGetter != null) { - drawableGetter.clear(drawableGetter); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssueTimelineViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssueTimelineViewHolder.java deleted file mode 100644 index 01e94d5ea..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssueTimelineViewHolder.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.timeline.GenericEvent; -import com.fastaccess.data.dao.types.IssueEventType; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.provider.timeline.TimelineProvider; -import com.fastaccess.provider.timeline.handler.drawable.DrawableGetter; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 13 Dec 2016, 1:42 AM - */ - -public class IssueTimelineViewHolder extends BaseViewHolder { - - @BindView(R.id.stateImage) ForegroundImageView stateImage; - @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.stateText) FontTextView stateText; - private boolean isMerged; - - private IssueTimelineViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter, boolean isMerged) { - super(itemView, adapter); - this.isMerged = isMerged; - } - - public static IssueTimelineViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter, boolean isMerged) { - return new IssueTimelineViewHolder(getView(viewGroup, R.layout.issue_timeline_row_item), adapter, isMerged); - } - - @Override public void bind(@NonNull TimelineModel timelineModel) { - GenericEvent issueEventModel = timelineModel.getGenericEvent(); - IssueEventType event = issueEventModel.getEvent(); - if (issueEventModel.getAssignee() != null && issueEventModel.getAssigner() != null) { - avatarLayout.setUrl(issueEventModel.getAssigner().getAvatarUrl(), issueEventModel.getAssigner().getLogin(), - false, LinkParserHelper.isEnterprise(issueEventModel.getUrl())); - } else { - if (event != IssueEventType.committed) { - avatarLayout.setVisibility(View.VISIBLE); - if (issueEventModel.getActor() != null) { - avatarLayout.setUrl(issueEventModel.getActor().getAvatarUrl(), issueEventModel.getActor().getLogin(), - false, LinkParserHelper.isEnterprise(issueEventModel.getUrl())); - } else if (issueEventModel.getAuthor() != null) { - avatarLayout.setUrl(issueEventModel.getAuthor().getAvatarUrl(), issueEventModel.getAuthor().getLogin(), - false, LinkParserHelper.isEnterprise(issueEventModel.getUrl())); - } - } else { - avatarLayout.setVisibility(View.GONE); - } - } - if (event != null) { - stateImage.setContentDescription(event.name()); - stateImage.setImageResource(event.getIconResId()); - } - if (event != null) { - stateText.setText(TimelineProvider.getStyledEvents(issueEventModel, itemView.getContext(), isMerged)); - } else { - stateText.setText(""); - stateImage.setImageResource(R.drawable.ic_label); - } - } - - @Override protected void onViewIsDetaching() { - DrawableGetter drawableGetter = (DrawableGetter) stateText.getTag(R.id.drawable_callback); - if (drawableGetter != null) { - drawableGetter.clear(drawableGetter); - } - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssuesViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssuesViewHolder.java deleted file mode 100644 index 024a80270..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/IssuesViewHolder.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatImageView; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindString; -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class IssuesViewHolder extends BaseViewHolder { - - @BindView(R.id.title) FontTextView title; - @Nullable @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.issue_state) AppCompatImageView issueState; - @BindView(R.id.details) FontTextView details; - @BindView(R.id.commentsNo) FontTextView commentsNo; - @BindString(R.string.by) String by; - - private boolean withAvatar; - private boolean showRepoName; - private boolean showState; - - private IssuesViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter, - boolean withAvatar, boolean showRepoName) { - this(itemView, adapter, withAvatar, showRepoName, false); - } - - private IssuesViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter, - boolean withAvatar, boolean showRepoName, boolean showState) { - super(itemView, adapter); - this.withAvatar = withAvatar; - this.showRepoName = showRepoName; - this.showState = showState; - } - - public static IssuesViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter, boolean withAvatar, boolean showRepoName) { - return newInstance(viewGroup, adapter, withAvatar, showRepoName, false); - } - - public static IssuesViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter, boolean withAvatar, - boolean showRepoName, boolean showState) { - if (withAvatar) { - return new IssuesViewHolder(getView(viewGroup, R.layout.issue_row_item), adapter, true, showRepoName, showState); - } else { - return new IssuesViewHolder(getView(viewGroup, R.layout.issue_no_image_row_item), adapter, false, showRepoName, showState); - } - } - - @Override public void bind(@NonNull Issue issueModel) { - title.setText(issueModel.getTitle()); - if (issueModel.getState() != null) { - CharSequence data = ParseDateFormat.getTimeAgo(issueModel.getState() == IssueState.open - ? issueModel.getCreatedAt() : issueModel.getClosedAt()); - SpannableBuilder builder = SpannableBuilder.builder(); - if (showRepoName) { - PullsIssuesParser parser = PullsIssuesParser.getForIssue(issueModel.getHtmlUrl()); - if (parser != null) builder.bold(parser.getLogin()) - .append("/") - .bold(parser.getRepoId()) - .bold("#") - .bold(String.valueOf(issueModel.getNumber())).append(" ") - .append(" "); - } - if (!showRepoName) { - if (issueModel.getState() == IssueState.closed) { - if (issueModel.getClosedBy() == null) { - builder.bold("#") - .bold(String.valueOf(issueModel.getNumber())).append(" ") - .append(" "); - } else { - builder.append("#") - .append(String.valueOf(issueModel.getNumber())).append(" ") - .append(issueModel.getClosedBy().getLogin()) - .append(" "); - } - } else { - builder.bold("#") - .bold(String.valueOf(issueModel.getNumber())).append(" ") - .append(issueModel.getUser().getLogin()) - .append(" "); - } - } - details.setText(builder - .append(itemView.getResources().getString(issueModel.getState().getStatus()).toLowerCase()) - .append(" ") - .append(data)); - if (issueModel.getComments() > 0) { - commentsNo.setText(String.valueOf(issueModel.getComments())); - commentsNo.setVisibility(View.VISIBLE); - } else { - commentsNo.setVisibility(View.GONE); - } - } - if (showState) { - issueState.setVisibility(View.VISIBLE); - issueState.setImageResource(issueModel.getState() == IssueState.open ? - R.drawable.ic_issue_opened_small : R.drawable.ic_issue_closed_small); - } else { - issueState.setVisibility(View.GONE); - } - if (withAvatar && avatarLayout != null) { - avatarLayout.setUrl(issueModel.getUser().getAvatarUrl(), issueModel.getUser().getLogin(), false, - LinkParserHelper.isEnterprise(issueModel.getUser().getHtmlUrl())); - avatarLayout.setVisibility(View.VISIBLE); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/LabelColorsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/LabelColorsViewHolder.java deleted file mode 100644 index a4e986da2..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/LabelColorsViewHolder.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.graphics.Color; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 02 Apr 2017, 5:19 PM - */ - -public class LabelColorsViewHolder extends BaseViewHolder { - - @BindView(R.id.color) FontTextView color; - - private LabelColorsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - } - - public static LabelColorsViewHolder newInstance(ViewGroup parent, BaseRecyclerAdapter adapter) { - return new LabelColorsViewHolder(getView(parent, R.layout.simple_color_row_item), adapter); - } - - @Override public void bind(@NonNull String labelModel) { - int labelColor = Color.parseColor(labelModel); - itemView.setBackgroundColor(labelColor); - color.setTextColor(ViewHelper.generateTextColor(labelColor)); - color.setText(labelModel); - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/LabelsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/LabelsViewHolder.java deleted file mode 100644 index 6f17803b5..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/LabelsViewHolder.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.graphics.Color; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatImageView; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.adapter.LabelsAdapter; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 22 Feb 2017, 7:36 PM - */ - -public class LabelsViewHolder extends BaseViewHolder { - - - @BindView(R.id.colorImage) AppCompatImageView colorImage; - @BindView(R.id.name) FontTextView name; - private LabelsAdapter.OnSelectLabel onSelectLabel; - - @Override public void onClick(View v) { - if (onSelectLabel != null) { - int position = getAdapterPosition(); - if (adapter != null) { - LabelModel labelModel = (LabelModel) adapter.getItem(position); - onSelectLabel.onToggleSelection(labelModel, !onSelectLabel.isLabelSelected(labelModel)); - } - } else { - super.onClick(v); - } - } - - private LabelsViewHolder(@NonNull View itemView, LabelsAdapter.OnSelectLabel onSelectLabel, @NonNull BaseRecyclerAdapter adapter) { - super(itemView, adapter); - this.onSelectLabel = onSelectLabel; - } - - public static LabelsViewHolder newInstance(@NonNull ViewGroup parent, @Nullable LabelsAdapter.OnSelectLabel onSelectLabel, - @NonNull BaseRecyclerAdapter adapter) { - return new LabelsViewHolder(getView(parent, R.layout.label_row_item), onSelectLabel, adapter); - } - - @Override public void bind(@NonNull LabelModel labelModel) { - name.setText(labelModel.getName()); - if (labelModel.getColor() != null) { - int color = Color.parseColor(labelModel.getColor().startsWith("#") ? labelModel.getColor() : "#" + labelModel.getColor()); - colorImage.setBackgroundColor(color); - if (onSelectLabel != null) { - if (onSelectLabel.isLabelSelected(labelModel)) { - name.setTextColor(ViewHelper.generateTextColor(color)); - } else { - name.setTextColor(ViewHelper.getPrimaryTextColor(itemView.getContext())); - } - itemView.setBackgroundColor(onSelectLabel.isLabelSelected(labelModel) ? color : 0); - } - } else { - colorImage.setBackgroundColor(0); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/LoginViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/LoginViewHolder.kt deleted file mode 100644 index 77945c825..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/LoginViewHolder.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.annotation.SuppressLint -import android.net.Uri -import android.view.View -import android.view.ViewGroup -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.model.Login -import com.fastaccess.ui.widgets.AvatarLayout -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Kosh on 09 Jul 2017, 4:54 PM - */ - -class LoginViewHolder private constructor(itemView: View, adapter: BaseRecyclerAdapter<*, *, *>?) : - BaseViewHolder(itemView, adapter) { - - val avatarLayout: AvatarLayout? by lazy { itemView.findViewById(R.id.avatarLayout) } - @BindView(R.id.title) lateinit var title: FontTextView - - @SuppressLint("SetTextI18n") - override fun bind(login: Login) { - avatarLayout?.setUrl(login.avatarUrl, null, false, false) - title.text = if (login.isIsEnterprise) { - val uri: String? = Uri.parse(login.enterpriseUrl).authority - "${login.login} ${if (uri.isNullOrBlank()) login.enterpriseUrl else uri}" - } else { - login.login - } - } - - companion object { - fun newInstance(parent: ViewGroup, adapter: BaseRecyclerAdapter<*, *, *>, small: Boolean): LoginViewHolder { - return LoginViewHolder(BaseViewHolder.getView(parent, if (small) R.layout.login_row_item_menu else R.layout.login_row_item), adapter) - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/MilestonesViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/MilestonesViewHolder.java deleted file mode 100644 index c38475a8f..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/MilestonesViewHolder.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class MilestonesViewHolder extends BaseViewHolder { - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.notificationTitle) FontTextView notificationTitle; - - private MilestonesViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - } - - public static MilestonesViewHolder newInstance(@NonNull ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter) { - return new MilestonesViewHolder(getView(viewGroup, R.layout.milestone_row_item), adapter); - } - - @Override public void bind(@NonNull MilestoneModel milestoneModel) { - title.setText(milestoneModel.getTitle()); - notificationTitle.setText(milestoneModel.getDescription()); - if (milestoneModel.getDueOn() != null) { - date.setText(ParseDateFormat.getTimeAgo(milestoneModel.getDueOn())); - } else if (milestoneModel.getCreatedAt() != null) { - date.setText(ParseDateFormat.getTimeAgo(milestoneModel.getCreatedAt())); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/NotificationsHeaderViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/NotificationsHeaderViewHolder.java deleted file mode 100644 index d92b40c6f..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/NotificationsHeaderViewHolder.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatImageButton; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.GroupedNotificationModel; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class NotificationsHeaderViewHolder extends BaseViewHolder { - - @Nullable @BindView(R.id.headerTitle) FontTextView headerTitle; - @BindView(R.id.markAsRead) AppCompatImageButton markAsRead; - - private NotificationsHeaderViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - markAsRead.setOnClickListener(this); - } - - public static NotificationsHeaderViewHolder newInstance(@NonNull ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter) { - return new NotificationsHeaderViewHolder(getView(viewGroup, R.layout.notification_header_row_item), adapter); - } - - @Override public void bind(@NonNull GroupedNotificationModel model) { - Repo repo = model.getRepo(); - if (repo != null && headerTitle != null) { - headerTitle.setText(repo.getFullName()); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/NotificationsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/NotificationsViewHolder.java deleted file mode 100644 index f4db564b0..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/NotificationsViewHolder.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.CardView; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.GroupedNotificationModel; -import com.fastaccess.data.dao.model.Notification; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class NotificationsViewHolder extends BaseViewHolder { - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.unsubsribe) ForegroundImageView unSubscribe; - @BindView(R.id.markAsRead) ForegroundImageView markAsRead; - @BindView(R.id.notificationType) ForegroundImageView notificationType; - @BindView(R.id.repoName) FontTextView repoName; - private boolean showUnreadState; - - private NotificationsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter, boolean showUnreadState) { - super(itemView, adapter); - unSubscribe.setOnClickListener(this); - markAsRead.setOnClickListener(this); - this.showUnreadState = showUnreadState; - } - - public static NotificationsViewHolder newInstance(@NonNull ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter, boolean showUnreadState) { - return new NotificationsViewHolder(getView(viewGroup, R.layout.notifications_row_item), adapter, showUnreadState); - } - - @Override public void bind(@NonNull GroupedNotificationModel model) { - Notification thread = model.getNotification(); - if (thread != null && thread.getSubject() != null) { - title.setText(thread.getSubject().getTitle()); - int cardBackground = ViewHelper.getCardBackground(itemView.getContext()); - int color; - date.setText(ParseDateFormat.getTimeAgo(thread.getUpdatedAt())); - markAsRead.setVisibility(thread.isUnread() ? View.VISIBLE : View.GONE); -// unSubscribe.setImageResource(thread.isIsSubscribed() ? R.drawable.ic_unsubscribe : R.drawable.ic_subscribe); - if (thread.getSubject().getType() != null) { - notificationType.setImageResource(thread.getSubject().getType().getDrawableRes()); - notificationType.setContentDescription(thread.getSubject().getType().name()); - } else { - notificationType.setImageResource(R.drawable.ic_info_outline); - } - if (showUnreadState) { - repoName.setVisibility(View.GONE); - if (AppHelper.isNightMode(itemView.getResources())) { - color = ContextCompat.getColor(itemView.getContext(), R.color.material_blue_grey_800); - } else { - color = ContextCompat.getColor(itemView.getContext(), R.color.material_blue_grey_200); - } - ((CardView) itemView).setCardBackgroundColor(thread.isUnread() ? color : cardBackground); - } else { - repoName.setVisibility(View.VISIBLE); - repoName.setText(thread.getRepository().getFullName()); - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PinnedReposViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PinnedReposViewHolder.java deleted file mode 100644 index 35adb8b51..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PinnedReposViewHolder.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.graphics.Color; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.PinnedRepos; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.provider.colors.ColorsProvider; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.LabelSpan; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.text.NumberFormat; - -import butterknife.BindColor; -import butterknife.BindString; -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class PinnedReposViewHolder extends BaseViewHolder { - - @BindView(R.id.title) FontTextView title; - @Nullable @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @Nullable @BindView(R.id.date) FontTextView date; - @Nullable @BindView(R.id.stars) FontTextView stars; - @Nullable @BindView(R.id.forks) FontTextView forks; - @Nullable @BindView(R.id.language) FontTextView language; - @BindString(R.string.forked) String forked; - @BindString(R.string.private_repo) String privateRepo; - @BindColor(R.color.material_indigo_700) int forkColor; - @BindColor(R.color.material_grey_700) int privateColor; - - private PinnedReposViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - } - - public static PinnedReposViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter, boolean singleLine) { - return new PinnedReposViewHolder(getView(viewGroup, - singleLine ? R.layout.repos_row_item_menu : R.layout.repos_row_item), adapter); - } - - @Override public void bind(@NonNull PinnedRepos pinnedRepos) { - Repo repo = pinnedRepos.getPinnedRepo(); - if (repo == null) return; - if (repo.isFork()) { - title.setText(SpannableBuilder.builder() - .append(" " + forked + " ", new LabelSpan(forkColor)) - .append(" ") - .append(repo.getName(), new LabelSpan(Color.TRANSPARENT))); - } else if (repo.isPrivateX()) { - title.setText(SpannableBuilder.builder() - .append(" " + privateRepo + " ", new LabelSpan(privateColor)) - .append(" ") - .append(repo.getName(), new LabelSpan(Color.TRANSPARENT))); - } else { - title.setText(repo.getFullName()); - } - String avatar = repo.getOwner() != null ? repo.getOwner().getAvatarUrl() : null; - String login = repo.getOwner() != null ? repo.getOwner().getLogin() : null; - boolean isOrg = repo.getOwner() != null && repo.getOwner().isOrganizationType(); - if (avatarLayout != null) { - avatarLayout.setVisibility(View.VISIBLE); - avatarLayout.setUrl(avatar, login, isOrg, LinkParserHelper.isEnterprise(repo.getHtmlUrl())); - } - if (stars != null && forks != null && date != null && language != null) { - NumberFormat numberFormat = NumberFormat.getNumberInstance(); - stars.setText(numberFormat.format(repo.getStargazersCount())); - forks.setText(numberFormat.format(repo.getForks())); - date.setText(ParseDateFormat.getTimeAgo(repo.getUpdatedAt())); - if (!InputHelper.isEmpty(repo.getLanguage())) { - language.setText(repo.getLanguage()); - language.setTextColor(ColorsProvider.getColorAsColor(repo.getLanguage(), language.getContext())); - language.setVisibility(View.VISIBLE); - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfileOrgsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfileOrgsViewHolder.java deleted file mode 100644 index ab58f0733..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfileOrgsViewHolder.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 21 May 2017, 12:27 PM - */ - -public class ProfileOrgsViewHolder extends BaseViewHolder { - - @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.name) FontTextView name; - - @Override public void onClick(View v) { - avatarLayout.callOnClick(); - } - - private ProfileOrgsViewHolder(@NonNull View itemView) { - super(itemView); - } - - public static ProfileOrgsViewHolder newInstance(@NonNull ViewGroup parent) { - return new ProfileOrgsViewHolder(getView(parent, R.layout.profile_org_row_item)); - } - - @Override public void bind(@NonNull User user) { - name.setText(user.getLogin()); - avatarLayout.setUrl(user.getAvatarUrl(), user.getLogin(), true, LinkParserHelper.isEnterprise(user.getUrl())); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt deleted file mode 100644 index e050efcb3..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProfilePinnedReposViewHolder.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.graphics.Color -import android.view.View -import android.view.ViewGroup -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder -import github.GetPinnedReposQuery -import java.text.NumberFormat - -/** - * Created by kosh on 09/08/2017. - */ -class ProfilePinnedReposViewHolder private constructor(view: View, adapter: BaseRecyclerAdapter<*, *, *>) : - BaseViewHolder(view, adapter) { - - @BindView(R.id.title) lateinit var title: FontTextView - @BindView(R.id.issues) lateinit var issues: FontTextView - @BindView(R.id.pullRequests) lateinit var pullRequest: FontTextView - @BindView(R.id.language) lateinit var language: FontTextView - @BindView(R.id.stars) lateinit var stars: FontTextView - @BindView(R.id.forks) lateinit var forks: FontTextView - - override fun bind(t: GetPinnedReposQuery.Node) {} - - fun bind(t: GetPinnedReposQuery.Node, numberFormat: NumberFormat) { - title.text = t.name() - issues.text = numberFormat.format(t.issues().totalCount()) - pullRequest.text = numberFormat.format(t.pullRequests().totalCount()) - forks.text = numberFormat.format(t.forks().totalCount()) - stars.text = numberFormat.format(t.stargazers().totalCount()) - t.primaryLanguage()?.let { - language.text = it.name() - it.color()?.let { - if (it.startsWith("#")) { - language.tintDrawables(Color.parseColor(it)) - } else { - val color = "#$it" - language.tintDrawables(Color.parseColor(color)) - } - } - } - } - - companion object { - fun newInstance(parent: ViewGroup, adapter: BaseRecyclerAdapter<*, *, *>): ProfilePinnedReposViewHolder { - return ProfilePinnedReposViewHolder(getView(parent, R.layout.profile_pinned_repo_row_item), adapter) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProjectViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProjectViewHolder.kt deleted file mode 100644 index 5a3a8f090..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ProjectViewHolder.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.view.View -import android.view.ViewGroup -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.helper.ParseDateFormat -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder -import github.RepoProjectsOpenQuery - -/** - * Created by kosh on 09/09/2017. - */ -class ProjectViewHolder(view: View, adapter: BaseRecyclerAdapter<*, *, *>) : BaseViewHolder(view, adapter) { - - @BindView(R.id.description) lateinit var description: FontTextView - @BindView(R.id.title) lateinit var title: FontTextView - @BindView(R.id.date) lateinit var date: FontTextView - - override fun bind(t: RepoProjectsOpenQuery.Node) { - title.text = t.name() - if (t.body().isNullOrBlank()) { - description.visibility = View.GONE - } else { - description.visibility = View.VISIBLE - description.text = t.body() - } - date.text = ParseDateFormat.getTimeAgo(t.createdAt().toString()) - } - - companion object { - fun newInstance(parent: ViewGroup, adapter: BaseRecyclerAdapter<*, *, *>): ProjectViewHolder { - return ProjectViewHolder(getView(parent, R.layout.feeds_row_no_image_item), adapter) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestEventViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestEventViewHolder.kt deleted file mode 100644 index 2d114306d..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestEventViewHolder.kt +++ /dev/null @@ -1,414 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.annotation.SuppressLint -import android.graphics.Color -import android.support.v4.content.ContextCompat -import android.text.style.BackgroundColorSpan -import android.view.View -import android.view.ViewGroup -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.timeline.PullRequestTimelineModel -import com.fastaccess.helper.ParseDateFormat -import com.fastaccess.helper.PrefGetter -import com.fastaccess.helper.ViewHelper -import com.fastaccess.provider.scheme.LinkParserHelper -import com.fastaccess.provider.timeline.HtmlHelper -import com.fastaccess.ui.widgets.AvatarLayout -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.ForegroundImageView -import com.fastaccess.ui.widgets.SpannableBuilder -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder -import com.zzhoujay.markdown.style.CodeSpan -import github.PullRequestTimelineQuery -import github.type.StatusState - -/** - * Created by kosh on 03/08/2017. - */ - -class PullRequestEventViewHolder private constructor(view: View, adapter: BaseRecyclerAdapter<*, *, *>) : - BaseViewHolder(view, adapter) { - - @BindView(R.id.stateImage) lateinit var stateImage: ForegroundImageView - @BindView(R.id.avatarLayout) lateinit var avatarLayout: AvatarLayout - @BindView(R.id.stateText) lateinit var stateText: FontTextView - @BindView(R.id.commitStatus) lateinit var commitStatus: ForegroundImageView - - override fun bind(t: PullRequestTimelineModel) { - val node = t.node - commitStatus.visibility = View.GONE - if (node != null) { - when { - node.asAssignedEvent() != null -> assignedEvent(node.asAssignedEvent()!!) - node.asBaseRefForcePushedEvent() != null -> forcePushEvent(node.asBaseRefForcePushedEvent()!!) - node.asClosedEvent() != null -> closedEvent(node.asClosedEvent()!!) - node.asCommit() != null -> commitEvent(node.asCommit()!!) - node.asDemilestonedEvent() != null -> demilestonedEvent(node.asDemilestonedEvent()!!) - node.asDeployedEvent() != null -> deployedEvent(node.asDeployedEvent()!!) - node.asHeadRefDeletedEvent() != null -> refDeletedEvent(node.asHeadRefDeletedEvent()!!) - node.asHeadRefForcePushedEvent() != null -> refForPushedEvent(node.asHeadRefForcePushedEvent()!!) - node.asHeadRefRestoredEvent() != null -> headRefRestoredEvent(node.asHeadRefRestoredEvent()!!) - node.asLabeledEvent() != null -> labeledEvent(node.asLabeledEvent()!!) - node.asLockedEvent() != null -> lockEvent(node.asLockedEvent()!!) - node.asMergedEvent() != null -> mergedEvent(node.asMergedEvent()!!) - node.asMilestonedEvent() != null -> milestoneEvent(node.asMilestonedEvent()!!) - node.asReferencedEvent() != null -> referenceEvent(node.asReferencedEvent()!!) - node.asRenamedTitleEvent() != null -> renamedEvent(node.asRenamedTitleEvent()!!) - node.asReopenedEvent() != null -> reopenedEvent(node.asReopenedEvent()!!) - node.asUnassignedEvent() != null -> unassignedEvent(node.asUnassignedEvent()!!) - node.asUnlabeledEvent() != null -> unlabeledEvent(node.asUnlabeledEvent()!!) - node.asUnlockedEvent() != null -> unlockedEvent(node.asUnlockedEvent()!!) - else -> reset() - } - } else { - reset() - } - } - - private fun reset() { - stateText.text = "" - avatarLayout.setUrl(null, null, false, false) - } - - @SuppressLint("SetTextI18n") - private fun unlockedEvent(event: PullRequestTimelineQuery.AsUnlockedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("unlocked this conversation") - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_lock) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun unlabeledEvent(event: PullRequestTimelineQuery.AsUnlabeledEvent) { - event.actor()?.let { - val color = Color.parseColor("#" + event.label().color()) - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("removed") - .append(" ") - .append(event.label().name(), CodeSpan(color, ViewHelper.generateTextColor(color), 5.0f)) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_label) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun unassignedEvent(event: PullRequestTimelineQuery.AsUnassignedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("unassigned") //TODO add "removed their assignment" for self - .append(" ") - .append(event.user()?.login()) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_profile) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun reopenedEvent(event: PullRequestTimelineQuery.AsReopenedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("reopened this") - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_issue_opened) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun renamedEvent(event: PullRequestTimelineQuery.AsRenamedTitleEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("changed the title from").append(" ").append(event.previousTitle()) - .append(" ").append("to").append(" ").bold(event.currentTitle()) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_edit) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun referenceEvent(event: PullRequestTimelineQuery.AsReferencedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("referenced in") - .append(" ") - .append("from").append(" ") - .url(if (event.commit() != null) { - substring(event.commit()?.oid()?.toString()) - } else if (event.subject().asIssue() != null) { - if (event.isCrossRepository) { - "${event.commitRepository().nameWithOwner()} ${event.subject().asIssue()?.title()}#${event.subject().asIssue()?.number()}" - } else { - "${event.subject().asIssue()?.title()}#${event.subject().asIssue()?.number()}" - } - } else if (event.subject().asPullRequest() != null) { - if (event.isCrossRepository) { - "${event.commitRepository().nameWithOwner()} ${event.subject().asPullRequest()?.title()}" + - "#${event.subject().asPullRequest()?.number()}" - } else { - "${event.subject().asPullRequest()?.title()}#${event.subject().asPullRequest()?.number()}" - } - } else { - event.commitRepository().nameWithOwner() - }) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_push) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun milestoneEvent(event: PullRequestTimelineQuery.AsMilestonedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("added this to the") - .append(" ") - .append(event.milestoneTitle()).append(" ").append("milestone") - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_milestone) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun mergedEvent(event: PullRequestTimelineQuery.AsMergedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("merged commit") - .append(" ") - .url(substring(event.commit()?.oid()?.toString())) - .append(" ") - .append("into") - .append(" ") - .append(event.actor()) - .append(":") - .append(event.mergeRefName(), BackgroundColorSpan(HtmlHelper.getWindowBackground(PrefGetter.getThemeType()))) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_merge) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun lockEvent(event: PullRequestTimelineQuery.AsLockedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("locked and limited conversation to collaborators") - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_lock) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun labeledEvent(event: PullRequestTimelineQuery.AsLabeledEvent) { - event.actor()?.let { - val color = Color.parseColor("#" + event.label().color()) - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("labeled") - .append(" ") - .append(event.label().name(), CodeSpan(color, ViewHelper.generateTextColor(color), 5.0f)) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_label) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun headRefRestoredEvent(event: PullRequestTimelineQuery.AsHeadRefRestoredEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("restored the") - .append(" ") - .append(it.login()) - .append(":") - .append(event.pullRequest().headRefName(), BackgroundColorSpan(HtmlHelper.getWindowBackground(PrefGetter.getThemeType()))) - .append(" ") - .append("branch") - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_push) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun refForPushedEvent(event: PullRequestTimelineQuery.AsHeadRefForcePushedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("reference force pushed to", BackgroundColorSpan(HtmlHelper.getWindowBackground(PrefGetter.getThemeType()))) - .append(" ") - .url(substring(event.afterCommit().oid().toString())) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_push) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun refDeletedEvent(event: PullRequestTimelineQuery.AsHeadRefDeletedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("deleted the") - .append(" ") - .append(it.login()) - .append(":") - .append(substring(event.headRefName()), BackgroundColorSpan(HtmlHelper.getWindowBackground(PrefGetter.getThemeType()))) - .append(" ") - .append("branch") - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_trash) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun deployedEvent(event: PullRequestTimelineQuery.AsDeployedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("made a deployment", BackgroundColorSpan(HtmlHelper.getWindowBackground(PrefGetter.getThemeType()))) - .append(" ") - .append(event.deployment().latestStatus()?.state()?.name) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_push) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun demilestonedEvent(event: PullRequestTimelineQuery.AsDemilestonedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("removed this from the") - .append(" ") - .append(event.milestoneTitle()).append(" ").append("milestone") - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_milestone) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun commitEvent(event: PullRequestTimelineQuery.AsCommit) { - event.author()?.let { - stateText.text = SpannableBuilder.builder()//Review[k0shk0sh] We may want to suppress more then 3 or 4 commits. since it will clog the it - .bold(if (it.user() == null) it.name() else it.user()?.login()) - .append(" ") - .append("committed") - .append(" ") - .append(event.messageHeadline()) - .append(" ") - .url(substring(event.oid().toString())) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.committedDate().toString()))) - stateImage.setImageResource(R.drawable.ic_push) - avatarLayout.setUrl(it.user()?.avatarUrl().toString(), it.user()?.login(), false, - LinkParserHelper.isEnterprise(it.user()?.url().toString())) - event.status()?.let { - commitStatus.visibility = View.VISIBLE - val context = commitStatus.context - commitStatus.tintDrawableColor(when (it.state()) { - StatusState.ERROR -> ContextCompat.getColor(context, R.color.material_red_700) - StatusState.FAILURE -> ContextCompat.getColor(context, R.color.material_deep_orange_700) - StatusState.SUCCESS -> ContextCompat.getColor(context, R.color.material_green_700) - else -> ContextCompat.getColor(context, R.color.material_yellow_700) - }) - } - } - } - - private fun closedEvent(event: PullRequestTimelineQuery.AsClosedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("closed this in") - .append(" ") - .url(substring(event.commit()?.oid()?.toString())) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_merge) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun forcePushEvent(event: PullRequestTimelineQuery.AsBaseRefForcePushedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("force pushed to", BackgroundColorSpan(HtmlHelper.getWindowBackground(PrefGetter.getThemeType()))) - .append(" ") - .url(substring(event.afterCommit().oid().toString())) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_push) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun assignedEvent(event: PullRequestTimelineQuery.AsAssignedEvent) { - event.actor()?.let { - stateText.text = SpannableBuilder.builder() - .bold(it.login()) - .append(" ") - .append("assigned") //TODO add "self-assigned" for self - .append(" ") - .append(event.user()?.login()) - .append(" ") - .append(ParseDateFormat.getTimeAgo((event.createdAt().toString()))) - stateImage.setImageResource(R.drawable.ic_profile) - avatarLayout.setUrl(it.avatarUrl().toString(), it.login(), false, LinkParserHelper.isEnterprise(it.url().toString())) - } - } - - private fun substring(value: String?): String { - if (value == null) { - return "" - } - return if (value.length <= 7) value - else value.substring(0, 7) - } - - companion object { - fun newInstance(parent: ViewGroup, adapter: BaseRecyclerAdapter<*, *, *>): PullRequestEventViewHolder { - return PullRequestEventViewHolder(getView(parent, R.layout.issue_timeline_row_item), adapter) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestFilesViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestFilesViewHolder.java deleted file mode 100644 index fbf8b7cc1..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestFilesViewHolder.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.CommitFileChanges; -import com.fastaccess.data.dao.CommitFileModel; -import com.fastaccess.data.dao.CommitLinesModel; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.ui.adapter.CommitLinesAdapter; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files.PullRequestFilesMvp; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; - -import butterknife.BindString; -import butterknife.BindView; -import es.dmoral.toasty.Toasty; - -/** - * Created by Kosh on 15 Feb 2017, 10:29 PM - */ - -public class PullRequestFilesViewHolder extends BaseViewHolder implements - BaseViewHolder.OnItemClickListener { - - @BindView(R.id.name) FontTextView name; - @BindView(R.id.patchList) DynamicRecyclerView patch; - @BindView(R.id.changes) FontTextView changes; - @BindView(R.id.addition) FontTextView addition; - @BindView(R.id.deletion) FontTextView deletion; - @BindView(R.id.status) FontTextView status; - @BindView(R.id.toggle) View toggle; - @BindView(R.id.open) View open; - @BindString(R.string.changes) String changesText; - @BindString(R.string.addition) String additionText; - @BindString(R.string.deletion) String deletionText; - @BindString(R.string.status) String statusText; - private OnToggleView onToggleView; - private ViewGroup viewGroup; - @Nullable private PullRequestFilesMvp.OnPatchClickListener onPatchClickListener; - - @Override public void onClick(View v) { - if (v.getId() != R.id.open) { - int position = getAdapterPosition(); - onToggleView.onToggle(position, !onToggleView.isCollapsed(position)); - onToggle(onToggleView.isCollapsed(position), true, position); - } else { - super.onClick(v); - } - } - - private PullRequestFilesViewHolder(@NonNull View itemView, @NonNull ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter, - @NonNull OnToggleView onToggleView, @Nullable PullRequestFilesMvp.OnPatchClickListener onPatchClickListener) { - super(itemView, adapter); - this.viewGroup = viewGroup; - this.onToggleView = onToggleView; - this.onPatchClickListener = onPatchClickListener; - open.setOnClickListener(this); - patch.setNestedScrollingEnabled(false); - } - - public static PullRequestFilesViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter, - @NonNull OnToggleView onToggleView, - @Nullable PullRequestFilesMvp.OnPatchClickListener onPatchClickListener) { - return new PullRequestFilesViewHolder(getView(viewGroup, R.layout.pullrequest_file_row_item), viewGroup, adapter, - onToggleView, onPatchClickListener); - } - - @Override public void bind(@NonNull CommitFileChanges commitFileChanges) { - CommitFileModel commit = commitFileChanges.getCommitFileModel(); - toggle.setVisibility(commit.getPatch() == null ? View.GONE : View.VISIBLE); - name.setText(commit.getFilename()); - changes.setText(SpannableBuilder.builder() - .append(changesText) - .append("\n") - .bold(String.valueOf(commit.getChanges()))); - addition.setText(SpannableBuilder.builder() - .append(additionText) - .append("\n") - .bold(String.valueOf(commit.getAdditions()))); - deletion.setText(SpannableBuilder.builder() - .append(deletionText) - .append("\n") - .bold(String.valueOf(commit.getDeletions()))); - status.setText(SpannableBuilder.builder() - .append(statusText) - .append("\n") - .bold(String.valueOf(commit.getStatus()))); - int position = getAdapterPosition(); - onToggle(onToggleView.isCollapsed(position), false, position); - } - - private void onToggle(boolean expanded, boolean animate, int position) { - if (!expanded) { - patch.swapAdapter(null, true); - patch.setVisibility(View.GONE); - name.setMaxLines(2); - toggle.setRotation(0.0f); - } else { - if (adapter != null) { - CommitFileChanges model = (CommitFileChanges) adapter.getItem(position); - if (model.getLinesModel() != null && !model.getLinesModel().isEmpty()) { - if (model.getLinesModel().size() <= 100) { - patch.setAdapter(new CommitLinesAdapter(model.getLinesModel(), this)); - patch.setVisibility(View.VISIBLE); - } else if (CommitFileChanges.canAttachToBundle(model)) { - if (adapter.getListener() != null) { - //noinspection unchecked - adapter.getListener().onItemClick(position, patch, model); - } - } else { - Toasty.warning(itemView.getContext(), itemView.getResources().getString(R.string.too_large_changes)).show(); - return; - } - } else { - patch.swapAdapter(null, true); - patch.setVisibility(View.GONE); - } - } - name.setMaxLines(5); - toggle.setRotation(180f); - } - } - - @Override public void onItemClick(int position, View v, CommitLinesModel item) { - if (onPatchClickListener != null && adapter != null) { - int groupPosition = getAdapterPosition(); - CommitFileChanges commitFileChanges = (CommitFileChanges) adapter.getItem(groupPosition); - onPatchClickListener.onPatchClicked(groupPosition, position, v, commitFileChanges.getCommitFileModel(), item); - } - } - - @Override public void onItemLongClick(int position, View v, CommitLinesModel item) { - if (adapter == null) return; - int groupPosition = getAdapterPosition(); - CommitFileChanges commitFileChanges = (CommitFileChanges) adapter.getItem(groupPosition); - int lineNo = item.getLeftLineNo() > 0 ? item.getLeftLineNo() : item.getRightLineNo(); - String url = commitFileChanges.getCommitFileModel().getBlobUrl() + "#L" + lineNo; - AppHelper.copyToClipboard(v.getContext(), url); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestViewHolder.java deleted file mode 100644 index 7898539a3..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullRequestViewHolder.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindString; -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class PullRequestViewHolder extends BaseViewHolder { - - @BindView(R.id.title) FontTextView title; - @Nullable @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.details) FontTextView details; - @BindView(R.id.commentsNo) FontTextView commentsNo; - @BindString(R.string.by) String by; - private boolean withAvatar; - private boolean showRepoName; - - private PullRequestViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter, boolean withAvatar, boolean showRepoName) { - super(itemView, adapter); - this.withAvatar = withAvatar; - this.showRepoName = showRepoName; - } - - public static PullRequestViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter, boolean withAvatar, - boolean showRepoName) { - if (withAvatar) { - return new PullRequestViewHolder(getView(viewGroup, R.layout.issue_row_item), adapter, true, showRepoName); - } - return new PullRequestViewHolder(getView(viewGroup, R.layout.issue_no_image_row_item), adapter, false, showRepoName); - } - - @Override public void bind(@NonNull PullRequest pullRequest) { - title.setText(pullRequest.getTitle()); - details.setText(PullRequest.getMergeBy(pullRequest, details.getContext(), showRepoName)); - if (pullRequest.getComments() > 0) { - commentsNo.setText(String.valueOf(pullRequest.getComments())); - commentsNo.setVisibility(View.VISIBLE); - } else { - commentsNo.setVisibility(View.GONE); - } - if (withAvatar && avatarLayout != null) { - avatarLayout.setUrl(pullRequest.getUser().getAvatarUrl(), pullRequest.getUser().getLogin(), - false, LinkParserHelper.isEnterprise(pullRequest.getHtmlUrl())); - avatarLayout.setVisibility(View.VISIBLE); - } - } - - -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullStatusViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullStatusViewHolder.java deleted file mode 100644 index 480dfa3db..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/PullStatusViewHolder.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.v4.content.ContextCompat; -import android.text.method.LinkMovementMethod; -import android.view.View; -import android.view.ViewGroup; - -import com.annimon.stream.Stream; -import com.fastaccess.R; -import com.fastaccess.data.dao.PullRequestStatusModel; -import com.fastaccess.data.dao.types.StatusStateType; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindColor; -import butterknife.BindView; - -/** - * Created by Kosh on 10 Apr 2017, 3:40 AM - */ - -public class PullStatusViewHolder extends BaseViewHolder { - - @BindView(R.id.stateImage) ForegroundImageView stateImage; - @BindView(R.id.status) FontTextView status; - @BindView(R.id.statuses) FontTextView statuses; - @BindColor(R.color.material_green_700) int green; - @BindColor(R.color.material_red_700) int red; - @BindColor(R.color.material_indigo_700) int indigo; - - private PullStatusViewHolder(@NonNull View itemView) { - super(itemView); - itemView.setOnClickListener(null); - itemView.setOnLongClickListener(null); - } - - public static PullStatusViewHolder newInstance(@NonNull ViewGroup parent) { - return new PullStatusViewHolder(getView(parent, R.layout.pull_status_row_item)); - } - - @Override public void bind(@NonNull PullRequestStatusModel pullRequestStatusModel) { - if (pullRequestStatusModel.getState() != null) { - StatusStateType stateType = pullRequestStatusModel.getState(); - stateImage.setImageResource(stateType.getDrawableRes()); - String mergeableState = pullRequestStatusModel.getMergeableState(); - boolean isBlocked = "blocked".equalsIgnoreCase(mergeableState); - if (stateType == StatusStateType.failure) { - stateImage.tintDrawableColor(red); - if (pullRequestStatusModel.isMergable()) { - status.setText(R.string.checks_failed); - } else { - status.setText(SpannableBuilder.builder() - .append(status.getResources().getString(R.string.checks_failed)) - .append("\n") - .append(status.getResources().getString(R.string.can_not_merge_pr))); - } - } else if (stateType == StatusStateType.pending) { - if (pullRequestStatusModel.isMergable()) { - stateImage.setImageResource(R.drawable.ic_check_small); - stateImage.tintDrawableColor(green); - status.setText(!isBlocked ? R.string.commit_can_be_merged : R.string.can_not_merge_pr); - } else { - stateImage.setImageResource(stateType.getDrawableRes()); - stateImage.tintDrawableColor(indigo); - status.setText(R.string.checks_pending); - } - } else { - stateImage.tintDrawableColor(green); - if (pullRequestStatusModel.isMergable()) { - status.setText(!isBlocked ? R.string.commit_can_be_merged : R.string.can_not_merge_pr); - } else { - status.setText(R.string.checks_passed); - } - } - } - if (pullRequestStatusModel.getStatuses() != null && !pullRequestStatusModel.getStatuses().isEmpty()) { - SpannableBuilder builder = SpannableBuilder.builder(); - Stream.of(pullRequestStatusModel.getStatuses()) - .filter(statusesModel -> statusesModel != null && statusesModel.getState() != null && statusesModel.getTargetUrl() != null) - .forEach(statusesModel -> { - if (!InputHelper.isEmpty(statusesModel.getTargetUrl())) { - builder.append(ContextCompat.getDrawable(statuses.getContext(), statusesModel.getState().getDrawableRes())); - builder.append(" ") - .append(statusesModel.getContext() != null ? statusesModel.getContext() + " " : "") - .url(statusesModel.getDescription(), v -> SchemeParser.launchUri(v.getContext(), statusesModel.getTargetUrl())) - .append("\n"); - } - }); - if (!InputHelper.isEmpty(builder)) { - statuses.setMovementMethod(LinkMovementMethod.getInstance()); - statuses.setText(builder); - statuses.setVisibility(View.VISIBLE); - } else { - statuses.setVisibility(View.GONE); - } - } else { - statuses.setVisibility(View.GONE); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReleasesViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReleasesViewHolder.java deleted file mode 100644 index 7dbf3e88c..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReleasesViewHolder.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Release; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindString; -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class ReleasesViewHolder extends BaseViewHolder { - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.details) FontTextView details; - @BindView(R.id.download) ForegroundImageView download; - @BindString(R.string.released) String released; - @BindString(R.string.drafted) String drafted; - - private ReleasesViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - download.setOnClickListener(this); - download.setOnLongClickListener(this); - } - - public static ReleasesViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter) { - return new ReleasesViewHolder(getView(viewGroup, R.layout.releases_row_item), adapter); - } - - @Override public void bind(@NonNull Release item) { - title.setText(SpannableBuilder.builder().bold(!InputHelper.isEmpty(item.getName()) ? item.getName() : item.getTagName())); - if (item.getAuthor() != null) { - details.setText(SpannableBuilder.builder() - .append(item.getAuthor().getLogin()) - .append(" ") - .append(item.isDraft() ? drafted : released) - .append(" ") - .append(ParseDateFormat.getTimeAgo(item.getCreatedAt()))); - } else { - details.setVisibility(View.GONE); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/RepoFilePathsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/RepoFilePathsViewHolder.java deleted file mode 100644 index 258c6d3bb..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/RepoFilePathsViewHolder.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.RepoFile; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 18 Feb 2017, 2:53 AM - */ - -public class RepoFilePathsViewHolder extends BaseViewHolder { - - @BindView(R.id.pathName) FontTextView pathName; - - private RepoFilePathsViewHolder(@NonNull View itemView, @NonNull BaseRecyclerAdapter baseAdapter) { - super(itemView, baseAdapter); - } - - public static RepoFilePathsViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter) { - return new RepoFilePathsViewHolder(getView(viewGroup, R.layout.file_path_row_item), adapter); - } - - @Override public void bind(@NonNull RepoFile filesModel) { - pathName.setText(filesModel.getName()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/RepoFilesViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/RepoFilesViewHolder.java deleted file mode 100644 index 222686783..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/RepoFilesViewHolder.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.text.format.Formatter; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.RepoFile; -import com.fastaccess.data.dao.types.FilesType; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindString; -import butterknife.BindView; - -/** - * Created by Kosh on 15 Feb 2017, 10:29 PM - */ - -public class RepoFilesViewHolder extends BaseViewHolder { - - @BindView(R.id.contentTypeImage) ForegroundImageView contentTypeImage; - @BindView(R.id.title) FontTextView title; - @BindView(R.id.size) FontTextView size; - @BindView(R.id.menu) ForegroundImageView menu; - @BindString(R.string.file) String file; - - @Override public void onClick(View v) { - if (v.getId() == R.id.contentTypeImage) { - itemView.callOnClick(); - } else { - super.onClick(v); - } - } - - private RepoFilesViewHolder(@NonNull View itemView, @NonNull BaseRecyclerAdapter adapter) { - super(itemView, adapter); - menu.setOnClickListener(this); - contentTypeImage.setOnClickListener(this); - } - - public static RepoFilesViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter) { - return new RepoFilesViewHolder(getView(viewGroup, R.layout.repo_files_row_item), adapter); - } - - @Override public void bind(@NonNull RepoFile filesModel) { - contentTypeImage.setContentDescription(String.format("%s %s", filesModel.getName(), file)); - title.setText(filesModel.getName()); - if (filesModel.getType() != null && filesModel.getType().getIcon() != 0) { - contentTypeImage.setImageResource(filesModel.getType().getIcon()); - if (filesModel.getType() == FilesType.file) { - size.setText(Formatter.formatFileSize(size.getContext(), filesModel.getSize())); - size.setVisibility(View.VISIBLE); - } else { - size.setVisibility(View.GONE); - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReposViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReposViewHolder.java deleted file mode 100644 index f849b29fc..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReposViewHolder.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.graphics.Color; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.format.Formatter; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.provider.colors.ColorsProvider; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.LabelSpan; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.text.NumberFormat; - -import butterknife.BindColor; -import butterknife.BindString; -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class ReposViewHolder extends BaseViewHolder { - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.stars) FontTextView stars; - @BindView(R.id.forks) FontTextView forks; - @BindView(R.id.language) FontTextView language; - @BindView(R.id.size) FontTextView size; - @Nullable @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindString(R.string.forked) String forked; - @BindString(R.string.private_repo) String privateRepo; - @BindColor(R.color.material_indigo_700) int forkColor; - @BindColor(R.color.material_grey_700) int privateColor; - private boolean isStarred; - private boolean withImage; - - private ReposViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter, boolean isStarred, boolean withImage) { - super(itemView, adapter); - this.isStarred = isStarred; - this.withImage = withImage; - } - - public static ReposViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter, boolean isStarred, boolean withImage) { - if (withImage) { - return new ReposViewHolder(getView(viewGroup, R.layout.repos_row_item), adapter, isStarred, true); - } else { - return new ReposViewHolder(getView(viewGroup, R.layout.repos_row_no_image_item), adapter, isStarred, false); - } - - } - - @Override public void bind(@NonNull Repo repo) { - if (repo.isFork() && !isStarred) { - title.setText(SpannableBuilder.builder() - .append(" " + forked + " ", new LabelSpan(forkColor)) - .append(" ") - .append(repo.getName(), new LabelSpan(Color.TRANSPARENT))); - } else if (repo.isPrivateX()) { - title.setText(SpannableBuilder.builder() - .append(" " + privateRepo + " ", new LabelSpan(privateColor)) - .append(" ") - .append(repo.getName(), new LabelSpan(Color.TRANSPARENT))); - } else { - title.setText(!isStarred ? repo.getName() : repo.getFullName()); - } - if (withImage) { - String avatar = repo.getOwner() != null ? repo.getOwner().getAvatarUrl() : null; - String login = repo.getOwner() != null ? repo.getOwner().getLogin() : null; - boolean isOrg = repo.getOwner() != null && repo.getOwner().isOrganizationType(); - if (avatarLayout != null) { - avatarLayout.setVisibility(View.VISIBLE); - avatarLayout.setUrl(avatar, login, isOrg, LinkParserHelper.isEnterprise(repo.getHtmlUrl())); - } - } - long repoSize = repo.getSize() > 0 ? (repo.getSize() * 1000) : repo.getSize(); - size.setText(Formatter.formatFileSize(size.getContext(), repoSize)); - NumberFormat numberFormat = NumberFormat.getNumberInstance(); - stars.setText(numberFormat.format(repo.getStargazersCount())); - forks.setText(numberFormat.format(repo.getForks())); - date.setText(ParseDateFormat.getTimeAgo(repo.getUpdatedAt())); - if (!InputHelper.isEmpty(repo.getLanguage())) { - language.setText(repo.getLanguage()); - language.setTextColor(ColorsProvider.getColorAsColor(repo.getLanguage(), language.getContext())); - language.setVisibility(View.VISIBLE); - } else { - language.setTextColor(Color.BLACK); - language.setVisibility(View.GONE); - language.setText(""); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReviewCommentsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReviewCommentsViewHolder.java deleted file mode 100644 index 72700d9e8..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReviewCommentsViewHolder.java +++ /dev/null @@ -1,241 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.transition.ChangeBounds; -import android.support.transition.TransitionManager; -import android.support.v7.widget.AppCompatImageView; -import android.text.TextUtils; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; - -import com.fastaccess.R; -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.data.dao.ReviewCommentModel; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.provider.timeline.HtmlHelper; -import com.fastaccess.provider.timeline.handler.drawable.DrawableGetter; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.adapter.callback.ReactionsCallback; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -public class ReviewCommentsViewHolder extends BaseViewHolder { - - @BindView(R.id.avatarView) AvatarLayout avatarView; - @BindView(R.id.name) FontTextView name; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.comment) FontTextView comment; - @BindView(R.id.toggle) AppCompatImageView toggle; - @BindView(R.id.toggleHolder) LinearLayout toggleHolder; - @BindView(R.id.thumbsUp) FontTextView thumbsUp; - @BindView(R.id.thumbsDown) FontTextView thumbsDown; - @BindView(R.id.laugh) FontTextView laugh; - @BindView(R.id.hurray) FontTextView hurray; - @BindView(R.id.sad) FontTextView sad; - @BindView(R.id.heart) FontTextView heart; - @BindView(R.id.commentMenu) ImageView commentMenu; - @BindView(R.id.commentOptions) RelativeLayout commentOptions; - @BindView(R.id.owner) FontTextView owner; - @BindView(R.id.reactionsList) View reactionsList; - @BindView(R.id.thumbsUpReaction) FontTextView thumbsUpReaction; - @BindView(R.id.thumbsDownReaction) FontTextView thumbsDownReaction; - @BindView(R.id.laughReaction) FontTextView laughReaction; - @BindView(R.id.hurrayReaction) FontTextView hurrayReaction; - @BindView(R.id.sadReaction) FontTextView sadReaction; - @BindView(R.id.heartReaction) FontTextView heartReaction; - private OnToggleView onToggleView; - private ReactionsCallback reactionsCallback; - private ViewGroup viewGroup; - private String repoOwner; - private String poster; - - @Override public void onClick(View v) { - if (v.getId() == R.id.toggle || v.getId() == R.id.toggleHolder) { - if (onToggleView != null) { - long id = getId(); - onToggleView.onToggle(id, !onToggleView.isCollapsed(id)); - onToggle(onToggleView.isCollapsed(id), true); - } - } else { - addReactionCount(v); - super.onClick(v); - } - } - - private ReviewCommentsViewHolder(@NonNull View itemView, ViewGroup viewGroup, @Nullable BaseRecyclerAdapter adapter, - @NonNull OnToggleView onToggleView, @NonNull ReactionsCallback reactionsCallback, - String repoOwner, String poster) { - super(itemView, adapter); - if (adapter != null && adapter.getRowWidth() == 0) { - itemView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override public boolean onPreDraw() { - itemView.getViewTreeObserver().removeOnPreDrawListener(this); - adapter.setRowWidth(itemView.getWidth() - ViewHelper.dpToPx(itemView.getContext(), 48)); - return false; - } - }); - } - this.onToggleView = onToggleView; - this.viewGroup = viewGroup; - this.reactionsCallback = reactionsCallback; - this.repoOwner = repoOwner; - this.poster = poster; - itemView.setOnClickListener(null); - itemView.setOnLongClickListener(null); - toggle.setOnClickListener(this); - commentMenu.setOnClickListener(this); - toggleHolder.setOnClickListener(this); - laugh.setOnClickListener(this); - sad.setOnClickListener(this); - thumbsDown.setOnClickListener(this); - thumbsUp.setOnClickListener(this); - hurray.setOnClickListener(this); - laugh.setOnLongClickListener(this); - sad.setOnLongClickListener(this); - thumbsDown.setOnLongClickListener(this); - thumbsUp.setOnLongClickListener(this); - hurray.setOnLongClickListener(this); - heart.setOnLongClickListener(this); - heart.setOnClickListener(this); - laughReaction.setOnClickListener(this); - sadReaction.setOnClickListener(this); - thumbsDownReaction.setOnClickListener(this); - thumbsUpReaction.setOnClickListener(this); - hurrayReaction.setOnClickListener(this); - heartReaction.setOnClickListener(this); - laughReaction.setOnLongClickListener(this); - sadReaction.setOnLongClickListener(this); - thumbsDownReaction.setOnLongClickListener(this); - thumbsUpReaction.setOnLongClickListener(this); - hurrayReaction.setOnLongClickListener(this); - heartReaction.setOnLongClickListener(this); - } - - public static ReviewCommentsViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter, - @NonNull OnToggleView onToggleView, @NonNull ReactionsCallback reactionsCallback, - String repoOwner, String poster) { - return new ReviewCommentsViewHolder(getView(viewGroup, R.layout.review_comments_row_item), - viewGroup, adapter, onToggleView, reactionsCallback, repoOwner, poster); - } - - @Override public void bind(@NonNull ReviewCommentModel commentModel) { - if (commentModel.getUser() != null) { - avatarView.setUrl(commentModel.getUser().getAvatarUrl(), commentModel.getUser().getLogin(), commentModel.getUser() - .isOrganizationType(), LinkParserHelper.isEnterprise(commentModel.getHtmlUrl())); - name.setText(commentModel.getUser().getLogin()); - if (commentModel.getAuthorAssociation() != null && !"none".equalsIgnoreCase(commentModel.getAuthorAssociation())) { - owner.setText(commentModel.getAuthorAssociation().toLowerCase()); - owner.setVisibility(View.VISIBLE); - } else { - boolean isRepoOwner = TextUtils.equals(commentModel.getUser().getLogin(), repoOwner); - if (isRepoOwner) { - owner.setVisibility(View.VISIBLE); - owner.setText(R.string.owner); - } else { - boolean isPoster = TextUtils.equals(commentModel.getUser().getLogin(), poster); - if (isPoster) { - owner.setVisibility(View.VISIBLE); - owner.setText(R.string.original_poster); - } else { - owner.setText(""); - owner.setVisibility(View.GONE); - } - } - } - } - date.setText(ParseDateFormat.getTimeAgo(commentModel.getCreatedAt())); - if (!InputHelper.isEmpty(commentModel.getBodyHtml())) { - int width = adapter != null ? adapter.getRowWidth() : 0; - HtmlHelper.htmlIntoTextView(comment, commentModel.getBodyHtml(), width > 0 ? width : viewGroup.getWidth()); - } else { - comment.setText(""); - } - if (commentModel.getReactions() != null) { - ReactionsModel reaction = commentModel.getReactions(); - appendEmojies(reaction); - } - if (onToggleView != null) onToggle(onToggleView.isCollapsed(getId()), false); - } - - private void addReactionCount(View v) { - if (adapter != null) { - ReviewCommentModel comment = (ReviewCommentModel) adapter.getItem(getAdapterPosition()); - if (comment != null) { - boolean isReacted = reactionsCallback == null || reactionsCallback.isPreviouslyReacted(comment.getId(), v.getId()); - ReactionsModel reactionsModel = comment.getReactions() != null ? comment.getReactions() : new ReactionsModel(); - switch (v.getId()) { - case R.id.heart: - case R.id.heartReaction: - reactionsModel.setHeart(!isReacted ? reactionsModel.getHeart() + 1 : reactionsModel.getHeart() - 1); - break; - case R.id.sad: - case R.id.sadReaction: - reactionsModel.setConfused(!isReacted ? reactionsModel.getConfused() + 1 : reactionsModel.getConfused() - 1); - break; - case R.id.thumbsDown: - case R.id.thumbsDownReaction: - reactionsModel.setMinusOne(!isReacted ? reactionsModel.getMinusOne() + 1 : reactionsModel.getMinusOne() - 1); - break; - case R.id.thumbsUp: - case R.id.thumbsUpReaction: - reactionsModel.setPlusOne(!isReacted ? reactionsModel.getPlusOne() + 1 : reactionsModel.getPlusOne() - 1); - break; - case R.id.laugh: - case R.id.laughReaction: - reactionsModel.setLaugh(!isReacted ? reactionsModel.getLaugh() + 1 : reactionsModel.getLaugh() - 1); - break; - case R.id.hurray: - case R.id.hurrayReaction: - reactionsModel.setHooray(!isReacted ? reactionsModel.getHooray() + 1 : reactionsModel.getHooray() - 1); - break; - } - comment.setReactions(reactionsModel); - appendEmojies(reactionsModel); - } - } - } - - private void appendEmojies(ReactionsModel reaction) { - CommentsHelper.appendEmojies(reaction, thumbsUp, thumbsUpReaction, thumbsDown, thumbsDownReaction, hurray, hurrayReaction, sad, - sadReaction, laugh, laughReaction, heart, heartReaction, reactionsList); - } - - private long getId() { - if (adapter != null) { - ReviewCommentModel comment = (ReviewCommentModel) adapter.getItem(getAdapterPosition()); - return comment.getId(); - } - return -1; - } - - private void onToggle(boolean expanded, boolean animate) { - if (animate) { - TransitionManager.beginDelayedTransition(viewGroup, new ChangeBounds()); - } - toggle.setRotation(!expanded ? 0.0F : 180F); - commentOptions.setVisibility(!expanded ? View.GONE : View.VISIBLE); - reactionsList.setVisibility(expanded ? View.GONE : View.VISIBLE); - reactionsList.setVisibility(expanded ? View.GONE : reactionsList.getTag() == null || (!((Boolean) reactionsList.getTag())) - ? View.GONE : View.VISIBLE); - } - - @Override protected void onViewIsDetaching() { - DrawableGetter drawableGetter = (DrawableGetter) comment.getTag(R.id.drawable_callback); - if (drawableGetter != null) { - drawableGetter.clear(drawableGetter); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReviewsViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReviewsViewHolder.kt deleted file mode 100644 index ea898017c..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/ReviewsViewHolder.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.view.View -import android.view.ViewGroup -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.TimelineModel -import com.fastaccess.helper.ParseDateFormat -import com.fastaccess.provider.timeline.HtmlHelper -import com.fastaccess.ui.widgets.AvatarLayout -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.ForegroundImageView -import com.fastaccess.ui.widgets.SpannableBuilder -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Kosh on 13 Dec 2016, 1:42 AM - */ - -class ReviewsViewHolder private constructor(itemView: View, - adapter: BaseRecyclerAdapter<*, *, *>?, - val viewGroup: ViewGroup) - : BaseViewHolder(itemView, adapter) { - - @BindView(R.id.stateImage) lateinit var stateImage: ForegroundImageView - @BindView(R.id.avatarLayout) lateinit var avatarLayout: AvatarLayout - @BindView(R.id.stateText) lateinit var stateText: FontTextView - @BindView(R.id.body) lateinit var body: FontTextView - - init { - itemView.setOnLongClickListener(null) - itemView.setOnClickListener(null) - } - - override fun bind(model: TimelineModel) { - val review = model.review - review?.let { - stateImage.setImageResource(R.drawable.ic_eye) - avatarLayout.setUrl(it.user?.avatarUrl, it.user?.login, false, false) - stateText.text = SpannableBuilder.builder().bold(if (it.user != null) { - it.user.login - } else { - "" - }).append(" ${review.state.replace("_", " ")} ").append(ParseDateFormat.getTimeAgo(it.submittedAt)) - if (!it.bodyHtml.isNullOrBlank()) { - HtmlHelper.htmlIntoTextView(body, it.bodyHtml, viewGroup.width) - body.visibility = View.VISIBLE - } else { - body.text = "" - body.visibility = View.GONE - } - } - } - - companion object { - fun newInstance(viewGroup: ViewGroup, adapter: BaseRecyclerAdapter<*, *, *>): ReviewsViewHolder { - return ReviewsViewHolder(BaseViewHolder.getView(viewGroup, R.layout.review_timeline_row_item), adapter, viewGroup) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/SearchCodeViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/SearchCodeViewHolder.java deleted file mode 100644 index b1ba2cdff..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/SearchCodeViewHolder.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.SearchCodeModel; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class SearchCodeViewHolder extends BaseViewHolder { - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.details) FontTextView details; - @BindView(R.id.commentsNo) View commentsNo; - - private SearchCodeViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - } - - public static SearchCodeViewHolder newInstance(ViewGroup viewGroup, BaseRecyclerAdapter adapter) { - return new SearchCodeViewHolder(getView(viewGroup, R.layout.issue_no_image_row_item), adapter); - } - - public void bind(@NonNull SearchCodeModel codeModel, boolean showRepoName) { - if (showRepoName) { - title.setText(codeModel.getRepository() != null ? codeModel.getRepository().getFullName() : "N/A"); - details.setText(codeModel.getName()); - commentsNo.setVisibility(View.GONE); - } else { - title.setText(codeModel.getName()); - details.setText(codeModel.getPath()); - commentsNo.setVisibility(View.GONE); - } - } - - @Override public void bind(@NonNull SearchCodeModel searchCodeModel) {} -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/SimpleViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/SimpleViewHolder.java deleted file mode 100644 index d91b25e29..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/SimpleViewHolder.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 31 Dec 2016, 3:12 PM - */ - -public class SimpleViewHolder extends BaseViewHolder { - - @BindView(R.id.title) FontTextView title; - - public SimpleViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - } - - @Override public void bind(@NonNull O o) { - title.setText(o.toString()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/TeamsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/TeamsViewHolder.java deleted file mode 100644 index 6183fd340..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/TeamsViewHolder.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.TeamsModel; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class TeamsViewHolder extends BaseViewHolder { - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.date) FontTextView date; - - private TeamsViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView, adapter); - } - - public static TeamsViewHolder newInstance(@NonNull ViewGroup viewGroup, @NonNull BaseRecyclerAdapter adapter) { - return new TeamsViewHolder(getView(viewGroup, R.layout.feeds_row_no_image_item), adapter); - } - - @Override public void bind(@NonNull TeamsModel user) { - title.setText(!InputHelper.isEmpty(user.getName()) ? user.getName() : user.getSlug()); - if (!InputHelper.isEmpty(user.getDescription())) { - date.setText(user.getDescription()); - } else { - date.setText(InputHelper.toNA(user.getSlug())); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/TimelineCommentsViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/TimelineCommentsViewHolder.java deleted file mode 100644 index f34e57729..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/TimelineCommentsViewHolder.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.transition.ChangeBounds; -import android.support.transition.TransitionManager; -import android.text.TextUtils; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.HorizontalScrollView; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; - -import com.fastaccess.R; -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.provider.timeline.HtmlHelper; -import com.fastaccess.provider.timeline.handler.drawable.DrawableGetter; -import com.fastaccess.ui.adapter.IssuesTimelineAdapter; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.adapter.callback.ReactionsCallback; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class TimelineCommentsViewHolder extends BaseViewHolder { - - - @BindView(R.id.avatarView) AvatarLayout avatar; - @BindView(R.id.name) FontTextView name; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.toggle) ForegroundImageView toggle; - @BindView(R.id.commentMenu) ForegroundImageView commentMenu; - @BindView(R.id.toggleHolder) LinearLayout toggleHolder; - @BindView(R.id.thumbsUp) FontTextView thumbsUp; - @BindView(R.id.thumbsDown) FontTextView thumbsDown; - @BindView(R.id.laugh) FontTextView laugh; - @BindView(R.id.hurray) FontTextView hurray; - @BindView(R.id.sad) FontTextView sad; - @BindView(R.id.heart) FontTextView heart; - @BindView(R.id.emojiesList) HorizontalScrollView emojiesList; - @BindView(R.id.commentOptions) RelativeLayout commentOptions; - @BindView(R.id.comment) FontTextView comment; - @BindView(R.id.owner) FontTextView owner; - @BindView(R.id.pathText) FontTextView pathText; - @BindView(R.id.reactionsList) View reactionsList; - @BindView(R.id.thumbsUpReaction) FontTextView thumbsUpReaction; - @BindView(R.id.thumbsDownReaction) FontTextView thumbsDownReaction; - @BindView(R.id.laughReaction) FontTextView laughReaction; - @BindView(R.id.hurrayReaction) FontTextView hurrayReaction; - @BindView(R.id.sadReaction) FontTextView sadReaction; - @BindView(R.id.heartReaction) FontTextView heartReaction; - private OnToggleView onToggleView; - private boolean showEmojies; - private ReactionsCallback reactionsCallback; - private ViewGroup viewGroup; - private String repoOwner; - private String poster; - - @Override public void onClick(View v) { - if (v.getId() == R.id.toggle || v.getId() == R.id.toggleHolder) { - if (onToggleView != null) { - int position = getAdapterPosition(); - onToggleView.onToggle(position, !onToggleView.isCollapsed(position)); - onToggle(onToggleView.isCollapsed(position), true); - } - } else { - super.onClick(v); - addReactionCount(v); - } - } - - private TimelineCommentsViewHolder(@NonNull View itemView, @NonNull ViewGroup viewGroup, @Nullable IssuesTimelineAdapter adapter, - @NonNull OnToggleView onToggleView, boolean showEmojies, @NonNull ReactionsCallback reactionsCallback, - String repoOwner, String poster) { - super(itemView, adapter); - if (adapter != null && adapter.getRowWidth() == 0) { - itemView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override public boolean onPreDraw() { - itemView.getViewTreeObserver().removeOnPreDrawListener(this); - adapter.setRowWidth(itemView.getWidth() - ViewHelper.dpToPx(itemView.getContext(), 48)); - return false; - } - }); - } - this.viewGroup = viewGroup; - this.onToggleView = onToggleView; - this.showEmojies = showEmojies; - this.reactionsCallback = reactionsCallback; - this.repoOwner = repoOwner; - this.poster = poster; - itemView.setOnClickListener(null); - itemView.setOnLongClickListener(null); - commentMenu.setOnClickListener(this); - commentMenu.setOnLongClickListener(this); - toggleHolder.setOnClickListener(this); - toggle.setOnClickListener(this); - laugh.setOnClickListener(this); - sad.setOnClickListener(this); - thumbsDown.setOnClickListener(this); - thumbsUp.setOnClickListener(this); - hurray.setOnClickListener(this); - heart.setOnClickListener(this); - laugh.setOnLongClickListener(this); - sad.setOnLongClickListener(this); - thumbsDown.setOnLongClickListener(this); - thumbsUp.setOnLongClickListener(this); - hurray.setOnLongClickListener(this); - heart.setOnLongClickListener(this); - laughReaction.setOnClickListener(this); - sadReaction.setOnClickListener(this); - thumbsDownReaction.setOnClickListener(this); - thumbsUpReaction.setOnClickListener(this); - hurrayReaction.setOnClickListener(this); - heartReaction.setOnClickListener(this); - laughReaction.setOnLongClickListener(this); - sadReaction.setOnLongClickListener(this); - thumbsDownReaction.setOnLongClickListener(this); - thumbsUpReaction.setOnLongClickListener(this); - hurrayReaction.setOnLongClickListener(this); - heartReaction.setOnLongClickListener(this); - } - - public static TimelineCommentsViewHolder newInstance(@NonNull ViewGroup viewGroup, @Nullable IssuesTimelineAdapter adapter, - @NonNull OnToggleView onToggleView, boolean showEmojies, - @NonNull ReactionsCallback reactionsCallback, String repoOwner, String poster) { - return new TimelineCommentsViewHolder(getView(viewGroup, R.layout.comments_row_item), viewGroup, adapter, - onToggleView, showEmojies, reactionsCallback, repoOwner, poster); - } - - @Override public void bind(@NonNull TimelineModel timelineModel) { - Comment commentsModel = timelineModel.getComment(); - if (commentsModel.getUser() != null) { - avatar.setUrl(commentsModel.getUser().getAvatarUrl(), commentsModel.getUser().getLogin(), - false, LinkParserHelper.isEnterprise(commentsModel.getHtmlUrl())); - name.setText(commentsModel.getUser() != null ? commentsModel.getUser().getLogin() : "Anonymous"); - if (commentsModel.getAuthorAssociation() != null && !"none".equalsIgnoreCase(commentsModel.getAuthorAssociation())) { - owner.setText(commentsModel.getAuthorAssociation().toLowerCase()); - owner.setVisibility(View.VISIBLE); - } else { - boolean isRepoOwner = TextUtils.equals(commentsModel.getUser().getLogin(), repoOwner); - if (isRepoOwner) { - owner.setVisibility(View.VISIBLE); - owner.setText(R.string.owner); - } else { - boolean isPoster = TextUtils.equals(commentsModel.getUser().getLogin(), poster); - if (isPoster) { - owner.setVisibility(View.VISIBLE); - owner.setText(R.string.original_poster); - } else { - owner.setText(""); - owner.setVisibility(View.GONE); - } - } - } - } else { - avatar.setUrl(null, null, false, false); - name.setText(""); - } - if (!InputHelper.isEmpty(commentsModel.getPath()) && commentsModel.getPosition() > 0) { - pathText.setVisibility(View.VISIBLE); - pathText.setText(String.format("Commented on %s#L%s", commentsModel.getPath(), - commentsModel.getLine() > 0 ? commentsModel.getLine() : commentsModel.getPosition())); - } else { - pathText.setText(""); - pathText.setVisibility(View.GONE); - } - if (!InputHelper.isEmpty(commentsModel.getBodyHtml())) { - String body = commentsModel.getBodyHtml(); - int width = adapter != null ? adapter.getRowWidth() : 0; - HtmlHelper.htmlIntoTextView(comment, body, width > 0 ? width : viewGroup.getWidth()); - } else { - comment.setText(""); - } - if (commentsModel.getCreatedAt().before(commentsModel.getUpdatedAt())) { - date.setText(String.format("%s %s", ParseDateFormat.getTimeAgo(commentsModel.getCreatedAt()), itemView - .getResources().getString(R.string.edited))); - } else { - date.setText(ParseDateFormat.getTimeAgo(commentsModel.getCreatedAt())); - } - if (showEmojies) { - if (commentsModel.getReactions() != null) { - ReactionsModel reaction = commentsModel.getReactions(); - appendEmojies(reaction); - } - } - emojiesList.setVisibility(showEmojies ? View.VISIBLE : View.GONE); - if (onToggleView != null) onToggle(onToggleView.isCollapsed(getAdapterPosition()), false); - } - - private void addReactionCount(View v) { - if (adapter != null) { - TimelineModel timelineModel = (TimelineModel) adapter.getItem(getAdapterPosition()); - if (timelineModel == null) return; - Comment comment = timelineModel.getComment(); - if (comment != null) { - boolean isReacted = reactionsCallback == null || reactionsCallback.isPreviouslyReacted(comment.getId(), v.getId()); - boolean isCallingApi = reactionsCallback != null && reactionsCallback.isCallingApi(comment.getId(), v.getId()); -// if (isCallingApi) return; - ReactionsModel reactionsModel = comment.getReactions() != null ? comment.getReactions() : new ReactionsModel(); - switch (v.getId()) { - case R.id.heart: - case R.id.heartReaction: - reactionsModel.setHeart(!isReacted ? reactionsModel.getHeart() + 1 : reactionsModel.getHeart() - 1); - break; - case R.id.sad: - case R.id.sadReaction: - reactionsModel.setConfused(!isReacted ? reactionsModel.getConfused() + 1 : reactionsModel.getConfused() - 1); - break; - case R.id.thumbsDown: - case R.id.thumbsDownReaction: - reactionsModel.setMinusOne(!isReacted ? reactionsModel.getMinusOne() + 1 : reactionsModel.getMinusOne() - 1); - break; - case R.id.thumbsUp: - case R.id.thumbsUpReaction: - reactionsModel.setPlusOne(!isReacted ? reactionsModel.getPlusOne() + 1 : reactionsModel.getPlusOne() - 1); - break; - case R.id.laugh: - case R.id.laughReaction: - reactionsModel.setLaugh(!isReacted ? reactionsModel.getLaugh() + 1 : reactionsModel.getLaugh() - 1); - break; - case R.id.hurray: - case R.id.hurrayReaction: - reactionsModel.setHooray(!isReacted ? reactionsModel.getHooray() + 1 : reactionsModel.getHooray() - 1); - break; - } - comment.setReactions(reactionsModel); - appendEmojies(reactionsModel); - timelineModel.setComment(comment); - } - } - } - - private void appendEmojies(ReactionsModel reaction) { - CommentsHelper.appendEmojies(reaction, thumbsUp, thumbsUpReaction, thumbsDown, thumbsDownReaction, hurray, hurrayReaction, sad, - sadReaction, laugh, laughReaction, heart, heartReaction, reactionsList); - } - - private void onToggle(boolean expanded, boolean animate) { - if (animate) { - TransitionManager.beginDelayedTransition(viewGroup, new ChangeBounds()); - } - toggle.setRotation(!expanded ? 0.0F : 180F); - commentOptions.setVisibility(!expanded ? View.GONE : View.VISIBLE); - reactionsList.setVisibility(expanded ? View.GONE : View.VISIBLE); - reactionsList.setVisibility(expanded ? View.GONE : reactionsList.getTag() == null || (!((Boolean) reactionsList.getTag())) - ? View.GONE : View.VISIBLE); - } - - @Override protected void onViewIsDetaching() { - DrawableGetter drawableGetter = (DrawableGetter) comment.getTag(R.id.drawable_callback); - if (drawableGetter != null) { - drawableGetter.clear(drawableGetter); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/TrendingViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/TrendingViewHolder.kt deleted file mode 100644 index 8c1510030..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/TrendingViewHolder.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.view.View -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.TrendingModel -import com.fastaccess.helper.Logger -import com.fastaccess.provider.colors.ColorsProvider -import com.fastaccess.provider.emoji.EmojiParser -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created: FontTextView by Kosh on 02 Jun 2017, 1:27 PM - */ - -open class TrendingViewHolder(itemView: View, adapter: BaseRecyclerAdapter>) : BaseViewHolder(itemView, adapter) { - - @BindView(R.id.title) lateinit var title: FontTextView - @BindView(R.id.description) lateinit var description: FontTextView - @BindView(R.id.todayStars) lateinit var todayStars: FontTextView - @BindView(R.id.stars) lateinit var stars: FontTextView - @BindView(R.id.forks) lateinit var fork: FontTextView - @BindView(R.id.language) lateinit var lang: FontTextView - - - override fun bind(t: TrendingModel) { - title.text = t.title - if (t.description.isNullOrBlank()) { - description.visibility = View.GONE - } else { - val descriptionValue: String = EmojiParser.parseToUnicode(t.description) - description.text = descriptionValue - description.visibility = View.VISIBLE - } - todayStars.text = t.todayStars - stars.text = t.stars - fork.text = t.forks - if (t.language.isNullOrBlank()) { - lang.visibility = View.GONE - lang.text = "" - } else { - val color = ColorsProvider.getColorAsColor(t.language!!, itemView.context) - Logger.e(color, t.language) - lang.tintDrawables(color) - lang.setTextColor(color) - lang.text = t.language - lang.visibility = View.VISIBLE - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/UnknownTypeViewHolder.kt b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/UnknownTypeViewHolder.kt deleted file mode 100644 index 3fa035890..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/UnknownTypeViewHolder.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder - -import android.view.View -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by kosh on 07/08/2017. - */ -class UnknownTypeViewHolder(view: View) : BaseViewHolder(view) { - override fun bind(t: Any) {} //DO NOTHING -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/UsersViewHolder.java b/app/src/main/java/com/fastaccess/ui/adapter/viewholder/UsersViewHolder.java deleted file mode 100644 index 2788e64cb..000000000 --- a/app/src/main/java/com/fastaccess/ui/adapter/viewholder/UsersViewHolder.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.fastaccess.ui.adapter.viewholder; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 2:08 PM - */ - -public class UsersViewHolder extends BaseViewHolder { - - @BindView(R.id.avatarLayout) AvatarLayout avatar; - @BindView(R.id.title) FontTextView title; - @BindView(R.id.date) FontTextView date; - private boolean isFilter; - - private UsersViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter, boolean isFilter) { - super(itemView, adapter); - this.isFilter = isFilter; - } - - public static UsersViewHolder newInstance(@NonNull ViewGroup parent, @Nullable BaseRecyclerAdapter adapter, boolean isFilter) { - return new UsersViewHolder(getView(parent, isFilter ? R.layout.users_small_row_item : R.layout.feeds_row_item), adapter, isFilter); - } - - @Override public void onClick(View v) { - if (isFilter) { - super.onClick(v); - } else { - avatar.findViewById(R.id.avatar).callOnClick(); - } - } - - @Override public void bind(@NonNull User user) {} - - public void bind(@NonNull User user, boolean isContributor) { - avatar.setUrl(user.getAvatarUrl(), user.getLogin(), user.isOrganizationType(), - LinkParserHelper.isEnterprise(user.getHtmlUrl())); - title.setText(user.getLogin()); - date.setVisibility(!isContributor ? View.GONE : View.VISIBLE); - if (isContributor) { - date.setText(String.format("%s (%s)", date.getResources().getString(R.string.commits), user.getContributions())); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java b/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java deleted file mode 100644 index a51d2aac4..000000000 --- a/app/src/main/java/com/fastaccess/ui/base/BaseActivity.java +++ /dev/null @@ -1,554 +0,0 @@ -package com.fastaccess.ui.base; - -import android.app.ActivityManager; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.DrawableRes; -import android.support.annotation.IdRes; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.design.widget.AppBarLayout; -import android.support.design.widget.NavigationView; -import android.support.v4.view.GravityCompat; -import android.support.v4.view.ViewPager; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.widget.Toolbar; -import android.text.TextUtils; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewTreeObserver; -import android.widget.Toast; - -import com.bumptech.glide.Glide; -import com.evernote.android.state.State; -import com.evernote.android.state.StateSaver; -import com.fastaccess.App; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.FastHubNotification; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.markdown.CachedComments; -import com.fastaccess.provider.theme.ThemeEngine; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.changelog.ChangelogBottomSheetDialog; -import com.fastaccess.ui.modules.gists.gist.GistActivity; -import com.fastaccess.ui.modules.login.chooser.LoginChooserActivity; -import com.fastaccess.ui.modules.main.MainActivity; -import com.fastaccess.ui.modules.main.drawer.MainDrawerFragment; -import com.fastaccess.ui.modules.main.notifications.FastHubNotificationDialog; -import com.fastaccess.ui.modules.main.orgs.OrgListDialogFragment; -import com.fastaccess.ui.modules.main.playstore.PlayStoreWarningActivity; -import com.fastaccess.ui.modules.repos.code.commit.details.CommitPagerActivity; -import com.fastaccess.ui.modules.repos.issues.issue.details.IssuePagerActivity; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.PullRequestPagerActivity; -import com.fastaccess.ui.modules.settings.SettingsActivity; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.dialog.ProgressDialogFragment; - -import net.grandcentrix.thirtyinch.TiActivity; - -import java.util.ArrayList; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.Optional; -import es.dmoral.toasty.Toasty; -import io.reactivex.Observable; - - -/** - * Created by Kosh on 24 May 2016, 8:48 PM - */ - -public abstract class BaseActivity> extends TiActivity implements BaseMvp.FAView { - - @State boolean isProgressShowing; - @Nullable @BindView(R.id.toolbar) protected Toolbar toolbar; - @Nullable @BindView(R.id.appbar) protected AppBarLayout appbar; - @Nullable @BindView(R.id.drawer) protected DrawerLayout drawer; - @Nullable @BindView(R.id.extrasNav) public NavigationView extraNav; - @Nullable @BindView(R.id.drawerViewPager) ViewPager drawerViewPager; - @State String schemeUrl; - - @State Bundle presenterStateBundle = new Bundle(); - - private MainNavDrawer mainNavDrawer; - - private long backPressTimer; - private Toast toast; - - @LayoutRes protected abstract int layout(); - - protected abstract boolean isTransparent(); - - protected abstract boolean canBack(); - - protected abstract boolean isSecured(); - - @Override protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - StateSaver.saveInstanceState(this, outState); - getPresenter().onSaveInstanceState(presenterStateBundle); - } - - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - setTaskName(null); - setupTheme(); - AppHelper.updateAppLanguage(this); - super.onCreate(savedInstanceState); - if (layout() != 0) { - setContentView(layout()); - ButterKnife.bind(this); - } - if (savedInstanceState == null) { - getPresenter().onCheckGitHubStatus(); - if (getIntent() != null) { - schemeUrl = getIntent().getStringExtra(BundleConstant.SCHEME_URL); - } - } - if (!validateAuth()) return; - if (savedInstanceState == null) { - if (showInAppNotifications()) { - FastHubNotificationDialog.Companion.show(getSupportFragmentManager()); - } - } - showChangelog(); - initPresenterBundle(savedInstanceState); - setupToolbarAndStatusBar(toolbar); - initEnterpriseExtra(savedInstanceState); - mainNavDrawer = new MainNavDrawer(this, extraNav); - setupDrawer(); - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { - return super.onCreateOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (canBack()) { - if (item.getItemId() == android.R.id.home) { - onBackPressed(); - return true; - } - } - return super.onOptionsItemSelected(item); - } - - @Override public void onDialogDismissed() { - - }//pass - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - if (isOk && bundle != null) { - boolean logout = bundle.getBoolean("logout"); - if (logout) { - onRequireLogin(); - } - } - }//pass - - @Override public void showMessage(@StringRes int titleRes, @StringRes int msgRes) { - showMessage(getString(titleRes), getString(msgRes)); - } - - @Override public void showMessage(@NonNull String titleRes, @NonNull String msgRes) { - hideProgress(); - if (toast != null) toast.cancel(); - Context context = App.getInstance(); // WindowManager$BadTokenException - toast = titleRes.equals(context.getString(R.string.error)) - ? Toasty.error(context, msgRes, Toast.LENGTH_LONG) - : Toasty.info(context, msgRes, Toast.LENGTH_LONG); - toast.show(); - } - - @Override public void showErrorMessage(@NonNull String msgRes) { - showMessage(getString(R.string.error), msgRes); - } - - @Override public boolean isLoggedIn() { - return Login.getUser() != null; - } - - @Override public void showProgress(@StringRes int resId) { - showProgress(resId, true); - } - - @Override public void showBlockingProgress(int resId) { - showProgress(resId, false); - } - - @Override public void hideProgress() { - ProgressDialogFragment fragment = (ProgressDialogFragment) AppHelper.getFragmentByTag(getSupportFragmentManager(), - ProgressDialogFragment.TAG); - if (fragment != null) { - isProgressShowing = false; - fragment.dismiss(); - } - } - - @Override public void onRequireLogin() { - Toasty.warning(App.getInstance(), getString(R.string.unauthorized_user), Toast.LENGTH_LONG).show(); - final Glide glide = Glide.get(App.getInstance()); - getPresenter().manageViewDisposable(RxHelper.getObservable(Observable.fromCallable(() -> { - glide.clearDiskCache(); - PrefGetter.setToken(null); - PrefGetter.setOtpCode(null); - PrefGetter.resetEnterprise(); - Login.logout(); - return true; - })).subscribe(aBoolean -> { - glide.clearMemory(); - Intent intent = new Intent(this, LoginChooserActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - finishAffinity(); - })); - } - - @Override public void onBackPressed() { - if (drawer != null && drawer.isDrawerOpen(GravityCompat.START)) { - closeDrawer(); - } else { - boolean clickTwiceToExit = !PrefGetter.isTwiceBackButtonDisabled(); - superOnBackPressed(clickTwiceToExit); - } - } - - @Override public void onLogoutPressed() { - MessageDialogView.newInstance(getString(R.string.logout), getString(R.string.confirm_message), - Bundler.start() - .put(BundleConstant.YES_NO_EXTRA, true) - .put("logout", true) - .end()) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - } - - @Override public void onThemeChanged() { - if (this instanceof MainActivity) { - recreate(); - } else { - Intent intent = new Intent(this, MainActivity.class); - intent.putExtras(Bundler.start().put(BundleConstant.YES_NO_EXTRA, true).end()); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); - finish(); - } - } - - @Override public void onOpenSettings() { - startActivityForResult(new Intent(this, SettingsActivity.class), BundleConstant.REFRESH_CODE); - } - - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == RESULT_OK) { - if (requestCode == BundleConstant.REFRESH_CODE) { - onThemeChanged(); - } - } - super.onActivityResult(requestCode, resultCode, data); - } - - @Override public void onScrollTop(int index) {} - - @Override public boolean isEnterprise() { - return getPresenter() != null && getPresenter().isEnterprise(); - } - - @Override public void onOpenUrlInBrowser() { - if (!InputHelper.isEmpty(schemeUrl)) { - ActivityHelper.startCustomTab(this, schemeUrl); - try { - finish(); - } catch (Exception ignored) {}// fragment might be committed and calling finish will crash the app. - } - } - - @Optional @OnClick(R.id.logout) void onLogoutClicked() { - closeDrawer(); - onLogoutPressed(); - } - - @Override protected void onDestroy() { - clearCachedComments(); - super.onDestroy(); - } - - protected void setTaskName(@Nullable String name) { - setTaskDescription(new ActivityManager.TaskDescription(name, null, ViewHelper.getPrimaryDarkColor(this))); - } - - protected void selectHome(boolean hideRepo) { - Menu menu = getMainDrawerMenu(); - if (menu != null) { - if (hideRepo) { - menu.findItem(R.id.navToRepo).setVisible(false); - menu.findItem(R.id.mainView).setVisible(true); - return; - } - menu.findItem(R.id.navToRepo).setVisible(false); - menu.findItem(R.id.mainView).setCheckable(true); - menu.findItem(R.id.mainView).setChecked(true); - } - } - - protected void selectProfile() { - selectHome(true); - selectMenuItem(R.id.profile); - } - - protected void selectPinned() { - selectMenuItem(R.id.pinnedMenu); - } - - protected void onSelectNotifications() { - selectMenuItem(R.id.notifications); - } - - protected void onSelectTrending() { - selectMenuItem(R.id.trending); - } - - public void onOpenOrgsDialog() { - OrgListDialogFragment.newInstance().show(getSupportFragmentManager(), "OrgListDialogFragment"); - } - - protected void showNavToRepoItem() { - Menu menu = getMainDrawerMenu(); - if (menu != null) { - menu.findItem(R.id.navToRepo).setVisible(true); - } - } - - protected void selectMenuItem(@IdRes int id) { - Menu menu = getMainDrawerMenu(); - if (menu != null) { - menu.findItem(id).setCheckable(true); - menu.findItem(id).setChecked(true); - } - } - - public void onNavToRepoClicked() {} - - private void setupToolbarAndStatusBar(@Nullable Toolbar toolbar) { - changeStatusBarColor(isTransparent()); - if (toolbar != null) { - setSupportActionBar(toolbar); - if (canBack()) { - if (getSupportActionBar() != null) { - getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_back); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - if (canBack()) { - View navIcon = getToolbarNavigationIcon(toolbar); - if (navIcon != null) { - navIcon.setOnLongClickListener(v -> { - Intent intent = new Intent(this, MainActivity.class); - startActivity(intent); - finish(); - return true; - }); - } - } - } - } - } - } - - protected void setToolbarIcon(@DrawableRes int res) { - if (getSupportActionBar() != null) { - getSupportActionBar().setHomeAsUpIndicator(res); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - } - } - - protected void hideShowShadow(boolean show) { - if (appbar != null) { - appbar.setElevation(show ? getResources().getDimension(R.dimen.spacing_micro) : 0.0f); - } - } - - protected void changeStatusBarColor(boolean isTransparent) { - if (!isTransparent) { - getWindow().setStatusBarColor(ViewHelper.getPrimaryDarkColor(this)); - } - } - - private void setupTheme() { - ThemeEngine.INSTANCE.apply(this); - } - - protected void setupNavigationView() { - if (mainNavDrawer != null) { - mainNavDrawer.setupView(); - } - } - - public void closeDrawer() { - if (drawer != null) { - if (drawer.isDrawerOpen(GravityCompat.START)) { - drawer.closeDrawer(GravityCompat.START); - } - } - } - - private void setupDrawer() { - if (drawer != null && !(this instanceof MainActivity)) { - if (!PrefGetter.isNavDrawerHintShowed()) { - drawer.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override public boolean onPreDraw() { - drawer.openDrawer(GravityCompat.START); - drawer.addDrawerListener(new DrawerLayout.SimpleDrawerListener() { - @Override public void onDrawerOpened(View drawerView) { - super.onDrawerOpened(drawerView); - drawerView.postDelayed(() -> { - if (drawer != null) { - closeDrawer(); - drawer.removeDrawerListener(this); - } - }, 1000); - } - }); - drawer.getViewTreeObserver().removeOnPreDrawListener(this); - return true; - } - }); - } - } - } - - private void superOnBackPressed(boolean didClickTwice) { - if (this instanceof MainActivity) { - if (didClickTwice) { - if (canExit()) { - super.onBackPressed(); - } - } else { - super.onBackPressed(); - } - } else { - super.onBackPressed(); - } - } - - private boolean canExit() { - if (backPressTimer + 2000 > System.currentTimeMillis()) { - return true; - } else { - showMessage(R.string.press_again_to_exit, R.string.press_again_to_exit); - } - backPressTimer = System.currentTimeMillis(); - return false; - } - - @Nullable private View getToolbarNavigationIcon(Toolbar toolbar) { - boolean hadContentDescription = TextUtils.isEmpty(toolbar.getNavigationContentDescription()); - String contentDescription = !hadContentDescription ? String.valueOf(toolbar.getNavigationContentDescription()) : "navigationIcon"; - toolbar.setNavigationContentDescription(contentDescription); - ArrayList potentialViews = new ArrayList<>(); - toolbar.findViewsWithText(potentialViews, contentDescription, View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION); - View navIcon = null; - if (potentialViews.size() > 0) { - navIcon = potentialViews.get(0); - } - if (hadContentDescription) toolbar.setNavigationContentDescription(null); - return navIcon; - } - - public void onRestartApp() { - Intent intent = new Intent(this, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - startActivity(intent); - finishAndRemoveTask(); - } - - private void showProgress(int resId, boolean cancelable) { - String msg = getString(R.string.in_progress); - if (resId != 0) { - msg = getString(resId); - } - if (!isProgressShowing && !isFinishing()) { - ProgressDialogFragment fragment = (ProgressDialogFragment) AppHelper.getFragmentByTag(getSupportFragmentManager(), - ProgressDialogFragment.TAG); - if (fragment == null) { - isProgressShowing = true; - fragment = ProgressDialogFragment.newInstance(msg, cancelable); - fragment.show(getSupportFragmentManager(), ProgressDialogFragment.TAG); - } - } - } - - /** - * not really needed but meh. - */ - private void clearCachedComments() { - if (this instanceof IssuePagerActivity || this instanceof CommitPagerActivity || - this instanceof PullRequestPagerActivity || this instanceof GistActivity) { - CachedComments.Companion.getInstance().clear(); - } - } - - private boolean validateAuth() { - if (!isSecured()) { - if (!isLoggedIn()) { - onRequireLogin(); - return false; - } - } - return true; - } - - private void initEnterpriseExtra(@Nullable Bundle savedInstanceState) { - if (savedInstanceState == null) { - if (getIntent() != null) { - if (getIntent().getExtras() != null) { - getPresenter().setEnterprise(getIntent().getExtras().getBoolean(BundleConstant.IS_ENTERPRISE)); - } else if (getIntent().hasExtra(BundleConstant.IS_ENTERPRISE)) { - getPresenter().setEnterprise(getIntent().getBooleanExtra(BundleConstant.IS_ENTERPRISE, false)); - } - } - } - } - - private void initPresenterBundle(@Nullable Bundle savedInstanceState) { - if (savedInstanceState != null && !savedInstanceState.isEmpty()) { - StateSaver.restoreInstanceState(this, savedInstanceState); - getPresenter().onRestoreInstanceState(presenterStateBundle); - } - } - - private void showChangelog() { - if (PrefGetter.showWhatsNew() && !(this instanceof PlayStoreWarningActivity)) { - new ChangelogBottomSheetDialog().show(getSupportFragmentManager(), "ChangelogBottomSheetDialog"); - } - } - - private boolean showInAppNotifications() { - return FastHubNotification.hasNotifications(); - } - - private Menu getMainDrawerMenu() { - if (drawerViewPager != null) { - FragmentsPagerAdapter adapter = (FragmentsPagerAdapter) drawerViewPager.getAdapter(); - if (adapter != null) { - MainDrawerFragment fragment = (MainDrawerFragment) adapter.instantiateItem(drawerViewPager, 0); - if (fragment != null) { - return fragment.getMenu(); - } - } - } - return null; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseBottomSheetDialog.java b/app/src/main/java/com/fastaccess/ui/base/BaseBottomSheetDialog.java deleted file mode 100644 index def0cc07a..000000000 --- a/app/src/main/java/com/fastaccess/ui/base/BaseBottomSheetDialog.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.fastaccess.ui.base; - -import android.app.Dialog; -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.BottomSheetBehavior; -import android.support.design.widget.BottomSheetDialogFragment; -import android.support.v7.view.ContextThemeWrapper; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; - -import com.evernote.android.state.StateSaver; -import com.fastaccess.R; -import com.fastaccess.helper.ViewHelper; - -import butterknife.ButterKnife; -import butterknife.Unbinder; - -/** - * Created by Kosh on 16 Sep 2016, 2:11 PM - */ - -@SuppressWarnings("RestrictedApi") public abstract class BaseBottomSheetDialog extends BottomSheetDialogFragment { - - protected BottomSheetBehavior bottomSheetBehavior; - private final BottomSheetBehavior.BottomSheetCallback bottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() { - @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { - if (newState == BottomSheetBehavior.STATE_HIDDEN) { - isAlreadyHidden = true; - onHidden(); - } - } - - @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { - if (slideOffset == -1.0) { - isAlreadyHidden = true; - onDismissedByScrolling(); - } - } - }; - protected boolean isAlreadyHidden; - @Nullable private Unbinder unbinder; - - @LayoutRes protected abstract int layoutRes(); - - @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - } - - @Override public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - StateSaver.saveInstanceState(this, outState); - } - - @Override public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState != null && !savedInstanceState.isEmpty()) { - StateSaver.restoreInstanceState(this, savedInstanceState); - } - } - - @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - final Context contextThemeWrapper = new ContextThemeWrapper(getContext(), getContext().getTheme()); - LayoutInflater themeAwareInflater = inflater.cloneInContext(contextThemeWrapper); - View view = themeAwareInflater.inflate(layoutRes(), container, false); - unbinder = ButterKnife.bind(this, view); - view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override public void onGlobalLayout() { - view.getViewTreeObserver().removeOnGlobalLayoutListener(this); - View parent = getDialog().findViewById(R.id.design_bottom_sheet); - if (parent != null) { - bottomSheetBehavior = BottomSheetBehavior.from(parent); - if (bottomSheetBehavior != null) { - bottomSheetBehavior.setBottomSheetCallback(bottomSheetCallback); - bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); - } - } - } - }); - return view; - } - - @Override public void setupDialog(Dialog dialog, int style) { - super.setupDialog(dialog, style); - } - - @Override public void onDestroyView() { - super.onDestroyView(); - if (unbinder != null) unbinder.unbind(); - } - - @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - final Dialog dialog = super.onCreateDialog(savedInstanceState); - dialog.setOnShowListener(dialogInterface -> { - if (ViewHelper.isTablet(getActivity())) { - if (dialog.getWindow() != null) { - dialog.getWindow().setLayout( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.MATCH_PARENT); - } - } - onDialogIsShowing(); - }); - dialog.setOnKeyListener((dialog1, keyCode, event) -> { - if (keyCode == KeyEvent.KEYCODE_BACK) { - isAlreadyHidden = true; - onDismissedByScrolling(); - } - return false; - }); - return dialog; - } - - @Override public void onDetach() { - if (!isAlreadyHidden) { - onDismissedByScrolling(); - } - super.onDetach(); - } - - protected void onHidden() { - try { - dismiss(); - } catch (IllegalStateException ignored) {} //FML FIXME - } - - protected void onDismissedByScrolling() {} - - private void onDialogIsShowing() {} - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseDialogFragment.java b/app/src/main/java/com/fastaccess/ui/base/BaseDialogFragment.java deleted file mode 100644 index 75af217bf..000000000 --- a/app/src/main/java/com/fastaccess/ui/base/BaseDialogFragment.java +++ /dev/null @@ -1,186 +0,0 @@ -package com.fastaccess.ui.base; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.annotation.SuppressLint; -import android.app.Dialog; -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v7.view.ContextThemeWrapper; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.evernote.android.state.StateSaver; -import com.fastaccess.R; -import com.fastaccess.helper.AnimHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.widgets.dialog.ProgressDialogFragment; - -import net.grandcentrix.thirtyinch.TiDialogFragment; - -import butterknife.ButterKnife; -import butterknife.Unbinder; - -/** - * Created by Kosh on 22 Feb 2017, 7:28 PM - */ - -public abstract class BaseDialogFragment> extends TiDialogFragment - implements BaseMvp.FAView { - protected BaseMvp.FAView callback; - - @Nullable private Unbinder unbinder; - protected boolean suppressAnimation = false; - - @LayoutRes protected abstract int fragmentLayout(); - - protected abstract void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState); - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof BaseMvp.FAView) { - callback = (BaseMvp.FAView) context; - } - } - - @Override public void onDetach() { - super.onDetach(); - callback = null; - } - - @Override public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - StateSaver.saveInstanceState(this, outState); - getPresenter().onSaveInstanceState(outState); - } - - @Override public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setStyle(STYLE_NO_TITLE, AppHelper.isNightMode(getResources()) ? R.style.DialogThemeDark : R.style.DialogThemeLight); - if (savedInstanceState != null && !savedInstanceState.isEmpty()) { - StateSaver.restoreInstanceState(this, savedInstanceState); - getPresenter().onRestoreInstanceState(savedInstanceState); - } - getPresenter().setEnterprise(isEnterprise()); - } - - @Override public void dismiss() { - if (suppressAnimation) { - super.dismiss(); - return; - } - if (PrefGetter.isAppAnimationDisabled()) { - super.dismiss(); - } else { - AnimHelper.dismissDialog(this, getResources().getInteger(android.R.integer.config_shortAnimTime), - new AnimatorListenerAdapter() { - @Override public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - BaseDialogFragment.super.dismiss(); - } - }); - } - } - - @SuppressLint("RestrictedApi") @Nullable @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - if (fragmentLayout() != 0) { - final Context contextThemeWrapper = new ContextThemeWrapper(getContext(), getContext().getTheme()); - LayoutInflater themeAwareInflater = inflater.cloneInContext(contextThemeWrapper); - View view = themeAwareInflater.inflate(fragmentLayout(), container, false); - unbinder = ButterKnife.bind(this, view); - return view; - } - return super.onCreateView(inflater, container, savedInstanceState); - } - - @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - final Dialog dialog = super.onCreateDialog(savedInstanceState); - if (!PrefGetter.isAppAnimationDisabled() && !(this instanceof ProgressDialogFragment) && !suppressAnimation) { - dialog.setOnShowListener(dialogInterface -> AnimHelper.revealDialog(dialog, - getResources().getInteger(android.R.integer.config_longAnimTime))); - } - return dialog; - } - - @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - onFragmentCreated(view, savedInstanceState); - } - - @Override public void showProgress(@StringRes int resId) { - callback.showProgress(resId); - } - - @Override public void showBlockingProgress(int resId) { - callback.showBlockingProgress(resId); - } - - @Override public void hideProgress() { - callback.hideProgress(); - } - - @Override public void showMessage(@StringRes int titleRes, @StringRes int msgRes) { - callback.showMessage(titleRes, msgRes); - } - - @Override public void showMessage(@NonNull String titleRes, @NonNull String msgRes) { - callback.showMessage(titleRes, msgRes); - } - - @Override public void showErrorMessage(@NonNull String msgRes) { - callback.showErrorMessage(msgRes); - } - - @Override public boolean isLoggedIn() { - return callback.isLoggedIn(); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - - } - - @Override public void onRequireLogin() { - callback.onRequireLogin(); - } - - @Override public void onLogoutPressed() { - callback.onLogoutPressed(); - } - - @Override public void onThemeChanged() { - callback.onThemeChanged(); - } - - @Override public void onOpenSettings() { - callback.onOpenSettings(); - } - - @Override public void onDestroyView() { - super.onDestroyView(); - if (unbinder != null) unbinder.unbind(); - } - - @Override public void onScrollTop(int index) {} - - @Override public void onDialogDismissed() { - - } - - @Override public boolean isEnterprise() { - return callback != null && callback.isEnterprise(); - } - - @Override public void onOpenUrlInBrowser() { - callback.onOpenUrlInBrowser(); - } -} - diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseFragment.java b/app/src/main/java/com/fastaccess/ui/base/BaseFragment.java deleted file mode 100644 index c79a305c3..000000000 --- a/app/src/main/java/com/fastaccess/ui/base/BaseFragment.java +++ /dev/null @@ -1,151 +0,0 @@ -package com.fastaccess.ui.base; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v7.view.ContextThemeWrapper; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.evernote.android.state.StateSaver; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import net.grandcentrix.thirtyinch.TiFragment; - -import butterknife.ButterKnife; -import butterknife.Unbinder; - -/** - * Created by Kosh on 27 May 2016, 7:54 PM - */ - -public abstract class BaseFragment> extends TiFragment implements BaseMvp.FAView { - - protected BaseMvp.FAView callback; - - @Nullable private Unbinder unbinder; - - @LayoutRes protected abstract int fragmentLayout(); - - protected abstract void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState); - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof BaseMvp.FAView) { - callback = (BaseMvp.FAView) context; - } - } - - @Override public void onDetach() { - super.onDetach(); - callback = null; - } - - @Override public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - StateSaver.saveInstanceState(this, outState); - getPresenter().onSaveInstanceState(outState); - } - - @Override public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState != null && !savedInstanceState.isEmpty()) { - StateSaver.restoreInstanceState(this, savedInstanceState); - getPresenter().onRestoreInstanceState(savedInstanceState); - } - getPresenter().setEnterprise(isEnterprise()); - } - - @SuppressLint("RestrictedApi") @Nullable @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - if (fragmentLayout() != 0) { - final Context contextThemeWrapper = new ContextThemeWrapper(getContext(), getContext().getTheme()); - LayoutInflater themeAwareInflater = inflater.cloneInContext(contextThemeWrapper); - View view = themeAwareInflater.inflate(fragmentLayout(), container, false); - unbinder = ButterKnife.bind(this, view); - return view; - } - return super.onCreateView(inflater, container, savedInstanceState); - } - - @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - if (Login.getUser() != null) { - onFragmentCreated(view, savedInstanceState); - } - } - - @Override public void onDestroyView() { - super.onDestroyView(); - if (unbinder != null) unbinder.unbind(); - } - - @Override public void showProgress(@StringRes int resId) { - callback.showProgress(resId); - } - - @Override public void showBlockingProgress(int resId) { - callback.showBlockingProgress(resId); - } - - @Override public void hideProgress() { - if (callback != null) callback.hideProgress(); - } - - @Override public void showMessage(@StringRes int titleRes, @StringRes int msgRes) { - callback.showMessage(titleRes, msgRes); - } - - @Override public void showMessage(@NonNull String titleRes, @NonNull String msgRes) { - callback.showMessage(titleRes, msgRes); - } - - @Override public void showErrorMessage(@NonNull String msgRes) { - callback.showErrorMessage(msgRes); - } - - @Override public boolean isLoggedIn() { - return callback.isLoggedIn(); - } - - @Override public void onRequireLogin() { - callback.onRequireLogin(); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) {} - - @Override public void onDialogDismissed() {} - - @Override public void onLogoutPressed() { - callback.onLogoutPressed(); - } - - @Override public void onThemeChanged() { - callback.onThemeChanged(); - } - - @Override public void onOpenSettings() { - callback.onOpenSettings(); - } - - @Override public void onScrollTop(int index) {} - - @Override public boolean isEnterprise() { - return callback != null && callback.isEnterprise(); - } - - @Override public void onOpenUrlInBrowser() { - callback.onOpenUrlInBrowser(); - } - - protected boolean isSafe() { - return getView() != null && getActivity() != null && !getActivity().isFinishing(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/base/BaseMvpBottomSheetDialogFragment.java b/app/src/main/java/com/fastaccess/ui/base/BaseMvpBottomSheetDialogFragment.java deleted file mode 100644 index 852e7121a..000000000 --- a/app/src/main/java/com/fastaccess/ui/base/BaseMvpBottomSheetDialogFragment.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.fastaccess.ui.base; - -import android.annotation.SuppressLint; -import android.app.Dialog; -import android.content.Context; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.os.Bundle; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.design.widget.BottomSheetDialog; -import android.support.v7.view.ContextThemeWrapper; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.evernote.android.state.StateSaver; -import com.fastaccess.R; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import net.grandcentrix.thirtyinch.TiDialogFragment; - -import butterknife.ButterKnife; -import butterknife.Unbinder; - -/** - * Created by Kosh on 27 May 2017, 1:51 PM - */ - -public abstract class BaseMvpBottomSheetDialogFragment> extends TiDialogFragment - implements BaseMvp.FAView { - - protected BaseMvp.FAView callback; - - @Nullable private Unbinder unbinder; - - @LayoutRes protected abstract int fragmentLayout(); - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof BaseMvp.FAView) { - callback = (BaseMvp.FAView) context; - } - } - - @Override public void onDetach() { - super.onDetach(); - callback = null; - } - - @Override public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - StateSaver.saveInstanceState(this, outState); - getPresenter().onSaveInstanceState(outState); - } - - @Override public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setStyle(STYLE_NO_TITLE, AppHelper.isNightMode(getResources()) ? R.style.DialogThemeDark : R.style.DialogThemeLight); - if (savedInstanceState != null && !savedInstanceState.isEmpty()) { - StateSaver.restoreInstanceState(this, savedInstanceState); - getPresenter().onRestoreInstanceState(savedInstanceState); - } - getPresenter().setEnterprise(isEnterprise()); - } - - @SuppressLint("RestrictedApi") @Nullable @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - if (fragmentLayout() != 0) { - final Context contextThemeWrapper = new ContextThemeWrapper(getContext(), getContext().getTheme()); - LayoutInflater themeAwareInflater = inflater.cloneInContext(contextThemeWrapper); - View view = themeAwareInflater.inflate(fragmentLayout(), container, false); - unbinder = ButterKnife.bind(this, view); - return view; - } - return super.onCreateView(inflater, container, savedInstanceState); - } - - @Override public void showProgress(@StringRes int resId) { - callback.showProgress(resId); - } - - @Override public void showBlockingProgress(int resId) { - callback.showBlockingProgress(resId); - } - - @Override public void hideProgress() { - callback.hideProgress(); - } - - @Override public void showMessage(@StringRes int titleRes, @StringRes int msgRes) { - callback.showMessage(titleRes, msgRes); - } - - @Override public void showMessage(@NonNull String titleRes, @NonNull String msgRes) { - callback.showMessage(titleRes, msgRes); - } - - @Override public void showErrorMessage(@NonNull String msgRes) { - callback.showErrorMessage(msgRes); - } - - @Override public boolean isLoggedIn() { - return callback.isLoggedIn(); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) {} - - @Override public void onDialogDismissed() { - - } - - @Override public void onRequireLogin() { - callback.onRequireLogin(); - } - - @Override public void onLogoutPressed() { - callback.onLogoutPressed(); - } - - @Override public void onThemeChanged() { - callback.onThemeChanged(); - } - - @Override public void onOpenSettings() { - callback.onOpenSettings(); - } - - @Override public void onScrollTop(int index) { - - } - - @Override public void onDestroyView() { - super.onDestroyView(); - if (unbinder != null) unbinder.unbind(); - } - - @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - final BottomSheetDialog dialog = new BottomSheetDialog(getContext(), getTheme()); - if (dialog.getWindow() != null) dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - dialog.setOnShowListener(dialogInterface -> { - if (ViewHelper.isTablet(getActivity())) { - if (dialog.getWindow() != null) { - dialog.getWindow().setLayout( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.MATCH_PARENT); - } - } - }); - return dialog; - } - - @Override public boolean isEnterprise() { - return callback != null && callback.isEnterprise(); - } - - @Override public void onOpenUrlInBrowser() { - callback.onOpenUrlInBrowser(); - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/base/MainNavDrawer.kt b/app/src/main/java/com/fastaccess/ui/base/MainNavDrawer.kt deleted file mode 100644 index 4e481a17e..000000000 --- a/app/src/main/java/com/fastaccess/ui/base/MainNavDrawer.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.fastaccess.ui.base - -import android.support.design.widget.NavigationView -import android.support.design.widget.TabLayout -import android.view.View -import android.widget.TextView -import com.fastaccess.R -import com.fastaccess.data.dao.FragmentPagerAdapterModel -import com.fastaccess.data.dao.model.Login -import com.fastaccess.helper.PrefGetter -import com.fastaccess.ui.adapter.FragmentsPagerAdapter -import com.fastaccess.ui.widgets.AvatarLayout -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.ViewPagerView - -/** - * Created by Kosh on 09 Jul 2017, 3:50 PM - */ -class MainNavDrawer(val view: BaseActivity<*, *>, private val extraNav: NavigationView?) { - - - init { - setupView() - val viewpager = view.findViewById(R.id.drawerViewPager) - viewpager?.let { - it.adapter = FragmentsPagerAdapter(view.getSupportFragmentManager(), FragmentPagerAdapterModel.buildForDrawer(view)) - view.findViewById(R.id.drawerTabLayout)?.setupWithViewPager(it) - } - } - - fun setupView() { - val view = extraNav?.getHeaderView(0) ?: return - val userModel: Login? = Login.getUser() - userModel?.let { - (view.findViewById(R.id.navAvatarLayout) as AvatarLayout).setUrl(it.avatarUrl, null, false, - PrefGetter.isEnterprise()) - (view.findViewById(R.id.navUsername) as TextView).text = it.login - val navFullName = view.findViewById(R.id.navFullName) - when (it.name.isNullOrBlank()) { - true -> navFullName.visibility = View.GONE - else -> { - navFullName.visibility = View.VISIBLE - navFullName.text = it.name - } - } - view.findViewById(R.id.donatedIcon).visibility = if (PrefGetter.hasSupported()) View.VISIBLE else View.GONE - view.findViewById(R.id.proTextView).visibility = if (PrefGetter.isProEnabled()) View.VISIBLE else View.GONE - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/base/mvp/BaseMvp.java b/app/src/main/java/com/fastaccess/ui/base/mvp/BaseMvp.java deleted file mode 100644 index 18c769b81..000000000 --- a/app/src/main/java/com/fastaccess/ui/base/mvp/BaseMvp.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.fastaccess.ui.base.mvp; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; - -import com.fastaccess.ui.widgets.dialog.MessageDialogView; - -import net.grandcentrix.thirtyinch.TiView; -import net.grandcentrix.thirtyinch.callonmainthread.CallOnMainThread; - -import io.reactivex.Observable; -import io.reactivex.disposables.Disposable; -import io.reactivex.functions.Consumer; - -/** - * Created by Kosh on 25 May 2016, 9:09 PM - */ - -public interface BaseMvp { - - interface FAView extends TiView, MessageDialogView.MessageDialogViewActionCallback, OnScrollTopListener { - - @CallOnMainThread void showProgress(@StringRes int resId); - - @CallOnMainThread void showBlockingProgress(@StringRes int resId); - - @CallOnMainThread void hideProgress(); - - @CallOnMainThread void showMessage(@StringRes int titleRes, @StringRes int msgRes); - - @CallOnMainThread void showMessage(@NonNull String titleRes, @NonNull String msgRes); - - @CallOnMainThread void showErrorMessage(@NonNull String msgRes); - - boolean isLoggedIn(); - - void onRequireLogin(); - - void onLogoutPressed(); - - void onThemeChanged(); - - void onOpenSettings(); - - boolean isEnterprise(); - - void onOpenUrlInBrowser(); - } - - interface FAPresenter { - - void onSaveInstanceState(Bundle outState); - - void onRestoreInstanceState(Bundle outState); - - void manageDisposable(@Nullable Disposable... disposables); - - void manageObservable(@Nullable Observable observable); - - void manageViewDisposable(@Nullable Disposable... disposables); - - boolean isApiCalled(); - - void onSubscribed(boolean cancelable); - - void onError(@NonNull Throwable throwable); - - void makeRestCall(@NonNull Observable observable, @NonNull Consumer onNext); - - void makeRestCall(@NonNull Observable observable, @NonNull Consumer onNext, boolean cancelable); - - void onCheckGitHubStatus(); - } - - interface PaginationListener

    { - int getCurrentPage(); - - int getPreviousTotal(); - - void setCurrentPage(int page); - - void setPreviousTotal(int previousTotal); - - boolean onCallApi(int page, @Nullable P parameter); - } - - interface OnScrollTopListener { - void onScrollTop(int index); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/base/mvp/presenter/BasePresenter.java b/app/src/main/java/com/fastaccess/ui/base/mvp/presenter/BasePresenter.java deleted file mode 100644 index d3c7da5d3..000000000 --- a/app/src/main/java/com/fastaccess/ui/base/mvp/presenter/BasePresenter.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.fastaccess.ui.base.mvp.presenter; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; - -import com.evernote.android.state.StateSaver; -import com.fastaccess.R; -import com.fastaccess.data.dao.GitHubErrorResponse; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; - -import net.grandcentrix.thirtyinch.TiPresenter; -import net.grandcentrix.thirtyinch.rx2.RxTiPresenterDisposableHandler; - -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -import io.reactivex.Observable; -import io.reactivex.disposables.Disposable; -import io.reactivex.functions.Consumer; -import retrofit2.HttpException; - - -/** - * Created by Kosh on 25 May 2016, 9:12 PM - */ - -public class BasePresenter extends TiPresenter implements BaseMvp.FAPresenter { - @com.evernote.android.state.State boolean enterprise; - - private boolean apiCalled; - private final RxTiPresenterDisposableHandler subscriptionHandler = new RxTiPresenterDisposableHandler(this); - - @Override public void onSaveInstanceState(Bundle outState) { - StateSaver.saveInstanceState(this, outState); - } - - @Override public void onRestoreInstanceState(Bundle outState) { - if (outState != null) StateSaver.restoreInstanceState(this, outState); - } - - @Override public void manageDisposable(@Nullable Disposable... disposables) { - if (disposables != null) { - subscriptionHandler.manageDisposables(disposables); - } - } - - @Override public void manageObservable(@Nullable Observable observable) { - if (observable != null) { - manageDisposable(RxHelper.getObservable(observable).subscribe(t -> {/**/}, Throwable::printStackTrace)); - } - } - - @Override public void manageViewDisposable(@Nullable Disposable... disposables) { - if (disposables != null) { - if (isViewAttached()) { - subscriptionHandler.manageViewDisposables(disposables); - } else { - sendToView(v -> manageViewDisposable(disposables)); - } - } - } - - @Override public boolean isApiCalled() { - return apiCalled; - } - - @Override public void onSubscribed(boolean cancelable) { - sendToView(v -> { - if (cancelable) { - v.showProgress(R.string.in_progress); - } else { - v.showBlockingProgress(R.string.in_progress); - } - }); - } - - @Override public void onError(@NonNull Throwable throwable) { - apiCalled = true; - throwable.printStackTrace(); - int code = RestProvider.getErrorCode(throwable); - if (code == 401) { - sendToView(BaseMvp.FAView::onRequireLogin); - return; - } - GitHubErrorResponse errorResponse = RestProvider.getErrorResponse(throwable); - if (errorResponse != null && errorResponse.getMessage() != null) { - sendToView(v -> v.showErrorMessage(errorResponse.getMessage())); - } else { - sendToView(v -> v.showMessage(R.string.error, getPrettifiedErrorMessage(throwable))); - } - } - - @Override public void makeRestCall(@NonNull Observable observable, @NonNull Consumer onNext) { - makeRestCall(observable, onNext, true); - } - - @Override public void makeRestCall(@NonNull Observable observable, @NonNull Consumer onNext, boolean cancelable) { - manageDisposable( - RxHelper.getObservable(observable) - .doOnSubscribe(disposable -> onSubscribed(cancelable)) - .subscribe(onNext, this::onError, () -> apiCalled = true) - ); - } - - @StringRes private int getPrettifiedErrorMessage(@Nullable Throwable throwable) { - int resId = R.string.network_error; - if (throwable instanceof HttpException) { - resId = R.string.network_error; - } else if (throwable instanceof IOException) { - resId = R.string.request_error; - } else if (throwable instanceof TimeoutException) { - resId = R.string.unexpected_error; - } - return resId; - } - - public void onCheckGitHubStatus() { - manageObservable(RestProvider.gitHubStatus() - .doOnNext(gitHubStatusModel -> { - if (!"good".equalsIgnoreCase(gitHubStatusModel.getStatus())) { - sendToView(v -> v.showErrorMessage("Github Status:\n" + gitHubStatusModel.getBody())); - } - })); - } - - public boolean isEnterprise() { - return enterprise; - } - - public void setEnterprise(boolean enterprise) { - this.enterprise = enterprise; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/about/FastHubAboutActivity.java b/app/src/main/java/com/fastaccess/ui/modules/about/FastHubAboutActivity.java deleted file mode 100644 index b70ca8352..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/about/FastHubAboutActivity.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.fastaccess.ui.modules.about; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.content.ContextCompat; -import android.view.MenuItem; -import android.view.View; -import android.widget.Toast; - -import com.danielstone.materialaboutlibrary.ConvenienceBuilder; -import com.danielstone.materialaboutlibrary.MaterialAboutActivity; -import com.danielstone.materialaboutlibrary.items.MaterialAboutActionItem; -import com.danielstone.materialaboutlibrary.model.MaterialAboutCard; -import com.danielstone.materialaboutlibrary.model.MaterialAboutList; -import com.fastaccess.App; -import com.fastaccess.BuildConfig; -import com.fastaccess.R; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.provider.tasks.version.CheckVersionService; -import com.fastaccess.provider.theme.ThemeEngine; -import com.fastaccess.ui.modules.changelog.ChangelogBottomSheetDialog; -import com.fastaccess.ui.modules.main.donation.DonationActivity; -import com.fastaccess.ui.modules.repos.RepoPagerActivity; -import com.fastaccess.ui.modules.repos.issues.create.CreateIssueActivity; -import com.fastaccess.ui.modules.user.UserPagerActivity; -import com.mikepenz.aboutlibraries.Libs; -import com.mikepenz.aboutlibraries.LibsBuilder; - -import es.dmoral.toasty.Toasty; - -/** - * Created by danielstone on 12 Mar 2017, 1:57 AM - */ -public class FastHubAboutActivity extends MaterialAboutActivity { - - private View malRecyclerview; - - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - ThemeEngine.INSTANCE.applyForAbout(this); - super.onCreate(savedInstanceState); - malRecyclerview = findViewById(R.id.mal_recyclerview); - } - - @NonNull @Override protected MaterialAboutList getMaterialAboutList(@NonNull Context context) { - MaterialAboutCard.Builder appCardBuilder = new MaterialAboutCard.Builder(); - buildApp(context, appCardBuilder); - MaterialAboutCard.Builder miscCardBuilder = new MaterialAboutCard.Builder(); - buildMisc(context, miscCardBuilder); - MaterialAboutCard.Builder authorCardBuilder = new MaterialAboutCard.Builder(); - buildAuthor(context, authorCardBuilder); - MaterialAboutCard.Builder newLogoAuthor = new MaterialAboutCard.Builder(); - MaterialAboutCard.Builder logoAuthor = new MaterialAboutCard.Builder(); - buildLogo(context, newLogoAuthor, logoAuthor); - return new MaterialAboutList(appCardBuilder.build(), miscCardBuilder.build(), authorCardBuilder.build(), - newLogoAuthor.build(), logoAuthor.build()); - } - - @Override protected CharSequence getActivityTitle() { - return getString(R.string.app_name); - } - - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK && requestCode == BundleConstant.REQUEST_CODE) { - Toasty.success(App.getInstance(), getString(R.string.thank_you_for_feedback), Toast.LENGTH_SHORT).show(); - } - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - finish(); - } - return false;//override - } - - private void buildLogo(Context context, MaterialAboutCard.Builder newLogoAuthor, MaterialAboutCard.Builder logoAuthor) { - newLogoAuthor.title(getString(R.string.logo_designer, "Cookicons")); - newLogoAuthor.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.google_plus) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_profile)) - .setOnClickAction(() -> ActivityHelper.startCustomTab(this, "https://plus.google.com/+CookiconsDesign")) - .build()) - .addItem(new MaterialAboutActionItem.Builder() - .text(R.string.twitter) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_profile)) - .setOnClickAction(() -> ActivityHelper.startCustomTab(this, "https://twitter.com/mcookie")) - .build()) - .addItem(new MaterialAboutActionItem.Builder() - .text(R.string.website) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_brower)) - .setOnClickAction(() -> ActivityHelper.startCustomTab(this, "https://cookicons.co/")) - .build()); - - logoAuthor.title(String.format("Old %s", getString(R.string.logo_designer, "Kevin Aguilar"))); - logoAuthor.addItem(new MaterialAboutActionItem.Builder() - .text(R.string.google_plus) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_profile)) - .setOnClickAction(() -> ActivityHelper.startCustomTab(this, "https://plus.google.com/+KevinAguilarC")) - .build()) - .addItem(new MaterialAboutActionItem.Builder() - .text(R.string.twitter) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_profile)) - .setOnClickAction(() -> ActivityHelper.startCustomTab(this, "https://twitter.com/kevttob")) - .build()) - .addItem(new MaterialAboutActionItem.Builder() - .text(R.string.website) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_brower)) - .setOnClickAction(() -> ActivityHelper.startCustomTab(this, "http://kevaguilar.com/")) - .build()); - } - - private void buildAuthor(Context context, MaterialAboutCard.Builder authorCardBuilder) { - authorCardBuilder.title(R.string.author); - authorCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text("Kosh Sergani") - .subText("k0shk0sh") - .icon(ContextCompat.getDrawable(context, R.drawable.ic_profile)) - .setOnClickAction(() -> UserPagerActivity.startActivity(context, "k0shk0sh", false, false,0)) - .build()) - .addItem(new MaterialAboutActionItem.Builder() - .text(R.string.fork_github) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_github)) - .setOnClickAction(() -> startActivity(RepoPagerActivity.createIntent(this, "FastHub", "k0shk0sh"))) - .build()) - .addItem(ConvenienceBuilder.createEmailItem(context, ContextCompat.getDrawable(context, R.drawable.ic_email), - getString(R.string.send_email), true, getString(R.string.email_address), getString(R.string.question_concerning_fasthub))); - } - - private void buildMisc(Context context, MaterialAboutCard.Builder miscCardBuilder) { - miscCardBuilder.title(R.string.about) - .addItem(new MaterialAboutActionItem.Builder() - .text(R.string.support_development) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_heart)) - .setOnClickAction(() -> startActivity(new Intent(context, DonationActivity.class))) - .build()) - .addItem(new MaterialAboutActionItem.Builder() - .text(R.string.changelog) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_track_changes)) - .setOnClickAction(() -> new ChangelogBottomSheetDialog().show(getSupportFragmentManager(), "ChangelogBottomSheetDialog")) - .build()) - .addItem(new MaterialAboutActionItem.Builder() - .text(R.string.join_slack) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_slack)) - .setOnClickAction(() -> ActivityHelper.startCustomTab(this, "http://rebrand.ly/fasthub")) - .build()) - .addItem(new MaterialAboutActionItem.Builder() - .text(R.string.open_source_libs) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_github)) - .setOnClickAction(() -> new LibsBuilder() - .withActivityStyle(AppHelper.isNightMode(getResources()) ? Libs.ActivityStyle.DARK : Libs.ActivityStyle.LIGHT) - .withAutoDetect(true) - .withActivityTitle(this.getResources().getString(R.string.open_source_libs)) - .withAboutIconShown(true) - .withAboutVersionShown(true) - .start(this)) - .build()); - } - - private void buildApp(Context context, MaterialAboutCard.Builder appCardBuilder) { - appCardBuilder.addItem(new MaterialAboutActionItem.Builder() - .text(getString(R.string.version)) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_update)) - .subText(BuildConfig.VERSION_NAME) - .setOnClickAction(() -> startService(new Intent(this, CheckVersionService.class))) - .build()) - .addItem(ConvenienceBuilder.createRateActionItem(context, ContextCompat.getDrawable(context, R.drawable.ic_star_filled), - getString(R.string.rate_app), null)) - .addItem(new MaterialAboutActionItem.Builder() - .text(R.string.report_issue) - .subText(R.string.report_issue_here) - .icon(ContextCompat.getDrawable(context, R.drawable.ic_bug)) - .setOnClickAction(() -> CreateIssueActivity.startForResult(this, CreateIssueActivity.startForResult(this), malRecyclerview)) - .build()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogBottomSheetDialog.java b/app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogBottomSheetDialog.java deleted file mode 100644 index c3f8acae5..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogBottomSheetDialog.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.fastaccess.ui.modules.changelog; - -import android.app.Dialog; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.ProgressBar; - -import com.fastaccess.R; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.ui.base.BaseMvpBottomSheetDialogFragment; -import com.fastaccess.ui.widgets.FontButton; -import com.fastaccess.ui.widgets.FontTextView; -import com.prettifier.pretty.PrettifyWebView; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 26 Mar 2017, 10:15 PM - */ - -public class ChangelogBottomSheetDialog extends BaseMvpBottomSheetDialogFragment implements - ChangelogMvp.View { - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.message) FontTextView message; - @BindView(R.id.cancel) FontButton cancel; - @BindView(R.id.messageLayout) View messageLayout; - @BindView(R.id.prettifyWebView) PrettifyWebView prettifyWebView; - @BindView(R.id.webProgress) ProgressBar webProgress; - - @OnClick(R.id.ok) void onOk() { - dismiss(); - } - - @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - if (savedInstanceState == null) { - PrefGetter.setWhatsNewVersion(); - } - webProgress.setVisibility(View.VISIBLE); - cancel.setVisibility(View.GONE); - title.setText(R.string.changelog); - if (getPresenter().getHtml() == null) { - getPresenter().onLoadChangelog(); - } else { - showChangelog(getPresenter().getHtml()); - } - } - - @Override protected int fragmentLayout() { - return R.layout.message_dialog; - } - - @Override public void onChangelogLoaded(@Nullable String html) { - showChangelog(html); - } - - @NonNull @Override public ChangelogPresenter providePresenter() { - return new ChangelogPresenter(); - } - - @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - Dialog dialog = super.onCreateDialog(savedInstanceState); - dialog.setCancelable(false); - dialog.setCanceledOnTouchOutside(false); - return dialog; - } - - private void showChangelog(String html) { - if (prettifyWebView == null) return; - webProgress.setVisibility(View.GONE); - if (html != null) { - message.setVisibility(View.GONE); - prettifyWebView.setVisibility(View.VISIBLE); - prettifyWebView.setGithubContent(html, null, false, false); - prettifyWebView.setNestedScrollingEnabled(false); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogMvp.java b/app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogMvp.java deleted file mode 100644 index 0245fc2f4..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogMvp.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.fastaccess.ui.modules.changelog; - -import android.support.annotation.Nullable; - -import com.fastaccess.ui.base.mvp.BaseMvp; - -/** - * Created by Kosh on 28 May 2017, 10:53 AM - */ - -public interface ChangelogMvp { - - interface View extends BaseMvp.FAView { - void onChangelogLoaded(@Nullable String html); - } - - interface Presenter { - void onLoadChangelog(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogPresenter.java deleted file mode 100644 index 599b9e364..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/changelog/ChangelogPresenter.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.fastaccess.ui.modules.changelog; - -import com.fastaccess.App; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.gson.ToGsonProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import lombok.Getter; - -/** - * Created by Kosh on 28 May 2017, 10:53 AM - */ - -@Getter public class ChangelogPresenter extends BasePresenter implements ChangelogMvp.Presenter { - private String html; - - @Override public void onLoadChangelog() { - manageDisposable(RxHelper.getObservable(ToGsonProvider.getChangelog(App.getInstance())) - .subscribe(s -> { - this.html = s; - sendToView(view -> view.onChangelogLoaded(html)); - }, throwable -> sendToView(view -> view.onChangelogLoaded(null)))); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/code/CodeViewerActivity.java b/app/src/main/java/com/fastaccess/ui/modules/code/CodeViewerActivity.java deleted file mode 100644 index 218a1741c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/code/CodeViewerActivity.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.fastaccess.ui.modules.code; - -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.Menu; -import android.view.MenuItem; -import android.webkit.MimeTypeMap; - -import com.annimon.stream.Objects; -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.gists.gist.GistActivity; -import com.fastaccess.ui.modules.repos.code.files.activity.RepoFilesActivity; -import com.fastaccess.ui.modules.repos.code.prettifier.ViewerFragment; - -import net.grandcentrix.thirtyinch.TiPresenter; - -/** - * Created by Kosh on 27 Nov 2016, 3:43 PM - */ - -public class CodeViewerActivity extends BaseActivity { - - @State String url; - @State String htmlUrl; - - public static void startActivity(@NonNull Context context, @NonNull String url, @NonNull String htmlUrl) { - if (!InputHelper.isEmpty(url)) { - Intent intent = ActivityHelper.editBundle(createIntent(context, url, htmlUrl), LinkParserHelper.isEnterprise(htmlUrl)); - context.startActivity(intent); - } - } - - public static Intent createIntent(@NonNull Context context, @NonNull String url, @NonNull String htmlUrl) { - Intent intent = new Intent(context, CodeViewerActivity.class); - boolean isEnterprise = LinkParserHelper.isEnterprise(htmlUrl); - url = LinkParserHelper.getEnterpriseGistUrl(url, isEnterprise); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA_TWO, htmlUrl) - .put(BundleConstant.EXTRA, url) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - return intent; - } - - @Override protected int layout() { - return R.layout.activity_fragment_layout; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } - - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState == null) { - Intent intent = Objects.requireNonNull(getIntent(), "Intent is null"); - Bundle bundle = Objects.requireNonNull(intent.getExtras()); - //noinspection ConstantConditions - url = Objects.requireNonNull(bundle.getString(BundleConstant.EXTRA), "Url is null"); - htmlUrl = bundle.getString(BundleConstant.EXTRA_TWO); - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.container, ViewerFragment.newInstance(url, htmlUrl), ViewerFragment.TAG) - .commit(); - } - String title = Uri.parse(url).getLastPathSegment(); - setTitle(title); - if (toolbar != null) toolbar.setSubtitle(MimeTypeMap.getFileExtensionFromUrl(url)); - setTaskName(title); - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.download_browser_menu, menu); - return super.onCreateOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (InputHelper.isEmpty(url)) return super.onOptionsItemSelected(item); - if (item.getItemId() == R.id.viewAsCode) { - ViewerFragment viewerFragment = (ViewerFragment) AppHelper.getFragmentByTag(getSupportFragmentManager(), ViewerFragment.TAG); - if (viewerFragment != null) { - viewerFragment.onViewAsCode(); - } - return true; - } else if (item.getItemId() == R.id.download) { - if (ActivityHelper.checkAndRequestReadWritePermission(this)) { - RestProvider.downloadFile(this, url); - } - return true; - } else if (item.getItemId() == R.id.browser) { - ActivityHelper.openChooser(this, htmlUrl != null ? htmlUrl : url); - return true; - } else if (item.getItemId() == R.id.copy) { - AppHelper.copyToClipboard(this, htmlUrl != null ? htmlUrl : url); - return true; - } else if (item.getItemId() == R.id.share) { - ActivityHelper.shareUrl(this, htmlUrl != null ? htmlUrl : url); - return true; - } else if (item.getItemId() == android.R.id.home) { - Uri uri = Uri.parse(url); - if (uri == null) { - finish(); - return true; - } - String gistId = LinkParserHelper.getGistId(uri); - if (!InputHelper.isEmpty(gistId)) { - startActivity(GistActivity.createIntent(this, gistId, isEnterprise())); - } else { - RepoFilesActivity.startActivity(this, url, isEnterprise()); - } - finish(); - return true; - } - return super.onOptionsItemSelected(item); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/editor/EditorActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/editor/EditorActivity.kt deleted file mode 100644 index e8ef9ac8a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/editor/EditorActivity.kt +++ /dev/null @@ -1,230 +0,0 @@ -package com.fastaccess.ui.modules.editor - -import android.annotation.SuppressLint -import android.app.Activity -import android.content.Intent -import android.os.Bundle -import android.support.annotation.StringRes -import android.support.transition.TransitionManager -import android.support.v4.app.FragmentManager -import android.view.Menu -import android.view.MenuItem -import android.view.View -import android.view.View.GONE -import android.view.ViewGroup -import android.widget.EditText -import android.widget.LinearLayout -import android.widget.ListView -import butterknife.BindView -import butterknife.OnClick -import com.evernote.android.state.State -import com.fastaccess.R -import com.fastaccess.data.dao.EditReviewCommentModel -import com.fastaccess.data.dao.model.Comment -import com.fastaccess.helper.* -import com.fastaccess.provider.emoji.Emoji -import com.fastaccess.provider.markdown.MarkDownProvider -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.dialog.MessageDialogView -import com.fastaccess.ui.widgets.markdown.MarkDownLayout -import com.fastaccess.ui.widgets.markdown.MarkdownEditText -import java.util.* - -/** - * Created by Kosh on 27 Nov 2016, 1:32 AM - */ - -class EditorActivity : BaseActivity(), EditorMvp.View { - - private var participants: ArrayList? = null - private val sentFromFastHub: String by lazy { - "\n\n_" + getString(R.string.sent_from_fasthub, AppHelper.getDeviceName(), "", - "[" + getString(R.string.app_name) + "](https://play.google.com/store/apps/details?id=com.fastaccess.github)") + "_" - } - - @BindView(R.id.replyQuote) lateinit var replyQuote: LinearLayout - @BindView(R.id.replyQuoteText) lateinit var quote: FontTextView - @BindView(R.id.markDownLayout) lateinit var markDownLayout: MarkDownLayout - @BindView(R.id.editText) lateinit var editText: MarkdownEditText - @BindView(R.id.list_divider) lateinit var listDivider: View - @BindView(R.id.parentView) lateinit var parentView: View - @BindView(R.id.autocomplete) lateinit var mention: ListView - - @State @BundleConstant.ExtraType var extraType: String? = null - @State var itemId: String? = null - @State var login: String? = null - @State var issueNumber: Int = 0 - @State var commentId: Long = 0 - @State var sha: String? = null - @State var reviewComment: EditReviewCommentModel? = null - - override fun layout(): Int = R.layout.editor_layout - - override fun isTransparent(): Boolean = false - - override fun canBack(): Boolean = true - - override fun isSecured(): Boolean = false - - override fun providePresenter(): EditorPresenter = EditorPresenter() - - @OnClick(R.id.replyQuoteText) internal fun onToggleQuote() { - TransitionManager.beginDelayedTransition((parentView as ViewGroup)) - if (quote.maxLines == 3) { - quote.maxLines = Integer.MAX_VALUE - } else { - quote.maxLines = 3 - } - quote.setCompoundDrawablesWithIntrinsicBounds(0, 0, - if (quote.maxLines == 3) R.drawable.ic_arrow_drop_down - else R.drawable.ic_arrow_drop_up, 0) - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - markDownLayout.markdownListener = this - setToolbarIcon(R.drawable.ic_clear) - if (savedInstanceState == null) { - onCreate() - } - invalidateOptionsMenu() - editText.initListView(mention, listDivider, participants) - editText.requestFocus() - } - - override fun onSendResultAndFinish(commentModel: Comment, isNew: Boolean) { - hideProgress() - val intent = Intent() - intent.putExtras(Bundler.start() - .put(BundleConstant.ITEM, commentModel) - .put(BundleConstant.EXTRA, isNew) - .end()) - setResult(Activity.RESULT_OK, intent) - finish() - } - - override fun onSendMarkDownResult() { - val intent = Intent() - intent.putExtras(Bundler.start().put(BundleConstant.EXTRA, editText.savedText).end()) - setResult(Activity.RESULT_OK, intent) - finish() - } - - override fun onSendReviewResultAndFinish(comment: EditReviewCommentModel, isNew: Boolean) { - hideProgress() - val intent = Intent() - intent.putExtras(Bundler.start() - .put(BundleConstant.ITEM, comment) - .put(BundleConstant.EXTRA, isNew) - .end()) - setResult(Activity.RESULT_OK, intent) - finish() - } - - override fun onCreateOptionsMenu(menu: Menu): Boolean { - menuInflater.inflate(R.menu.done_menu, menu) - return super.onCreateOptionsMenu(menu) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == R.id.submit) { - if (PrefGetter.isSentViaEnabled()) { - val temp = editText.savedText.toString() - if (!temp.contains(sentFromFastHub)) { - editText.savedText = editText.savedText.toString() + sentFromFastHub - } - } - presenter.onHandleSubmission(editText.savedText, extraType, itemId, commentId, login, issueNumber, sha, reviewComment) - return true - } - return super.onOptionsItemSelected(item) - } - - override fun onPrepareOptionsMenu(menu: Menu): Boolean { - if (menu.findItem(R.id.submit) != null) { - menu.findItem(R.id.submit).isEnabled = true - } - if (BundleConstant.ExtraType.FOR_RESULT_EXTRA.equals(extraType, ignoreCase = true)) { - menu.findItem(R.id.submit).setIcon(R.drawable.ic_done) - } - return super.onPrepareOptionsMenu(menu) - } - - override fun showProgress(@StringRes resId: Int) { - super.showProgress(resId) - invalidateOptionsMenu() - } - - override fun hideProgress() { - invalidateOptionsMenu() - super.hideProgress() - } - - override fun onBackPressed() { - if (!InputHelper.isEmpty(editText)) { - ViewHelper.hideKeyboard(editText) - MessageDialogView.newInstance(getString(R.string.close), getString(R.string.unsaved_data_warning), - Bundler.start() - .put("primary_extra", getString(R.string.discard)) - .put("secondary_extra", getString(R.string.cancel)) - .put(BundleConstant.EXTRA, true) - .end()) - .show(supportFragmentManager, MessageDialogView.TAG) - return - - } - super.onBackPressed() - } - - override fun onMessageDialogActionClicked(isOk: Boolean, bundle: Bundle?) { - super.onMessageDialogActionClicked(isOk, bundle) - if (isOk && bundle != null) { - finish() - } - } - - override fun onAppendLink(title: String?, link: String?, isLink: Boolean) { - markDownLayout.onAppendLink(title, link, isLink) - } - - override fun getEditText(): EditText = editText - - override fun getSavedText(): CharSequence? = editText.savedText - - override fun fragmentManager(): FragmentManager = supportFragmentManager - - @SuppressLint("SetTextI18n") - override fun onEmojiAdded(emoji: Emoji?) { - markDownLayout.onEmojiAdded(emoji) - } - - private fun onCreate() { - val intent = intent - if (intent != null && intent.extras != null) { - val bundle = intent.extras - extraType = bundle.getString(BundleConstant.EXTRA_TYPE) - reviewComment = bundle.getParcelable(BundleConstant.REVIEW_EXTRA) - itemId = bundle.getString(BundleConstant.ID) - login = bundle.getString(BundleConstant.EXTRA_TWO) - if (extraType.equals(BundleConstant.ExtraType.EDIT_COMMIT_COMMENT_EXTRA, ignoreCase = true) - || extraType.equals(BundleConstant.ExtraType.NEW_COMMIT_COMMENT_EXTRA, ignoreCase = true)) { - sha = bundle.getString(BundleConstant.EXTRA_THREE) - } else { - issueNumber = bundle.getInt(BundleConstant.EXTRA_THREE) - } - commentId = bundle.getLong(BundleConstant.EXTRA_FOUR) - val textToUpdate = bundle.getString(BundleConstant.EXTRA) - if (!InputHelper.isEmpty(textToUpdate)) { - editText.setText(String.format("%s ", textToUpdate)) - editText.setSelection(InputHelper.toString(editText).length) - } - if (bundle.getString("message", "").isBlank()) { - replyQuote.visibility = GONE - } else { - MarkDownProvider.setMdText(quote, bundle.getString("message", "")) - } - participants = bundle.getStringArrayList("participants") - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/editor/EditorMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/editor/EditorMvp.kt deleted file mode 100644 index 114176171..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/editor/EditorMvp.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.fastaccess.ui.modules.editor - -import com.fastaccess.data.dao.EditReviewCommentModel -import com.fastaccess.data.dao.model.Comment -import com.fastaccess.helper.BundleConstant -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.modules.editor.emoji.EmojiMvp -import com.fastaccess.ui.modules.editor.popup.EditorLinkImageMvp -import com.fastaccess.ui.widgets.markdown.MarkDownLayout - -/** - * Created by Kosh on 27 Nov 2016, 1:31 AM - */ - -interface EditorMvp { - - interface View : BaseMvp.FAView, EditorLinkImageMvp.EditorLinkCallback, - MarkDownLayout.MarkdownListener, EmojiMvp.EmojiCallback { - fun onSendResultAndFinish(commentModel: Comment, isNew: Boolean) - - fun onSendMarkDownResult() - - fun onSendReviewResultAndFinish(comment: EditReviewCommentModel, isNew: Boolean) - } - - interface Presenter : BaseMvp.FAPresenter { - - fun onEditGistComment(id: Long, savedText: CharSequence?, gistId: String) - - fun onSubmitGistComment(savedText: CharSequence?, gistId: String) - - fun onSubmitIssueComment(savedText: CharSequence, itemId: String, login: String, issueNumber: Int) - - fun onEditIssueComment(savedText: CharSequence, itemId: String, id: Long, login: String, issueNumber: Int) - - fun onSubmitCommitComment(savedText: CharSequence, itemId: String, login: String, sha: String) - - fun onEditCommitComment(savedText: CharSequence, itemId: String, login: String, id: Long) - - fun onHandleSubmission(savedText: CharSequence?, @BundleConstant.ExtraType extraType: String?, - itemId: String?, id: Long, login: String?, issueNumber: Int, sha: String?, - reviewComment: EditReviewCommentModel?) - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/editor/EditorPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/editor/EditorPresenter.kt deleted file mode 100644 index df35994ba..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/editor/EditorPresenter.kt +++ /dev/null @@ -1,157 +0,0 @@ -package com.fastaccess.ui.modules.editor - -import com.fastaccess.data.dao.CommentRequestModel -import com.fastaccess.data.dao.EditReviewCommentModel -import com.fastaccess.data.dao.model.Comment -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.BundleConstant.ExtraType.* -import com.fastaccess.helper.InputHelper -import com.fastaccess.provider.rest.RestProvider -import com.fastaccess.ui.base.mvp.presenter.BasePresenter - -/** - * Created by Kosh on 27 Nov 2016, 1:31 AM - */ - -class EditorPresenter : BasePresenter(), EditorMvp.Presenter { - - override fun onEditGistComment(id: Long, savedText: CharSequence?, gistId: String) { - if (!InputHelper.isEmpty(savedText)) { - val requestModel = CommentRequestModel() - requestModel.body = savedText!!.toString() - makeRestCall(RestProvider.getGistService(isEnterprise).editGistComment(gistId, id, requestModel), - { comment -> sendToView { view -> view.onSendResultAndFinish(comment, false) } }, false) - } - } - - override fun onSubmitGistComment(savedText: CharSequence?, gistId: String) { - if (!InputHelper.isEmpty(savedText)) { - val requestModel = CommentRequestModel() - requestModel.body = savedText!!.toString() - makeRestCall(RestProvider.getGistService(isEnterprise).createGistComment(gistId, requestModel), - { comment -> sendToView { view -> view.onSendResultAndFinish(comment, true) } }, false) - } - } - - override fun onHandleSubmission(savedText: CharSequence?, @BundleConstant.ExtraType extraType: String?, - itemId: String?, id: Long, login: String?, issueNumber: Int, - sha: String?, reviewComment: EditReviewCommentModel?) { - if (extraType == null) { - throw NullPointerException("extraType is null") - } - when (extraType) { - EDIT_GIST_COMMENT_EXTRA -> { - if (itemId == null) { - throw NullPointerException("itemId is null") - } - onEditGistComment(id, savedText, itemId) - } - NEW_GIST_COMMENT_EXTRA -> { - if (itemId == null) { - throw NullPointerException("itemId is null") - } - onSubmitGistComment(savedText, itemId) - } - FOR_RESULT_EXTRA -> sendToView({ it.onSendMarkDownResult() }) - EDIT_ISSUE_COMMENT_EXTRA -> { - if (itemId == null || login == null) { - throw NullPointerException("itemId or login is null") - } - onEditIssueComment(savedText!!, itemId, id, login, issueNumber) - } - NEW_ISSUE_COMMENT_EXTRA -> { - if (itemId == null || login == null) { - throw NullPointerException("itemId or login is null") - } - onSubmitIssueComment(savedText!!, itemId, login, issueNumber) - } - NEW_COMMIT_COMMENT_EXTRA -> { - if (itemId == null || login == null || sha == null) { - throw NullPointerException("itemId or login is null") - } - onSubmitCommitComment(savedText!!, itemId, login, sha) - } - EDIT_COMMIT_COMMENT_EXTRA -> { - if (itemId == null || login == null) { - throw NullPointerException("itemId or login is null") - } - onEditCommitComment(savedText!!, itemId, login, id) - } - NEW_REVIEW_COMMENT_EXTRA -> { - if (reviewComment == null || itemId == null || login == null || savedText == null) { - throw NullPointerException("reviewComment null") - } - onSubmitReviewComment(reviewComment, savedText, itemId, login, issueNumber) - } - EDIT_REVIEW_COMMENT_EXTRA -> { - if (reviewComment == null || itemId == null || login == null || savedText == null) { - throw NullPointerException("reviewComment null") - } - onEditReviewComment(reviewComment, savedText, itemId, login, issueNumber, id) - } - } - } - - private fun onEditReviewComment(reviewComment: EditReviewCommentModel, savedText: CharSequence, repoId: String, - login: String, @Suppress("UNUSED_PARAMETER") issueNumber: Int, id: Long) { - if (!InputHelper.isEmpty(savedText)) { - val requestModel = CommentRequestModel() - requestModel.body = savedText.toString() - makeRestCall(RestProvider.getReviewService(isEnterprise).editComment(login, repoId, id, requestModel) - .map { comment -> - reviewComment.commentModel = comment - reviewComment - }, { comment -> sendToView { view -> view.onSendReviewResultAndFinish(comment, false) } }, false) - } - } - - private fun onSubmitReviewComment(reviewComment: EditReviewCommentModel, savedText: CharSequence, - repoId: String, login: String, issueNumber: Int) { - if (!InputHelper.isEmpty(savedText)) { - val requestModel = CommentRequestModel() - requestModel.body = savedText.toString() - requestModel.inReplyTo = reviewComment.inReplyTo - makeRestCall(RestProvider.getReviewService(isEnterprise).submitComment(login, repoId, issueNumber.toLong(), requestModel) - .map { comment -> - reviewComment.commentModel = comment - reviewComment - }, { comment -> sendToView { view -> view.onSendReviewResultAndFinish(comment, true) } }, false) - } - } - - override fun onSubmitIssueComment(savedText: CharSequence, itemId: String, login: String, issueNumber: Int) { - if (!InputHelper.isEmpty(savedText)) { - val requestModel = CommentRequestModel() - requestModel.body = savedText.toString() - makeRestCall(RestProvider.getIssueService(isEnterprise).createIssueComment(login, itemId, issueNumber, requestModel) - ) { comment -> sendToView { view -> view.onSendResultAndFinish(comment, true) } } - } - } - - override fun onEditIssueComment(savedText: CharSequence, itemId: String, id: Long, login: String, issueNumber: Int) { - if (!InputHelper.isEmpty(savedText)) { - val requestModel = CommentRequestModel() - requestModel.body = savedText.toString() - makeRestCall(RestProvider.getIssueService(isEnterprise).editIssueComment(login, itemId, id, requestModel), - { comment -> sendToView { view -> view.onSendResultAndFinish(comment, false) } }, false) - } - } - - override fun onSubmitCommitComment(savedText: CharSequence, itemId: String, login: String, sha: String) { - if (!InputHelper.isEmpty(savedText)) { - val requestModel = CommentRequestModel() - requestModel.body = savedText.toString() - makeRestCall(RestProvider.getRepoService(isEnterprise).postCommitComment(login, itemId, sha, requestModel), - { comment -> sendToView { view -> view.onSendResultAndFinish(comment, true) } }, false) - } - } - - override fun onEditCommitComment(savedText: CharSequence, itemId: String, login: String, id: Long) { - if (!InputHelper.isEmpty(savedText)) { - val requestModel = CommentRequestModel() - requestModel.body = savedText.toString() - makeRestCall(RestProvider.getRepoService(isEnterprise).editCommitComment(login, itemId, id, requestModel), - { comment -> sendToView { view -> view.onSendResultAndFinish(comment, false) } }, false) - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/editor/comment/CommentEditorFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/editor/comment/CommentEditorFragment.kt deleted file mode 100644 index bfb552b80..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/editor/comment/CommentEditorFragment.kt +++ /dev/null @@ -1,174 +0,0 @@ -package com.fastaccess.ui.modules.editor.comment - -import android.annotation.SuppressLint -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.support.transition.TransitionManager -import android.support.v4.app.FragmentManager -import android.view.View -import android.view.ViewGroup -import android.widget.EditText -import butterknife.BindView -import butterknife.OnClick -import com.fastaccess.R -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.helper.InputHelper -import com.fastaccess.helper.ViewHelper -import com.fastaccess.provider.emoji.Emoji -import com.fastaccess.ui.base.BaseFragment -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.editor.EditorActivity -import com.fastaccess.ui.modules.editor.emoji.EmojiMvp -import com.fastaccess.ui.modules.editor.popup.EditorLinkImageMvp -import com.fastaccess.ui.widgets.markdown.MarkDownLayout -import com.fastaccess.ui.widgets.markdown.MarkdownEditText -import net.yslibrary.android.keyboardvisibilityevent.KeyboardVisibilityEvent -import net.yslibrary.android.keyboardvisibilityevent.Unregistrar - -/** - * Created by kosh on 21/08/2017. - */ -class CommentEditorFragment : BaseFragment>(), MarkDownLayout.MarkdownListener, - EmojiMvp.EmojiCallback, EditorLinkImageMvp.EditorLinkCallback { - - @BindView(R.id.commentBox) lateinit var commentBox: View - @BindView(R.id.markdDownLayout) lateinit var markdDownLayout: MarkDownLayout - @BindView(R.id.commentText) lateinit var commentText: MarkdownEditText - @BindView(R.id.markdownBtnHolder) lateinit var markdownBtnHolder: View - @BindView(R.id.sendComment) lateinit var sendComment: View - @BindView(R.id.toggleButtons) lateinit var toggleButtons: View - private var commentListener: CommentListener? = null - private var keyboardListener: Unregistrar? = null - - @OnClick(R.id.sendComment) internal fun onComment() { - if (!InputHelper.isEmpty(getEditText())) { - commentListener?.onSendActionClicked(InputHelper.toString(getEditText()), arguments?.getBundle(BundleConstant.ITEM)) - ViewHelper.hideKeyboard(getEditText()) - arguments = null - } - } - - @OnClick(R.id.fullScreenComment) internal fun onExpandScreen() { - val intent = Intent(context, EditorActivity::class.java) - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA_TYPE, BundleConstant.ExtraType.FOR_RESULT_EXTRA) - .put(BundleConstant.EXTRA, getEditText().text.toString()) - .putStringArrayList("participants", commentListener?.getNamesToTag()) - .end()) - startActivityForResult(intent, BundleConstant.REQUEST_CODE) - } - - @OnClick(R.id.toggleButtons) internal fun onToggleButtons(v: View) { - TransitionManager.beginDelayedTransition((view as ViewGroup?)!!) - v.isActivated = !v.isActivated - markdownBtnHolder.visibility = if (markdownBtnHolder.visibility == View.VISIBLE) View.GONE else View.VISIBLE - } - - override fun onAttach(context: Context?) { - super.onAttach(context) - if (parentFragment is CommentListener) { - commentListener = parentFragment as CommentListener - } else if (context is CommentListener) { - commentListener = context - } - } - - override fun onDetach() { - commentListener = null - super.onDetach() - } - - override fun providePresenter(): BasePresenter = BasePresenter() - - override fun fragmentLayout(): Int = R.layout.comment_box_layout - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - arguments?.let { - val hideSendButton = it.getBoolean(BundleConstant.YES_NO_EXTRA) - if (hideSendButton) { - sendComment.visibility = View.GONE - } - } - markdDownLayout.markdownListener = this - if (savedInstanceState == null) { - arguments?.getBundle(BundleConstant.ITEM)?.getString(BundleConstant.EXTRA)?.let { commentText.setText(it) } - } - } - - override fun onStart() { - super.onStart() - keyboardListener = KeyboardVisibilityEvent.registerEventListener(activity, { - TransitionManager.beginDelayedTransition((view as ViewGroup?)!!) - toggleButtons.isActivated = it - markdownBtnHolder.visibility = if (!it) View.GONE else View.VISIBLE - }) - } - - override fun onStop() { - keyboardListener?.unregister() - super.onStop() - } - - override fun getEditText(): EditText = commentText - - override fun fragmentManager(): FragmentManager = childFragmentManager - - override fun getSavedText(): CharSequence? = commentText.savedText - - override fun onEmojiAdded(emoji: Emoji?) = markdDownLayout.onEmojiAdded(emoji) - - @SuppressLint("SetTextI18n") - fun onCreateComment(text: String, bundle: Bundle?) { - arguments = Bundler.start().put(BundleConstant.ITEM, bundle).end() - commentText.setText("${if (commentText.text.isNullOrBlank()) "" else "${commentText.text} "}$text") - getEditText().setSelection(getEditText().text.length) - commentText.requestFocus() - ViewHelper.showKeyboard(commentText) - } - - fun onAddUserName(username: String) { - getEditText().setText(if (getEditText().text.isNullOrBlank()) { - "@$username" - } else { - "${getEditText().text} @$username" - }) - getEditText().setSelection(getEditText().text.length) - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (resultCode == Activity.RESULT_OK) { - if (requestCode == BundleConstant.REQUEST_CODE) { - val text = data?.extras?.getCharSequence(BundleConstant.EXTRA) - getEditText().setText(text) - getEditText().setSelection(getEditText().text.length) - } - } - } - - override fun onAppendLink(title: String?, link: String?, isLink: Boolean) { - markdDownLayout.onAppendLink(title, link, isLink) - } - - interface CommentListener { - fun onCreateComment(text: String, bundle: Bundle?) {} - fun onSendActionClicked(text: String, bundle: Bundle?) - fun onTagUser(username: String) - fun onClearEditText() - fun getNamesToTag(): ArrayList? - } - - companion object { - fun newInstance(bundle: Bundle?): CommentEditorFragment { - val fragment = CommentEditorFragment() - bundle?.let { - fragment.arguments = Bundler.start().put(BundleConstant.ITEM, bundle).end() - } - return fragment - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiBottomSheet.kt b/app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiBottomSheet.kt deleted file mode 100644 index 0ea734044..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiBottomSheet.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.fastaccess.ui.modules.editor.emoji - -import android.content.Context -import android.os.Bundle -import android.text.Editable -import android.view.View -import butterknife.BindView -import butterknife.OnTextChanged -import com.fastaccess.R -import com.fastaccess.provider.emoji.Emoji -import com.fastaccess.ui.adapter.EmojiAdapter -import com.fastaccess.ui.base.BaseMvpBottomSheetDialogFragment -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView -import com.fastaccess.ui.widgets.recyclerview.layout_manager.GridManager -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller - -/** - * Created by kosh on 17/08/2017. - */ -class EmojiBottomSheet : BaseMvpBottomSheetDialogFragment(), EmojiMvp.View { - - @BindView(R.id.recycler) lateinit var recycler: DynamicRecyclerView - @BindView(R.id.fastScroller) lateinit var fastScroller: RecyclerViewFastScroller - - val adapter: EmojiAdapter by lazy { EmojiAdapter(this) } - - var emojiCallback: EmojiMvp.EmojiCallback? = null - - - @OnTextChanged(value = [(R.id.editText)], callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) - fun onTextChange(text: Editable) { - adapter.filter.filter(text) - } - - override fun onAttach(context: Context) { - super.onAttach(context) - emojiCallback = when { - parentFragment is EmojiMvp.EmojiCallback -> parentFragment as EmojiMvp.EmojiCallback - context is EmojiMvp.EmojiCallback -> context - else -> throw IllegalArgumentException("${context.javaClass.simpleName} must implement EmojiMvp.EmojiCallback") - } - } - - override fun onDetach() { - emojiCallback = null - super.onDetach() - } - - override fun fragmentLayout(): Int = R.layout.emoji_popup_layout - - override fun providePresenter(): EmojiPresenter = EmojiPresenter() - - override fun clearAdapter() { - adapter.clear() - } - - override fun onAddEmoji(emoji: Emoji) { - adapter.addItem(emoji) - } - - override fun onItemClick(position: Int, v: View?, item: Emoji) { - emojiCallback?.onEmojiAdded(item) - dismiss() - } - - override fun onItemLongClick(position: Int, v: View?, item: Emoji?) {} - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - recycler.adapter = adapter - fastScroller.attachRecyclerView(recycler) - presenter.onLoadEmoji() - val gridManager = recycler.layoutManager as GridManager - gridManager.iconSize = resources.getDimensionPixelSize(R.dimen.header_icon_zie) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiMvp.kt deleted file mode 100644 index eec2eb1f9..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiMvp.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.fastaccess.ui.modules.editor.emoji - -import com.fastaccess.provider.emoji.Emoji -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by kosh on 17/08/2017. - */ -interface EmojiMvp { - - interface View : BaseMvp.FAView, BaseViewHolder.OnItemClickListener { - fun clearAdapter() - fun onAddEmoji(emoji: Emoji) - } - - interface Presenter { - fun onLoadEmoji() - } - - interface EmojiCallback { - fun onEmojiAdded(emoji: Emoji?) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiPresenter.kt deleted file mode 100644 index 3ae507b8f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/editor/emoji/EmojiPresenter.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.fastaccess.ui.modules.editor.emoji - -import com.fastaccess.provider.emoji.Emoji -import com.fastaccess.provider.emoji.EmojiManager -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import io.reactivex.Observable - -/** - * Created by kosh on 17/08/2017. - */ - -class EmojiPresenter : BasePresenter(), EmojiMvp.Presenter { - override fun onLoadEmoji() { - manageObservable(Observable.create { e -> - val emojies = EmojiManager.getAll() - emojies?.let { - it.onEach { - if (!e.isDisposed) { - e.onNext(it) - } - } - } - e.onComplete() - } - .doOnSubscribe { sendToView { it.clearAdapter() } } - .doOnNext { emoji -> sendToView { it.onAddEmoji(emoji) } }) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImageDialogFragment.java b/app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImageDialogFragment.java deleted file mode 100644 index a79a2b803..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImageDialogFragment.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.fastaccess.ui.modules.editor.popup; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TextInputLayout; -import android.view.View; - -import com.fastaccess.App; -import com.fastaccess.R; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.FileHelper; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.widgets.FontButton; - -import java.io.File; - -import butterknife.BindView; -import butterknife.OnClick; -import es.dmoral.toasty.Toasty; - -/** - * Created by Kosh on 15 Apr 2017, 9:14 PM - */ - -public class EditorLinkImageDialogFragment extends BaseDialogFragment - implements EditorLinkImageMvp.View { - - private EditorLinkImageMvp.EditorLinkCallback callback; - - @BindView(R.id.title) TextInputLayout title; - @BindView(R.id.link) TextInputLayout link; - @BindView(R.id.select) FontButton select; - - public static EditorLinkImageDialogFragment newInstance(boolean isLink, @Nullable String link) { - EditorLinkImageDialogFragment fragment = new EditorLinkImageDialogFragment(); - fragment.setArguments(Bundler - .start() - .put(BundleConstant.YES_NO_EXTRA, isLink) - .put(BundleConstant.ITEM, link) - .end()); - return fragment; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof EditorLinkImageMvp.EditorLinkCallback) { - callback = (EditorLinkImageMvp.EditorLinkCallback) getParentFragment(); - } else if (context instanceof EditorLinkImageMvp.EditorLinkCallback) { - callback = (EditorLinkImageMvp.EditorLinkCallback) context; - } - } - - @Override public void onDetach() { - callback = null; - super.onDetach(); - } - - @Override public void onUploaded(@Nullable String title, @Nullable String link) { - hideProgress(); - if (callback != null) { - callback.onAppendLink(title, link != null ? link.replace("http:", "https:") : null, isLink()); - } - dismiss(); - } - - @Override protected int fragmentLayout() { - return R.layout.markdown_link_image_dialog_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - select.setVisibility(isLink() ? View.GONE : View.VISIBLE); - if (savedInstanceState == null) { - title.getEditText().setText(getArguments().getString(BundleConstant.ITEM)); - } - } - - @NonNull @Override public EditorLinkImagePresenter providePresenter() { - return new EditorLinkImagePresenter(); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK && requestCode == BundleConstant.REQUEST_CODE) { - if (data != null && data.getData() != null) { - String path = FileHelper.getPath(getContext(), data.getData()); - if (!InputHelper.isEmpty(path)) { - getPresenter().onSubmit(InputHelper.toString(title), new File(path)); - } else { - Toasty.error(App.getInstance(), getString(R.string.failed_selecting_image)).show(); - } - } - } - } - - @OnClick(R.id.select) public void onSelectClicked() { - if (ActivityHelper.checkAndRequestReadWritePermission(getActivity())) { - Intent intent = new Intent(); - intent.setType("image/*"); - intent.setAction(Intent.ACTION_GET_CONTENT); - startActivityForResult(Intent.createChooser(intent, getString(R.string.select_picture)), BundleConstant.REQUEST_CODE); - } - } - - @OnClick(R.id.cancel) public void onCancelClicked() { - dismiss(); - } - - @OnClick(R.id.insert) public void onInsertClicked() { - if (callback != null) { - callback.onAppendLink(InputHelper.toString(title), InputHelper.toString(link), isLink()); - } - dismiss(); - } - - private boolean isLink() { - return getArguments() != null && getArguments().getBoolean(BundleConstant.YES_NO_EXTRA); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImageMvp.java b/app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImageMvp.java deleted file mode 100644 index 07ad87e15..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImageMvp.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.fastaccess.ui.modules.editor.popup; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.ui.base.mvp.BaseMvp; - -import java.io.File; - -/** - * Created by Kosh on 15 Apr 2017, 9:06 PM - */ - -public interface EditorLinkImageMvp { - - interface EditorLinkCallback { - void onAppendLink(@Nullable String title, @Nullable String link, boolean isLink); - } - - interface View extends BaseMvp.FAView { - void onUploaded(@Nullable String title, @Nullable String link); - } - - interface Presenter { - void onSubmit(@Nullable String title, @NonNull File file); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImagePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImagePresenter.java deleted file mode 100644 index 303ef6ee6..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/editor/popup/EditorLinkImagePresenter.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.fastaccess.ui.modules.editor.popup; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.ImgurReponseModel; -import com.fastaccess.provider.rest.ImgurProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.io.File; - -import okhttp3.MediaType; -import okhttp3.RequestBody; - -/** - * Created by Kosh on 15 Apr 2017, 9:08 PM - */ - -public class EditorLinkImagePresenter extends BasePresenter implements EditorLinkImageMvp.Presenter { - @Override public void onSubmit(@Nullable String title, @NonNull File file) { - if (file.exists()) { - RequestBody image = RequestBody.create(MediaType.parse("image/*"), file); - makeRestCall(ImgurProvider.getImgurService().postImage(title, image), - imgurReponseModel -> { - if (imgurReponseModel.getData() != null) { - ImgurReponseModel.ImgurImage imageResponse = imgurReponseModel.getData(); - sendToView(view -> view.onUploaded(title == null ? imageResponse.getTitle() : title, imageResponse.getLink())); - return; - } - sendToView(view -> view.onUploaded(null, null)); - }, false); - } else { - if (getView() != null) getView().onUploaded(null, null); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsFragment.java b/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsFragment.java deleted file mode 100644 index 672418306..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsFragment.java +++ /dev/null @@ -1,186 +0,0 @@ -package com.fastaccess.ui.modules.feeds; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.GitCommitModel; -import com.fastaccess.data.dao.NameParser; -import com.fastaccess.data.dao.SimpleUrlsModel; -import com.fastaccess.data.dao.model.Event; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.adapter.FeedsAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.code.commit.details.CommitPagerActivity; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.ListDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.ArrayList; -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -public class FeedsFragment extends BaseFragment implements FeedsMvp.View { - - public static final String TAG = FeedsFragment.class.getSimpleName(); - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private FeedsAdapter adapter; - private OnLoadMore onLoadMore; - - public static FeedsFragment newInstance(@Nullable String user) { - return newInstance(user, false); - } - - public static FeedsFragment newInstance(@Nullable String user, boolean isOrg) { - FeedsFragment feedsFragment = new FeedsFragment(); - feedsFragment.setArguments(Bundler.start() - .put(BundleConstant.EXTRA, user) - .put(BundleConstant.EXTRA_TWO, isOrg) - .end()); - return feedsFragment; - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - stateLayout.setEmptyText(R.string.no_feeds); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - adapter = new FeedsAdapter(getPresenter().getEvents(), isProfile()); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter() - .getPreviousTotal()); - recycler.setAdapter(adapter); - if (isProfile()) { - recycler.addDivider(); - } - recycler.addOnScrollListener(getLoadMore()); - fastScroller.attachRecyclerView(recycler); - if (getPresenter().getEvents().isEmpty() && !getPresenter().isApiCalled()) { - getPresenter().onFragmentCreated(getArguments()); - } - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @Override public void onOpenRepoChooser(@NonNull ArrayList models) { - ListDialogView dialogView = new ListDialogView<>(); - dialogView.initArguments(getString(R.string.repo_chooser), models); - dialogView.show(getChildFragmentManager(), "ListDialogView"); - } - - @NonNull @Override public FeedsPresenter providePresenter() { - return new FeedsPresenter(); - } - - @SuppressWarnings("unchecked") @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()); - } - return onLoadMore; - } - - @Override public void onOpenCommitChooser(@NonNull List commits) { - ListDialogView dialogView = new ListDialogView<>(); - dialogView.initArguments(getString(R.string.commits), commits); - dialogView.show(getChildFragmentManager(), "ListDialogView"); - } - - @Override public void onDestroyView() { - recycler.removeOnScrollListener(getLoadMore()); - super.onDestroyView(); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onItemSelected(Parcelable item) { - if (item instanceof SimpleUrlsModel) { - SchemeParser.launchUri(getContext(), Uri.parse(((SimpleUrlsModel) item).getItem())); - } else if (item instanceof GitCommitModel) { - GitCommitModel model = (GitCommitModel) item; - NameParser nameParser = new NameParser(model.getUrl()); - Intent intent = CommitPagerActivity.createIntent(getContext(), nameParser.getName(), - nameParser.getUsername(), model.getSha(), true, LinkParserHelper.isEnterprise(model.getUrl())); - getContext().startActivity(intent); - } - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) { - recycler.scrollToPosition(0); - } - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } - - public boolean isProfile() { - return !InputHelper.isEmpty(getArguments().getString(BundleConstant.EXTRA)) && - !getArguments().getBoolean(BundleConstant.EXTRA_TWO); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsMvp.java deleted file mode 100644 index 051c87757..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsMvp.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fastaccess.ui.modules.feeds; - -import android.os.Bundle; -import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.GitCommitModel; -import com.fastaccess.data.dao.SimpleUrlsModel; -import com.fastaccess.data.dao.model.Event; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.dialog.ListDialogView; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 12:35 PM - */ - -public interface FeedsMvp { - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, - android.view.View.OnClickListener, ListDialogView.onSimpleItemSelection { - - void onNotifyAdapter(@Nullable List events, int page); - - void onOpenRepoChooser(@NonNull ArrayList models); - - @NonNull OnLoadMore getLoadMore(); - - void onOpenCommitChooser(@NonNull List commits); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - void onFragmentCreated(@NonNull Bundle argument); - - boolean onCallApi(int page); - - @NonNull ArrayList getEvents(); - - void onWorkOffline(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsPresenter.java deleted file mode 100644 index 8d704c458..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/feeds/FeedsPresenter.java +++ /dev/null @@ -1,200 +0,0 @@ -package com.fastaccess.ui.modules.feeds; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.fastaccess.data.dao.NameParser; -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.PayloadModel; -import com.fastaccess.data.dao.SimpleUrlsModel; -import com.fastaccess.data.dao.model.Event; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.data.dao.types.EventsType; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.repos.RepoPagerActivity; -import com.fastaccess.ui.modules.repos.code.commit.details.CommitPagerActivity; -import com.fastaccess.ui.modules.repos.code.releases.ReleasesListActivity; -import com.fastaccess.ui.modules.repos.wiki.WikiActivity; - -import java.util.ArrayList; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -public class FeedsPresenter extends BasePresenter implements FeedsMvp.Presenter { - private ArrayList eventsModels = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - @com.evernote.android.state.State String user; - @com.evernote.android.state.State boolean isOrg; - - @Override public void onFragmentCreated(@NonNull Bundle argument) { - user = argument.getString(BundleConstant.EXTRA); - isOrg = argument.getBoolean(BundleConstant.EXTRA_TWO); - if (eventsModels.isEmpty()) { - onCallApi(1); - } - } - - @Override public boolean onCallApi(int page) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - if (page > lastPage || lastPage == 0) { - sendToView(FeedsMvp.View::hideProgress); - return false; - } - setCurrentPage(page); - Login login = Login.getUser(); - if (login == null) return false;// I can't understand how this could possibly be reached lol. - Observable> observable; - Logger.e(isOrg); - if (user != null) { - if (isOrg) { - observable = RestProvider.getOrgService(isEnterprise()).getReceivedEvents(login.getLogin(), user, page); - } else { - observable = RestProvider.getUserService(login.getLogin().equalsIgnoreCase(user) - ? PrefGetter.isEnterprise() : isEnterprise()).getUserEvents(user, page); - } - } else { - observable = RestProvider.getUserService(PrefGetter.isEnterprise()).getReceivedEvents(login.getLogin(), page); - } - makeRestCall(observable, response -> { - lastPage = response.getLast(); - if (getCurrentPage() == 1) { - manageDisposable(Event.save(response.getItems(), user)); - } - sendToView(view -> view.onNotifyAdapter(response.getItems(), page)); - }); - return true; - } - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable Object parameter) { - return onCallApi(page); - } - - @Override public void onSubscribed(boolean cancelable) { - sendToView(view -> view.showProgress(0)); - } - - @Override public void onError(@NonNull Throwable throwable) { - onWorkOffline(); - super.onError(throwable); - } - - @NonNull @Override public ArrayList getEvents() { - return eventsModels; - } - - @Override public void onWorkOffline() { - if (eventsModels.isEmpty() && InputHelper.isEmpty(user)) { - manageDisposable(RxHelper.getObservable(Event.getEvents(Login.getUser().getLogin()).toObservable()) - .subscribe(modelList -> { - if (modelList != null) { - sendToView(view -> view.onNotifyAdapter(modelList, 1)); - } - }, Throwable::printStackTrace)); - } else { - sendToView(FeedsMvp.View::hideProgress); - } - } - - @Override public void onItemClick(int position, View v, Event item) { - if (item.getType() == EventsType.ForkEvent) { - NameParser parser = new NameParser(item.getPayload().getForkee().getHtmlUrl()); - RepoPagerActivity.startRepoPager(v.getContext(), parser); - } else { - PayloadModel payloadModel = item.getPayload(); - if (payloadModel != null) { - if (payloadModel.getHead() != null) { - if (payloadModel.getCommits() != null && payloadModel.getCommits().size() > 1) { - sendToView(view -> view.onOpenCommitChooser(payloadModel.getCommits())); - } else { - Repo repoModel = item.getRepo(); - NameParser nameParser = new NameParser(repoModel.getUrl()); - Intent intent = CommitPagerActivity.createIntent(v.getContext(), nameParser.getName(), - nameParser.getUsername(), payloadModel.getHead(), true, - LinkParserHelper.isEnterprise(repoModel.getUrl())); - v.getContext().startActivity(intent); - } - } else if (payloadModel.getIssue() != null) { - SchemeParser.launchUri(v.getContext(), Uri.parse(payloadModel.getIssue().getHtmlUrl()), true); - } else if (payloadModel.getPullRequest() != null) { - SchemeParser.launchUri(v.getContext(), Uri.parse(payloadModel.getPullRequest().getHtmlUrl()), true); - } else if (payloadModel.getComment() != null) { - SchemeParser.launchUri(v.getContext(), Uri.parse(payloadModel.getComment().getHtmlUrl()), true); - } else if (item.getType() == EventsType.ReleaseEvent && payloadModel.getRelease() != null) { - NameParser nameParser = new NameParser(payloadModel.getRelease().getHtmlUrl()); - v.getContext().startActivity(ReleasesListActivity.getIntent(v.getContext(), nameParser.getUsername(), nameParser.getName(), - payloadModel.getRelease().getId(), LinkParserHelper.isEnterprise(payloadModel.getRelease().getHtmlUrl()))); - - } else if (item.getType() == EventsType.CreateEvent && "tag".equalsIgnoreCase(payloadModel.getRefType())) { - Repo repoModel = item.getRepo(); - NameParser nameParser = new NameParser(repoModel.getUrl()); - v.getContext().startActivity(ReleasesListActivity.getIntent(v.getContext(), nameParser.getUsername(), nameParser.getName(), - payloadModel.getRef(), LinkParserHelper.isEnterprise(repoModel.getUrl()))); - } else if (item.getType() == EventsType.GollumEvent) { - Repo repoModel = item.getRepo(); - NameParser parser = new NameParser(repoModel.getUrl()); - v.getContext().startActivity(WikiActivity.Companion.getWiki(v.getContext(), parser.getName(), parser.getUsername())); - } else { - Repo repoModel = item.getRepo(); - NameParser parser = new NameParser(repoModel.getUrl()); - RepoPagerActivity.startRepoPager(v.getContext(), parser); - } - } - } - } - - @Override public void onItemLongClick(int position, View v, Event item) { - if (item.getType() == EventsType.ForkEvent) { - if (getView() != null) { - getView().onOpenRepoChooser(Stream.of(new SimpleUrlsModel(item.getRepo().getName(), item.getRepo().getUrl()), - new SimpleUrlsModel(item.getPayload().getForkee().getFullName(), item.getPayload().getForkee().getHtmlUrl())) - .collect(Collectors.toCollection(ArrayList::new))); - } - } else { - Repo repo = item.getRepo(); - if (repo != null) { - NameParser parser = new NameParser(repo.getUrl()); - RepoPagerActivity.startRepoPager(v.getContext(), parser); - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/filter/chooser/FilterAddChooserListener.java b/app/src/main/java/com/fastaccess/ui/modules/filter/chooser/FilterAddChooserListener.java deleted file mode 100644 index cf94c3b0c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/filter/chooser/FilterAddChooserListener.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.fastaccess.ui.modules.filter.chooser; - -/** - * Created by Kosh on 10 Apr 2017, 12:19 PM - */ - -public interface FilterAddChooserListener { - - void onAddSelected(); - - void onSearchSelected(); -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/filter/chooser/FilterChooserBottomSheetDialog.java b/app/src/main/java/com/fastaccess/ui/modules/filter/chooser/FilterChooserBottomSheetDialog.java deleted file mode 100644 index 786436760..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/filter/chooser/FilterChooserBottomSheetDialog.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.fastaccess.ui.modules.filter.chooser; - -import android.content.Context; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.ui.base.BaseBottomSheetDialog; - -import butterknife.OnClick; - -/** - * Created by Kosh on 10 Apr 2017, 12:18 PM - */ - -public class FilterChooserBottomSheetDialog extends BaseBottomSheetDialog { - - private FilterAddChooserListener listener; - - public static FilterChooserBottomSheetDialog newInstance() { - return new FilterChooserBottomSheetDialog(); - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof FilterAddChooserListener) { - listener = (FilterAddChooserListener) getParentFragment(); - } else if (context instanceof FilterAddChooserListener) { - listener = (FilterAddChooserListener) context; - } - } - - @Override public void onDestroy() { - listener = null; - super.onDestroy(); - } - - @Override protected int layoutRes() { - return R.layout.add_filter_row_layout; - } - - @OnClick({R.id.add, R.id.search}) public void onViewClicked(View view) { - switch (view.getId()) { - case R.id.add: - listener.onAddSelected(); - break; - case R.id.search: - listener.onSearchSelected(); - break; - } - dismiss(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivity.java b/app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivity.java deleted file mode 100644 index b089b7ef2..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivity.java +++ /dev/null @@ -1,585 +0,0 @@ -package com.fastaccess.ui.modules.filter.issues; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.graphics.drawable.ColorDrawable; -import android.os.Bundle; -import android.os.Handler; -import android.support.annotation.NonNull; -import android.text.Editable; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.PopupWindow; -import android.widget.Toast; - -import com.evernote.android.state.State; -import com.fastaccess.App; -import com.fastaccess.R; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AnimHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.ui.adapter.LabelsAdapter; -import com.fastaccess.ui.adapter.MilestonesAdapter; -import com.fastaccess.ui.adapter.SimpleListAdapter; -import com.fastaccess.ui.adapter.UsersAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.modules.filter.issues.fragment.FilterIssueFragment; -import com.fastaccess.ui.widgets.FontEditText; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; - -import java.util.ArrayList; -import java.util.Collections; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.OnEditorAction; -import butterknife.OnTextChanged; -import es.dmoral.toasty.Toasty; - -/** - * Created by Kosh on 09 Apr 2017, 6:23 PM - */ - -public class FilterIssuesActivity extends BaseActivity implements - FilterIssuesActivityMvp.View { - @BindView(R.id.back) ForegroundImageView back; - @BindView(R.id.open) FontTextView open; - @BindView(R.id.close) FontTextView close; - @BindView(R.id.author) FontTextView author; - @BindView(R.id.labels) FontTextView labels; - @BindView(R.id.milestone) FontTextView milestone; - @BindView(R.id.assignee) FontTextView assignee; - @BindView(R.id.sort) FontTextView sort; - @BindView(R.id.searchEditText) FontEditText searchEditText; - @BindView(R.id.clear) View clear; - @State boolean isIssue; - @State boolean isOpen; - @State String login; - @State String repoId; - @State String criteria; - - private FilterIssueFragment filterFragment; - private MilestonesAdapter milestonesAdapter; - private LabelsAdapter labelsAdapter; - private UsersAdapter assigneesAdapter; - private PopupWindow popupWindow; - - - public static Intent getIntent(@NonNull Context context, @NonNull String login, @NonNull String repoId, @NonNull String criteria) { - Intent intent = new Intent(context, FilterIssuesActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA_FOUR, criteria) - .put(BundleConstant.EXTRA_TWO, true) - .put(BundleConstant.EXTRA_THREE, true) - .end()); - return intent; - } - - public static void startActivity(@NonNull Activity context, @NonNull String login, @NonNull String repoId, - boolean isIssue, boolean isOpen, boolean isEnterprise) { - Intent intent = new Intent(context, FilterIssuesActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA_TWO, isIssue) - .put(BundleConstant.EXTRA_THREE, isOpen) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - View view = context.findViewById(R.id.fab); - if (view != null) { - ActivityHelper.startReveal(context, intent, view); - } else { - context.startActivity(intent); - } - } - - public static void startActivity(@NonNull View view, @NonNull String login, @NonNull String repoId, - boolean isIssue, boolean isOpen, boolean isEnterprise, @NonNull String criteria) { - Intent intent = new Intent(view.getContext(), FilterIssuesActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA_TWO, isIssue) - .put(BundleConstant.EXTRA_THREE, isOpen) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .put(BundleConstant.EXTRA_FOUR, criteria) - .end()); - //noinspection ConstantConditions - ActivityHelper.startReveal(ActivityHelper.getActivity(view.getContext()), intent, view); - } - - @Override protected int layout() { - return R.layout.filter_issues_prs_layout; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public FilterIssuesActivityPresenter providePresenter() { - return new FilterIssuesActivityPresenter(); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState == null) { - Bundle bundle = getIntent().getExtras(); - isIssue = bundle.getBoolean(BundleConstant.EXTRA_TWO); - isOpen = bundle.getBoolean(BundleConstant.EXTRA_THREE); - repoId = bundle.getString(BundleConstant.ID); - login = bundle.getString(BundleConstant.EXTRA); - criteria = bundle.getString(BundleConstant.EXTRA_FOUR); - getPresenter().onStart(login, repoId); - if (isOpen) { - onOpenClicked(); - } else { - onCloseClicked(); - } - } - } - - @OnClick(R.id.back) public void onBackClicked() { - onBackPressed(); - } - - @OnClick(R.id.open) public void onOpenClicked() { - if (!open.isSelected()) { - open.setSelected(true); - close.setSelected(false); - String text = InputHelper.toString(searchEditText); - if (!InputHelper.isEmpty(text)) { - text = text.replace("is:closed", "is:open"); - searchEditText.setText(text); - onSearch(); - } else { - searchEditText.setText(String.format("%s %s ", isOpen ? "is:open" : "is:closed", isIssue ? "is:issue" : "is:pr")); - if (!InputHelper.isEmpty(criteria)) { - searchEditText.setText(String.format("%s%s", InputHelper.toString(searchEditText), criteria)); - criteria = null; - } - onSearch(); - } - } - } - - @OnClick(R.id.close) public void onCloseClicked() { - if (!close.isSelected()) { - open.setSelected(false); - close.setSelected(true); - String text = InputHelper.toString(searchEditText); - if (!InputHelper.isEmpty(text)) { - text = text.replace("is:open", "is:closed"); - searchEditText.setText(text); - onSearch(); - } else { - searchEditText.setText(String.format("%s %s ", isOpen ? "is:open" : "is:closed", isIssue ? "is:issue" : "is:pr")); - onSearch(); - } - } - } - - @OnClick(R.id.author) public void onAuthorClicked() { - Toasty.info(App.getInstance(), "GitHub doesn't have this API yet!\nYou can try typing it yourself for example author:k0shk0sh", - Toast.LENGTH_LONG).show(); - } - - @SuppressLint("InflateParams") @OnClick(R.id.labels) public void onLabelsClicked() { - if (labels.getTag() != null) return; - labels.setTag(true); - ViewHolder viewHolder = new ViewHolder(LayoutInflater.from(this).inflate(R.layout.simple_list_dialog, null)); - setupPopupWindow(viewHolder); - viewHolder.recycler.setAdapter(getLabelsAdapter()); - AnimHelper.revealPopupWindow(popupWindow, labels); - } - - @SuppressLint("InflateParams") @OnClick(R.id.milestone) public void onMilestoneClicked() { - if (milestone.getTag() != null) return; - milestone.setTag(true); - ViewHolder viewHolder = new ViewHolder(LayoutInflater.from(this).inflate(R.layout.simple_list_dialog, null)); - setupPopupWindow(viewHolder); - viewHolder.recycler.setAdapter(getMilestonesAdapter()); - AnimHelper.revealPopupWindow(popupWindow, milestone); - } - - @SuppressLint("InflateParams") @OnClick(R.id.assignee) public void onAssigneeClicked() { - if (assignee.getTag() != null) return; - assignee.setTag(true); - ViewHolder viewHolder = new ViewHolder(LayoutInflater.from(this).inflate(R.layout.simple_list_dialog, null)); - setupPopupWindow(viewHolder); - viewHolder.recycler.setAdapter(getAssigneesAdapter()); - AnimHelper.revealPopupWindow(popupWindow, assignee); - } - - @SuppressLint("InflateParams") @OnClick(R.id.sort) public void onSortClicked() { - if (sort.getTag() != null) return; - sort.setTag(true); - ViewHolder viewHolder = new ViewHolder(LayoutInflater.from(this).inflate(R.layout.simple_list_dialog, null)); - setupPopupWindow(viewHolder); - ArrayList lists = new ArrayList<>(); - Collections.addAll(lists, getResources().getStringArray(R.array.sort_prs_issues)); - lists.add(CommentsHelper.getThumbsUp()); - lists.add(CommentsHelper.getThumbsDown()); - lists.add(CommentsHelper.getLaugh()); - lists.add(CommentsHelper.getHooray()); - lists.add(CommentsHelper.getSad()); - lists.add(CommentsHelper.getHeart()); - viewHolder.recycler.setAdapter(new SimpleListAdapter<>(lists, new BaseViewHolder.OnItemClickListener() { - @Override public void onItemClick(int position, View v, String item) { - appendSort(item); - } - - @Override public void onItemLongClick(int position, View v, String item) {} - })); - AnimHelper.revealPopupWindow(popupWindow, sort); - } - - @OnClick(value = {R.id.clear}) void onClear(View view) { - if (view.getId() == R.id.clear) { - AppHelper.hideKeyboard(searchEditText); - searchEditText.setText(""); - } - } - - @OnClick(R.id.search) void onSearchClicked() { - onSearch(); - } - - @OnTextChanged(value = R.id.searchEditText, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) void onTextChange(Editable s) { - String text = s.toString(); - if (text.length() == 0) { - AnimHelper.animateVisibility(clear, false); - } else { - AnimHelper.animateVisibility(clear, true); - } - } - - @OnEditorAction(R.id.searchEditText) protected boolean onEditor() { - onSearchClicked(); - return true; - } - - @Override public void onSetCount(int count, boolean isOpen) { - if (isOpen) { - open.setText(SpannableBuilder.builder() - .append(getString(R.string.open)) - .append("(") - .append(String.valueOf(count)) - .append(")")); - close.setText(R.string.closed); - } else { - close.setText(SpannableBuilder.builder() - .append(getString(R.string.closed)) - .append("(") - .append(String.valueOf(count)) - .append(")")); - open.setText(R.string.open); - } - } - - @Override public void showProgress(int resId) { - super.showProgress(resId); - } - - @Override public void hideProgress() { - super.hideProgress(); - } - - @NonNull private String getRepoName() { - return "repo:" + login + "/" + repoId + " "; - }// let users stay within selected repo context. - - @Override public void onBackPressed() { - if (popupWindow != null && popupWindow.isShowing()) { - popupWindow.dismiss(); - } else { - super.onBackPressed(); - } - } - - private void setupPopupWindow(@NonNull ViewHolder viewHolder) { - if (popupWindow == null) { - popupWindow = new PopupWindow(this); - popupWindow.setElevation(getResources().getDimension(R.dimen.spacing_micro)); - popupWindow.setOutsideTouchable(true); - popupWindow.setBackgroundDrawable(new ColorDrawable(ViewHelper.getWindowBackground(this))); - popupWindow.setElevation(getResources().getDimension(R.dimen.spacing_normal)); - popupWindow.setOnDismissListener(() -> new Handler().postDelayed(() -> { - //hacky way to dismiss on re-selecting tab. - if (assignee == null || milestone == null || sort == null || labels == null) return; - assignee.setTag(null); - milestone.setTag(null); - sort.setTag(null); - labels.setTag(null); - }, 100)); - } - popupWindow.setContentView(viewHolder.view); - } - - private void onSearch() { - if (!InputHelper.isEmpty(searchEditText)) { - getFilterFragment().onSearch(getRepoName() + InputHelper.toString(searchEditText), - open.isSelected(), isIssue, isEnterprise()); - searchEditText.setSelection(searchEditText.getEditableText().length()); - } else { - getFilterFragment().onClear(); - showErrorMessage(getString(R.string.empty_search_error)); - } - } - - private FilterIssueFragment getFilterFragment() { - if (filterFragment == null) { - filterFragment = (FilterIssueFragment) getSupportFragmentManager().findFragmentById(R.id.filterFragment); - } - return filterFragment; - } - - private MilestonesAdapter getMilestonesAdapter() { - if (milestonesAdapter == null) { - if (!getPresenter().getMilestones().isEmpty()) { - MilestoneModel milestone = new MilestoneModel(); - milestone.setTitle(getString(R.string.clear)); - getPresenter().getMilestones().add(0, milestone); - } - milestonesAdapter = new MilestonesAdapter(getPresenter().getMilestones()); - milestonesAdapter.setListener(new BaseViewHolder.OnItemClickListener() { - @Override public void onItemClick(int position, View v, MilestoneModel item) { - appendMilestone(item); - } - - @Override public void onItemLongClick(int position, View v, MilestoneModel item) { - - } - }); - } - return milestonesAdapter; - } - - private LabelsAdapter getLabelsAdapter() { - if (labelsAdapter == null) { - if (!getPresenter().getLabels().isEmpty()) { - LabelModel label = new LabelModel(); - label.setName(getString(R.string.clear)); - getPresenter().getLabels().add(0, label); - } - labelsAdapter = new LabelsAdapter(getPresenter().getLabels(), null); - labelsAdapter.setListener(new BaseViewHolder.OnItemClickListener() { - @Override public void onItemClick(int position, View v, LabelModel item) { - appendLabel(item); - } - - @Override public void onItemLongClick(int position, View v, LabelModel item) { - - } - }); - } - return labelsAdapter; - } - - private UsersAdapter getAssigneesAdapter() { - if (assigneesAdapter == null) { - if (!getPresenter().getAssignees().isEmpty()) { - User user = new User(); - user.setLogin(getString(R.string.clear)); - getPresenter().getAssignees().add(0, user); - } - assigneesAdapter = new UsersAdapter(getPresenter().getAssignees(), false, true); - assigneesAdapter.setListener(new BaseViewHolder.OnItemClickListener() { - @Override public void onItemClick(int position, View v, User item) { - appendAssignee(item); - } - - @Override public void onItemLongClick(int position, View v, User item) {} - }); - } - return assigneesAdapter; - } - - private void appendIfEmpty() { - if (InputHelper.isEmpty(searchEditText)) - if (open.isSelected()) { - searchEditText.setText(isIssue ? "is:issue is:open " : "is:pr is:open "); - } else if (close.isSelected()) { - searchEditText.setText(isIssue ? "is:issue is:close " : "is:pr is:close "); - } else { - searchEditText.setText(isIssue ? "is:issue is:open " : "is:pr is:open "); - } - } - - private void appendMilestone(MilestoneModel item) { - if (popupWindow != null) { - popupWindow.dismiss(); - } - appendIfEmpty(); - String text = InputHelper.toString(searchEditText); - String regex = "milestone:(\".+\"|\\S+)"; - if (item.getTitle().equalsIgnoreCase(getString(R.string.clear))) { - text = text.replaceAll(regex, ""); - searchEditText.setText(text); - onSearch(); - return; - } - if (!text.replaceAll(regex, "milestone:\"" + item.getTitle() + "\"").equalsIgnoreCase(text)) { - String space = text.endsWith(" ") ? "" : " "; - text = text.replaceAll(regex, space + "milestone:\"" + item.getTitle() + "\""); - } else { - text += text.endsWith(" ") ? "" : " "; - text += "milestone:\"" + item.getTitle() + "\""; - } - searchEditText.setText(text); - onSearch(); - } - - private void appendLabel(LabelModel item) { - if (popupWindow != null) { - popupWindow.dismiss(); - } - appendIfEmpty(); - String text = InputHelper.toString(searchEditText); - String regex = "label:(\".+\"|\\S+)"; - if (item.getName().equalsIgnoreCase(getString(R.string.clear))) { - text = text.replaceAll(regex, ""); - searchEditText.setText(text); - onSearch(); - return; - } - if (!text.replaceAll(regex, "label:\"" + item.getName() + "\"").equalsIgnoreCase(text)) { - String space = text.endsWith(" ") ? "" : " "; - text = text.replaceAll(regex, space + "label:\"" + item.getName() + "\""); - } else { - text += text.endsWith(" ") ? "" : " "; - text += "label:\"" + item.getName() + "\""; - } - searchEditText.setText(text); - onSearch(); - } - - private void appendAssignee(User item) { - if (popupWindow != null) { - popupWindow.dismiss(); - } - appendIfEmpty(); - String text = InputHelper.toString(searchEditText); - String regex = "assignee:(\".+\"|\\S+)"; - if (item.getLogin().equalsIgnoreCase(getString(R.string.clear))) { - text = text.replaceAll(regex, ""); - searchEditText.setText(text); - onSearch(); - return; - } - if (!text.replaceAll(regex, "assignee:\"" + item.getLogin() + "\"").equalsIgnoreCase(text)) { - String space = text.endsWith(" ") ? "" : " "; - text = text.replaceAll(regex, space + "assignee:\"" + item.getLogin() + "\""); - } else { - text += text.endsWith(" ") ? "" : " "; - text += "assignee:\"" + item.getLogin() + "\""; - } - searchEditText.setText(text); - onSearch(); - } - - private void appendSort(String item) { - dismissPopup(); - appendIfEmpty(); - Resources resources = getResources(); - String regex = "sort:(\".+\"|\\S+)"; - String oldestQuery = "created-asc"; - String mostCommentedQuery = "comments-desc"; - String leastCommentedQuery = "comments-asc"; - String recentlyUpdatedQuery = "updated-desc"; - String leastRecentUpdatedQuery = "updated-asc"; - String sortThumbUp = "reactions-%2B1-desc"; - String sortThumbDown = "reactions--1-desc"; - String sortThumbLaugh = "reactions-smile-desc"; - String sortThumbHooray = "reactions-tada-desc"; - String sortThumbConfused = "reactions-thinking_face-desc"; - String sortThumbHeart = "reactions-heart-desc"; - String toQuery = ""; - String text = InputHelper.toString(searchEditText); - if (item.equalsIgnoreCase(resources.getString(R.string.newest))) { - text = text.replaceAll(regex, ""); - if (!InputHelper.toString(searchEditText).equalsIgnoreCase(text)) { - searchEditText.setText(text); - onSearch(); - } - return; - } - if (item.equalsIgnoreCase(resources.getString(R.string.oldest))) { - toQuery = oldestQuery; - } else if (item.equalsIgnoreCase(resources.getString(R.string.most_commented))) { - toQuery = mostCommentedQuery; - } else if (item.equalsIgnoreCase(resources.getString(R.string.least_commented))) { - toQuery = leastCommentedQuery; - } else if (item.equalsIgnoreCase(resources.getString(R.string.recently_updated))) { - toQuery = recentlyUpdatedQuery; - } else if (item.equalsIgnoreCase(resources.getString(R.string.least_recent_updated))) { - toQuery = leastRecentUpdatedQuery; - } else if (item.equalsIgnoreCase(CommentsHelper.getThumbsUp())) { - toQuery = sortThumbUp; - } else if (item.equalsIgnoreCase(CommentsHelper.getThumbsDown())) { - toQuery = sortThumbDown; - } else if (item.equalsIgnoreCase(CommentsHelper.getLaugh())) { - toQuery = sortThumbLaugh; - } else if (item.equalsIgnoreCase(CommentsHelper.getHooray())) { - toQuery = sortThumbHooray; - } else if (item.equalsIgnoreCase(CommentsHelper.getSad())) { - toQuery = sortThumbConfused; - } else if (item.equalsIgnoreCase(CommentsHelper.getHeart())) { - toQuery = sortThumbHeart; - } - if (!text.replaceAll(regex, "sort:\"" + toQuery + "\"").equalsIgnoreCase(text)) { - String space = text.endsWith(" ") ? "" : " "; - text = text.replaceAll(regex, space + "sort:\"" + toQuery + "\""); - } else { - text += text.endsWith(" ") ? "" : " "; - text += "sort:\"" + toQuery + "\""; - } - if (!InputHelper.toString(searchEditText).equalsIgnoreCase(text)) { - searchEditText.setText(text); - onSearch(); - } - } - - private void dismissPopup() { - if (popupWindow != null) { - popupWindow.dismiss(); - } - } - - static class ViewHolder { - @BindView(R.id.title) FontTextView title; - @BindView(R.id.recycler) DynamicRecyclerView recycler; - View view; - - ViewHolder(View view) { - this.view = view; - ButterKnife.bind(this, view); - title.setVisibility(View.GONE); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivityMvp.java b/app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivityMvp.java deleted file mode 100644 index 2a6821bc1..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivityMvp.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.fastaccess.ui.modules.filter.issues; - -import android.support.annotation.NonNull; - -import com.fastaccess.ui.base.mvp.BaseMvp; - -/** - * Created by Kosh on 09 Apr 2017, 6:19 PM - */ - -public interface FilterIssuesActivityMvp { - - interface View extends BaseMvp.FAView { - void onSetCount(int count, boolean isOpen); - } - - interface Presenter { - void onStart(@NonNull String login, @NonNull String repoId); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivityPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivityPresenter.java deleted file mode 100644 index ae65e5f7a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/FilterIssuesActivityPresenter.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.fastaccess.ui.modules.filter.issues; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -import io.reactivex.Observable; -import lombok.Getter; - -/** - * Created by Kosh on 09 Apr 2017, 6:22 PM - */ - -@Getter public class FilterIssuesActivityPresenter extends BasePresenter implements FilterIssuesActivityMvp.Presenter { - - @com.evernote.android.state.State @NonNull ArrayList labels = new ArrayList<>(); - @com.evernote.android.state.State @NonNull ArrayList milestones = new ArrayList<>(); - @com.evernote.android.state.State @NonNull ArrayList assignees = new ArrayList<>(); - - @Override public void onStart(@NonNull String login, @NonNull String repoId) { - Observable> observable = RestProvider.getRepoService(isEnterprise()).getLabels(login, repoId) - .flatMap(labelModelPageable -> { - if (labelModelPageable != null && labelModelPageable.getItems() != null) { - labels.clear(); - labels.addAll(labelModelPageable.getItems()); - } - return RestProvider.getRepoService(isEnterprise()).getAssignees(login, repoId); - }) - .flatMap(userPageable -> { - if (userPageable != null && userPageable.getItems() != null) { - assignees.clear(); - assignees.addAll(userPageable.getItems()); - } - return RestProvider.getRepoService(isEnterprise()).getMilestones(login, repoId); - }); - makeRestCall(observable, response -> { - if (response != null && response.getItems() != null) { - milestones.clear(); - milestones.addAll(response.getItems()); - } - sendToView(BaseMvp.FAView::hideProgress); - }); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssueFragment.java b/app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssueFragment.java deleted file mode 100644 index dbbac5130..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssueFragment.java +++ /dev/null @@ -1,171 +0,0 @@ -package com.fastaccess.ui.modules.filter.issues.fragment; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.adapter.IssuesAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.filter.issues.FilterIssuesActivityMvp; -import com.fastaccess.ui.modules.repos.extras.popup.IssuePopupFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 09 Apr 2017, 7:13 PM - */ - -public class FilterIssueFragment extends BaseFragment implements FilterIssuesMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private IssuesAdapter adapter; - - @State IssueState issueState = IssueState.open; - @State boolean isIssue; - @State String query; - - private FilterIssuesActivityMvp.View callback; - - @Override public void onAttach(Context context) { - super.onAttach(context); - callback = (FilterIssuesActivityMvp.View) context; - } - - @Override public void onDetach() { - callback = null; - super.onDetach(); - } - - @Override public void onRefresh() { - if (!InputHelper.isEmpty(query)) { - getPresenter().onCallApi(1, query); - } - } - - @Override public void onClick(View v) { - onRefresh(); - } - - @Override public void onClear() { - hideProgress(); - getPresenter().getIssues().clear(); - adapter.notifyDataSetChanged(); - } - - @Override public void onSearch(@NonNull String query, boolean isOpen, boolean isIssue, boolean isEnterprise) { - getPresenter().setEnterprise(isEnterprise); - this.query = query; - this.issueState = isOpen ? IssueState.open : IssueState.closed; - this.isIssue = isIssue; - onClear(); - onRefresh(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter()); - } - onLoadMore.setParameter(query); - return onLoadMore; - } - - @Override public void onSetCount(int totalCount) { - if (callback != null) { - callback.onSetCount(totalCount, issueState == IssueState.open); - } - } - - @Override public void onItemClicked(@NonNull Issue item) { - SchemeParser.launchUri(getContext(), item.getHtmlUrl()); - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - stateLayout.setEmptyText(R.string.no_search_results); - recycler.setEmptyView(stateLayout, refresh); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - adapter = new IssuesAdapter(getPresenter().getIssues(), true, false, true); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addKeyLineDivider(); - if (savedInstanceState != null) { - if (!InputHelper.isEmpty(query) && getPresenter().getIssues().isEmpty()) { - onRefresh(); - } - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public FilterIssuePresenter providePresenter() { - return new FilterIssuePresenter(); - } - - @Override public void onShowPopupDetails(@NonNull Issue item) { - IssuePopupFragment.showPopup(getChildFragmentManager(), item); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssuePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssuePresenter.java deleted file mode 100644 index bef879192..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssuePresenter.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.fastaccess.ui.modules.filter.issues.fragment; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 09 Apr 2017, 7:10 PM - */ - -public class FilterIssuePresenter extends BasePresenter implements FilterIssuesMvp.Presenter { - - - private ArrayList issues = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public void onItemClick(int position, View v, Issue item) { - if (getView() != null) { - getView().onItemClicked(item); - } - } - - @Override public void onItemLongClick(int position, View v, Issue item) { - if (getView() != null) getView().onShowPopupDetails(item); - } - - @NonNull @Override public ArrayList getIssues() { - return issues; - } - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (page == 1 || parameter == null) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - if (page > lastPage || lastPage == 0 || parameter == null) { - sendToView(FilterIssuesMvp.View::hideProgress); - return false; - } - setCurrentPage(page); - makeRestCall(RestProvider.getSearchService(isEnterprise()).searchIssues(parameter, page), - issues -> { - lastPage = issues.getLast(); - if (getCurrentPage() == 1) { - sendToView(view -> view.onSetCount(issues.getTotalCount())); - } - sendToView(view -> view.onNotifyAdapter(issues.getItems(), page)); - }); - return true; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssuesMvp.java b/app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssuesMvp.java deleted file mode 100644 index 448e3b62e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/filter/issues/fragment/FilterIssuesMvp.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.fastaccess.ui.modules.filter.issues.fragment; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 09 Apr 2017, 7:06 PM - */ - -public interface FilterIssuesMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - - void onClear(); - - void onSearch(@NonNull String query, boolean isOpen, boolean isIssue, boolean isEnterprise); - - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onSetCount(int totalCount); - - void onItemClicked(@NonNull Issue item); - - void onShowPopupDetails(@NonNull Issue item); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getIssues(); - - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/GistsFragment.java b/app/src/main/java/com/fastaccess/ui/modules/gists/GistsFragment.java deleted file mode 100644 index eb0de57fb..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/GistsFragment.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.fastaccess.ui.modules.gists; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.GistsAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -public class GistsFragment extends BaseFragment implements GistsMvp.View { - - public static final String TAG = GistsFragment.class.getSimpleName(); - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private GistsAdapter adapter; - private OnLoadMore onLoadMore; - - public static GistsFragment newInstance() { - return new GistsFragment(); - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - refresh.setOnRefreshListener(this); - stateLayout.setOnReloadListener(this); - stateLayout.setEmptyText(R.string.no_gists); - recycler.setEmptyView(stateLayout, refresh); - adapter = new GistsAdapter(getPresenter().getGists()); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - recycler.addOnScrollListener(getLoadMore()); - if (getPresenter().getGists().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, null); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public GistsPresenter providePresenter() { - return new GistsPresenter(); - } - - @SuppressWarnings("unchecked") @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()); - } - return onLoadMore; - } - - @Override public void onDestroyView() { - recycler.removeOnScrollListener(getLoadMore()); - super.onDestroyView(); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/GistsListActivity.java b/app/src/main/java/com/fastaccess/ui/modules/gists/GistsListActivity.java deleted file mode 100644 index c84edd429..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/GistsListActivity.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.fastaccess.ui.modules.gists; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; -import android.view.MenuItem; - -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.gists.create.CreateGistActivity; -import com.fastaccess.ui.modules.main.MainActivity; -import com.fastaccess.ui.widgets.ViewPagerView; - -import net.grandcentrix.thirtyinch.TiPresenter; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 25 Mar 2017, 11:28 PM - */ - -public class GistsListActivity extends BaseActivity { - - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.gistsContainer) ViewPagerView pager; - @BindView(R.id.fab) FloatingActionButton fab; - - public static void startActivity(@NonNull Context context) { - context.startActivity(new Intent(context, GistsListActivity.class)); - } - - @Override protected int layout() { - return R.layout.gists_activity_layout; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle(R.string.gists); - setTaskName(getString(R.string.gists)); - setupTabs(); - fab.show(); - tabs.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager) { - @Override public void onTabReselected(TabLayout.Tab tab) { - super.onTabReselected(tab); - onScrollTop(tab.getPosition()); - } - }); - } - - @Override public void onScrollTop(int index) { - if (pager == null || pager.getAdapter() == null) return; - Fragment fragment = (BaseFragment) pager.getAdapter().instantiateItem(pager, index); - if (fragment instanceof BaseFragment) { - ((BaseFragment) fragment).onScrollTop(index); - } - } - - @OnClick(R.id.fab) public void onViewClicked() { - ActivityHelper.startReveal(this, new Intent(this, CreateGistActivity.class), fab, BundleConstant.REQUEST_CODE); - } - - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK && requestCode == BundleConstant.REQUEST_CODE) { - if (pager != null && pager.getAdapter() != null) { - ((Fragment) pager.getAdapter().instantiateItem(pager, 0)).onActivityResult(resultCode, resultCode, data); - } - } - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - startActivity(new Intent(this, MainActivity.class)); - finish(); - return true; - } - return super.onOptionsItemSelected(item); - } - - private void setupTabs() { - pager.setAdapter(new FragmentsPagerAdapter(getSupportFragmentManager(), FragmentPagerAdapterModel.buildForGists(this))); - tabs.setupWithViewPager(pager); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/GistsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/gists/GistsMvp.java deleted file mode 100644 index 414e84401..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/GistsMvp.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.fastaccess.ui.modules.gists; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 12:35 PM - */ - -interface GistsMvp { - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getGists(); - - void onWorkOffline(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/GistsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/gists/GistsPresenter.java deleted file mode 100644 index 8e4e7f76b..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/GistsPresenter.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.fastaccess.ui.modules.gists; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.gists.gist.GistActivity; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -class GistsPresenter extends BasePresenter implements GistsMvp.Presenter { - private ArrayList gistsModels = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - onWorkOffline(); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable Object parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - if (page > lastPage || lastPage == 0) { - sendToView(GistsMvp.View::hideProgress); - return false; - } - setCurrentPage(page); - makeRestCall(RestProvider.getGistService(isEnterprise()).getPublicGists(RestProvider.PAGE_SIZE, page), - listResponse -> { - lastPage = listResponse.getLast(); - sendToView(view -> view.onNotifyAdapter(listResponse.getItems(), page)); - }); - return true; - } - - @NonNull @Override public ArrayList getGists() { - return gistsModels; - } - - @Override public void onWorkOffline() { - if (gistsModels.isEmpty()) { - manageDisposable(RxHelper.getObservable(Gist.getGists().toObservable()) - .subscribe(gists -> sendToView(view -> view.onNotifyAdapter(gists, 1)))); - } else { - sendToView(GistsMvp.View::hideProgress); - } - } - - @Override public void onItemClick(int position, View v, Gist item) { - v.getContext().startActivity(GistActivity.createIntent(v.getContext(), item.getGistId(), isEnterprise())); - } - - @Override public void onItemLongClick(int position, View v, Gist item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistActivity.java b/app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistActivity.java deleted file mode 100644 index 38e638326..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistActivity.java +++ /dev/null @@ -1,183 +0,0 @@ -package com.fastaccess.ui.modules.gists.create; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TextInputLayout; -import android.support.v4.app.Fragment; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.FilesListModel; -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.modules.gists.gist.files.GistFilesListFragment; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; - -import java.util.ArrayList; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 30 Nov 2016, 11:02 AM - */ - -public class CreateGistActivity extends BaseActivity implements CreateGistMvp.View { - - @BindView(R.id.description) TextInputLayout description; - @BindView(R.id.buttonsHolder) View buttonsHolder; - @State String id; - - private GistFilesListFragment filesListFragment; - - - public static void start(@NonNull Activity context, @NonNull Gist gistsModel) { - Intent starter = new Intent(context, CreateGistActivity.class); - putBundle(gistsModel, starter); - context.startActivityForResult(starter, BundleConstant.REQUEST_CODE); - } - - public static void start(@NonNull Fragment context, @NonNull Gist gistsModel) { - Intent starter = new Intent(context.getContext(), CreateGistActivity.class); - putBundle(gistsModel, starter); - context.startActivityForResult(starter, BundleConstant.REQUEST_CODE); - } - - private static void putBundle(@NonNull Gist gistsModel, @NonNull Intent starter) { - String login = gistsModel.getOwner() != null ? gistsModel.getOwner().getLogin() : - gistsModel.getUser() != null ? gistsModel.getUser().getLogin() : ""; - starter.putExtras(Bundler.start() - .putParcelableArrayList(BundleConstant.ITEM, gistsModel.getFilesAsList()) - .put(BundleConstant.EXTRA, Login.getUser().getLogin().equalsIgnoreCase(login)) - .put(BundleConstant.ID, gistsModel.getGistId()) - .put(BundleConstant.EXTRA_TWO, gistsModel.getDescription()) - .end()); - } - - @OnClick(value = {R.id.createPublicGist, R.id.createSecretGist}) void onClick(View view) { - if (view.getId() == R.id.createSecretGist) { - ActivityHelper.startCustomTab(this, "https://blog.github.com/2018-02-18-deprecation-notice-removing-anonymous-gist-creation/"); - return; - } - getPresenter().onSubmit(InputHelper.toString(description), - getFilesFragment().getFiles(), view.getId() == R.id.createPublicGist); - } - - @OnClick(R.id.addFile) public void onViewClicked() { - Logger.e(getFilesFragment()); - getFilesFragment().onAddNewFile(); - } - - @Override public void onDescriptionError(boolean isEmptyDesc) { - description.setError(isEmptyDesc ? getString(R.string.required_field) : null); - } - - @Override public void onFileNameError(boolean isEmptyDesc) { -// fileName.setError(isEmptyDesc ? getString(R.string.required_field) : null); - } - - @Override public void onFileContentError(boolean isEmptyDesc) { -// fileContent.setError(isEmptyDesc ? getString(R.string.required_field) : null); - } - - @Override public void onSuccessSubmission(Gist gistsModel) { - hideProgress(); - setResult(RESULT_OK); - finish(); - showMessage(R.string.success, R.string.successfully_submitted); - } - - @Override protected int layout() { - return R.layout.create_gist_layout; - } - - @Override protected boolean isTransparent() { - return false; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public CreateGistPresenter providePresenter() { - return new CreateGistPresenter(); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getPresenter().setEnterprise(PrefGetter.isEnterprise()); - setTaskName(getString(R.string.create_gist)); - if (savedInstanceState == null) { - if (getIntent() != null && getIntent().getExtras() != null) { - Bundle bundle = getIntent().getExtras(); - ArrayList models = bundle.getParcelableArrayList(BundleConstant.ITEM); - boolean isOwner = bundle.getBoolean(BundleConstant.EXTRA); - id = bundle.getString(BundleConstant.ID); - String descriptionText = bundle.getString(BundleConstant.EXTRA_TWO); - if (description.getEditText() != null) description.getEditText().setText(descriptionText); - getFilesFragment().onInitFiles(models, isOwner); - } else { - getFilesFragment().onInitFiles(new ArrayList<>(), true); - } - } - buttonsHolder.setVisibility(!InputHelper.isEmpty(id) ? View.GONE : View.VISIBLE); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk && bundle != null) { - finish(); - } - } - - @Override public void onBackPressed() { - if (InputHelper.isEmpty(description)) { - super.onBackPressed(); - } else { - ViewHelper.hideKeyboard(description); - MessageDialogView.newInstance(getString(R.string.close), getString(R.string.unsaved_data_warning), - Bundler.start().put("primary_extra", getString(R.string.discard)).put("secondary_extra", getString(R.string.cancel)) - .put(BundleConstant.EXTRA, true).end()).show(getSupportFragmentManager(), MessageDialogView.TAG); - } - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { - if (!InputHelper.isEmpty(id)) { - getMenuInflater().inflate(R.menu.done_menu, menu); - } - return super.onCreateOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.submit) { - getPresenter().onSubmitUpdate(id, InputHelper.toString(description), getFilesFragment().getFiles()); - return true; - } - return super.onOptionsItemSelected(item); - } - - private GistFilesListFragment getFilesFragment() { - if (filesListFragment == null) { - filesListFragment = (GistFilesListFragment) getSupportFragmentManager().findFragmentById(R.id.files); - } - return filesListFragment; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistMvp.java b/app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistMvp.java deleted file mode 100644 index a7a6a9edd..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistMvp.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.fastaccess.ui.modules.gists.create; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.CreateGistModel; -import com.fastaccess.data.dao.FilesListModel; -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.ui.base.mvp.BaseMvp; - -import java.util.HashMap; - -/** - * Created by Kosh on 30 Nov 2016, 10:43 AM - */ - -interface CreateGistMvp { - - interface View extends BaseMvp.FAView { - void onDescriptionError(boolean isEmptyDesc); - - void onFileNameError(boolean isEmptyDesc); - - void onFileContentError(boolean isEmptyDesc); - - void onSuccessSubmission(Gist gistsModel); - } - - interface Presenter extends BaseMvp.FAPresenter { - - void onSubmit(@NonNull String description, @NonNull HashMap files, boolean isPublic); - - void onSubmit(@NonNull CreateGistModel model); - - void onSubmitUpdate(@NonNull String id, @NonNull String description, @NonNull HashMap files); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistPresenter.java deleted file mode 100644 index 03af1aa1c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/create/CreateGistPresenter.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.fastaccess.ui.modules.gists.create; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.CreateGistModel; -import com.fastaccess.data.dao.FilesListModel; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.HashMap; - -/** - * Created by Kosh on 30 Nov 2016, 10:51 AM - */ - -class CreateGistPresenter extends BasePresenter implements CreateGistMvp.Presenter { - @Override public void onSubmit(@NonNull String description, @NonNull HashMap files, boolean isPublic) { - if (files.isEmpty()) return; - CreateGistModel createGistModel = new CreateGistModel(); - createGistModel.setDescription(InputHelper.toString(description)); - createGistModel.setPublicGist(isPublic); - createGistModel.setFiles(files); - onSubmit(createGistModel); - } - - @Override public void onSubmit(@NonNull CreateGistModel model) { - makeRestCall(RestProvider.getGistService(isEnterprise()).createGist(model), - gistsModel -> sendToView(view -> view.onSuccessSubmission(gistsModel)), false); - } - - @Override public void onSubmitUpdate(@NonNull String id, @NonNull String description, @NonNull HashMap files) { - boolean isEmptyDesc = InputHelper.isEmpty(description); - if (getView() != null) { - getView().onDescriptionError(isEmptyDesc); - } - if (isEmptyDesc) return; - CreateGistModel createGistModel = new CreateGistModel(); - createGistModel.setDescription(InputHelper.toString(description)); - createGistModel.setFiles(files); - makeRestCall(RestProvider.getGistService(isEnterprise()).editGist(createGistModel, id), - gistsModel -> sendToView(view -> view.onSuccessSubmission(gistsModel)), false); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistBottomSheetDialog.kt b/app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistBottomSheetDialog.kt deleted file mode 100644 index 9ef205a2f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistBottomSheetDialog.kt +++ /dev/null @@ -1,130 +0,0 @@ -package com.fastaccess.ui.modules.gists.create.dialog - -import android.annotation.SuppressLint -import android.content.Context -import android.os.Bundle -import android.os.Parcelable -import android.support.design.widget.TextInputLayout -import android.support.v4.app.FragmentManager -import android.support.v7.widget.Toolbar -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.WindowManager -import android.webkit.MimeTypeMap -import android.widget.EditText -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.FilesListModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.helper.InputHelper -import com.fastaccess.helper.ViewHelper -import com.fastaccess.provider.emoji.Emoji -import com.fastaccess.ui.base.BaseDialogFragment -import com.fastaccess.ui.modules.gists.create.dialog.AddGistMvp.AddGistFileListener -import com.fastaccess.ui.widgets.markdown.MarkDownLayout -import com.fastaccess.ui.widgets.markdown.MarkdownEditText - -/** - * Created by kosh on 14/08/2017. - */ -class AddGistBottomSheetDialog : BaseDialogFragment(), AddGistMvp.View { - - @BindView(R.id.editText) lateinit var editText: MarkdownEditText - @BindView(R.id.description) lateinit var description: TextInputLayout - @BindView(R.id.toolbar) lateinit var toolbar: Toolbar - @BindView(R.id.markDownLayout) lateinit var markDownLayout: MarkDownLayout - - private var addFileListener: AddGistFileListener? = null - - override fun onAttach(context: Context) { - super.onAttach(context) - addFileListener = when { - parentFragment is AddGistFileListener -> parentFragment as AddGistFileListener - context is AddGistFileListener -> context - else -> throw NullPointerException("${context::class.java.simpleName} most implement AddGistFileListener") - } - } - - override fun onDetach() { - addFileListener = null - super.onDetach() - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN) - return super.onCreateView(inflater, container, savedInstanceState) - } - - override fun providePresenter(): AddGistPresenter = AddGistPresenter() - - override fun onAppendLink(title: String?, link: String?, isLink: Boolean) { - markDownLayout.onAppendLink(title, link, isLink) - } - - override fun fragmentLayout(): Int = R.layout.add_gist_file_layout - - override fun getEditText(): EditText = editText - - override fun fragmentManager(): FragmentManager = childFragmentManager - - override fun getSavedText(): CharSequence? = editText.savedText - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - markDownLayout.markdownListener = this - var file = arguments?.getParcelable(BundleConstant.ITEM) - val position = arguments?.getInt(BundleConstant.ID) - if (position != null) { - toolbar.title = if (position > 0) getString(R.string.edit_gist) else getString(R.string.create_gist) - } else { - toolbar.title = getString(R.string.create_gist) - } - editText.setOnFocusChangeListener { _, focused -> markDownLayout.visibility = if (focused) View.VISIBLE else View.GONE } - toolbar.inflateMenu(R.menu.done_menu) - toolbar.menu.findItem(R.id.submit)?.setIcon(R.drawable.ic_done) - toolbar.setNavigationIcon(R.drawable.ic_clear) - toolbar.setNavigationOnClickListener { dismiss() } - toolbar.setOnMenuItemClickListener { - if (it.itemId == R.id.submit) { - if (file == null) { - file = FilesListModel() - } - file?.let { - it.content = getSavedText().toString() - it.filename = InputHelper.toString(description) - it.type = MimeTypeMap.getFileExtensionFromUrl(file!!.filename) - it.size = it.content?.length?.toLong() - ViewHelper.hideKeyboard(editText) - addFileListener?.onFileAdded(it, position) - } - } - dismiss() - return@setOnMenuItemClickListener true - } - file?.let { - description.editText?.setText(it.filename) - editText.setText(it.content) - } - } - - @SuppressLint("SetTextI18n") - override fun onEmojiAdded(emoji: Emoji?) { - markDownLayout.onEmojiAdded(emoji) - } - - companion object { - val TAG = AddGistBottomSheetDialog::class.java.simpleName!! - - fun newInstance(file: FilesListModel?, position: Int = -1): AddGistBottomSheetDialog { - val fragment = AddGistBottomSheetDialog() - file?.let { - fragment.arguments = Bundler.start() - .put(BundleConstant.ITEM, file as Parcelable) - .put(BundleConstant.ID, position) - .end() - } - return fragment - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistMvp.kt deleted file mode 100644 index 228f91982..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistMvp.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.fastaccess.ui.modules.gists.create.dialog - -import com.fastaccess.data.dao.FilesListModel -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.modules.editor.emoji.EmojiMvp -import com.fastaccess.ui.modules.editor.popup.EditorLinkImageMvp -import com.fastaccess.ui.widgets.markdown.MarkDownLayout - -/** - * Created by kosh on 14/08/2017. - */ -interface AddGistMvp { - - interface View : BaseMvp.FAView, EditorLinkImageMvp.EditorLinkCallback, MarkDownLayout.MarkdownListener, EmojiMvp.EmojiCallback - interface Presenter - interface AddGistFileListener { - fun onFileAdded(file: FilesListModel, position: Int? = -1) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistPresenter.kt deleted file mode 100644 index 7329e6e1f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/create/dialog/AddGistPresenter.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.fastaccess.ui.modules.gists.create.dialog - -import com.fastaccess.ui.base.mvp.presenter.BasePresenter - -/** - * Created by kosh on 14/08/2017. - */ -class AddGistPresenter : BasePresenter(), AddGistMvp.Presenter \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistActivity.java b/app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistActivity.java deleted file mode 100644 index 24b737281..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistActivity.java +++ /dev/null @@ -1,331 +0,0 @@ -package com.fastaccess.ui.modules.gists.gist; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; -import android.support.v4.content.ContextCompat; -import android.support.v4.view.ViewPager; -import android.text.format.Formatter; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.PinnedGists; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.provider.tasks.git.GithubActionService; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; -import com.fastaccess.ui.modules.gists.GistsListActivity; -import com.fastaccess.ui.modules.gists.create.CreateGistActivity; -import com.fastaccess.ui.modules.gists.gist.comments.GistCommentsFragment; -import com.fastaccess.ui.modules.main.premium.PremiumActivity; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.ViewPagerView; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; - -import java.util.ArrayList; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 12 Nov 2016, 12:18 PM - */ - -public class GistActivity extends BaseActivity - implements GistMvp.View { - - @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.headerTitle) FontTextView title; - @BindView(R.id.size) FontTextView size; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.pager) ViewPagerView pager; - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.fab) FloatingActionButton fab; - @BindView(R.id.startGist) ForegroundImageView startGist; - @BindView(R.id.forkGist) ForegroundImageView forkGist; - @BindView(R.id.detailsIcon) View detailsIcon; - @BindView(R.id.edit) View edit; - @BindView(R.id.pinUnpin) ForegroundImageView pinUnpin; - private int accentColor; - private int iconColor; - private CommentEditorFragment commentEditorFragment; - - public static Intent createIntent(@NonNull Context context, @NonNull String gistId, boolean isEnterprise) { - Intent intent = new Intent(context, GistActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, gistId) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - return intent; - } - - @OnClick(R.id.detailsIcon) void onTitleClick() { - if (getPresenter().getGist() != null && !InputHelper.isEmpty(getPresenter().getGist().getDescription())) - MessageDialogView.newInstance(getString(R.string.details), getPresenter().getGist().getDescription(), false, true) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - } - - @OnClick({R.id.startGist, R.id.forkGist, R.id.browser}) public void onGistActions(View view) { - if (getPresenter().getGist() == null) return; - if (view.getId() != R.id.browser) { - view.setEnabled(false); - } - switch (view.getId()) { - case R.id.startGist: - GithubActionService.startForGist(this, getPresenter().getGist().getGistId(), - getPresenter().isStarred() ? GithubActionService.UNSTAR_GIST : GithubActionService.STAR_GIST, isEnterprise()); - getPresenter().onStarGist(); - break; - case R.id.forkGist: - GithubActionService.startForGist(this, getPresenter().getGist().getGistId(), - GithubActionService.FORK_GIST, isEnterprise()); - getPresenter().onForkGist(); - break; - case R.id.browser: - ActivityHelper.startCustomTab(this, getPresenter().getGist().getHtmlUrl()); - break; - } - } - - @OnClick(R.id.edit) void onEdit() { - if (PrefGetter.isProEnabled() || PrefGetter.isAllFeaturesUnlocked()) { - if (getPresenter().getGist() != null) CreateGistActivity.start(this, getPresenter().getGist()); - } else { - PremiumActivity.Companion.startActivity(this); - } - } - - @OnClick(R.id.pinUnpin) void pinUpin() { - if (PrefGetter.isProEnabled()) { - getPresenter().onPinUnpinGist(); - } else { - PremiumActivity.Companion.startActivity(this); - } - } - - @Override protected int layout() { - return R.layout.gists_pager_layout; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public GistPresenter providePresenter() { - return new GistPresenter(); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - fab.hide(); - commentEditorFragment = (CommentEditorFragment) getSupportFragmentManager().findFragmentById(R.id.commentFragment); - accentColor = ViewHelper.getAccentColor(this); - iconColor = ViewHelper.getIconColor(this); - if (savedInstanceState == null) { - getPresenter().onActivityCreated(getIntent()); - } else { - if (getPresenter().getGist() != null) { - onSetupDetails(); - } - } - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.gist_menu, menu); - return super.onCreateOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.share) { - if (getPresenter().getGist() != null) ActivityHelper.shareUrl(this, getPresenter().getGist().getHtmlUrl()); - return true; - } else if (item.getItemId() == R.id.deleteGist) { - MessageDialogView.newInstance( - getString(R.string.delete_gist), getString(R.string.confirm_message), - Bundler.start() - .put(BundleConstant.YES_NO_EXTRA, true) - .put(BundleConstant.EXTRA, true).end()) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - return true; - } else if (item.getItemId() == android.R.id.home) { - GistsListActivity.startActivity(this); - finish(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override public boolean onPrepareOptionsMenu(Menu menu) { - menu.findItem(R.id.deleteGist).setVisible(getPresenter().isOwner()); - return super.onPrepareOptionsMenu(menu); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (bundle != null) { - boolean isDelete = bundle.getBoolean(BundleConstant.EXTRA) && isOk; - if (isDelete) { - getPresenter().onDeleteGist(); - } - } - } - - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK) { - if (requestCode == BundleConstant.REQUEST_CODE) { - getPresenter().callApi(); - } - } - } - - @Override public void onSuccessDeleted() { - hideProgress(); - if (getPresenter().getGist() != null) { - Intent intent = new Intent(); - Gist gistsModel = new Gist(); - gistsModel.setUrl(getPresenter().getGist().getHtmlUrl()); - intent.putExtras(Bundler.start().put(BundleConstant.ITEM, gistsModel).end()); - setResult(RESULT_OK, intent); - } - finish(); - } - - @Override public void onErrorDeleting() { - showErrorMessage(getString(R.string.error_deleting_gist)); - } - - @Override public void onGistStarred(boolean isStarred) { - startGist.setImageResource(isStarred ? R.drawable.ic_star_filled : R.drawable.ic_star); - startGist.tintDrawableColor(isStarred ? accentColor : iconColor); - startGist.setEnabled(true); - } - - @Override public void onGistForked(boolean isForked) { - forkGist.tintDrawableColor(isForked ? accentColor : iconColor); - forkGist.setEnabled(true); - } - - @Override public void onSetupDetails() { - hideProgress(); - Gist gistsModel = getPresenter().getGist(); - if (gistsModel == null) { - return; - } - onUpdatePinIcon(gistsModel); - String url = gistsModel.getOwner() != null ? gistsModel.getOwner().getAvatarUrl() : - gistsModel.getUser() != null ? gistsModel.getUser().getAvatarUrl() : ""; - String login = gistsModel.getOwner() != null ? gistsModel.getOwner().getLogin() : - gistsModel.getUser() != null ? gistsModel.getUser().getLogin() : ""; - avatarLayout.setUrl(url, login, false, LinkParserHelper.isEnterprise(gistsModel.getHtmlUrl())); - title.setText(gistsModel.getDisplayTitle(false, true)); - setTaskName(gistsModel.getDisplayTitle(false, true).toString()); - edit.setVisibility(Login.getUser().getLogin().equals(login) ? View.VISIBLE : View.GONE); - detailsIcon.setVisibility(InputHelper.isEmpty(gistsModel.getDescription()) || !ViewHelper.isEllipsed(title) ? View.GONE : View.VISIBLE); - if (gistsModel.getCreatedAt().before(gistsModel.getUpdatedAt())) { - date.setText(String.format("%s %s", ParseDateFormat.getTimeAgo(gistsModel.getCreatedAt()), getString(R.string.edited))); - } else { - date.setText(ParseDateFormat.getTimeAgo(gistsModel.getCreatedAt())); - } - size.setText(Formatter.formatFileSize(this, gistsModel.getSize())); - pager.setAdapter(new FragmentsPagerAdapter(getSupportFragmentManager(), FragmentPagerAdapterModel.buildForGist(this, gistsModel))); - tabs.setupWithViewPager(pager); - pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { - @Override public void onPageSelected(int position) { - super.onPageSelected(position); - hideShowFab(); - } - }); - supportInvalidateOptionsMenu(); - onGistForked(getPresenter().isForked()); - onGistStarred(getPresenter().isStarred()); - hideShowFab(); - tabs.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager) { - @Override public void onTabReselected(TabLayout.Tab tab) { - super.onTabReselected(tab); - onScrollTop(tab.getPosition()); - } - }); - } - - @Override public void onUpdatePinIcon(@NonNull Gist gist) { - pinUnpin.setImageDrawable(PinnedGists.isPinned(gist.getGistId().hashCode()) - ? ContextCompat.getDrawable(this, R.drawable.ic_pin_filled) - : ContextCompat.getDrawable(this, R.drawable.ic_pin)); - } - - @Override public void onScrollTop(int index) { - if (pager == null || pager.getAdapter() == null) return; - Fragment fragment = (BaseFragment) pager.getAdapter().instantiateItem(pager, index); - if (fragment instanceof BaseFragment) { - ((BaseFragment) fragment).onScrollTop(index); - } - } - - @Override public void onSendActionClicked(@NonNull String text, Bundle bundle) { - GistCommentsFragment view = getGistCommentsFragment(); - if (view != null) { - view.onHandleComment(text, bundle); - } - } - - @Override public void onTagUser(@NonNull String username) { - commentEditorFragment.onAddUserName(username); - } - - @Override public void onCreateComment(String text, Bundle bundle) { - - } - - @SuppressWarnings("ConstantConditions") @Override public void onClearEditText() { - if (commentEditorFragment != null && commentEditorFragment.commentText != null) commentEditorFragment.commentText.setText(""); - } - - @NonNull @Override public ArrayList getNamesToTag() { - GistCommentsFragment view = getGistCommentsFragment(); - if (view != null) return view.getNamesToTag(); - return new ArrayList<>(); - } - - @Nullable private GistCommentsFragment getGistCommentsFragment() { - if (pager == null || pager.getAdapter() == null) return null; - return (GistCommentsFragment) pager.getAdapter().instantiateItem(pager, 1); - } - - private void hideShowFab() { - if (pager.getCurrentItem() == 1) { - getSupportFragmentManager().beginTransaction().show(commentEditorFragment).commit(); - } else { - getSupportFragmentManager().beginTransaction().hide(commentEditorFragment).commit(); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistMvp.java b/app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistMvp.java deleted file mode 100644 index 09a289f25..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistMvp.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.fastaccess.ui.modules.gists.gist; - -import android.content.Intent; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; - -/** - * Created by Kosh on 12 Nov 2016, 12:17 PM - */ - -interface GistMvp { - - interface View extends BaseMvp.FAView, CommentEditorFragment.CommentListener { - void onSuccessDeleted(); - - void onErrorDeleting(); - - void onGistStarred(boolean isStarred); - - void onGistForked(boolean isForked); - - void onSetupDetails(); - - void onUpdatePinIcon(Gist gist); - } - - interface Presenter extends BaseMvp.FAPresenter { - - @Nullable Gist getGist(); - - @NonNull String gistId(); - - void onActivityCreated(@Nullable Intent intent); - - void onDeleteGist(); - - boolean isOwner(); - - void onStarGist(); - - void onForkGist(); - - boolean isForked(); - - boolean isStarred(); - - void checkStarring(@NonNull String gistId); - - void callApi(); - - void onWorkOffline(@NonNull String gistId); - - void onPinUnpinGist(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistPresenter.java deleted file mode 100644 index 0f724e68a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/GistPresenter.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.fastaccess.ui.modules.gists.gist; - -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.PinnedGists; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by Kosh on 12 Nov 2016, 12:17 PM - */ - -class GistPresenter extends BasePresenter implements GistMvp.Presenter { - @com.evernote.android.state.State boolean isGistStarred; - @com.evernote.android.state.State boolean isGistForked; - @com.evernote.android.state.State Gist gist; - @com.evernote.android.state.State String gistId; - - @Nullable @Override public Gist getGist() { - return gist; - } - - @NonNull @Override public String gistId() { - return gistId; - } - - @SuppressWarnings("unchecked") @Override public void onActivityCreated(@Nullable Intent intent) { - if (intent == null || intent.getExtras() == null) { - return; - } - Bundle bundle = intent.getExtras(); - gistId = bundle.getString(BundleConstant.EXTRA); - if (gist != null) { - checkStarring(gist.getGistId()); - sendToView(GistMvp.View::onSetupDetails); - } else if (gistId != null) { - callApi(); - } else { - sendToView(GistMvp.View::onSetupDetails); - } - } - - @Override public void onDeleteGist() { - if (getGist() == null) return; - manageDisposable(RxHelper.getObservable(RestProvider.getGistService(isEnterprise()).deleteGist(getGist().getGistId())) - .doOnSubscribe(disposable -> onSubscribed(false)) - .doOnNext(booleanResponse -> { - if (booleanResponse.code() == 204) { - sendToView(GistMvp.View::onSuccessDeleted); - } else { - sendToView(GistMvp.View::onErrorDeleting); - } - }) - .subscribe(booleanResponse -> {/**/}, throwable -> sendToView(view -> view.showErrorMessage(throwable.getMessage())))); - } - - @Override public boolean isOwner() { - return getGist() != null && getGist().getOwner() != null && - getGist().getOwner().getLogin().equals(Login.getUser().getLogin()); - } - - @Override public void onStarGist() { - isGistStarred = !isGistStarred; - sendToView(view -> view.onGistStarred(isGistStarred)); - } - - @Override public void onForkGist() { - isGistForked = !isGistForked; - sendToView(view -> view.onGistForked(isGistForked)); - } - - @Override public boolean isForked() { - return isGistForked; - } - - @Override public boolean isStarred() { - return isGistStarred; - } - - @Override public void checkStarring(@NonNull String gistId) { - makeRestCall(RestProvider.getGistService(isEnterprise()).checkGistStar(gistId), - booleanResponse -> { - isGistStarred = booleanResponse.code() == 204; - sendToView(view -> view.onGistStarred(isGistStarred)); - }); - } - - @Override public void onWorkOffline(@NonNull String gistId) { - if (gist == null) { - manageDisposable(RxHelper.getObservable(Gist.getGist(gistId)) - .subscribe(gistsModel -> { - this.gist = gistsModel; - sendToView(GistMvp.View::onSetupDetails); - })); - } - } - - @Override public void onPinUnpinGist() { - if (getGist() == null) return; - PinnedGists.pinUpin(getGist()); - sendToView(view -> view.onUpdatePinIcon(getGist())); - } - - @Override public void callApi() { - if (!InputHelper.isEmpty(gistId)) { - checkStarring(gistId); - makeRestCall(RestProvider.getGistService(isEnterprise()).getGist(gistId), gistsModel -> { - this.gist = gistsModel; - sendToView(GistMvp.View::onSetupDetails); - }); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsFragment.java b/app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsFragment.java deleted file mode 100644 index 3e74e18ff..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsFragment.java +++ /dev/null @@ -1,271 +0,0 @@ -package com.fastaccess.ui.modules.gists.gist.comments; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.SparseBooleanArrayParcelable; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.ui.adapter.CommentsAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.editor.EditorActivity; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.ArrayList; -import java.util.List; - -import butterknife.BindView; - -import static com.fastaccess.helper.BundleConstant.ExtraType.EDIT_GIST_COMMENT_EXTRA; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -public class GistCommentsFragment extends BaseFragment implements GistCommentsMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @State SparseBooleanArrayParcelable sparseBooleanArray; - private CommentEditorFragment.CommentListener commentsCallback; - private String gistId; - private CommentsAdapter adapter; - private OnLoadMore onLoadMore; - - public static GistCommentsFragment newInstance(@NonNull String gistId) { - GistCommentsFragment view = new GistCommentsFragment(); - view.setArguments(Bundler.start().put("gistId", gistId).end()); - return view; - } - - @SuppressWarnings("unchecked") @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof CommentEditorFragment.CommentListener) { - commentsCallback = (CommentEditorFragment.CommentListener) getParentFragment(); - } else if (context instanceof CommentEditorFragment.CommentListener) { - commentsCallback = (CommentEditorFragment.CommentListener) context; - } else { - throw new IllegalArgumentException(String.format("%s or parent fragment must implement CommentEditorFragment.CommentListener", - context.getClass().getSimpleName())); - } - } - - @Override public void onDetach() { - commentsCallback = null; - super.onDetach(); - } - - @Override protected int fragmentLayout() { - return R.layout.fab_micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - gistId = getArguments().getString("gistId"); - recycler.setEmptyView(stateLayout, refresh); - if (gistId == null) return; - stateLayout.setEmptyText(R.string.no_comments); - recycler.setItemViewCacheSize(30); - refresh.setOnRefreshListener(this); - stateLayout.setOnReloadListener(this); - adapter = new CommentsAdapter(getPresenter().getComments()); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - recycler.addOnScrollListener(getLoadMore()); - recycler.addNormalSpacingDivider(); - if (getPresenter().getComments().isEmpty() && !getPresenter().isApiCalled()) { - sparseBooleanArray = new SparseBooleanArrayParcelable(); - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, gistId); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void onRemove(@NonNull Comment comment) { - hideProgress(); - adapter.removeItem(comment); - } - - @Override public void hideProgress() { - super.hideProgress(); - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public GistCommentsPresenter providePresenter() { - return new GistCommentsPresenter(); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), gistId); - } - return onLoadMore; - } - - @Override public void onEditComment(@NonNull Comment item) { - Intent intent = new Intent(getContext(), EditorActivity.class); - intent.putExtras(Bundler - .start() - .put(BundleConstant.ID, gistId) - .put(BundleConstant.EXTRA, item.getBody()) - .put(BundleConstant.EXTRA_FOUR, item.getId()) - .put(BundleConstant.EXTRA_TYPE, EDIT_GIST_COMMENT_EXTRA) - .putStringArrayList("participants", CommentsHelper.getUsers(adapter.getData())) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise()) - .end()); - View view = getActivity() != null && getActivity().findViewById(R.id.fab) != null ? getActivity().findViewById(R.id.fab) : recycler; - ActivityHelper.startReveal(this, intent, view, BundleConstant.REQUEST_CODE); - } - - @Override public void onShowDeleteMsg(long id) { - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), - Bundler.start() - .put(BundleConstant.EXTRA, id) - .put(BundleConstant.ID, gistId) - .put(BundleConstant.YES_NO_EXTRA, true) - .putStringArrayList("participants", CommentsHelper.getUsers(adapter.getData())) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - - @Override public void onTagUser(@Nullable User user) { - if (commentsCallback != null && user != null) { - commentsCallback.onTagUser(user.getLogin()); - } - } - - @Override public void onReply(User user, String message) { - onTagUser(user); - } - - @Override public void onHandleComment(@NonNull String text, @Nullable Bundle bundle) { - getPresenter().onHandleComment(text, bundle, gistId); - } - - @Override public void onAddNewComment(@NonNull Comment comment) { - hideBlockingProgress(); - adapter.addItem(comment); - if (commentsCallback != null) commentsCallback.onClearEditText(); - } - - @NonNull @Override public ArrayList getNamesToTag() { - return CommentsHelper.getUsers(adapter.getData()); - } - - @Override public void hideBlockingProgress() { - hideProgress(); - super.hideProgress(); - } - - @Override public void onDestroyView() { - recycler.removeOnScrollListener(getLoadMore()); - super.onDestroyView(); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK) { - if (requestCode == BundleConstant.REQUEST_CODE) { - if (data == null) { - onRefresh(); - return; - } - Bundle bundle = data.getExtras(); - if (bundle != null) { - boolean isNew = bundle.getBoolean(BundleConstant.EXTRA); - Comment commentsModel = bundle.getParcelable(BundleConstant.ITEM); - if (commentsModel == null) return; - if (isNew) { - adapter.addItem(commentsModel); - recycler.smoothScrollToPosition(adapter.getItemCount()); - } else { - int position = adapter.getItem(commentsModel); - if (position != -1) { - adapter.swapItem(commentsModel, position); - recycler.smoothScrollToPosition(position); - } else { - adapter.addItem(commentsModel); - recycler.smoothScrollToPosition(adapter.getItemCount()); - } - } - } - } - } - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk) { - getPresenter().onHandleDeletion(bundle); - } - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsMvp.java deleted file mode 100644 index ae637373b..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsMvp.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.fastaccess.ui.modules.gists.gist.comments; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 20 Nov 2016, 11:10 AM - */ - -interface GistCommentsMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, - android.view.View.OnClickListener { - - void onNotifyAdapter(@Nullable List items, int page); - - void onRemove(@NonNull Comment comment); - - @NonNull OnLoadMore getLoadMore(); - - void onEditComment(@NonNull Comment item); - - void onShowDeleteMsg(long id); - - void onTagUser(@NonNull User user); - - void onReply(User user, String message); - - void onHandleComment(@NonNull String text, @Nullable Bundle bundle); - - void onAddNewComment(@NonNull Comment comment); - - @NonNull ArrayList getNamesToTag(); - - void hideBlockingProgress(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseMvp.PaginationListener, BaseViewHolder.OnItemClickListener { - - @NonNull ArrayList getComments(); - - - void onHandleDeletion(@Nullable Bundle bundle); - - void onWorkOffline(@NonNull String gistId); - - void onHandleComment(@NonNull String text, @Nullable Bundle bundle, String gistId); - } - - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsPresenter.java deleted file mode 100644 index c6e9f7787..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/comments/GistCommentsPresenter.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.fastaccess.ui.modules.gists.gist.comments; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import android.view.View; -import android.widget.PopupMenu; - -import com.fastaccess.R; -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -class GistCommentsPresenter extends BasePresenter implements GistCommentsMvp.Presenter { - private ArrayList comments = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - //noinspection ConstantConditions - sendToView(view -> onWorkOffline(view.getLoadMore().getParameter())); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - if (page > lastPage || parameter == null || lastPage == 0) { - sendToView(GistCommentsMvp.View::hideProgress); - return false; - } - setCurrentPage(page); - makeRestCall(RestProvider.getGistService(isEnterprise()).getGistComments(parameter, page), - listResponse -> { - lastPage = listResponse.getLast(); - if (getCurrentPage() == 1) { - manageDisposable(Comment.saveForGist(listResponse.getItems(), parameter)); - } - sendToView(view -> view.onNotifyAdapter(listResponse.getItems(), page)); - }); - return true; - } - - @NonNull @Override public ArrayList getComments() { - return comments; - } - - @Override public void onHandleDeletion(@Nullable Bundle bundle) { - if (bundle != null) { - long commId = bundle.getLong(BundleConstant.EXTRA, 0); - String gistId = bundle.getString(BundleConstant.ID); - if (commId != 0 && gistId != null) { - makeRestCall(RestProvider.getGistService(isEnterprise()).deleteGistComment(gistId, commId), - booleanResponse -> sendToView(view -> { - if (booleanResponse.code() == 204) { - Comment comment = new Comment(); - comment.setId(commId); - view.onRemove(comment); - } else { - view.showMessage(R.string.error, R.string.error_deleting_comment); - } - })); - } - } - } - - @Override public void onWorkOffline(@NonNull String gistId) { - if (comments.isEmpty()) { - manageDisposable(RxHelper.getObservable(Comment.getGistComments(gistId).toObservable()) - .subscribe(localComments -> sendToView(view -> view.onNotifyAdapter(localComments, 1)))); - } else { - sendToView(BaseMvp.FAView::hideProgress); - } - } - - @Override public void onHandleComment(@NonNull String text, @Nullable Bundle bundle, String gistId) { - CommentRequestModel model = new CommentRequestModel(); - model.setBody(text); - manageDisposable(RxHelper.getObservable(RestProvider.getGistService(isEnterprise()).createGistComment(gistId, model)) - .doOnSubscribe(disposable -> sendToView(view -> view.showBlockingProgress(0))) - .subscribe(comment -> sendToView(view -> view.onAddNewComment(comment)), throwable -> { - onError(throwable); - sendToView(GistCommentsMvp.View::hideBlockingProgress); - })); - } - - @Override public void onItemClick(int position, View v, Comment item) { - if (getView() == null) return; - if (v.getId() == R.id.toggle || v.getId() == R.id.toggleHolder) { - PopupMenu popupMenu = new PopupMenu(v.getContext(), v); - popupMenu.inflate(R.menu.comments_menu); - String username = Login.getUser().getLogin(); - popupMenu.getMenu().findItem(R.id.delete).setVisible(username.equalsIgnoreCase(item.getUser().getLogin())); - popupMenu.getMenu().findItem(R.id.edit).setVisible(username.equalsIgnoreCase(item.getUser().getLogin())); - popupMenu.setOnMenuItemClickListener(item1 -> { - if (getView() == null) return false; - if (item1.getItemId() == R.id.delete) { - getView().onShowDeleteMsg(item.getId()); - } else if (item1.getItemId() == R.id.reply) { - getView().onReply(item.getUser(), item.getBody()); - } else if (item1.getItemId() == R.id.edit) { - getView().onEditComment(item); - } - return true; - }); - popupMenu.show(); - } - } - - @Override public void onItemLongClick(int position, View v, Comment item) { - if (v.getId() == R.id.toggle) { - if (getView() != null) getView().onReply(item.getUser(), item.getBody()); - } else { - if (item.getUser() != null && TextUtils.equals(item.getUser().getLogin(), Login.getUser().getLogin())) { - if (getView() != null) getView().onShowDeleteMsg(item.getId()); - } else { - onItemClick(position, v, item); - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListFragment.java b/app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListFragment.java deleted file mode 100644 index c87109af1..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListFragment.java +++ /dev/null @@ -1,191 +0,0 @@ -package com.fastaccess.ui.modules.gists.gist.files; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.FilesListModel; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.FileHelper; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.markdown.MarkDownProvider; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.adapter.GistFilesAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.code.CodeViewerActivity; -import com.fastaccess.ui.modules.gists.create.dialog.AddGistBottomSheetDialog; -import com.fastaccess.ui.modules.main.premium.PremiumActivity; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.ArrayList; -import java.util.HashMap; - -import butterknife.BindView; - -/** - * Created by Kosh on 13 Nov 2016, 1:36 PM - */ - -public class GistFilesListFragment extends BaseFragment implements - GistFilesListMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @State boolean isOwner; - private GistFilesAdapter adapter; - - public static GistFilesListFragment newInstance(@NonNull ArrayList files, boolean isOwner) { - GistFilesListFragment view = new GistFilesListFragment(); - view.setArguments(Bundler.start() - .putParcelableArrayList(BundleConstant.ITEM, files) - .put(BundleConstant.EXTRA_TYPE, isOwner) - .end()); - return view; - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @NonNull @Override public GistFilesListPresenter providePresenter() { - return new GistFilesListPresenter(); - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - stateLayout.setEmptyText(R.string.no_files); - stateLayout.showEmptyState(); - recycler.setEmptyView(stateLayout, refresh); - refresh.setEnabled(false); - adapter = new GistFilesAdapter(getPresenter().getFiles(), getPresenter(), isOwner); - recycler.setAdapter(adapter); - if (getArguments() != null && savedInstanceState == null) { - ArrayList filesListModel = getArguments().getParcelableArrayList(BundleConstant.ITEM); - isOwner = getArguments().getBoolean(BundleConstant.EXTRA_TYPE); - onInitFiles(filesListModel, isOwner); - setArguments(null);//CLEAR - } else { - onInitFiles(getPresenter().getFiles(), isOwner); - } - fastScroller.attachRecyclerView(recycler); - } - - @Override public void onOpenFile(@NonNull FilesListModel item, int position) { - if (canOpen(item) && !isOwner) { - CodeViewerActivity.startActivity(getContext(), item.getRawUrl(), item.getRawUrl()); - } else if (isOwner && canOpen(item)) { - onEditFile(item, position); - } - } - - @Override public void onDeleteFile(@NonNull FilesListModel item, int position) { - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), false, - Bundler.start() - .put(BundleConstant.ID, position) - .put(BundleConstant.YES_NO_EXTRA, true) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - - @Override public void onEditFile(@NonNull FilesListModel item, int position) { - AddGistBottomSheetDialog.Companion.newInstance(item, position).show(getChildFragmentManager(), AddGistBottomSheetDialog.Companion.getTAG()); - } - - @Override public void onInitFiles(@Nullable ArrayList filesListModel, boolean isOwner) { - if (filesListModel == null) { - filesListModel = new ArrayList<>();//DO NOT PASS NULL TO ADAPTER - } - if (getPresenter().getFilesMap().isEmpty()) { - for (FilesListModel listModel : filesListModel) { - getPresenter().getFilesMap().put(listModel.getFilename(), listModel); - } - } - adapter.setOwner(isOwner); - getPresenter().onSetList(filesListModel); - adapter.insertItems(filesListModel); - } - - @Override public void onAddNewFile() { - Logger.e("Hello world"); - if (adapter.getItemCount() == 0 || (PrefGetter.isProEnabled() || PrefGetter.isAllFeaturesUnlocked())) { - AddGistBottomSheetDialog.Companion.newInstance(null, -1) - .show(getChildFragmentManager(), AddGistBottomSheetDialog.Companion.getTAG()); - } else { - PremiumActivity.Companion.startActivity(getContext()); - } - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk && bundle != null) { - String url = bundle.getString(BundleConstant.EXTRA); - if (!InputHelper.isEmpty(url)) { - if (ActivityHelper.checkAndRequestReadWritePermission(getActivity())) { - RestProvider.downloadFile(getContext(), url); - } - } else if (bundle.getBoolean(BundleConstant.YES_NO_EXTRA)) { - if (adapter != null) { - int position = bundle.getInt(BundleConstant.ID); - FilesListModel file = adapter.getItem(position); - if (file != null) { - if (getPresenter().getFilesMap().get(file.getFilename()) != null) { - file = getPresenter().getFilesMap().get(file.getFilename()); - file.setContent(null); - getPresenter().getFilesMap().put(file.getFilename(), file); - } - } - adapter.removeItem(position); - } - } - } - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - @Override public void onFileAdded(@NonNull FilesListModel file, Integer position) { - if (position == null || position == -1) { - adapter.addItem(file); - getPresenter().getFilesMap().put(file.getFilename(), file); - } else { - FilesListModel current = adapter.getItem(position); - if (getPresenter().getFilesMap().get(current.getFilename()) != null) { - FilesListModel toUpdate = getPresenter().getFilesMap().get(current.getFilename()); - toUpdate.setFilename(file.getFilename()); - toUpdate.setContent(file.getContent()); - getPresenter().getFilesMap().put(current.getFilename(), toUpdate); - } - adapter.swapItem(file, position); - - } - } - - private boolean canOpen(@NonNull FilesListModel item) { - if (item.getRawUrl() == null) return false; - if (item.getSize() > FileHelper.ONE_MB && !MarkDownProvider.isImage(item.getRawUrl())) { - MessageDialogView.newInstance(getString(R.string.big_file), getString(R.string.big_file_description), false, true, - Bundler.start().put(BundleConstant.YES_NO_EXTRA, true).put(BundleConstant.EXTRA, item.getRawUrl()).end()) - .show(getChildFragmentManager(), "MessageDialogView"); - return false; - } - return true; - } - - @NonNull @Override public HashMap getFiles() { - return getPresenter().getFilesMap(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListMvp.java b/app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListMvp.java deleted file mode 100644 index cbda030a1..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListMvp.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fastaccess.ui.modules.gists.gist.files; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.FilesListModel; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.gists.create.dialog.AddGistMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - * Created by Kosh on 13 Nov 2016, 1:35 PM - */ - -public interface GistFilesListMvp { - - interface View extends BaseMvp.FAView, AddGistMvp.AddGistFileListener { - void onOpenFile(@NonNull FilesListModel item, int position); - - void onDeleteFile(@NonNull FilesListModel item, int position); - - void onEditFile(@NonNull FilesListModel item, int position); - - void onInitFiles(@Nullable ArrayList file, boolean isOwner); - - void onAddNewFile(); - - @NonNull HashMap getFiles(); - } - - interface Presenter extends BaseMvp.FAPresenter, BaseViewHolder.OnItemClickListener { - void onSetList(@Nullable ArrayList files); - - @NonNull ArrayList getFiles(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListPresenter.java deleted file mode 100644 index 7b94da524..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/gist/files/GistFilesListPresenter.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.fastaccess.ui.modules.gists.gist.files; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.FilesListModel; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; -import java.util.HashMap; - -import lombok.Getter; - -/** - * Created by Kosh on 13 Nov 2016, 1:35 PM - */ - -public class GistFilesListPresenter extends BasePresenter implements GistFilesListMvp.Presenter { - private ArrayList listModels; - @Getter private HashMap filesMap = new HashMap<>(); - - @Override public void onItemClick(int position, View v, FilesListModel item) { - if (getView() != null) { - if (v.getId() == R.id.delete) { - getView().onDeleteFile(item, position); - } else if (v.getId() == R.id.edit) { - getView().onEditFile(item, position); - } else { - getView().onOpenFile(item, position); - } - } - } - - @Override public void onItemLongClick(int position, View v, FilesListModel item) {} - - @Override public void onSetList(@Nullable ArrayList files) { - this.listModels = files; - } - - @NonNull @Override public ArrayList getFiles() { - if (listModels == null) { - return new ArrayList<>(); - } - return listModels; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsFragment.java b/app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsFragment.java deleted file mode 100644 index 8ff79f90e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsFragment.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.fastaccess.ui.modules.gists.starred; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.GistsAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.gists.gist.GistActivity; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -public class StarredGistsFragment extends BaseFragment implements StarredGistsMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - - private GistsAdapter adapter; - private OnLoadMore onLoadMore; - - public static StarredGistsFragment newInstance() { - return new StarredGistsFragment(); - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - stateLayout.setEmptyText(R.string.no_gists); - refresh.setOnRefreshListener(this); - stateLayout.setOnReloadListener(this); - recycler.setEmptyView(stateLayout, refresh); - adapter = new GistsAdapter(getPresenter().getGists(), true); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addDivider(); - if (getPresenter().getGists().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, null); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public StarredGistsPresenter providePresenter() { - return new StarredGistsPresenter(); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), null); - } - return onLoadMore; - } - - @Override public void onStartGistView(@NonNull String gistId) { - startActivityForResult(GistActivity.createIntent(getContext(), gistId, isEnterprise()), BundleConstant.REQUEST_CODE); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK && requestCode == BundleConstant.REQUEST_CODE) { - if (data != null && data.getExtras() != null) { - Gist gistsModel = data.getExtras().getParcelable(BundleConstant.ITEM); - if (gistsModel != null && adapter != null) { - adapter.removeItem(gistsModel); - } - } else { - onRefresh(); - } - } - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsMvp.java deleted file mode 100644 index da11aa08b..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsMvp.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.fastaccess.ui.modules.gists.starred; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 12:35 PM - */ - -interface StarredGistsMvp { - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onStartGistView(@NonNull String gistId); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getGists(); - - void onWorkOffline(@NonNull String login); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsPresenter.java deleted file mode 100644 index 10534953b..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/gists/starred/StarredGistsPresenter.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.fastaccess.ui.modules.gists.starred; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -class StarredGistsPresenter extends BasePresenter implements StarredGistsMvp.Presenter { - private ArrayList gistsModels = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - sendToView(view -> { - if (view.getLoadMore().getParameter() != null) { - onWorkOffline(view.getLoadMore().getParameter()); - } - }); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(StarredGistsMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getGistService(isEnterprise()).getStarredGists(page), - listResponse -> { - lastPage = listResponse.getLast(); - sendToView(view -> view.onNotifyAdapter(listResponse.getItems(), page)); - }); - return true; - } - - @NonNull @Override public ArrayList getGists() { - return gistsModels; - } - - @Override public void onWorkOffline(@NonNull String login) {}// do nothing for now. - - @Override public void onItemClick(int position, View v, Gist item) { - SchemeParser.launchUri(v.getContext(), item.getHtmlUrl()); - } - - @Override public void onItemLongClick(int position, View v, Gist item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/LoginActivity.java b/app/src/main/java/com/fastaccess/ui/modules/login/LoginActivity.java deleted file mode 100644 index b645d9401..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/login/LoginActivity.java +++ /dev/null @@ -1,262 +0,0 @@ -package com.fastaccess.ui.modules.login; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.TextInputEditText; -import android.support.design.widget.TextInputLayout; -import android.view.View; -import android.widget.ProgressBar; - -import com.evernote.android.state.State; -import com.fastaccess.App; -import com.fastaccess.BuildConfig; -import com.fastaccess.R; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AnimHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.modules.login.chooser.LoginChooserActivity; -import com.fastaccess.ui.modules.main.donation.DonateActivity; -import com.fastaccess.ui.widgets.FontCheckbox; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.miguelbcr.io.rx_billing_service.RxBillingService; -import com.miguelbcr.io.rx_billing_service.entities.ProductType; -import com.miguelbcr.io.rx_billing_service.entities.Purchase; - -import butterknife.BindView; -import butterknife.OnCheckedChanged; -import butterknife.OnClick; -import butterknife.OnEditorAction; -import es.dmoral.toasty.Toasty; -import io.reactivex.functions.Action; - -/** - * Created by Kosh on 08 Feb 2017, 9:10 PM - */ - -public class LoginActivity extends BaseActivity implements LoginMvp.View { - - @BindView(R.id.usernameEditText) TextInputEditText usernameEditText; - @BindView(R.id.username) TextInputLayout username; - @BindView(R.id.passwordEditText) TextInputEditText passwordEditText; - @BindView(R.id.password) TextInputLayout password; - @BindView(R.id.twoFactor) TextInputLayout twoFactor; - @BindView(R.id.twoFactorEditText) TextInputEditText twoFactorEditText; - @BindView(R.id.login) FloatingActionButton login; - @BindView(R.id.progress) ProgressBar progress; - @BindView(R.id.accessTokenCheckbox) FontCheckbox accessTokenCheckbox; - @BindView(R.id.endpoint) TextInputLayout endpoint; - @State boolean isBasicAuth; - - public static void startOAuth(@NonNull Activity activity) { - Intent intent = new Intent(activity, LoginActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.YES_NO_EXTRA, true) - .put(BundleConstant.EXTRA_TWO, true) - .end()); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); - activity.startActivity(intent); - activity.finish(); - } - - public static void start(@NonNull Activity activity, boolean isBasicAuth) { - start(activity, isBasicAuth, false); - } - - public static void start(@NonNull Activity activity, boolean isBasicAuth, boolean isEnterprise) { - Intent intent = new Intent(activity, LoginActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.YES_NO_EXTRA, isBasicAuth) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); - activity.startActivity(intent); - activity.finish(); - } - - @OnClick(R.id.browserLogin) void onOpenBrowser() { - if (isEnterprise()) { - MessageDialogView.newInstance(getString(R.string.warning), getString(R.string.github_enterprise_reply), - true, Bundler.start().put("hide_buttons", true).end()) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - return; - } - ActivityHelper.startCustomTab(this, getPresenter().getAuthorizationUrl()); - } - - @OnClick(R.id.login) public void onClick() { - doLogin(); - } - - @OnCheckedChanged(R.id.accessTokenCheckbox) void onCheckChanged(boolean checked) { - isBasicAuth = !checked; - password.setHint(checked ? getString(R.string.access_token) : getString(R.string - .password)); - } - - @OnEditorAction(R.id.passwordEditText) public boolean onSendPassword() { - if (twoFactor.getVisibility() == View.VISIBLE) { - twoFactorEditText.requestFocus(); - } else if (endpoint.getVisibility() == View.VISIBLE) { - endpoint.requestFocus(); - } else { - doLogin(); - } - return true; - } - - @OnEditorAction(R.id.twoFactorEditText) public boolean onSend2FA() { - doLogin(); - return true; - } - - @OnEditorAction(R.id.endpointEditText) boolean onSendEndpoint() { - doLogin(); - return true; - } - - @Override protected int layout() { - return R.layout.login_form_layout; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return false; - } - - @Override protected boolean isSecured() { - return true; - } - - @NonNull @Override public LoginPresenter providePresenter() { - return new LoginPresenter(); - } - - @Override public void onEmptyUserName(boolean isEmpty) { - username.setError(isEmpty ? getString(R.string.required_field) : null); - } - - @Override public void onRequire2Fa() { - Toasty.warning(App.getInstance(), getString(R.string.two_factors_otp_error)).show(); - twoFactor.setVisibility(View.VISIBLE); - hideProgress(); - } - - @Override public void onEmptyPassword(boolean isEmpty) { - password.setError(isEmpty ? getString(R.string.required_field) : null); - } - - @Override public void onEmptyEndpoint(boolean isEmpty) { - endpoint.setError(isEmpty ? getString(R.string.required_field) : null); - } - - @Override public void onSuccessfullyLoggedIn(boolean extraLogin) { - checkPurchases(() -> { - hideProgress(); - onRestartApp(); - }); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - setTheme(R.style.LoginTheme); - super.onCreate(savedInstanceState); - if (savedInstanceState == null) { - if (getIntent() != null && getIntent().getExtras() != null) { - isBasicAuth = getIntent().getExtras().getBoolean(BundleConstant.YES_NO_EXTRA); - password.setHint(isBasicAuth ? getString(R.string.password) : getString(R.string.access_token)); - if (getIntent().getExtras().getBoolean(BundleConstant.EXTRA_TWO)) { - onOpenBrowser(); - } - } - } - accessTokenCheckbox.setVisibility(isEnterprise() ? View.VISIBLE : View.GONE); - endpoint.setVisibility(isEnterprise() ? View.VISIBLE : View.GONE); - } - - @Override protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - getPresenter().onHandleAuthIntent(intent); - setIntent(null); - } - - @Override protected void onResume() { - super.onResume(); - getPresenter().onHandleAuthIntent(getIntent()); - setIntent(null); - } - - @Override public void showErrorMessage(@NonNull String msgRes) { - hideProgress(); - super.showErrorMessage(msgRes); - } - - @Override public void showMessage(@StringRes int titleRes, @StringRes int msgRes) { - hideProgress(); - super.showMessage(titleRes, msgRes); - } - - @Override public void showMessage(@NonNull String titleRes, @NonNull String msgRes) { - hideProgress(); - super.showMessage(titleRes, msgRes); - } - - @Override public void showProgress(@StringRes int resId) { - login.hide(); - AppHelper.hideKeyboard(login); - AnimHelper.animateVisibility(progress, true); - } - - @Override public void onBackPressed() { - startActivity(new Intent(this, LoginChooserActivity.class)); - finish(); - } - - @Override public void hideProgress() { - progress.setVisibility(View.GONE); - login.show(); - } - - protected void checkPurchases(@Nullable Action action) { - getPresenter().manageViewDisposable(RxBillingService.getInstance(this, BuildConfig.DEBUG) - .getPurchases(ProductType.IN_APP) - .doOnSubscribe(disposable -> showProgress(0)) - .subscribe((purchases, throwable) -> { - hideProgress(); - if (throwable == null) { - Logger.e(purchases); - if (purchases != null && !purchases.isEmpty()) { - for (Purchase purchase : purchases) { - String sku = purchase.sku(); - if (!InputHelper.isEmpty(sku)) { - DonateActivity.Companion.enableProduct(sku, App.getInstance()); - } - } - } - } else { - throwable.printStackTrace(); - } - if (action != null) action.run(); - })); - } - - private void doLogin() { - if (progress.getVisibility() == View.GONE) { - getPresenter().login(InputHelper.toString(username), - InputHelper.toString(password), - InputHelper.toString(twoFactor), - isBasicAuth, InputHelper.toString(endpoint)); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java b/app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java deleted file mode 100644 index 239f1bccc..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/login/LoginMvp.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.fastaccess.ui.modules.login; - -import android.content.Intent; -import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.AccessTokenModel; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.ui.base.mvp.BaseMvp; - -/** - * Created by Kosh on 09 Nov 2016, 9:41 PM - */ - -public interface LoginMvp { - - interface View extends BaseMvp.FAView { - - void onRequire2Fa(); - - void onEmptyUserName(boolean isEmpty); - - void onEmptyPassword(boolean isEmpty); - - void onEmptyEndpoint(boolean isEmpty); - - void onSuccessfullyLoggedIn(boolean extraLogin); - } - - interface Presenter extends BaseMvp.FAPresenter { - - @NonNull Uri getAuthorizationUrl(); - - void onHandleAuthIntent(@Nullable Intent intent); - - void onTokenResponse(@Nullable AccessTokenModel response); - - void onUserResponse(@Nullable Login response); - - void login(@NonNull String username, @NonNull String password, - @Nullable String twoFactorCode, boolean isBasicAuth, - @Nullable String endpoint); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java deleted file mode 100644 index b1f592409..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/login/LoginPresenter.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.fastaccess.ui.modules.login; - -import android.content.Intent; -import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.BuildConfig; -import com.fastaccess.R; -import com.fastaccess.data.dao.AccessTokenModel; -import com.fastaccess.data.dao.AuthModel; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.helper.GithubConfigHelper; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.rest.LoginProvider; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.Arrays; - -import okhttp3.Credentials; -import retrofit2.HttpException; - -/** - * Created by Kosh on 09 Nov 2016, 9:43 PM - */ - -public class LoginPresenter extends BasePresenter implements LoginMvp.Presenter { - - LoginPresenter() { - RestProvider.clearHttpClient(); - } - - @Override protected void onDestroy() { - super.onDestroy(); - } - - @Override public void onError(@NonNull Throwable throwable) { - if (RestProvider.getErrorCode(throwable) == 401 && throwable instanceof HttpException) { - retrofit2.Response response = ((HttpException) throwable).response(); - if (response != null && response.headers() != null) { - String twoFaToken = response.headers().get("X-GitHub-OTP"); - if (twoFaToken != null) { - sendToView(LoginMvp.View::onRequire2Fa); - return; - } else { - sendToView(view -> view.showMessage(R.string.error, R.string.failed_login)); - return; - } - } - } - sendToView(view -> view.showErrorMessage(throwable.getMessage())); - } - - @Override public void onTokenResponse(@Nullable AccessTokenModel modelResponse) { - if (modelResponse != null) { - String token = modelResponse.getToken() != null ? modelResponse.getToken() : modelResponse.getAccessToken(); - if (!InputHelper.isEmpty(token)) { - PrefGetter.setToken(token); - makeRestCall(RestProvider.getUserService(false).getUser(), this::onUserResponse); - return; - } - } - sendToView(view -> view.showMessage(R.string.error, R.string.failed_login)); - } - - @NonNull @Override public Uri getAuthorizationUrl() { - return new Uri.Builder().scheme("https") - .authority("github.com") - .appendPath("login") - .appendPath("oauth") - .appendPath("authorize") - .appendQueryParameter("client_id", GithubConfigHelper.getClientId()) - .appendQueryParameter("redirect_uri", GithubConfigHelper.getRedirectUrl()) - .appendQueryParameter("scope", "user,repo,gist,notifications,read:org") - .appendQueryParameter("state", BuildConfig.APPLICATION_ID) - .build(); - } - - @Override public void onHandleAuthIntent(@Nullable Intent intent) { - if (intent != null && intent.getData() != null) { - Uri uri = intent.getData(); - if (uri.toString().startsWith(GithubConfigHelper.getRedirectUrl())) { - String tokenCode = uri.getQueryParameter("code"); - if (!InputHelper.isEmpty(tokenCode)) { - makeRestCall(LoginProvider.getLoginRestService().getAccessToken(tokenCode, - GithubConfigHelper.getClientId(), GithubConfigHelper.getSecret(), - BuildConfig.APPLICATION_ID, GithubConfigHelper.getRedirectUrl()), - this::onTokenResponse); - } else { - sendToView(view -> view.showMessage(R.string.error, R.string.error)); - } - } - } - } - - @Override public void onUserResponse(@Nullable Login userModel) { - if (userModel != null) { - manageObservable(Login.onMultipleLogin(userModel, isEnterprise(), true) - .doOnComplete(() -> sendToView(view -> view.onSuccessfullyLoggedIn(isEnterprise())))); - return; - } - sendToView(view -> view.showMessage(R.string.error, R.string.failed_login)); - } - - @Override public void login(@NonNull String username, @NonNull String password, @Nullable String twoFactorCode, - boolean isBasicAuth, @Nullable String endpoint) { - boolean usernameIsEmpty = InputHelper.isEmpty(username); - boolean passwordIsEmpty = InputHelper.isEmpty(password); - boolean endpointIsEmpty = InputHelper.isEmpty(endpoint) && isEnterprise(); - if (getView() == null) return; - getView().onEmptyUserName(usernameIsEmpty); - getView().onEmptyPassword(passwordIsEmpty); - getView().onEmptyEndpoint(endpointIsEmpty); - if ((!usernameIsEmpty && !passwordIsEmpty)) { - try { - String authToken = Credentials.basic(username, password); - if (isBasicAuth && !isEnterprise()) { - AuthModel authModel = new AuthModel(); - authModel.setScopes(Arrays.asList("user", "repo", "gist", "notifications", "read:org")); - authModel.setNote(BuildConfig.APPLICATION_ID); - authModel.setClientSecret(GithubConfigHelper.getSecret()); - authModel.setClientId(GithubConfigHelper.getClientId()); - authModel.setNoteUrl(GithubConfigHelper.getRedirectUrl()); - if (!InputHelper.isEmpty(twoFactorCode)) { - authModel.setOtpCode(twoFactorCode); - } - makeRestCall(LoginProvider.getLoginRestService(authToken, twoFactorCode, null).login(authModel), accessTokenModel -> { - if (!InputHelper.isEmpty(twoFactorCode)) { - PrefGetter.setOtpCode(twoFactorCode); - } - onTokenResponse(accessTokenModel); - }); - } else { - accessTokenLogin(password, endpoint, twoFactorCode, authToken); - } - } catch (Exception e) { - sendToView(view -> view.showMessage("Error", "The app was about to crash!!(" + e.getMessage() + ")")); - } - } - } - - private void accessTokenLogin(@NonNull String password, @Nullable String endpoint, @Nullable String otp, - @NonNull String authToken) { - makeRestCall(LoginProvider.getLoginRestService(authToken, otp, endpoint).loginAccessToken(), - login -> { - if (!isEnterprise()) { - PrefGetter.setToken(password); - } else { - PrefGetter.setEnterpriseOtpCode(otp); - PrefGetter.setTokenEnterprise(authToken); - PrefGetter.setEnterpriseUrl(endpoint); - } - onUserResponse(login); - }); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserActivity.kt deleted file mode 100644 index 6bd8318ef..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserActivity.kt +++ /dev/null @@ -1,138 +0,0 @@ -package com.fastaccess.ui.modules.login.chooser - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.support.design.widget.CoordinatorLayout -import android.support.transition.TransitionManager -import android.view.View -import android.widget.RelativeLayout -import butterknife.BindView -import butterknife.OnClick -import com.fastaccess.BuildConfig -import com.fastaccess.R -import com.fastaccess.data.dao.model.Login -import com.fastaccess.helper.Bundler -import com.fastaccess.helper.PrefGetter -import com.fastaccess.ui.adapter.LoginAdapter -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.modules.login.LoginActivity -import com.fastaccess.ui.modules.main.premium.PremiumActivity -import com.fastaccess.ui.modules.settings.LanguageBottomSheetDialog -import com.fastaccess.ui.widgets.dialog.MessageDialogView -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView -import io.reactivex.functions.Action -import java.util.* - -/** - * Created by Kosh on 28 Apr 2017, 9:03 PM - */ - -class LoginChooserActivity : BaseActivity(), LoginChooserMvp.View { - - @BindView(R.id.language_selector) lateinit var language_selector: RelativeLayout - @BindView(R.id.recycler) lateinit var recycler: DynamicRecyclerView - @BindView(R.id.multiAccLayout) lateinit var multiAccLayout: View - @BindView(R.id.viewGroup) lateinit var viewGroup: CoordinatorLayout - @BindView(R.id.toggleImage) lateinit var toggleImage: View - - private val adapter = LoginAdapter() - - override fun layout(): Int = R.layout.login_chooser_layout - - override fun isTransparent(): Boolean = true - - override fun canBack(): Boolean = false - - override fun isSecured(): Boolean = true - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - adapter.listener = this - recycler.adapter = adapter - val languages = resources.getStringArray(R.array.languages_array_values) - if (Locale.getDefault().language in languages) { - val language = PrefGetter.getAppLanguage() - PrefGetter.setAppLangauge(Locale.getDefault().language) - if (!BuildConfig.DEBUG) language_selector.visibility = View.GONE - if (Locale.getDefault().language != language) recreate() - } - } - - @OnClick(R.id.basicAuth) fun onBasicAuthClicked() { - LoginActivity.start(this, true) - } - - @OnClick(R.id.accessToken) fun onAccessTokenClicked() { - LoginActivity.start(this, false) - } - - @OnClick(R.id.enterprise) internal fun onEnterpriseClicked() { - if (Login.hasNormalLogin()) { - if (PrefGetter.isAllFeaturesUnlocked() || PrefGetter.isEnterpriseEnabled()) { - LoginActivity.start(this, true, true) - } else { - startActivity(Intent(this, PremiumActivity::class.java)) - } - } else { - MessageDialogView.newInstance(getString(R.string.warning), getString(R.string.enterprise_login_warning), - false, Bundler.start().put("hide_buttons", true).end()) - .show(supportFragmentManager, MessageDialogView.TAG) - } - } - - @OnClick(R.id.browserLogin) internal fun onOpenBrowser() { - LoginActivity.startOAuth(this) - } - - @OnClick(R.id.language_selector_clicker) fun onChangeLanguage() { - showLanguage() - } - - @OnClick(R.id.toggle) internal fun onToggle() { - TransitionManager.beginDelayedTransition(viewGroup) - val isVisible = recycler.visibility == View.VISIBLE - recycler.visibility = if (isVisible) View.GONE else View.VISIBLE - toggleImage.rotation = if (!isVisible) 180f else 0f - } - - override fun onLanguageChanged(action: Action) { - try { - action.run() - recreate() - } catch (e: Exception) { - e.printStackTrace() - } - - } - - override fun providePresenter(): LoginChooserPresenter { - return LoginChooserPresenter() - } - - override fun onAccountsLoaded(accounts: List?) { - if (accounts == null || accounts.isEmpty()) { - multiAccLayout.visibility = View.GONE - } else { - TransitionManager.beginDelayedTransition(viewGroup) - adapter.insertItems(accounts) - multiAccLayout.visibility = View.VISIBLE - } - } - - override fun onItemClick(position: Int, v: View, item: Login) { - presenter.manageViewDisposable(Login.onMultipleLogin(item, item.isIsEnterprise, false) - .doOnSubscribe { showProgress(0) } - .doOnComplete { this.hideProgress() } - .subscribe({ onRestartApp() }, ::println)) - } - - override fun onItemLongClick(position: Int, v: View, item: Login) {} - - private fun showLanguage() { - val languageBottomSheetDialog = LanguageBottomSheetDialog() - languageBottomSheetDialog.onAttach(this as Context) - languageBottomSheetDialog.show(supportFragmentManager, "LanguageBottomSheetDialog") - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserMvp.kt deleted file mode 100644 index 9620a98cd..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserMvp.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.fastaccess.ui.modules.login.chooser - -import com.fastaccess.data.dao.model.Login -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.modules.settings.LanguageBottomSheetDialog -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -interface LoginChooserMvp { - - interface View : BaseMvp.FAView, LanguageBottomSheetDialog.LanguageDialogListener, - BaseViewHolder.OnItemClickListener { - fun onAccountsLoaded(accounts: List?) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserPresenter.kt deleted file mode 100644 index 85b23b4bd..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/login/chooser/LoginChooserPresenter.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.fastaccess.ui.modules.login.chooser - -import com.fastaccess.data.dao.model.Login -import com.fastaccess.ui.base.mvp.presenter.BasePresenter - -class LoginChooserPresenter : BasePresenter() { - init { - manageObservable(Login.getAccounts().toList() - .toObservable() - .doOnNext { sendToView { view -> view.onAccountsLoaded(it) } }) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/MainActivity.java b/app/src/main/java/com/fastaccess/ui/modules/main/MainActivity.java deleted file mode 100644 index d4fac2378..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/MainActivity.java +++ /dev/null @@ -1,217 +0,0 @@ -package com.fastaccess.ui.modules.main; - -import android.content.Intent; -import android.graphics.Typeface; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.FloatingActionButton; -import android.support.v4.app.FragmentManager; -import android.support.v4.view.GravityCompat; -import android.view.Menu; -import android.view.MenuItem; -import android.widget.Toast; - -import com.evernote.android.state.State; -import com.fastaccess.App; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.Notification; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.TypeFaceHelper; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.modules.feeds.FeedsFragment; -import com.fastaccess.ui.modules.main.issues.pager.MyIssuesPagerFragment; -import com.fastaccess.ui.modules.main.pullrequests.pager.MyPullsPagerFragment; -import com.fastaccess.ui.modules.notification.NotificationActivity; -import com.fastaccess.ui.modules.search.SearchActivity; -import com.fastaccess.ui.modules.settings.SlackBottomSheetDialog; -import com.fastaccess.ui.modules.user.UserPagerActivity; - -import butterknife.BindView; -import butterknife.OnClick; -import it.sephiroth.android.library.bottomnavigation.BottomNavigation; -import shortbread.Shortcut; - -import static com.fastaccess.helper.AppHelper.getFragmentByTag; - -public class MainActivity extends BaseActivity implements MainMvp.View { - - @State @MainMvp.NavigationType int navType = MainMvp.FEEDS; - @BindView(R.id.bottomNavigation) BottomNavigation bottomNavigation; - @BindView(R.id.fab) FloatingActionButton fab; - - @OnClick(R.id.fab) void onFilter() {} - - @NonNull @Override public MainPresenter providePresenter() { - return new MainPresenter(); - } - - @Override protected int layout() { - return R.layout.activity_main_view; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return false; - } - - @Override protected boolean isSecured() { - return false; - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState == null) { - if (getIntent() != null && getIntent().getBooleanExtra(SlackBottomSheetDialog.TAG, false)) { - new SlackBottomSheetDialog().show(getSupportFragmentManager(), SlackBottomSheetDialog.TAG); - } - } - getPresenter().setEnterprise(PrefGetter.isEnterprise()); - selectHome(false); - hideShowShadow(navType == MainMvp.FEEDS); - setToolbarIcon(R.drawable.ic_menu); - onInit(savedInstanceState); - fab.setImageResource(R.drawable.ic_filter); - onNewIntent(getIntent()); - } - - @Override protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - if (intent != null && intent.getExtras() != null) { - boolean recreate = intent.getExtras().getBoolean(BundleConstant.YES_NO_EXTRA); - if (recreate) recreate(); - } - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.search_menu, menu); - return super.onCreateOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if (item.getItemId() == android.R.id.home) { - if (drawer != null) drawer.openDrawer(GravityCompat.START); - return true; - } else if (item.getItemId() == R.id.search) { - startActivity(new Intent(this, SearchActivity.class)); - return true; - } else if (item.getItemId() == R.id.notifications) { - ViewHelper.tintDrawable(item.setIcon(R.drawable.ic_notifications_none).getIcon(), ViewHelper.getIconColor(this)); - startActivity(new Intent(this, NotificationActivity.class)); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override public boolean onPrepareOptionsMenu(Menu menu) { - if (isLoggedIn() && Notification.hasUnreadNotifications()) { - ViewHelper.tintDrawable(menu.findItem(R.id.notifications).setIcon(R.drawable.ic_ring).getIcon(), ViewHelper.getAccentColor(this)); - } else { - ViewHelper.tintDrawable(menu.findItem(R.id.notifications) - .setIcon(R.drawable.ic_notifications_none).getIcon(), ViewHelper.getIconColor(this)); - } - return super.onPrepareOptionsMenu(menu); - } - - @Override public void onNavigationChanged(@MainMvp.NavigationType int navType) { - if (navType == MainMvp.PROFILE) { - getPresenter().onModuleChanged(getSupportFragmentManager(), navType); - bottomNavigation.setSelectedIndex(this.navType, true); - return; - } - this.navType = navType; - //noinspection WrongConstant - if (bottomNavigation.getSelectedIndex() != navType) bottomNavigation.setSelectedIndex(navType, true); - hideShowShadow(navType == MainMvp.FEEDS); - getPresenter().onModuleChanged(getSupportFragmentManager(), navType); - } - - @Override public void onUpdateDrawerMenuHeader() { - setupNavigationView(); - } - - @Override public void onOpenProfile() { - UserPagerActivity.startActivity(this, Login.getUser().getLogin(), false, PrefGetter.isEnterprise(), -1); - } - - @Override public void onInvalidateNotification() { - invalidateOptionsMenu(); - } - - @Override public void onUserIsBlackListed() { - Toast.makeText(App.getInstance(), "You are blacklisted, please contact the dev", Toast.LENGTH_LONG).show(); - finish(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - FragmentManager fragmentManager = getSupportFragmentManager(); - if (index == 0) { - FeedsFragment homeView = (FeedsFragment) getFragmentByTag(fragmentManager, FeedsFragment.TAG); - if (homeView != null) { - homeView.onScrollTop(index); - } - } else if (index == 1) { - MyIssuesPagerFragment issuesView = (MyIssuesPagerFragment) getFragmentByTag - (fragmentManager, MyIssuesPagerFragment.TAG); - if (issuesView != null) { - issuesView.onScrollTop(index); - } - } else if (index == 2) { - MyPullsPagerFragment pullRequestView = (MyPullsPagerFragment) getFragmentByTag - (fragmentManager, MyPullsPagerFragment.TAG); - if (pullRequestView != null) { - pullRequestView.onScrollTop(0); - } - } - } - - @Shortcut(id = "myIssues", icon = R.drawable.ic_app_shortcut_issues, shortLabelRes = R.string.issues, rank = 2, action = "myIssues") - public void myIssues() {}//do nothing - - @Shortcut(id = "myPulls", icon = R.drawable.ic_app_shortcut_pull_requests, shortLabelRes = R.string.pull_requests, rank = 3, action = "myPulls") - public void myPulls() {}//do nothing - - private void onInit(@Nullable Bundle savedInstanceState) { - if (isLoggedIn()) { - if (savedInstanceState == null) { - boolean attachFeeds = true; - if (getIntent().getAction() != null) { - if (getIntent().getAction().equalsIgnoreCase("myPulls")) { - navType = MainMvp.PULL_REQUESTS; - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.container, MyPullsPagerFragment.newInstance(), MyPullsPagerFragment.TAG) - .commit(); - bottomNavigation.setSelectedIndex(2, true); - attachFeeds = false; - } else if (getIntent().getAction().equalsIgnoreCase("myIssues")) { - navType = MainMvp.ISSUES; - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.container, MyIssuesPagerFragment.newInstance(), MyIssuesPagerFragment.TAG) - .commit(); - bottomNavigation.setSelectedIndex(1, true); - attachFeeds = false; - } - } - hideShowShadow(navType == MainMvp.FEEDS); - if (attachFeeds) { - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.container, FeedsFragment.newInstance(null), FeedsFragment.TAG) - .commit(); - } - } - Typeface myTypeface = TypeFaceHelper.getTypeface(); - bottomNavigation.setDefaultTypeface(myTypeface); - bottomNavigation.setOnMenuItemClickListener(getPresenter()); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/MainMvp.java b/app/src/main/java/com/fastaccess/ui/modules/main/MainMvp.java deleted file mode 100644 index 50b04eea6..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/MainMvp.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.fastaccess.ui.modules.main; - -import android.support.annotation.IntDef; -import android.support.annotation.NonNull; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.widget.DrawerLayout; - -import com.fastaccess.ui.base.mvp.BaseMvp; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import it.sephiroth.android.library.bottomnavigation.BottomNavigation; - -/** - * Created by Kosh on 09 Nov 2016, 7:51 PM - */ - -public interface MainMvp { - - int FEEDS = 0; - int ISSUES = 1; - int PULL_REQUESTS = 2; - int PROFILE = 3; - - @IntDef({ - FEEDS, - ISSUES, - PULL_REQUESTS, - PROFILE - }) - @Retention(RetentionPolicy.SOURCE) @interface NavigationType {} - - interface View extends BaseMvp.FAView { - - void onNavigationChanged(@NavigationType int navType); - - void onUpdateDrawerMenuHeader(); - - void onOpenProfile(); - - void onInvalidateNotification(); - - void onUserIsBlackListed(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BottomNavigation.OnMenuItemSelectionListener { - - boolean canBackPress(@NonNull DrawerLayout drawerLayout); - - void onModuleChanged(@NonNull FragmentManager fragmentManager, @NavigationType int type); - - void onShowHideFragment(@NonNull FragmentManager fragmentManager, @NonNull Fragment toShow, @NonNull Fragment toHide); - - void onAddAndHide(@NonNull FragmentManager fragmentManager, @NonNull Fragment toAdd, @NonNull Fragment toHide); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/MainPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/main/MainPresenter.java deleted file mode 100644 index 4e2fb50a0..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/MainPresenter.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.fastaccess.ui.modules.main; - -import android.support.annotation.IdRes; -import android.support.annotation.NonNull; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.view.GravityCompat; -import android.support.v4.widget.DrawerLayout; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.Notification; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.feeds.FeedsFragment; -import com.fastaccess.ui.modules.main.issues.pager.MyIssuesPagerFragment; -import com.fastaccess.ui.modules.main.pullrequests.pager.MyPullsPagerFragment; - -import io.reactivex.Single; - -import static com.fastaccess.helper.ActivityHelper.getVisibleFragment; -import static com.fastaccess.helper.AppHelper.getFragmentByTag; - -/** - * Created by Kosh on 09 Nov 2016, 7:53 PM - */ - -public class MainPresenter extends BasePresenter implements MainMvp.Presenter { - - MainPresenter() { - setEnterprise(PrefGetter.isEnterprise()); - manageDisposable(RxHelper.getObservable(RestProvider.getUserService(isEnterprise()).getUser()) - .flatMap(login -> { - Login current = Login.getUser(); - current.setLogin(login.getLogin()); - current.setName(login.getName()); - current.setAvatarUrl(login.getAvatarUrl()); - current.setEmail(login.getEmail()); - current.setBio(login.getBio()); - current.setBlog(login.getBlog()); - current.setCompany(current.getCompany()); - return login.update(current); - }) - .flatMap(login -> RxHelper.getObservable(RestProvider.getNotificationService(isEnterprise()) - .getNotifications(ParseDateFormat.getLastWeekDate()))) - .flatMapSingle(notificationPageable -> { - if (notificationPageable != null && (notificationPageable.getItems() != null && !notificationPageable.getItems().isEmpty())) { - return Notification.saveAsSingle(notificationPageable.getItems()); - } else { - Notification.deleteAll(); - } - return Single.just(true); - }) - .subscribe(unread -> {/**/}, Throwable::printStackTrace/*fail silently*/, () -> sendToView(view -> { - view.onInvalidateNotification(); - view.onUpdateDrawerMenuHeader(); - }))); - } - - @Override public boolean canBackPress(@NonNull DrawerLayout drawerLayout) { - return !drawerLayout.isDrawerOpen(GravityCompat.START); - } - - @SuppressWarnings("ConstantConditions") - @Override public void onModuleChanged(@NonNull FragmentManager fragmentManager, @MainMvp.NavigationType - int type) { - Fragment currentVisible = getVisibleFragment(fragmentManager); - FeedsFragment homeView = (FeedsFragment) getFragmentByTag(fragmentManager, FeedsFragment - .TAG); - MyPullsPagerFragment pullRequestView = (MyPullsPagerFragment) getFragmentByTag - (fragmentManager, MyPullsPagerFragment.TAG); - MyIssuesPagerFragment issuesView = (MyIssuesPagerFragment) getFragmentByTag - (fragmentManager, MyIssuesPagerFragment.TAG); - switch (type) { - case MainMvp.PROFILE: - sendToView(MainMvp.View::onOpenProfile); - break; - case MainMvp.FEEDS: - if (homeView == null) { - onAddAndHide(fragmentManager, FeedsFragment.newInstance(null), - currentVisible); - } else { - onShowHideFragment(fragmentManager, homeView, currentVisible); - } - break; - case MainMvp.PULL_REQUESTS: - if (pullRequestView == null) { - onAddAndHide(fragmentManager, MyPullsPagerFragment.newInstance( - ), currentVisible); - } else { - onShowHideFragment(fragmentManager, pullRequestView, currentVisible); - } - break; - case MainMvp.ISSUES: - if (issuesView == null) { - onAddAndHide(fragmentManager, MyIssuesPagerFragment.newInstance(), currentVisible); - } else { - onShowHideFragment(fragmentManager, issuesView, currentVisible); - } - break; - } - } - - @Override public void onShowHideFragment(@NonNull FragmentManager fragmentManager, @NonNull Fragment toShow, - @NonNull Fragment toHide) { - toHide.onHiddenChanged(true); - fragmentManager - .beginTransaction() - .hide(toHide) - .show(toShow) - .commit(); - toShow.onHiddenChanged(false); - } - - @Override public void onAddAndHide(@NonNull FragmentManager fragmentManager, @NonNull Fragment toAdd, - @NonNull Fragment toHide) { - toHide.onHiddenChanged(true); - fragmentManager - .beginTransaction() - .hide(toHide) - .add(R.id.container, toAdd, toAdd.getClass().getSimpleName()) - .commit(); - toAdd.onHiddenChanged(false); - } - - @Override public void onMenuItemSelect(@IdRes int id, int position, boolean fromUser) { - if (getView() != null) { - getView().onNavigationChanged(position); - } - } - - @Override public void onMenuItemReselect(@IdRes int id, int position, boolean fromUser) { - sendToView(view -> view.onScrollTop(position)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/donation/CheckPurchaseActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/main/donation/CheckPurchaseActivity.kt deleted file mode 100644 index acd1b1e5e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/donation/CheckPurchaseActivity.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.fastaccess.ui.modules.main.donation - -import android.app.Activity -import android.app.ProgressDialog -import android.os.Bundle -import android.widget.Toast -import com.fastaccess.App -import com.fastaccess.BuildConfig -import com.fastaccess.R -import com.fastaccess.helper.AppHelper -import com.fastaccess.helper.RxHelper -import com.miguelbcr.io.rx_billing_service.RxBillingService -import com.miguelbcr.io.rx_billing_service.entities.ProductType -import es.dmoral.toasty.Toasty -import io.reactivex.Observable -import io.reactivex.disposables.Disposable - -/** - * Created by kosh on 14/07/2017. - */ -class CheckPurchaseActivity : Activity() { - - private var progress: ProgressDialog? = null - private var disposable: Disposable? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - progress = ProgressDialog(this) - .apply { - setMessage(getString(R.string.in_progress)) - setOnCancelListener { finishActivity(false) } - show() - } - if (AppHelper.isGoogleAvailable(this) && !AppHelper.isEmulator()) { - disposable = RxHelper.getObservable(Observable.fromCallable { - try { - val purchases = RxBillingService.getInstance(this, BuildConfig.DEBUG) - .getPurchases(ProductType.IN_APP) - .toMaybe() - .blockingGet(mutableListOf()) - if (!purchases.isEmpty()) { - purchases.filterNotNull() - .map { it.sku() } - .filterNot { !it.isNullOrBlank() } - .onEach { DonateActivity.enableProduct(it, App.getInstance()) } - return@fromCallable true - } - } catch (e: Exception) { - e.printStackTrace() - } - return@fromCallable false - }).subscribe({ finishActivity(it) }, { finishActivity(false) }) - } else { - finishActivity(false) - } - } - - override fun onStart() { - super.onStart() - setVisible(true) - } - - override fun onBackPressed() = Unit - - private fun finishActivity(showMessage: Boolean) { - if (showMessage) Toasty.success(App.getInstance(), getString(R.string.success_purchase_message), Toast.LENGTH_LONG).show() - finish() - } - - override fun onDestroy() { - progress?.let { - it.dismiss() - } - disposable?.let { - if (!it.isDisposed) it.dispose() - } - super.onDestroy() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/donation/DonateActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/main/donation/DonateActivity.kt deleted file mode 100644 index 08d9a0504..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/donation/DonateActivity.kt +++ /dev/null @@ -1,118 +0,0 @@ -package com.fastaccess.ui.modules.main.donation - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.support.v4.app.Fragment -import com.fastaccess.BuildConfig -import com.fastaccess.R -import com.fastaccess.helper.* -import com.fastaccess.provider.fabric.FabricProvider -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.miguelbcr.io.rx_billing_service.RxBillingService -import com.miguelbcr.io.rx_billing_service.RxBillingServiceError -import com.miguelbcr.io.rx_billing_service.RxBillingServiceException -import com.miguelbcr.io.rx_billing_service.entities.ProductType -import com.miguelbcr.io.rx_billing_service.entities.Purchase -import io.reactivex.disposables.Disposable - -/** - * Created by Kosh on 10 Jun 2017, 1:04 PM - */ - -class DonateActivity : BaseActivity>() { - - private var subscription: Disposable? = null - - override fun layout(): Int = 0 - - override fun isTransparent(): Boolean = true - - override fun canBack(): Boolean = false - - override fun isSecured(): Boolean = true - - override fun providePresenter(): BasePresenter = BasePresenter() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val bundle: Bundle = intent.extras - val productKey = bundle.getString(BundleConstant.EXTRA) - val price = bundle.getLong(BundleConstant.EXTRA_FOUR, 0) - val priceText = bundle.getString(BundleConstant.EXTRA_FIVE) - subscription = RxHelper.getSingle(RxBillingService.getInstance(this, BuildConfig.DEBUG) - .purchase(ProductType.IN_APP, productKey, "inapp:com.fastaccess.github:" + productKey)) - .subscribe({ _: Purchase?, throwable: Throwable? -> - if (throwable == null) { - FabricProvider.logPurchase(productKey, price, priceText) - showMessage(R.string.success, R.string.success_purchase_message) - enableProduct(productKey, applicationContext) - val intent = Intent() - intent.putExtra(BundleConstant.ITEM, productKey) - setResult(Activity.RESULT_OK, intent) - } else { - if (throwable is RxBillingServiceException) { - val code = throwable.code - if (code == RxBillingServiceError.ITEM_ALREADY_OWNED) { - enableProduct(productKey, applicationContext) - val intent = Intent() - intent.putExtra(BundleConstant.ITEM, productKey) - setResult(Activity.RESULT_OK, intent) - } else { - showErrorMessage(throwable.message!!) - Logger.e(code) - setResult(Activity.RESULT_CANCELED) - } - } - throwable.printStackTrace() - } - finish() - }) - } - - override fun onDestroy() { - subscription?.let { if (!it.isDisposed) it.dispose() } - super.onDestroy() - } - - companion object { - fun start(context: Activity, product: String?, price: Long? = 0, priceText: String? = null) { - val intent = Intent(context, DonateActivity::class.java) - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, product) - .put(BundleConstant.EXTRA_FOUR, price) - .put(BundleConstant.EXTRA_FIVE, priceText) - .end()) - context.startActivityForResult(intent, BundleConstant.REQUEST_CODE) - } - - fun start(context: Fragment, product: String?, price: Long? = 0, priceText: String? = null) { - val intent = Intent(context.context, DonateActivity::class.java) - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, product) - .put(BundleConstant.EXTRA_FOUR, price) - .put(BundleConstant.EXTRA_FIVE, priceText) - .end()) - context.startActivityForResult(intent, BundleConstant.REQUEST_CODE) - } - - fun enableProduct(productKey: String, context: Context) { - when (productKey) { - context.getString(R.string.donation_product_3), context.getString(R.string.donation_product_4), - context.getString(R.string.fasthub_all_features_purchase) -> { - PrefGetter.setProItems() - PrefGetter.setEnterpriseItem() - } - context.getString(R.string.donation_product_2), context.getString(R.string.fasthub_pro_purchase) -> PrefGetter.setProItems() - context.getString(R.string.fasthub_enterprise_purchase) -> PrefGetter.setEnterpriseItem() - context.getString(R.string.donation_product_1), context.getString(R.string.amlod_theme_purchase) -> PrefGetter.enableAmlodTheme() - context.getString(R.string.midnight_blue_theme_purchase) -> PrefGetter.enableMidNightBlueTheme() - context.getString(R.string.theme_bluish_purchase) -> PrefGetter.enableBluishTheme() - else -> Logger.e(productKey) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/donation/DonationActivity.java b/app/src/main/java/com/fastaccess/ui/modules/main/donation/DonationActivity.java deleted file mode 100644 index 11588940f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/donation/DonationActivity.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.fastaccess.ui.modules.main.donation; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.design.widget.AppBarLayout; -import android.view.View; - -import com.fastaccess.App; -import com.fastaccess.BuildConfig; -import com.fastaccess.R; -import com.fastaccess.helper.AnimHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.main.premium.PremiumActivity; -import com.miguelbcr.io.rx_billing_service.RxBillingService; -import com.miguelbcr.io.rx_billing_service.entities.ProductType; -import com.miguelbcr.io.rx_billing_service.entities.Purchase; - -import net.grandcentrix.thirtyinch.TiPresenter; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 24 Mar 2017, 9:16 PM - */ - -public class DonationActivity extends BaseActivity { - @BindView(R.id.cardsHolder) View cardsHolder; - @BindView(R.id.appbar) AppBarLayout appBarLayout; - - @Override protected int layout() { - return R.layout.support_development_layout; - } - - @Override protected boolean isTransparent() { - return false; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return true; - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - AnimHelper.animateVisibility(cardsHolder, true); - checkPurchase(); - } - - @OnClick(R.id.two) void onTwoClicked(View v) { - onProceed(getString(R.string.donation_product_1)); - } - - @OnClick(R.id.five) void onFiveClicked(View v) { - onProceed(getString(R.string.donation_product_2)); - } - - @OnClick(R.id.ten) void onTenClicked(View v) { - onProceed(getString(R.string.donation_product_3)); - } - - @OnClick(R.id.twenty) void onTwentyClicked(View v) { - onProceed(getString(R.string.donation_product_4)); - } - - @OnClick(R.id.premium) void onNavToPremium() { - PremiumActivity.Companion.startActivity(this); - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } - - private void onProceed(@NonNull String productKey) { - if (AppHelper.isGoogleAvailable(this)) { - DonateActivity.Companion.start(this, productKey, null, null); - } else { - showErrorMessage(getString(R.string.google_play_service_error)); - } - } - - private void checkPurchase() { - ((BasePresenter) getPresenter()).manageViewDisposable(RxBillingService.getInstance(this, BuildConfig.DEBUG) - .getPurchases(ProductType.IN_APP) - .subscribe((purchases, throwable) -> { - if (purchases != null && !purchases.isEmpty()) { - for (Purchase purchase : purchases) { - String sku = purchase.sku(); - if (!InputHelper.isEmpty(sku)) { - DonateActivity.Companion.enableProduct(sku, App.getInstance()); - } - } - } - })); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/drawer/AccountDrawerFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/main/drawer/AccountDrawerFragment.kt deleted file mode 100644 index 9cd674765..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/drawer/AccountDrawerFragment.kt +++ /dev/null @@ -1,132 +0,0 @@ -package com.fastaccess.ui.modules.main.drawer - -import android.content.Intent -import android.os.Bundle -import android.view.View -import com.fastaccess.R -import com.fastaccess.data.dao.model.Login -import com.fastaccess.data.dao.model.PinnedRepos -import com.fastaccess.helper.PrefGetter -import com.fastaccess.helper.RxHelper -import com.fastaccess.provider.scheme.SchemeParser -import com.fastaccess.ui.adapter.LoginAdapter -import com.fastaccess.ui.adapter.PinnedReposAdapter -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.base.BaseFragment -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.login.chooser.LoginChooserActivity -import com.fastaccess.ui.modules.main.MainMvp -import com.fastaccess.ui.modules.main.premium.PremiumActivity -import com.fastaccess.ui.modules.pinned.PinnedReposActivity -import com.fastaccess.ui.modules.user.UserPagerActivity -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder -import kotlinx.android.synthetic.main.accounts_menu_layout.* - -/** - * Created by Kosh on 25.03.18. - */ -class AccountDrawerFragment : BaseFragment>(), - BaseViewHolder.OnItemClickListener { - - private val pinnedListAdapter = PinnedReposAdapter(true) - private val adapter = LoginAdapter(true) - private val userModel by lazy { Login.getUser() } - - override fun fragmentLayout() = R.layout.accounts_menu_layout - - override fun providePresenter() = BasePresenter() - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - pinnedListAdapter.listener = this - pinnedList.adapter = pinnedListAdapter - - adapter.listener = object : BaseViewHolder.OnItemClickListener { - override fun onItemLongClick(position: Int, v: View?, item: Login?) {} - - override fun onItemClick(position: Int, v: View?, item: Login) { - presenter.manageViewDisposable(RxHelper.getObservable(Login.onMultipleLogin(item, item.isIsEnterprise, false)) - .doOnSubscribe { showProgress(0) } - .doOnComplete { hideProgress() } - .subscribe({ (activity as? BaseActivity<*, *>?)?.onRestartApp() }, ::println)) - } - } - accLists.adapter = adapter - - logout.setOnClickListener { - postDelayedAndClose { - activity?.let { - (it as? BaseActivity<*, *>)?.onLogoutPressed() - } - } - } - togglePinned?.setOnClickListener { - postDelayedAndClose { PinnedReposActivity.startActivity(it.context) } - } - addAccLayout.setOnClickListener { - postDelayedAndClose { - if (PrefGetter.isProEnabled() || PrefGetter.isEnterpriseEnabled()) { - val intent = Intent(it.context, LoginChooserActivity::class.java) - intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP - startActivity(intent) - } else { - startActivity(Intent(it.context, PremiumActivity::class.java)) - } - } - } - repos.setOnClickListener { - postDelayedAndClose { - UserPagerActivity.startActivity(it.context, userModel.login, false, PrefGetter.isEnterprise(), 2) - } - } - starred.setOnClickListener { - postDelayedAndClose { - UserPagerActivity.startActivity(it.context, userModel.login, false, PrefGetter.isEnterprise(), 3) - } - } - - loadAccount() - loadPinned() - } - - override fun onItemClick(position: Int, v: View?, item: PinnedRepos?) { - if (v != null && item != null) { - postDelayedAndClose { SchemeParser.launchUri(v.context, item.pinnedRepo.htmlUrl) } - } - } - - override fun onItemLongClick(position: Int, v: View?, item: PinnedRepos?) = Unit - - override fun setUserVisibleHint(isVisibleToUser: Boolean) { - super.setUserVisibleHint(isVisibleToUser) - if (isVisibleToUser) { - loadPinned() - } - } - - private fun loadAccount() { - presenter.manageViewDisposable(Login.getAccounts() - .doOnComplete { - if (!adapter.isEmpty) { - toggleAccountsLayout.visibility = View.VISIBLE - } else { - toggleAccountsLayout.visibility = View.GONE - } - } - .subscribe({ adapter.addItem(it) }, ::print)) - } - - private fun loadPinned() { - presenter?.manageViewDisposable(PinnedRepos.getMenuRepos() - .subscribe({ pinnedListAdapter.insertItems(it) }, ::println)) - } - - private fun closeDrawer() { - val activity = activity as? BaseActivity<*, *>? ?: return - activity.closeDrawer() - } - - private fun postDelayedAndClose(method: () -> Unit) { - closeDrawer() - view?.postDelayed({ method.invoke() }, 250) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/drawer/MainDrawerFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/main/drawer/MainDrawerFragment.kt deleted file mode 100644 index 1976d8f8d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/drawer/MainDrawerFragment.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.fastaccess.ui.modules.main.drawer - -import android.content.Intent -import android.os.Bundle -import android.support.design.widget.NavigationView -import android.view.MenuItem -import android.view.View -import com.fastaccess.R -import com.fastaccess.data.dao.model.Login -import com.fastaccess.helper.PrefGetter -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.base.BaseFragment -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.about.FastHubAboutActivity -import com.fastaccess.ui.modules.gists.GistsListActivity -import com.fastaccess.ui.modules.main.MainActivity -import com.fastaccess.ui.modules.main.MainMvp -import com.fastaccess.ui.modules.main.donation.CheckPurchaseActivity -import com.fastaccess.ui.modules.main.playstore.PlayStoreWarningActivity -import com.fastaccess.ui.modules.notification.NotificationActivity -import com.fastaccess.ui.modules.pinned.PinnedReposActivity -import com.fastaccess.ui.modules.repos.issues.create.CreateIssueActivity -import com.fastaccess.ui.modules.trending.TrendingActivity -import com.fastaccess.ui.modules.user.UserPagerActivity -import kotlinx.android.synthetic.main.main_nav_fragment_layout.* - -/** - * Created by Kosh on 25.03.18. - */ -class MainDrawerFragment : BaseFragment>(), NavigationView.OnNavigationItemSelectedListener { - - private val userModel by lazy { Login.getUser() } - - override fun fragmentLayout() = R.layout.main_nav_fragment_layout - - override fun providePresenter() = BasePresenter() - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - mainNav.setNavigationItemSelectedListener(this) - } - - override fun onNavigationItemSelected(item: MenuItem): Boolean { - val activity = activity as? BaseActivity<*, *>? ?: return false - activity.closeDrawer() - if (item.isChecked) return false - mainNav.postDelayed({ - if (!activity.isFinishing()) { - when { - item.itemId == R.id.navToRepo -> activity.onNavToRepoClicked() - item.itemId == R.id.gists -> GistsListActivity.startActivity(activity) - item.itemId == R.id.pinnedMenu -> PinnedReposActivity.startActivity(activity) - item.itemId == R.id.mainView -> { - if (activity !is MainActivity) { - val intent = Intent(activity, MainActivity::class.java) - intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP - activity.startActivity(intent) - activity.finish() - } - } - item.itemId == R.id.profile -> userModel?.let { - UserPagerActivity.startActivity(activity, it.login, false, PrefGetter.isEnterprise(), 0) - } - item.itemId == R.id.settings -> activity.onOpenSettings() - item.itemId == R.id.about -> activity.startActivity(Intent(activity, FastHubAboutActivity::class.java)) - item.itemId == R.id.orgs -> activity.onOpenOrgsDialog() - item.itemId == R.id.notifications -> activity.startActivity(Intent(activity, NotificationActivity::class.java)) - item.itemId == R.id.trending -> activity.startActivity(Intent(activity, TrendingActivity::class.java)) - item.itemId == R.id.reportBug -> activity.startActivity(CreateIssueActivity.startForResult(activity)) - item.itemId == R.id.faq -> activity.startActivity(Intent(activity, PlayStoreWarningActivity::class.java)) - item.itemId == R.id.restorePurchase -> activity.startActivity(Intent(activity, CheckPurchaseActivity::class.java)) - } - } - }, 250) - return true - } - - fun getMenu() = mainNav?.menu -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesFragment.java b/app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesFragment.java deleted file mode 100644 index a46784cb8..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesFragment.java +++ /dev/null @@ -1,198 +0,0 @@ -package com.fastaccess.ui.modules.main.issues; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.data.dao.types.MyIssuesType; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.IssuesAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.extras.popup.IssuePopupFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 25 Mar 2017, 11:48 PM - */ - -public class MyIssuesFragment extends BaseFragment implements MyIssuesMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @State IssueState issueState; - private OnLoadMore onLoadMore; - private IssuesAdapter adapter; - private MyIssuesType issuesType; - private RepoPagerMvp.TabsBadgeListener tabsBadgeListener; - - public static MyIssuesFragment newInstance(@NonNull IssueState issueState, @NonNull MyIssuesType issuesType) { - MyIssuesFragment view = new MyIssuesFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.EXTRA, issueState) - .put(BundleConstant.EXTRA_TWO, issuesType) - .end()); - return view; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) getParentFragment(); - } else if (context instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) context; - } - } - - @Override public void onDetach() { - tabsBadgeListener = null; - super.onDetach(); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, issueState); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter()); - } - onLoadMore.setParameter(issueState); - return onLoadMore; - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (savedInstanceState == null) { - issueState = (IssueState) getArguments().getSerializable(BundleConstant.EXTRA); - } - getPresenter().onSetIssueType(getIssuesType()); - stateLayout.setEmptyText(R.string.no_issues); - recycler.setEmptyView(stateLayout, refresh); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - adapter = new IssuesAdapter(getPresenter().getIssues(), false, true); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addDivider(); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null || (getPresenter().getIssues().isEmpty() && !getPresenter().isApiCalled())) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public MyIssuesPresenter providePresenter() { - return new MyIssuesPresenter(); - } - - @Override public void onSetCount(int totalCount) { - if (tabsBadgeListener != null) { - switch (getIssuesType()) { - case CREATED: - tabsBadgeListener.onSetBadge(0, totalCount); - break; - case ASSIGNED: - tabsBadgeListener.onSetBadge(1, totalCount); - break; - case MENTIONED: - tabsBadgeListener.onSetBadge(2, totalCount); - break; - case PARTICIPATED: - tabsBadgeListener.onSetBadge(3, totalCount); - break; - } - } - } - - @Override public void onFilterIssue(@NonNull IssueState issueState) { - if (this.issueState != null && this.issueState != issueState) { - this.issueState = issueState; - getArguments().putSerializable(BundleConstant.ITEM, issueState); - getLoadMore().reset(); - adapter.clear(); - onRefresh(); - } - } - - @Override public void onShowPopupDetails(@NonNull Issue item) { - IssuePopupFragment.showPopup(getChildFragmentManager(), item); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private MyIssuesType getIssuesType() { - if (issuesType == null) { - issuesType = (MyIssuesType) getArguments().getSerializable(BundleConstant.EXTRA_TWO); - } - return issuesType; - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesMvp.java b/app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesMvp.java deleted file mode 100644 index 8981af773..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesMvp.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.fastaccess.ui.modules.main.issues; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.data.dao.types.MyIssuesType; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 25 Mar 2017, 11:39 PM - */ - -public interface MyIssuesMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onSetCount(int totalCount); - - void onFilterIssue(@NonNull IssueState issueState); - - void onShowPopupDetails(@NonNull Issue item); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getIssues(); - - void onSetIssueType(@NonNull MyIssuesType issuesType); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesPresenter.java deleted file mode 100644 index 50c4d55ed..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/issues/MyIssuesPresenter.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.fastaccess.ui.modules.main.issues; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.data.dao.types.MyIssuesType; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.rest.RepoQueryProvider; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 25 Mar 2017, 11:39 PM - */ - -public class MyIssuesPresenter extends BasePresenter implements MyIssuesMvp.Presenter { - - private ArrayList issues = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - @com.evernote.android.state.State MyIssuesType issuesType; - @NonNull private String login = Login.getUser().getLogin(); - - MyIssuesPresenter() { - setEnterprise(PrefGetter.isEnterprise()); - } - - @Override public void onItemClick(int position, View v, Issue item) { - SchemeParser.launchUri(v.getContext(), item.getHtmlUrl()); - } - - @Override public void onItemLongClick(int position, View v, Issue item) { - if (getView() != null) getView().onShowPopupDetails(item); - } - - @NonNull @Override public ArrayList getIssues() { - return issues; - } - - @Override public void onSetIssueType(@NonNull MyIssuesType issuesType) { - this.issuesType = issuesType; - } - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable IssueState parameter) { - if (parameter == null) { - throw new NullPointerException("parameter is null"); - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - if (page > lastPage || lastPage == 0) { - sendToView(MyIssuesMvp.View::hideProgress); - return false; - } - setCurrentPage(page); - makeRestCall(RestProvider.getIssueService(isEnterprise()).getIssuesWithCount(getUrl(parameter), page), issues -> { - lastPage = issues.getLast(); - if (getCurrentPage() == 1) { - sendToView(view -> view.onSetCount(issues.getTotalCount())); - } - sendToView(view -> view.onNotifyAdapter(issues.getItems(), page)); - }); - return true; - } - - @NonNull private String getUrl(@NonNull IssueState parameter) { - switch (issuesType) { - case CREATED: - return RepoQueryProvider.getMyIssuesPullRequestQuery(login, parameter, false); - case ASSIGNED: - return RepoQueryProvider.getAssigned(login, parameter, false); - case MENTIONED: - return RepoQueryProvider.getMentioned(login, parameter, false); - case PARTICIPATED: - return RepoQueryProvider.getParticipated(login, parameter, false); - } - return RepoQueryProvider.getMyIssuesPullRequestQuery(login, parameter, false); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerFragment.java b/app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerFragment.java deleted file mode 100644 index d7ac22abb..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerFragment.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.fastaccess.ui.modules.main.issues.pager; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; -import android.support.v4.view.ViewPager; -import android.view.MenuInflater; -import android.view.View; -import android.widget.PopupMenu; -import android.widget.TextView; - -import com.annimon.stream.Stream; -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.TabsCountStateModel; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.main.issues.MyIssuesFragment; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.ViewPagerView; - -import java.util.HashSet; - -import butterknife.BindView; - -/** - * Created by Kosh on 26 Mar 2017, 12:14 AM - */ - -public class MyIssuesPagerFragment extends BaseFragment implements MyIssuesPagerMvp.View { - - public static final String TAG = MyIssuesPagerFragment.class.getSimpleName(); - - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.pager) ViewPagerView pager; - @State HashSet counts = new HashSet<>(); - - public static MyIssuesPagerFragment newInstance() { - return new MyIssuesPagerFragment(); - } - - @Override protected int fragmentLayout() { - return R.layout.tabbed_viewpager; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - FragmentsPagerAdapter adapter = new FragmentsPagerAdapter(getChildFragmentManager(), - FragmentPagerAdapterModel.buildForMyIssues(getContext())); - pager.setAdapter(adapter); - //noinspection deprecation - tabs.setTabsFromPagerAdapter(adapter); - tabs.setTabGravity(TabLayout.GRAVITY_FILL); - tabs.setTabMode(TabLayout.MODE_SCROLLABLE); - if (savedInstanceState == null) { - tabs.getTabAt(0).select(); - } - pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { - @Override public void onPageSelected(int position) { - super.onPageSelected(position); - selectTab(position, true); - } - }); - tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { - @Override public void onTabSelected(TabLayout.Tab tab) { - if (tab.getTag() == null) { - int position = tab.getPosition(); - selectTab(position, false); - } - tab.setTag(null); - } - - @Override public void onTabUnselected(TabLayout.Tab tab) {} - - @Override public void onTabReselected(TabLayout.Tab tab) { - selectTab(tab.getPosition(), false); - } - }); - if (savedInstanceState != null && !counts.isEmpty()) { - Stream.of(counts).forEach(this::updateCount); - } - } - - @NonNull @Override public MyIssuesPagerPresenter providePresenter() { - return new MyIssuesPagerPresenter(); - } - - @Override public void onSetBadge(int tabIndex, int count) { - TabsCountStateModel model = getModelAtIndex(tabIndex); - if (model == null) { - model = new TabsCountStateModel(); - } - model.setTabIndex(tabIndex); - model.setCount(count); - boolean removed = counts.remove(model); - counts.add(model); - if (tabs != null) { - updateCount(model); - } - } - - @Nullable private TabsCountStateModel getModelAtIndex(int index) { - return Stream.of(counts) - .filter(model -> model.getTabIndex() == index) - .findFirst() - .orElse(null); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (pager != null && pager.getAdapter() != null) { - MyIssuesFragment myIssuesFragment = (MyIssuesFragment) pager.getAdapter().instantiateItem(pager, pager.getCurrentItem()); - if (myIssuesFragment != null) { - myIssuesFragment.onScrollTop(0); - } - } - } - - private void selectTab(int position, boolean fromViewPager) { - if (!fromViewPager) { - onShowFilterMenu(getModelAtIndex(position), ViewHelper.getTabTextView(tabs, position)); - pager.setCurrentItem(position); - } else { - TabLayout.Tab tab = tabs.getTabAt(position); - if (tab != null) { - tab.setTag("hello"); - if (!tab.isSelected()) tab.select(); - } - } - } - - private void updateCount(@NonNull TabsCountStateModel model) { - TextView tv = ViewHelper.getTabTextView(tabs, model.getTabIndex()); - String title = getString(R.string.created); - switch (model.getTabIndex()) { - case 0: - title = getString(R.string.created); - break; - case 1: - title = getString(R.string.assigned); - break; - case 2: - title = getString(R.string.mentioned); - break; - case 3: - title = getString(R.string.participated); - } - updateDrawable(model, tv); - tv.setText(SpannableBuilder.builder() - .append(title) - .append(" ") - .append("(") - .bold(String.valueOf(model.getCount())) - .append(")")); - } - - private void onShowFilterMenu(@Nullable TabsCountStateModel model, TextView tv) { - if (model == null) return; - PopupMenu popup = new PopupMenu(getContext(), tv); - MenuInflater inflater = popup.getMenuInflater(); - inflater.inflate(R.menu.filter_issue_state_menu, popup.getMenu()); - popup.setOnMenuItemClickListener(item -> { - if (pager == null || pager.getAdapter() == null) return false; - MyIssuesFragment myIssuesFragment = (MyIssuesFragment) pager.getAdapter().instantiateItem(pager, model.getTabIndex()); - if (myIssuesFragment == null) return false; - switch (item.getItemId()) { - case R.id.opened: - counts.remove(model); - model.setDrawableId(R.drawable.ic_issue_opened_small); - counts.add(model); - updateDrawable(model, tv); - myIssuesFragment.onFilterIssue(IssueState.open); - return true; - case R.id.closed: - counts.remove(model); - model.setDrawableId(R.drawable.ic_issue_closed_small); - counts.add(model); - updateDrawable(model, tv); - myIssuesFragment.onFilterIssue(IssueState.closed); - return true; - } - return false; - }); - popup.show(); - } - - private void updateDrawable(@NonNull TabsCountStateModel model, TextView tv) { - model.setDrawableId(model.getDrawableId() == 0 ? R.drawable.ic_issue_opened_small : model.getDrawableId()); - tv.setCompoundDrawablePadding(16); - tv.setCompoundDrawablesWithIntrinsicBounds(model.getDrawableId(), 0, R.drawable.ic_arrow_drop_down, 0); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerMvp.java deleted file mode 100644 index b6527f3f0..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerMvp.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.fastaccess.ui.modules.main.issues.pager; - -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; - -/** - * Created by Kosh on 26 Mar 2017, 12:15 AM - */ - -public interface MyIssuesPagerMvp { - - interface View extends BaseMvp.FAView, RepoPagerMvp.TabsBadgeListener {} - - interface Presenter {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerPresenter.java deleted file mode 100644 index 650e3fab3..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/issues/pager/MyIssuesPagerPresenter.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.ui.modules.main.issues.pager; - -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by Kosh on 26 Mar 2017, 12:17 AM - */ - -public class MyIssuesPagerPresenter extends BasePresenter implements MyIssuesPagerMvp.Presenter {} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/notifications/FastHubNotificationDialog.kt b/app/src/main/java/com/fastaccess/ui/modules/main/notifications/FastHubNotificationDialog.kt deleted file mode 100644 index f53f43143..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/notifications/FastHubNotificationDialog.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.fastaccess.ui.modules.main.notifications - -import android.os.Bundle -import android.support.v4.app.FragmentManager -import android.text.Html -import android.view.View -import butterknife.OnClick -import com.fastaccess.R -import com.fastaccess.data.dao.model.AbstractFastHubNotification.NotificationType -import com.fastaccess.data.dao.model.FastHubNotification -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.helper.PrefGetter -import com.fastaccess.ui.base.BaseDialogFragment -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import kotlinx.android.synthetic.main.dialog_guide_layout.* - -/** - * Created by Kosh on 17.11.17. - */ -class FastHubNotificationDialog : BaseDialogFragment>() { - - init { - suppressAnimation = true - isCancelable = false - } - - private val model by lazy { arguments?.getParcelable(BundleConstant.ITEM) } - - @OnClick(R.id.cancel) fun onCancel() { - dismiss() - } - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - model?.let { - title?.text = it.title - description?.text = Html.fromHtml(it.body) - it.isRead = true - FastHubNotification.update(it) - } ?: dismiss() - } - - override fun providePresenter(): BasePresenter = BasePresenter() - - override fun fragmentLayout(): Int = R.layout.dialog_guide_layout - - companion object { - @JvmStatic private val TAG = FastHubNotificationDialog::class.java.simpleName - - fun newInstance(model: FastHubNotification): FastHubNotificationDialog { - val fragment = FastHubNotificationDialog() - fragment.arguments = Bundler.start() - .put(BundleConstant.ITEM, model) - .end() - return fragment - } - - fun show(fragmentManager: FragmentManager, model: FastHubNotification? = null) { - val notification = model ?: FastHubNotification.getLatest() - notification?.let { - if (it.type == NotificationType.PROMOTION || it.type == NotificationType.PURCHASE && model == null) { - if (PrefGetter.isProEnabled()) { - it.isRead = true - FastHubNotification.update(it) - return - } - } - newInstance(it).show(fragmentManager, TAG) - } - } - - fun show(fragmentManager: FragmentManager) { - show(fragmentManager, null) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogFragment.java b/app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogFragment.java deleted file mode 100644 index f96e2e090..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogFragment.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.fastaccess.ui.modules.main.orgs; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.support.v7.widget.Toolbar; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.ui.adapter.UsersAdapter; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 15 Apr 2017, 1:57 PM - */ - -public class OrgListDialogFragment extends BaseDialogFragment - implements OrgListDialogMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private UsersAdapter adapter; - - public static OrgListDialogFragment newInstance() { - return new OrgListDialogFragment(); - } - - @Override public void onNotifyAdapter(@Nullable List items) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - adapter.insertItems(items); - } - - @Override protected int fragmentLayout() { - return R.layout.milestone_dialog_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - toolbar.setTitle(R.string.organizations); - toolbar.inflateMenu(R.menu.add_menu); - toolbar.getMenu().findItem(R.id.add).setIcon(R.drawable.ic_info_outline).setTitle(R.string.no_orgs_dialog_title); - toolbar.setOnMenuItemClickListener(item -> { - MessageDialogView.newInstance(getString(R.string.no_orgs_dialog_title), getString(R.string.no_orgs_description), false, true) - .show(getChildFragmentManager(), MessageDialogView.TAG); - return true; - }); - toolbar.setNavigationIcon(R.drawable.ic_clear); - toolbar.setNavigationOnClickListener(v -> dismiss()); - stateLayout.setEmptyText(R.string.no_orgs); - stateLayout.setOnReloadListener(v -> getPresenter().onLoadOrgs()); - refresh.setOnRefreshListener(() -> getPresenter().onLoadOrgs()); - recycler.setEmptyView(stateLayout, refresh); - adapter = new UsersAdapter(getPresenter().getOrgs()); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - if (savedInstanceState == null) { - getPresenter().onLoadOrgs(); - } - fastScroller.attachRecyclerView(recycler); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OrgListDialogPresenter providePresenter() { - return new OrgListDialogPresenter(); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogMvp.java b/app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogMvp.java deleted file mode 100644 index 922b42627..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogMvp.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.fastaccess.ui.modules.main.orgs; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.ui.base.mvp.BaseMvp; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 15 Apr 2017, 1:53 PM - */ - -public interface OrgListDialogMvp { - - interface View extends BaseMvp.FAView { - void onNotifyAdapter(@Nullable List items); - - } - - interface Presenter { - void onLoadOrgs(); - - @NonNull ArrayList getOrgs(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogPresenter.java deleted file mode 100644 index 392aae3e0..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/orgs/OrgListDialogPresenter.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.fastaccess.ui.modules.main.orgs; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; -import java.util.List; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 15 Apr 2017, 1:54 PM - */ - -public class OrgListDialogPresenter extends BasePresenter implements OrgListDialogMvp.Presenter { - private ArrayList orgs = new ArrayList<>(); - - @Override public void onLoadOrgs() { - makeRestCall(RestProvider.getOrgService(PrefGetter.isEnterprise()).getMyOrganizations() - .flatMap(userPageable -> { - if (userPageable != null && userPageable.getItems() != null) { - return Observable.fromIterable(userPageable.getItems()); - } - return Observable.empty(); - }) - .map(user -> { - if (user != null) user.setType("Organization"); - return user; - }) - .toList() - .toObservable(), list -> { - List myOrgs = new ArrayList<>(); - if (list != null && !list.isEmpty()) { - myOrgs.addAll(list); - } - sendToView(view -> view.onNotifyAdapter(myOrgs)); - }); - } - - @NonNull @Override public ArrayList getOrgs() { - return orgs; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/playstore/PlayStoreWarningActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/main/playstore/PlayStoreWarningActivity.kt deleted file mode 100644 index 4c83c9747..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/playstore/PlayStoreWarningActivity.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.fastaccess.ui.modules.main.playstore - -import android.os.Bundle -import android.widget.TextView -import butterknife.OnClick -import com.fastaccess.R -import com.fastaccess.helper.PrefGetter -import com.fastaccess.provider.timeline.HtmlHelper -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter - -/** - * Created by Hashemsergani on 21.09.17. - */ -class PlayStoreWarningActivity : BaseActivity>() { - - @OnClick(R.id.done) fun onDone() { - PrefGetter.setPlayStoreWarningShowed() - finish() - } - - override fun layout(): Int = R.layout.playstore_review_layout_warning - - override fun isTransparent(): Boolean = true - - override fun canBack(): Boolean = false - - override fun isSecured(): Boolean = true - - override fun providePresenter(): BasePresenter = BasePresenter() - - override fun onBackPressed() {} - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val textView = findViewById(R.id.description) - textView.post { HtmlHelper.htmlIntoTextView(textView, getString(R.string.fasthub_faq_description), textView.width) } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/premium/GmsTaskListeners.java b/app/src/main/java/com/fastaccess/ui/modules/main/premium/GmsTaskListeners.java deleted file mode 100644 index e15fd70c5..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/premium/GmsTaskListeners.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.github.b3er.rxfirebase.common; - -import android.support.annotation.NonNull; -import com.google.android.gms.tasks.OnCompleteListener; -import com.google.android.gms.tasks.Task; -import io.reactivex.CompletableEmitter; -import io.reactivex.SingleEmitter; - -public final class GmsTaskListeners { - - private GmsTaskListeners() { - throw new AssertionError("No instances"); - } - - public static OnCompleteListener listener(@NonNull final SingleEmitter emitter) { - return new OnCompleteListener() { - @Override public void onComplete(@NonNull Task task) { - if (!task.isSuccessful()) { - if (!emitter.isDisposed()) { - emitter.onError(task.getException()); - } - return; - } - - if (!emitter.isDisposed()) { - emitter.onSuccess(task.getResult()); - } - } - }; - } - - public static OnCompleteListener listener(@NonNull final CompletableEmitter emitter) { - return new OnCompleteListener() { - @Override public void onComplete(@NonNull Task task) { - if (!task.isSuccessful()) { - if (!emitter.isDisposed()) { - emitter.onError(task.getException()); - } - return; - } - - if (!emitter.isDisposed()) { - emitter.onComplete(); - } - } - }; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumActivity.kt deleted file mode 100644 index 36f791bf9..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumActivity.kt +++ /dev/null @@ -1,190 +0,0 @@ -package com.fastaccess.ui.modules.main.premium - -import android.animation.Animator -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.support.transition.TransitionManager -import android.view.View -import android.widget.Button -import android.widget.EditText -import android.widget.FrameLayout -import android.widget.TextView -import butterknife.BindView -import butterknife.OnClick -import butterknife.OnEditorAction -import com.airbnb.lottie.LottieAnimationView -import com.fastaccess.BuildConfig -import com.fastaccess.R -import com.fastaccess.helper.* -import com.fastaccess.provider.fabric.FabricProvider -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.modules.main.donation.DonateActivity -import com.miguelbcr.io.rx_billing_service.RxBillingService -import com.miguelbcr.io.rx_billing_service.entities.ProductType -import io.reactivex.Observable -import io.reactivex.disposables.Disposable - -/** - * Created by kosh on 13/07/2017. - */ -class PremiumActivity : BaseActivity(), PremiumMvp.View { - - @BindView(R.id.editText) lateinit var editText: EditText - @BindView(R.id.viewGroup) lateinit var viewGroup: FrameLayout - @BindView(R.id.progressLayout) lateinit var progressLayout: View - @BindView(R.id.successActivationView) lateinit var successActivationView: LottieAnimationView - @BindView(R.id.successActivationHolder) lateinit var successActivationHolder: View - @BindView(R.id.proPrice) lateinit var proPriceText: TextView - @BindView(R.id.enterprisePrice) lateinit var enterpriseText: TextView - @BindView(R.id.buyAll) lateinit var buyAll: Button - private var disposable: Disposable? = null - private val allFeaturesKey by lazy { getString(R.string.fasthub_all_features_purchase) } - private val enterpriseKey by lazy { getString(R.string.fasthub_enterprise_purchase) } - private val proKey by lazy { getString(R.string.fasthub_pro_purchase) } - - override fun layout(): Int = R.layout.pro_features_layout - - override fun isTransparent(): Boolean = true - - override fun providePresenter(): PremiumPresenter = PremiumPresenter() - - override fun canBack(): Boolean = false - - override fun isSecured(): Boolean = true - - @OnClick(R.id.buyAll) fun onBuyAll() { - if (!isGoogleSupported()) return - val price = buyAll.tag as? Long? - DonateActivity.Companion.start(this, allFeaturesKey, price, buyAll.text.toString()) - } - - @OnClick(R.id.buyPro) fun onBuyPro() { - if (!isGoogleSupported()) return - val price = proPriceText.tag as? Long? - DonateActivity.Companion.start(this, proKey, price, proPriceText.text.toString()) - } - - @OnClick(R.id.buyEnterprise) fun onBuyEnterprise() { - if (!isGoogleSupported()) return - val price = enterpriseText.tag as? Long? - DonateActivity.Companion.start(this, enterpriseKey, price, enterpriseText.text.toString()) - } - - @OnClick(R.id.unlock) fun onUnlock() { - if (!isGoogleSupported()) return - if (BuildConfig.DEBUG) { - PrefGetter.setProItems() - PrefGetter.setEnterpriseItem() - onSuccessfullyActivated() - return - } - val isEmpty = editText.text.isNullOrBlank() - editText.error = if (isEmpty) getString(R.string.required_field) else null - if (!isEmpty) { - presenter.onCheckPromoCode(editText.text.toString()) - } - } - - @OnEditorAction(R.id.editText) fun onEditorAction(): Boolean { - onUnlock() - return true - } - - @OnClick(R.id.close) fun onClose() = finish() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - buyAll.text = getString(R.string.purchase_all).replace("%price%", "$7.99") - RxHelper.getObservable(RxBillingService.getInstance(this, BuildConfig.DEBUG) - .getSkuDetails(ProductType.IN_APP, arrayListOf(enterpriseKey, proKey, allFeaturesKey)) - .toObservable()) - .flatMap { Observable.fromIterable(it) } - .subscribe({ - Logger.e(it.sku(), it.price(), it.priceCurrencyCode(), it.priceAmountMicros()) - when (it.sku()) { - enterpriseKey -> { - enterpriseText.text = it.price() - enterpriseText.tag = it.priceAmountMicros() - } - proKey -> { - proPriceText.text = it.price() - proPriceText.tag = it.priceAmountMicros() - } - allFeaturesKey -> { - buyAll.text = getString(R.string.purchase_all).replace("%price%", it.price()) - buyAll.tag = it.priceAmountMicros() - } - } - }, { t -> t.printStackTrace() }) - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (resultCode == Activity.RESULT_OK) { - successResult() - } - } - - private fun successResult() { - hideProgress() - setResult(Activity.RESULT_OK) - finish() - } - - override fun onSuccessfullyActivated() { - ViewHelper.hideKeyboard(editText) - hideProgress() - successActivationHolder.visibility = View.VISIBLE - FabricProvider.logPurchase(InputHelper.toString(editText)) - successActivationView.addAnimatorListener(object : Animator.AnimatorListener { - override fun onAnimationRepeat(p0: Animator?) {} - override fun onAnimationEnd(p0: Animator?) { - showMessage(R.string.success, R.string.success) - successResult() - } - - override fun onAnimationCancel(p0: Animator?) {} - - override fun onAnimationStart(p0: Animator?) {} - }) - successActivationView.playAnimation() - } - - override fun onNoMatch() { - hideProgress() - showErrorMessage(getString(R.string.not_match)) - } - - override fun showProgress(resId: Int) { - ViewHelper.hideKeyboard(editText) - TransitionManager.beginDelayedTransition(viewGroup) - progressLayout.visibility = View.VISIBLE - } - - override fun hideProgress() { - TransitionManager.beginDelayedTransition(viewGroup) - progressLayout.visibility = View.GONE - } - - override fun onDestroy() { - val disposable = disposable - if (disposable != null && !disposable.isDisposed) disposable.dispose() - super.onDestroy() - } - - private fun isGoogleSupported(): Boolean { - if (AppHelper.isGoogleAvailable(this)) { - return true - } - showErrorMessage(getString(R.string.google_play_service_error)) - return false - } - - companion object { - fun startActivity(context: Context) { - context.startActivity(Intent(context, PremiumActivity::class.java)) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumMvp.kt deleted file mode 100644 index e5018d73b..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumMvp.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.fastaccess.ui.modules.main.premium - -import com.fastaccess.ui.base.mvp.BaseMvp - -/** - * Created by kosh on 15/07/2017. - */ -interface PremiumMvp { - - interface View : BaseMvp.FAView { - fun onSuccessfullyActivated() - fun onNoMatch() - } - - interface Presenter { - fun onCheckPromoCode(promo: String) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumPresenter.kt deleted file mode 100644 index 9750e59ef..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/premium/PremiumPresenter.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.fastaccess.ui.modules.main.premium - -import com.fastaccess.data.dao.ProUsersModel -import com.fastaccess.helper.PrefGetter -import com.fastaccess.helper.RxHelper -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.github.b3er.rxfirebase.database.data -import com.github.b3er.rxfirebase.database.rxUpdateChildren -import com.google.firebase.database.FirebaseDatabase -import com.google.firebase.database.GenericTypeIndicator -import io.reactivex.Completable -import io.reactivex.Observable - - -/** - * Created by kosh on 15/07/2017. - */ -class PremiumPresenter : BasePresenter(), PremiumMvp.Presenter { - override fun onCheckPromoCode(promo: String) { - val ref = FirebaseDatabase.getInstance().reference - manageDisposable(RxHelper.getObservable(ref.child("fasthub_pro").child(promo) - .data() - .toObservable()) - .doOnSubscribe { sendToView { it.showProgress(0) } } - .flatMap { - var user = ProUsersModel() - if (it.exists() && it.hasChildren()) { - val gti = object : GenericTypeIndicator() {} - user = it.getValue(gti) ?: ProUsersModel() - } - return@flatMap Observable.just(user) - } - .subscribe({ user -> - var completable: Completable? = null - val isAllowed = user.isAllowed - if (isAllowed && !user.isBlocked) { - if (user.type == 1) { - PrefGetter.setProItems() - user.isAllowed = false - user.count = user.count + 1 - completable = ref.child("fasthub_pro") - .rxUpdateChildren(hashMapOf(Pair(promo, user))) - } else { - PrefGetter.setProItems() - PrefGetter.setEnterpriseItem() - user.count = user.count + 1 - completable = ref.child("fasthub_pro") - .rxUpdateChildren(hashMapOf(Pair(promo, user))) - } - } - if (completable != null) { - manageDisposable(completable.doOnComplete({ - if (isAllowed) { - sendToView { it.onSuccessfullyActivated() } - } else { - sendToView { it.onNoMatch() } - } - }).subscribe({}, { it.printStackTrace() })) - } else { - if (isAllowed) { - sendToView { it.onSuccessfullyActivated() } - } else { - if (user.isBlocked) { - PrefGetter.clearPurchases() - } - sendToView { it.onNoMatch() } - } - } - }, { it.printStackTrace() })) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestFragment.java b/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestFragment.java deleted file mode 100644 index cadfef8d2..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestFragment.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.fastaccess.ui.modules.main.pullrequests; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.data.dao.types.MyIssuesType; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.PullRequestAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.extras.popup.IssuePopupFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 25 Mar 2017, 11:48 PM - */ - -public class MyPullRequestFragment extends BaseFragment implements MyPullRequestsMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @State IssueState issueState; - private OnLoadMore onLoadMore; - private PullRequestAdapter adapter; - private RepoPagerMvp.TabsBadgeListener tabsBadgeListener; - - public static MyPullRequestFragment newInstance(@NonNull IssueState issueState, @NonNull MyIssuesType issuesType) { - MyPullRequestFragment view = new MyPullRequestFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.EXTRA, issueState) - .put(BundleConstant.EXTRA_TWO, issuesType) - .end()); - return view; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) getParentFragment(); - } else if (context instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) context; - } - } - - @Override public void onDetach() { - tabsBadgeListener = null; - super.onDetach(); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, issueState); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter()); - } - onLoadMore.setParameter(issueState); - return onLoadMore; - } - - @Override public void onSetCount(int totalCount) { - if (tabsBadgeListener != null) { - switch (getIssuesType()) { - case CREATED: - tabsBadgeListener.onSetBadge(0, totalCount); - break; - case ASSIGNED: - tabsBadgeListener.onSetBadge(1, totalCount); - break; - case MENTIONED: - tabsBadgeListener.onSetBadge(2, totalCount); - break; - case REVIEW: - tabsBadgeListener.onSetBadge(3, totalCount); - break; - } - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (savedInstanceState == null) { - issueState = (IssueState) getArguments().getSerializable(BundleConstant.EXTRA); - } - getPresenter().onSetPullType(getIssuesType()); - recycler.setEmptyView(stateLayout, refresh); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - adapter = new PullRequestAdapter(getPresenter().getPullRequests(), false, true); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addDivider(); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null || (getPresenter().getPullRequests().isEmpty() && !getPresenter().isApiCalled())) { - onRefresh(); - } - stateLayout.setEmptyText(getString((R.string.no_pull_requests))); - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public MyPullRequestsPresenter providePresenter() { - return new MyPullRequestsPresenter(); - } - - @Override public void onFilterIssue(@NonNull IssueState issueState) { - if (this.issueState != null && this.issueState != issueState) { - this.issueState = issueState; - getArguments().putSerializable(BundleConstant.ITEM, issueState); - getLoadMore().reset(); - adapter.clear(); - onRefresh(); - } - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - @Override public void onShowPopupDetails(@NonNull PullRequest item) { - IssuePopupFragment.showPopup(getChildFragmentManager(), item); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } - - private MyIssuesType getIssuesType() { - return (MyIssuesType) getArguments().getSerializable(BundleConstant.EXTRA_TWO); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestsMvp.java deleted file mode 100644 index 3bf2bba17..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestsMvp.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.fastaccess.ui.modules.main.pullrequests; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.data.dao.types.MyIssuesType; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 25 Mar 2017, 11:39 PM - */ - -public interface MyPullRequestsMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onSetCount(int totalCount); - - void onFilterIssue(@NonNull IssueState issueState); - - void onShowPopupDetails(@NonNull PullRequest item); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getPullRequests(); - - void onSetPullType(@NonNull MyIssuesType issuesType); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestsPresenter.java deleted file mode 100644 index 62ee0e90d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/MyPullRequestsPresenter.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.fastaccess.ui.modules.main.pullrequests; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.data.dao.types.MyIssuesType; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.rest.RepoQueryProvider; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 25 Mar 2017, 11:53 PM - */ - -public class MyPullRequestsPresenter extends BasePresenter implements MyPullRequestsMvp.Presenter { - - private ArrayList pullRequests = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - @com.evernote.android.state.State MyIssuesType issuesType; - @NonNull private String login = Login.getUser().getLogin(); - - MyPullRequestsPresenter() { - setEnterprise(PrefGetter.isEnterprise()); - } - - @Override public void onItemClick(int position, View v, PullRequest item) { - SchemeParser.launchUri(v.getContext(), item.getHtmlUrl()); - } - - @Override public void onItemLongClick(int position, View v, PullRequest item) { - if (getView() != null) getView().onShowPopupDetails(item); - } - - @NonNull @Override public ArrayList getPullRequests() { - return pullRequests; - } - - @Override public void onSetPullType(@NonNull MyIssuesType issuesType) { - this.issuesType = issuesType; - } - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable IssueState parameter) { - if (parameter == null) { - throw new NullPointerException("Parameter is null"); - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - if (page > lastPage || lastPage == 0) { - sendToView(MyPullRequestsMvp.View::hideProgress); - return false; - } - setCurrentPage(page); - makeRestCall(RestProvider.getPullRequestService(isEnterprise()).getPullsWithCount(getUrl(parameter), page), response -> { - lastPage = response.getLast(); - if (getCurrentPage() == 1) { - sendToView(view -> view.onSetCount(response.getTotalCount())); - } - sendToView(view -> view.onNotifyAdapter(response.getItems(), page)); - }); - return true; - } - - @NonNull private String getUrl(@NonNull IssueState parameter) { - switch (issuesType) { - case CREATED: - return RepoQueryProvider.getMyIssuesPullRequestQuery(login, parameter, true); - case ASSIGNED: - return RepoQueryProvider.getAssigned(login, parameter, true); - case MENTIONED: - return RepoQueryProvider.getMentioned(login, parameter, true); - case REVIEW: - return RepoQueryProvider.getReviewRequests(login, parameter); - } - return RepoQueryProvider.getMyIssuesPullRequestQuery(login, parameter, false); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerFragment.java b/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerFragment.java deleted file mode 100644 index 08efda433..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerFragment.java +++ /dev/null @@ -1,196 +0,0 @@ -package com.fastaccess.ui.modules.main.pullrequests.pager; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; -import android.support.v4.view.ViewPager; -import android.view.MenuInflater; -import android.view.View; -import android.widget.PopupMenu; -import android.widget.TextView; - -import com.annimon.stream.Stream; -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.TabsCountStateModel; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.main.pullrequests.MyPullRequestFragment; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.ViewPagerView; - -import java.util.HashSet; - -import butterknife.BindView; - -/** - * Created by Kosh on 26 Mar 2017, 12:14 AM - */ - -public class MyPullsPagerFragment extends BaseFragment implements MyPullsPagerMvp.View { - - public static final String TAG = MyPullsPagerFragment.class.getSimpleName(); - - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.pager) ViewPagerView pager; - @State HashSet counts = new HashSet<>(); - - public static MyPullsPagerFragment newInstance() { - return new MyPullsPagerFragment(); - } - - @Override protected int fragmentLayout() { - return R.layout.tabbed_viewpager; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - FragmentsPagerAdapter adapter = new FragmentsPagerAdapter(getChildFragmentManager(), - FragmentPagerAdapterModel.buildForMyPulls(getContext())); - pager.setAdapter(adapter); - //noinspection deprecation - tabs.setTabsFromPagerAdapter(adapter); - tabs.setTabGravity(TabLayout.GRAVITY_FILL); - tabs.setTabMode(TabLayout.MODE_SCROLLABLE); - if (savedInstanceState == null) { - tabs.getTabAt(0).select(); - } - pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { - @Override public void onPageSelected(int position) { - super.onPageSelected(position); - selectTab(position, true); - } - }); - tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { - @Override public void onTabSelected(TabLayout.Tab tab) { - if (tab.getTag() == null) { - int position = tab.getPosition(); - selectTab(position, false); - } - tab.setTag(null); - } - - @Override public void onTabUnselected(TabLayout.Tab tab) {} - - @Override public void onTabReselected(TabLayout.Tab tab) { - selectTab(tab.getPosition(), false); - } - }); - if (savedInstanceState != null && !counts.isEmpty()) { - Stream.of(counts).forEach(this::updateCount); - } - } - - @NonNull @Override public MyPullsPagerPresenter providePresenter() { - return new MyPullsPagerPresenter(); - } - - @Override public void onSetBadge(int tabIndex, int count) { - TabsCountStateModel model = getModelAtIndex(tabIndex); - if (model == null) { - model = new TabsCountStateModel(); - } - model.setTabIndex(tabIndex); - model.setCount(count); - boolean removed = counts.remove(model); - counts.add(model); - if (tabs != null) { - updateCount(model); - } - } - - @Nullable private TabsCountStateModel getModelAtIndex(int index) { - return Stream.of(counts) - .filter(model -> model.getTabIndex() == index) - .findFirst() - .orElse(null); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (pager != null && pager.getAdapter() != null) { - MyPullRequestFragment myIssuesFragment = (MyPullRequestFragment) pager.getAdapter().instantiateItem(pager, pager.getCurrentItem()); - if (myIssuesFragment != null) { - myIssuesFragment.onScrollTop(0); - } - } - } - - private void selectTab(int position, boolean fromViewPager) { - if (!fromViewPager) { - onShowFilterMenu(getModelAtIndex(position), ViewHelper.getTabTextView(tabs, position)); - pager.setCurrentItem(position); - } else { - TabLayout.Tab tab = tabs.getTabAt(position); - if (tab != null) { - tab.setTag("hello"); - if (!tab.isSelected()) tab.select(); - } - } - } - - private void updateCount(@NonNull TabsCountStateModel model) { - TextView tv = ViewHelper.getTabTextView(tabs, model.getTabIndex()); - String title = getString(R.string.created); - switch (model.getTabIndex()) { - case 0: - title = getString(R.string.created); - break; - case 1: - title = getString(R.string.assigned); - break; - case 2: - title = getString(R.string.mentioned); - break; - case 3: - title = getString(R.string.review_requests); - break; - } - updateDrawable(model, tv); - tv.setText(SpannableBuilder.builder() - .append(title) - .append(" ") - .append("(") - .bold(String.valueOf(model.getCount())) - .append(")")); - } - - private void onShowFilterMenu(@Nullable TabsCountStateModel model, TextView tv) { - if (model == null) return; - PopupMenu popup = new PopupMenu(getContext(), tv); - MenuInflater inflater = popup.getMenuInflater(); - inflater.inflate(R.menu.filter_issue_state_menu, popup.getMenu()); - popup.setOnMenuItemClickListener(item -> { - if (pager == null || pager.getAdapter() == null) return false; - MyPullRequestFragment myIssuesFragment = (MyPullRequestFragment) pager.getAdapter().instantiateItem(pager, model.getTabIndex()); - if (myIssuesFragment == null) return false; - switch (item.getItemId()) { - case R.id.opened: - counts.remove(model); - model.setDrawableId(R.drawable.ic_issue_opened_small); - counts.add(model); - updateDrawable(model, tv); - myIssuesFragment.onFilterIssue(IssueState.open); - return true; - case R.id.closed: - counts.remove(model); - model.setDrawableId(R.drawable.ic_issue_closed_small); - counts.add(model); - updateDrawable(model, tv); - myIssuesFragment.onFilterIssue(IssueState.closed); - return true; - } - return false; - }); - popup.show(); - } - - private void updateDrawable(@NonNull TabsCountStateModel model, TextView tv) { - model.setDrawableId(model.getDrawableId() == 0 ? R.drawable.ic_issue_opened_small : model.getDrawableId()); - tv.setCompoundDrawablePadding(16); - tv.setCompoundDrawablesWithIntrinsicBounds(model.getDrawableId(), 0, R.drawable.ic_arrow_drop_down, 0); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerMvp.java deleted file mode 100644 index caeb8d8e2..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerMvp.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.fastaccess.ui.modules.main.pullrequests.pager; - -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; - -/** - * Created by Kosh on 26 Mar 2017, 12:15 AM - */ - -public interface MyPullsPagerMvp { - - interface View extends BaseMvp.FAView, RepoPagerMvp.TabsBadgeListener {} - - interface Presenter {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerPresenter.java deleted file mode 100644 index dca9c89d6..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/main/pullrequests/pager/MyPullsPagerPresenter.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.ui.modules.main.pullrequests.pager; - -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by Kosh on 26 Mar 2017, 12:17 AM - */ - -public class MyPullsPagerPresenter extends BasePresenter implements MyPullsPagerMvp.Presenter {} diff --git a/app/src/main/java/com/fastaccess/ui/modules/notification/NotificationActivity.java b/app/src/main/java/com/fastaccess/ui/modules/notification/NotificationActivity.java deleted file mode 100644 index 31821191e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/notification/NotificationActivity.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.fastaccess.ui.modules.notification; - -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; - -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.GroupedNotificationModel; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.main.MainActivity; -import com.fastaccess.ui.modules.notification.all.AllNotificationsFragment; -import com.fastaccess.ui.modules.notification.callback.OnNotificationChangedListener; -import com.fastaccess.ui.modules.notification.unread.UnreadNotificationsFragment; -import com.fastaccess.ui.widgets.ViewPagerView; - -import net.grandcentrix.thirtyinch.TiPresenter; - -import butterknife.BindView; - -/** - * Created by Kosh on 27 Feb 2017, 12:36 PM - */ - -public class NotificationActivity extends BaseActivity implements OnNotificationChangedListener { - - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.notificationContainer) - ViewPagerView pager; - - @Override protected int layout() { - return R.layout.notification_activity_layout; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } - - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - AppHelper.cancelNotification(this); - onSelectNotifications(); - setupTabs(); - tabs.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager) { - @Override public void onTabReselected(TabLayout.Tab tab) { - super.onTabReselected(tab); - onScrollTop(tab.getPosition()); - } - }); - } - - @Override public void onScrollTop(int index) { - if (pager == null || pager.getAdapter() == null) return; - Fragment fragment = (BaseFragment) pager.getAdapter().instantiateItem(pager, index); - if (fragment instanceof BaseFragment) { - ((BaseFragment) fragment).onScrollTop(index); - } - } - - @Override public void onBackPressed() { - if (isTaskRoot()) { - startActivity(new Intent(this, MainActivity.class)); - } - super.onBackPressed(); - } - - @Override public void onNotificationChanged(@NonNull GroupedNotificationModel notification, int index) { - if (pager != null && pager.getAdapter() != null) { - if (index == 0) { - UnreadNotificationsFragment fragment = (UnreadNotificationsFragment) pager.getAdapter().instantiateItem(pager, 0); - fragment.onNotifyNotificationChanged(notification); - } else { - AllNotificationsFragment fragment = (AllNotificationsFragment) pager.getAdapter().instantiateItem(pager, 1); - fragment.onNotifyNotificationChanged(notification); - } - } - } - - private void setupTabs() { - pager.setAdapter(new FragmentsPagerAdapter(getSupportFragmentManager(), - FragmentPagerAdapterModel.buildForNotifications(this))); - tabs.setupWithViewPager(pager); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsFragment.java b/app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsFragment.java deleted file mode 100644 index 5340e6e07..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsFragment.java +++ /dev/null @@ -1,201 +0,0 @@ -package com.fastaccess.ui.modules.notification.all; - -import android.content.Context; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; - -import com.annimon.stream.Stream; -import com.fastaccess.R; -import com.fastaccess.data.dao.GroupedNotificationModel; -import com.fastaccess.data.dao.model.Notification; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.ObjectsCompat; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.provider.tasks.notification.ReadNotificationService; -import com.fastaccess.ui.adapter.NotificationsAdapter; -import com.fastaccess.ui.adapter.viewholder.NotificationsViewHolder; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.notification.callback.OnNotificationChangedListener; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 20 Feb 2017, 8:50 PM - */ - -public class AllNotificationsFragment extends BaseFragment - implements AllNotificationsMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private NotificationsAdapter adapter; - private OnNotificationChangedListener onNotificationChangedListener; - - public static AllNotificationsFragment newInstance() { - return new AllNotificationsFragment(); - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof OnNotificationChangedListener) { - onNotificationChangedListener = (OnNotificationChangedListener) context; - } - } - - @Override public void onDetach() { - onNotificationChangedListener = null; - super.onDetach(); - } - - @Override public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setHasOptionsMenu(true); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(); - } - - @Override public void onUpdateReadState(GroupedNotificationModel item, int position) { - if (onNotificationChangedListener != null) onNotificationChangedListener.onNotificationChanged(item, 0); - adapter.swapItem(item, position); - } - - @Override public void onNotifyAdapter(@Nullable List items) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - adapter.insertItems(items); - if (isSafe()) getActivity().invalidateOptionsMenu(); - } - - @Override public void onClick(@NonNull String url) { - SchemeParser.launchUri(getContext(), Uri.parse(url), true); - } - - @Override public void onReadNotification(@NonNull Notification notification) { - GroupedNotificationModel model = new GroupedNotificationModel(notification); - if (onNotificationChangedListener != null) onNotificationChangedListener.onNotificationChanged(model, 0); - adapter.swapItem(model); - ReadNotificationService.start(getContext(), notification.getId()); - } - - @Override public void onMarkAllByRepo(@NonNull Repo repo) { - getPresenter().onMarkReadByRepo(adapter.getData(), repo); - } - - @Override public void onNotifyNotificationChanged(@NonNull GroupedNotificationModel notification) { - if (adapter != null) { - adapter.swapItem(notification); - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - adapter = new NotificationsAdapter(getPresenter().getNotifications(), true, true); - adapter.setListener(getPresenter()); - refresh.setOnRefreshListener(this); - stateLayout.setEmptyText(R.string.no_notifications); - stateLayout.setOnReloadListener(v -> onRefresh()); - recycler.setEmptyView(stateLayout, refresh); - recycler.setAdapter(adapter); - recycler.addDivider(NotificationsViewHolder.class); - if (savedInstanceState == null || !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public AllNotificationsPresenter providePresenter() { - return new AllNotificationsPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.notification_menu, menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.readAll) { - if (!adapter.getData().isEmpty()) { - MessageDialogView.newInstance(getString(R.string.mark_all_as_read), getString(R.string.confirm_message), - false, false, Bundler.start() - .put("primary_button", getString(R.string.yes)) - .put("secondary_button", getString(R.string.no)) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override public void onPrepareOptionsMenu(Menu menu) { - boolean hasUnread = Stream.of(adapter.getData()) - .filter(ObjectsCompat::nonNull) - .filter(group -> group.getType() == GroupedNotificationModel.ROW) - .anyMatch(group -> group.getNotification().isUnread()); - menu.findItem(R.id.readAll).setVisible(hasUnread); - super.onPrepareOptionsMenu(menu); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk) { - getPresenter().onMarkAllAsRead(adapter.getData()); - } - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsMvp.java deleted file mode 100644 index 5b8297aa3..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsMvp.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.fastaccess.ui.modules.notification.all; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.GroupedNotificationModel; -import com.fastaccess.data.dao.model.Notification; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import net.grandcentrix.thirtyinch.callonmainthread.CallOnMainThread; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 19 Feb 2017, 7:53 PM - */ - -public interface AllNotificationsMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener { - - @CallOnMainThread void onNotifyAdapter(@Nullable List items); - - void onUpdateReadState(GroupedNotificationModel item, int position); - - void onClick(@NonNull String url); - - void onReadNotification(@NonNull Notification notification); - - void onMarkAllByRepo(@NonNull Repo repo); - - void onNotifyNotificationChanged(@NonNull GroupedNotificationModel notification); - } - - interface Presenter extends BaseViewHolder.OnItemClickListener { - - void onWorkOffline(); - - @NonNull ArrayList getNotifications(); - - void onCallApi(); - - void onMarkAllAsRead(@NonNull List data); - - void onMarkReadByRepo(@NonNull List data, @NonNull Repo repo); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsPresenter.java deleted file mode 100644 index ddfb9270b..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/notification/all/AllNotificationsPresenter.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.fastaccess.ui.modules.notification.all; - -import android.support.annotation.NonNull; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.GroupedNotificationModel; -import com.fastaccess.data.dao.NameParser; -import com.fastaccess.data.dao.model.Notification; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.tasks.notification.ReadNotificationService; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.repos.RepoPagerActivity; - -import java.util.ArrayList; -import java.util.List; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 20 Feb 2017, 8:46 PM - */ - -public class AllNotificationsPresenter extends BasePresenter implements AllNotificationsMvp.Presenter { - private final ArrayList notifications = new ArrayList<>(); - - @Override public void onItemClick(int position, View v, GroupedNotificationModel model) { - if (getView() == null) return; - if (model.getType() == GroupedNotificationModel.ROW) { - Notification item = model.getNotification(); - if (v.getId() == R.id.markAsRead) { - if (item.isUnread() && !PrefGetter.isMarkAsReadEnabled()) { - markAsRead(position, v, item); - } - } else if (v.getId() == R.id.unsubsribe) { - item.setUnread(false); - manageDisposable(item.save(item)); - sendToView(view -> view.onUpdateReadState(new GroupedNotificationModel(item), position)); - ReadNotificationService.unSubscribe(v.getContext(), item.getId()); - } else { - if (item.getSubject() != null && item.getSubject().getUrl() != null) { - if (item.isUnread() && !PrefGetter.isMarkAsReadEnabled()) { - markAsRead(position, v, item); - } - if (getView() != null) getView().onClick(item.getSubject().getUrl()); - } - } - } else { - Repo repo = model.getRepo(); - if (repo == null) return; - if (v.getId() == R.id.markAsRead) { - getView().onMarkAllByRepo(repo); - } else { - RepoPagerActivity.startRepoPager(v.getContext(), new NameParser(repo.getUrl())); - } - } - } - - private void markAsRead(int position, View v, Notification item) { - item.setUnread(false); - manageDisposable(item.save(item)); - sendToView(view -> view.onUpdateReadState(new GroupedNotificationModel(item), position)); - ReadNotificationService.start(v.getContext(), item.getId()); - } - - @Override public void onItemLongClick(int position, View v, GroupedNotificationModel item) {} - - @Override public void onError(@NonNull Throwable throwable) { - onWorkOffline(); - super.onError(throwable); - } - - @Override public void onWorkOffline() { - if (notifications.isEmpty()) { - manageDisposable(RxHelper.getObservable(Notification.getAllNotifications().toObservable()) - .flatMap(notifications -> Observable.just(GroupedNotificationModel.construct(notifications))) - .subscribe(models -> sendToView(view -> view.onNotifyAdapter(models)))); - } else { - sendToView(BaseMvp.FAView::hideProgress); - } - } - - @NonNull @Override public ArrayList getNotifications() { - return notifications; - } - - @Override public void onCallApi() { -// Observable> notifications = RestProvider.getNotificationService().getAllNotifications() -// .flatMap(response -> response.getItems() != null ? Observable.fromIterable(response.getItems()) : Observable.empty()) -// .filter(ObjectsCompat::nonNull) -// .flatMap(notification -> RestProvider.getNotificationService().isSubscribed(notification.getId()) -// .onErrorReturn(throwable -> null), -// (notification, subscriptionModel) -> { -// if (subscriptionModel != null) { -// notification.setIsSubscribed(subscriptionModel.isSubscribed()); -// } else { -// notification.setIsSubscribed(true); -// } -// return notification; -// }) -// .toList(); - Observable> observable = RestProvider.getNotificationService(PrefGetter.isEnterprise()) - .getAllNotifications().flatMap(response -> { - manageDisposable(Notification.save(response.getItems())); - if (response.getItems() != null && !response.getItems().isEmpty()) { - return Observable.just(GroupedNotificationModel.construct(response.getItems())); - } - return Observable.empty(); - }); - makeRestCall(observable.doOnComplete(() -> sendToView(BaseMvp.FAView::hideProgress)), response -> sendToView(view -> view.onNotifyAdapter - (response))); - } - - @Override public void onMarkAllAsRead(@NonNull List data) { - manageDisposable(RxHelper.getObservable(Observable.fromIterable(data)) - .filter(group -> group.getType() == GroupedNotificationModel.ROW) - .filter(group -> group.getNotification() != null && group.getNotification().isUnread()) - .map(GroupedNotificationModel::getNotification) - .subscribe(notification -> { - notification.setUnread(false); - manageDisposable(notification.save(notification)); - sendToView(view -> view.onReadNotification(notification)); - }, this::onError)); - } - - @Override public void onMarkReadByRepo(@NonNull List data, @NonNull Repo repo) { - manageDisposable(RxHelper.getObservable(Observable.fromIterable(data)) - .filter(group -> group.getType() == GroupedNotificationModel.ROW) - .filter(group -> group.getNotification() != null && group.getNotification().isUnread()) - .filter(group -> group.getNotification().getRepository().getFullName().equalsIgnoreCase(repo.getFullName())) - .map(GroupedNotificationModel::getNotification) - .subscribe(notification -> { - notification.setUnread(false); - manageDisposable(notification.save(notification)); - sendToView(view -> view.onReadNotification(notification)); - }, this::onError)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/notification/callback/OnNotificationChangedListener.java b/app/src/main/java/com/fastaccess/ui/modules/notification/callback/OnNotificationChangedListener.java deleted file mode 100644 index 1df8c5f0d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/notification/callback/OnNotificationChangedListener.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.fastaccess.ui.modules.notification.callback; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.GroupedNotificationModel; - -public interface OnNotificationChangedListener { - - void onNotificationChanged(@NonNull GroupedNotificationModel notification, int index); -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsFragment.kt deleted file mode 100644 index 5c15cab54..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsFragment.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.fastaccess.ui.modules.notification.fasthub - -import android.os.Bundle -import android.view.View -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.model.FastHubNotification -import com.fastaccess.ui.adapter.FastHubNotificationsAdapter -import com.fastaccess.ui.base.BaseFragment -import com.fastaccess.ui.modules.main.notifications.FastHubNotificationDialog -import com.fastaccess.ui.widgets.AppbarRefreshLayout -import com.fastaccess.ui.widgets.StateLayout -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller - -/** - * Created by Kosh on 19.11.17. - */ -class FastHubNotificationsFragment : BaseFragment(), FastHubNotificationsMvp.View { - - @BindView(R.id.recycler) lateinit var recycler: DynamicRecyclerView - @BindView(R.id.refresh) lateinit var refresh: AppbarRefreshLayout - @BindView(R.id.stateLayout) lateinit var stateLayout: StateLayout - @BindView(R.id.fastScroller) lateinit var fastScroller: RecyclerViewFastScroller - private val adapter by lazy { FastHubNotificationsAdapter(presenter.getData()) } - - override fun fragmentLayout(): Int = R.layout.small_grid_refresh_list - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - adapter.listener = this - stateLayout.setEmptyText(R.string.no_notifications) - recycler.setEmptyView(stateLayout, refresh) - recycler.addDivider() - refresh.setOnRefreshListener { presenter.load() } - stateLayout.setOnReloadListener { presenter.load() } - if (savedInstanceState == null) { - stateLayout.showProgress() - presenter.load() - } - recycler.adapter = adapter - fastScroller.attachRecyclerView(recycler) - } - - override fun providePresenter(): FastHubNotificationsPresenter = FastHubNotificationsPresenter() - - override fun notifyAdapter(items: List?) { - refresh.isRefreshing = false - stateLayout.hideProgress() - if (items != null) { - adapter.insertItems(items) - } else { - adapter.clear() - } - } - - override fun onItemClick(position: Int, v: View?, item: FastHubNotification) = FastHubNotificationDialog.show(childFragmentManager, item) - - override fun onItemLongClick(position: Int, v: View?, item: FastHubNotification) {} -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsMvp.kt deleted file mode 100644 index 22ad54ab6..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsMvp.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.fastaccess.ui.modules.notification.fasthub - -import com.fastaccess.data.dao.model.FastHubNotification -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Kosh on 19.11.17. - */ -interface FastHubNotificationsMvp { - - interface View : BaseMvp.FAView, BaseViewHolder.OnItemClickListener { - fun notifyAdapter(items: List?) - } - - interface Presenter { - fun getData(): List - fun load() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsPresenter.kt deleted file mode 100644 index d5dedd89d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/notification/fasthub/FastHubNotificationsPresenter.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.fastaccess.ui.modules.notification.fasthub - -import com.fastaccess.data.dao.model.FastHubNotification -import com.fastaccess.ui.base.mvp.presenter.BasePresenter - -/** - * Created by Kosh on 19.11.17. - */ -class FastHubNotificationsPresenter : BasePresenter(), FastHubNotificationsMvp.Presenter { - private val data = mutableListOf() - - override fun getData(): List = data - - override fun load() { - manageObservable(FastHubNotification.getNotifications() - .toList() - .toObservable() - .doOnNext { - sendToView({ v -> v.notifyAdapter(it) }) - }) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationMvp.java b/app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationMvp.java deleted file mode 100644 index 40fd70a45..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationMvp.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.fastaccess.ui.modules.notification.unread; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.GroupedNotificationModel; -import com.fastaccess.data.dao.model.Notification; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import net.grandcentrix.thirtyinch.callonmainthread.CallOnMainThread; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 25 Apr 2017, 3:51 PM - */ - -public interface UnreadNotificationMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener { - @CallOnMainThread void onNotifyAdapter(@Nullable List items); - - void onRemove(int position); - - void onReadNotification(@NonNull Notification notification); - - void onClick(@NonNull String url); - - void onNotifyNotificationChanged(@NonNull GroupedNotificationModel notification); - } - - interface Presenter extends BaseViewHolder.OnItemClickListener { - - void onWorkOffline(); - - @NonNull ArrayList getNotifications(); - - void onMarkAllAsRead(@NonNull List data); - - void onCallApi(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationsFragment.java b/app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationsFragment.java deleted file mode 100644 index fb5962b66..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationsFragment.java +++ /dev/null @@ -1,197 +0,0 @@ -package com.fastaccess.ui.modules.notification.unread; - -import android.content.Context; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.GroupedNotificationModel; -import com.fastaccess.data.dao.model.Notification; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.provider.tasks.notification.ReadNotificationService; -import com.fastaccess.ui.adapter.NotificationsAdapter; -import com.fastaccess.ui.adapter.viewholder.NotificationsViewHolder; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.notification.callback.OnNotificationChangedListener; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 25 Apr 2017, 4:06 PM - */ - -public class UnreadNotificationsFragment extends BaseFragment - implements UnreadNotificationMvp.View { - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private NotificationsAdapter adapter; - private OnNotificationChangedListener onNotificationChangedListener; - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof OnNotificationChangedListener) { - onNotificationChangedListener = (OnNotificationChangedListener) context; - } - } - - @Override public void onDetach() { - onNotificationChangedListener = null; - super.onDetach(); - } - - @Override public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setHasOptionsMenu(true); - } - - @Override public void onNotifyAdapter(@Nullable List items) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - adapter.insertItems(items); - invalidateMenu(); - } - - @Override public void onRemove(int position) { - hideProgress(); - GroupedNotificationModel model = adapter.getItem(position); - if (model != null) { - if (onNotificationChangedListener != null) onNotificationChangedListener.onNotificationChanged(model, 1); - } - adapter.removeItem(position); - invalidateMenu(); - } - - @Override public void onReadNotification(@NonNull Notification notification) { - GroupedNotificationModel model = new GroupedNotificationModel(notification); - if (onNotificationChangedListener != null) onNotificationChangedListener.onNotificationChanged(model, 1); - adapter.removeItem(model); - ReadNotificationService.start(getContext(), notification.getId()); - invalidateMenu(); - } - - @Override public void onClick(@NonNull String url) { - SchemeParser.launchUri(getContext(), Uri.parse(url), true); - } - - @Override public void onNotifyNotificationChanged(@NonNull GroupedNotificationModel notification) { - if (adapter != null) { - adapter.removeItem(notification); - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - adapter = new NotificationsAdapter(getPresenter().getNotifications(), false); - adapter.setListener(getPresenter()); - refresh.setOnRefreshListener(this); - stateLayout.setEmptyText(R.string.no_notifications); - stateLayout.setOnReloadListener(v -> onRefresh()); - recycler.setEmptyView(stateLayout, refresh); - recycler.setAdapter(adapter); - recycler.addDivider(NotificationsViewHolder.class); - if (savedInstanceState == null || !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public UnreadNotificationsPresenter providePresenter() { - return new UnreadNotificationsPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.notification_menu, menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.readAll) { - if (!adapter.getData().isEmpty()) { - MessageDialogView.newInstance(getString(R.string.mark_all_as_read), getString(R.string.confirm_message), - false, false, Bundler.start() - .put("primary_button", getString(R.string.yes)) - .put("secondary_button", getString(R.string.no)) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override public void onPrepareOptionsMenu(Menu menu) { - boolean hasUnread = !adapter.getData().isEmpty(); - menu.findItem(R.id.readAll).setVisible(hasUnread); - super.onPrepareOptionsMenu(menu); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk) { - getPresenter().onMarkAllAsRead(adapter.getData()); - } - } - - private void invalidateMenu() { - if (isSafe()) getActivity().invalidateOptionsMenu(); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationsPresenter.java deleted file mode 100644 index 75ea175f5..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/notification/unread/UnreadNotificationsPresenter.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.fastaccess.ui.modules.notification.unread; - -import android.support.annotation.NonNull; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.GroupedNotificationModel; -import com.fastaccess.data.dao.model.Notification; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.tasks.notification.ReadNotificationService; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; -import java.util.List; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 25 Apr 2017, 3:55 PM - */ - -public class UnreadNotificationsPresenter extends BasePresenter implements UnreadNotificationMvp.Presenter { - private ArrayList notifications = new ArrayList<>(); - - @Override public void onItemClick(int position, View v, GroupedNotificationModel model) { - if (getView() == null) return; - Notification item = model.getNotification(); - if (v.getId() == R.id.markAsRead) { - if (item.isUnread()) markAsRead(position, v, item); - } else if (v.getId() == R.id.unsubsribe) { - item.setUnread(false); - manageDisposable(item.save(item)); - sendToView(view -> view.onRemove(position)); - ReadNotificationService.unSubscribe(v.getContext(), item.getId()); - } else { - if (item.getSubject() != null && item.getSubject().getUrl() != null) { - if (item.isUnread() && !PrefGetter.isMarkAsReadEnabled()) { - markAsRead(position, v, item); - } - if (getView() != null) getView().onClick(item.getSubject().getUrl()); - } - } - } - - @Override public void onItemLongClick(int position, View v, GroupedNotificationModel item) {} - - @Override public void onWorkOffline() { - if (notifications.isEmpty()) { - manageDisposable(RxHelper.getObservable(Notification.getUnreadNotifications().toObservable()) - .flatMap(notifications -> Observable.just(GroupedNotificationModel.onlyNotifications(notifications))) - .subscribe(models -> sendToView(view -> view.onNotifyAdapter(models)))); - } else { - sendToView(BaseMvp.FAView::hideProgress); - } - } - - @NonNull @Override public ArrayList getNotifications() { - return notifications; - } - - @Override public void onMarkAllAsRead(@NonNull List data) { - manageDisposable(RxHelper.getObservable(Observable.fromIterable(data)) - .filter(group -> group.getType() == GroupedNotificationModel.ROW) - .filter(group -> group.getNotification() != null && group.getNotification().isUnread()) - .map(GroupedNotificationModel::getNotification) - .subscribe(notification -> { - notification.setUnread(false); - manageDisposable(notification.save(notification)); - sendToView(view -> view.onReadNotification(notification)); - }, this::onError)); - } - - @Override public void onCallApi() { - Observable> observable = RestProvider.getNotificationService(PrefGetter.isEnterprise()) - .getNotifications(ParseDateFormat.getLastWeekDate()).flatMap(response -> { - if (response.getItems() != null) manageDisposable(Notification.save(response.getItems())); - return Observable.just(GroupedNotificationModel.onlyNotifications(response.getItems())); - }); - makeRestCall(observable, response -> sendToView(view -> view.onNotifyAdapter(response))); - } - - private void markAsRead(int position, View v, Notification item) { - item.setUnread(false); - manageDisposable(item.save(item)); - sendToView(view -> view.onRemove(position)); - ReadNotificationService.start(v.getContext(), item.getId()); - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/parser/LinksParserActivity.java b/app/src/main/java/com/fastaccess/ui/modules/parser/LinksParserActivity.java deleted file mode 100644 index f053f3d93..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/parser/LinksParserActivity.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.fastaccess.ui.modules.parser; - -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.widget.Toast; - -import com.fastaccess.App; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.modules.login.chooser.LoginChooserActivity; - -import org.apache.tools.ant.ExitException; - -/** - * Created by Kosh on 09 Dec 2016, 12:31 PM - */ - -public class LinksParserActivity extends Activity { - - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (Login.getUser() == null) { - Toast.makeText(App.getInstance(), R.string.please_login, Toast.LENGTH_SHORT).show(); - startActivity(new Intent(this, LoginChooserActivity.class)); - finish(); - return; - } - onCreate(getIntent()); - } - - @Override protected void onStart() { - super.onStart(); - setVisible(true); - } - - private void onCreate(@Nullable Intent intent) { - if (intent == null || intent.getAction() == null) { - finish(); - return; - } - if (Intent.ACTION_SEND.equals(intent.getAction())) { - try { - String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); - if (!InputHelper.isEmpty(sharedText)) { - Uri uri = Uri.parse(sharedText); - onUriReceived(uri); - } - } catch (ExitException ignored) {} - } else if (intent.getAction().equals(Intent.ACTION_VIEW)) { - if (intent.getData() != null) { - onUriReceived(intent.getData()); - } - } - finish(); - } - - private void onUriReceived(@NonNull Uri uri) { - SchemeParser.launchUri(this, uri, false, true); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/PinnedReposActivity.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/PinnedReposActivity.java deleted file mode 100644 index f32dfd4a8..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/PinnedReposActivity.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.fastaccess.ui.modules.pinned; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; - -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.main.MainActivity; -import com.fastaccess.ui.widgets.ViewPagerView; - -import net.grandcentrix.thirtyinch.TiPresenter; - -import butterknife.BindView; -import shortbread.Shortcut; - -/** - * Created by Kosh on 25 Mar 2017, 11:14 PM - */ - -@Shortcut(id = "pinned", icon = R.drawable.ic_app_shortcut_pinned, shortLabelRes = R.string.pinned, backStack = {MainActivity.class}, rank = 5) -public class PinnedReposActivity extends BaseActivity { - - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.tabbedPager) ViewPagerView tabbedPager; - - public static void startActivity(@NonNull Context context) { - context.startActivity(new Intent(context, PinnedReposActivity.class)); - } - - @Override protected int layout() { - return R.layout.tabbed_pager_layout; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } - - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - selectPinned(); - tabbedPager.setAdapter(new FragmentsPagerAdapter(getSupportFragmentManager(), FragmentPagerAdapterModel.buildForPinned(this))); - tabs.setupWithViewPager(tabbedPager); - tabs.setPadding(0, 0, 0, 0); - tabs.setTabMode(TabLayout.MODE_SCROLLABLE); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistFragment.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistFragment.java deleted file mode 100644 index e599bdfeb..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistFragment.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.fastaccess.ui.modules.pinned.gist; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.data.dao.model.PinnedGists; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.adapter.GistsAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 25 Mar 2017, 8:04 PM - */ - -public class PinnedGistFragment extends BaseFragment implements PinnedGistMvp.View { - - public static final String TAG = PinnedGistFragment.class.getSimpleName(); - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private GistsAdapter adapter; - - public static PinnedGistFragment newInstance() { - return new PinnedGistFragment(); - } - - @Override public void onNotifyAdapter(@Nullable List items) { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - if (items != null) adapter.insertItems(items); - else adapter.clear(); - } - - @Override public void onDeletePinnedGist(long id, int position) { - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), - Bundler.start().put(BundleConstant.YES_NO_EXTRA, true) - .put(BundleConstant.EXTRA, position) - .put(BundleConstant.ID, id) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - adapter = new GistsAdapter(getPresenter().getPinnedGists()); - adapter.setListener(getPresenter()); - stateLayout.setEmptyText(R.string.no_gists); - recycler.setEmptyView(stateLayout, refresh); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - refresh.setOnRefreshListener(() -> getPresenter().onReload()); - stateLayout.setOnReloadListener(v -> getPresenter().onReload()); - if (savedInstanceState == null) { - stateLayout.showProgress(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public PinnedGistPresenter providePresenter() { - return new PinnedGistPresenter(); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (bundle != null && isOk) { - long id = bundle.getLong(BundleConstant.ID); - int position = bundle.getInt(BundleConstant.EXTRA); - PinnedGists.delete(id); - adapter.removeItem(position); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistMvp.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistMvp.java deleted file mode 100644 index a6db4ed52..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistMvp.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.ui.modules.pinned.gist; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 25 Mar 2017, 7:57 PM - */ - -public interface PinnedGistMvp { - - interface View extends BaseMvp.FAView { - void onNotifyAdapter(@Nullable List items); - - void onDeletePinnedGist(long id, int position); - } - - interface Presenter extends BaseViewHolder.OnItemClickListener { - @NonNull ArrayList getPinnedGists(); - - void onReload(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistPresenter.java deleted file mode 100644 index b2db040bd..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/gist/PinnedGistPresenter.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.fastaccess.ui.modules.pinned.gist; - -import android.support.annotation.NonNull; -import android.view.View; - -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.data.dao.model.PinnedGists; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 25 Mar 2017, 8:00 PM - */ - -public class PinnedGistPresenter extends BasePresenter implements PinnedGistMvp.Presenter { - private ArrayList issues = new ArrayList<>(); - - @Override protected void onAttachView(@NonNull PinnedGistMvp.View view) { - super.onAttachView(view); - if (issues.isEmpty()) { - onReload(); - } - } - - @NonNull @Override public ArrayList getPinnedGists() { - return issues; - } - - @Override public void onReload() { - manageDisposable(PinnedGists.getMyPinnedGists() - .subscribe(repos -> sendToView(view -> view.onNotifyAdapter(repos)), throwable -> - sendToView(view -> view.onNotifyAdapter(null)))); - } - - @Override public void onItemClick(int position, View v, Gist item) { - SchemeParser.launchUri(v.getContext(), !InputHelper.isEmpty(item.getHtmlUrl()) ? item.getHtmlUrl() : item.getUrl()); - } - - @Override public void onItemLongClick(int position, View v, Gist item) { - if (getView() != null) { - getView().onDeletePinnedGist(item.getId(), position); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssueFragment.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssueFragment.java deleted file mode 100644 index 2120c35e8..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssueFragment.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.fastaccess.ui.modules.pinned.issue; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PinnedIssues; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.adapter.IssuesAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 25 Mar 2017, 8:04 PM - */ - -public class PinnedIssueFragment extends BaseFragment implements PinnedIssueMvp.View { - - public static final String TAG = PinnedIssueFragment.class.getSimpleName(); - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private IssuesAdapter adapter; - - public static PinnedIssueFragment newInstance() { - return new PinnedIssueFragment(); - } - - @Override public void onNotifyAdapter(@Nullable List items) { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - if (items != null) adapter.insertItems(items); - else adapter.clear(); - } - - @Override public void onDeletePinnedIssue(long id, int position) { - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), - Bundler.start().put(BundleConstant.YES_NO_EXTRA, true) - .put(BundleConstant.EXTRA, position) - .put(BundleConstant.ID, id) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - adapter = new IssuesAdapter(getPresenter().getPinnedIssue(), true, true, true); - adapter.setListener(getPresenter()); - stateLayout.setEmptyText(R.string.no_issues); - recycler.setEmptyView(stateLayout, refresh); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - refresh.setOnRefreshListener(() -> getPresenter().onReload()); - stateLayout.setOnReloadListener(v -> getPresenter().onReload()); - if (savedInstanceState == null) { - stateLayout.showProgress(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public PinnedIssuePresenter providePresenter() { - return new PinnedIssuePresenter(); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (bundle != null && isOk) { - long id = bundle.getLong(BundleConstant.ID); - int position = bundle.getInt(BundleConstant.EXTRA); - PinnedIssues.delete(id); - adapter.removeItem(position); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssueMvp.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssueMvp.java deleted file mode 100644 index dd0dadd4d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssueMvp.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.ui.modules.pinned.issue; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 25 Mar 2017, 7:57 PM - */ - -public interface PinnedIssueMvp { - - interface View extends BaseMvp.FAView { - void onNotifyAdapter(@Nullable List items); - - void onDeletePinnedIssue(long id, int position); - } - - interface Presenter extends BaseViewHolder.OnItemClickListener { - @NonNull ArrayList getPinnedIssue(); - - void onReload(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssuePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssuePresenter.java deleted file mode 100644 index d2f2d1b31..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/issue/PinnedIssuePresenter.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.fastaccess.ui.modules.pinned.issue; - -import android.support.annotation.NonNull; -import android.view.View; - -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PinnedIssues; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 25 Mar 2017, 8:00 PM - */ - -public class PinnedIssuePresenter extends BasePresenter implements PinnedIssueMvp.Presenter { - private ArrayList issues = new ArrayList<>(); - - @Override protected void onAttachView(@NonNull PinnedIssueMvp.View view) { - super.onAttachView(view); - if (issues.isEmpty()) { - onReload(); - } - } - - @NonNull @Override public ArrayList getPinnedIssue() { - return issues; - } - - @Override public void onReload() { - manageDisposable(PinnedIssues.getMyPinnedIssues() - .subscribe(repos -> sendToView(view -> view.onNotifyAdapter(repos)), throwable -> - sendToView(view -> view.onNotifyAdapter(null)))); - } - - @Override public void onItemClick(int position, View v, Issue item) { - SchemeParser.launchUri(v.getContext(), !InputHelper.isEmpty(item.getHtmlUrl()) ? item.getHtmlUrl() : item.getUrl()); - } - - @Override public void onItemLongClick(int position, View v, Issue item) { - if (getView() != null) { - getView().onDeletePinnedIssue(item.getId(), position); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestFragment.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestFragment.java deleted file mode 100644 index 6ad0593cc..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestFragment.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.fastaccess.ui.modules.pinned.pullrequest; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.PinnedPullRequests; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.adapter.PullRequestAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 25 Mar 2017, 8:04 PM - */ - -public class PinnedPullRequestFragment extends BaseFragment implements PinnedPullRequestMvp - .View { - - public static final String TAG = PinnedPullRequestFragment.class.getSimpleName(); - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private PullRequestAdapter adapter; - - public static PinnedPullRequestFragment newInstance() { - return new PinnedPullRequestFragment(); - } - - @Override public void onNotifyAdapter(@Nullable List items) { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - if (items != null) adapter.insertItems(items); - else adapter.clear(); - } - - @Override public void onDeletePinnedPullRequest(long id, int position) { - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), - Bundler.start().put(BundleConstant.YES_NO_EXTRA, true) - .put(BundleConstant.EXTRA, position) - .put(BundleConstant.ID, id) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - adapter = new PullRequestAdapter(getPresenter().getPinnedPullRequest(), true, true); - adapter.setListener(getPresenter()); - stateLayout.setEmptyText(getString((R.string.no_pull_requests))); - recycler.setEmptyView(stateLayout, refresh); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - refresh.setOnRefreshListener(() -> getPresenter().onReload()); - stateLayout.setOnReloadListener(v -> getPresenter().onReload()); - if (savedInstanceState == null) { - stateLayout.showProgress(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public PinnedPullRequestPresenter providePresenter() { - return new PinnedPullRequestPresenter(); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (bundle != null && isOk) { - long id = bundle.getLong(BundleConstant.ID); - int position = bundle.getInt(BundleConstant.EXTRA); - PinnedPullRequests.delete(id); - adapter.removeItem(position); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestMvp.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestMvp.java deleted file mode 100644 index 380275f15..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestMvp.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.ui.modules.pinned.pullrequest; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 25 Mar 2017, 7:57 PM - */ - -public interface PinnedPullRequestMvp { - - interface View extends BaseMvp.FAView { - void onNotifyAdapter(@Nullable List items); - - void onDeletePinnedPullRequest(long id, int position); - } - - interface Presenter extends BaseViewHolder.OnItemClickListener { - @NonNull ArrayList getPinnedPullRequest(); - - void onReload(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestPresenter.java deleted file mode 100644 index df8687b9d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/pullrequest/PinnedPullRequestPresenter.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.fastaccess.ui.modules.pinned.pullrequest; - -import android.support.annotation.NonNull; -import android.view.View; - -import com.fastaccess.data.dao.model.PinnedPullRequests; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 25 Mar 2017, 8:00 PM - */ - -public class PinnedPullRequestPresenter extends BasePresenter implements PinnedPullRequestMvp.Presenter { - private ArrayList pullRequests = new ArrayList<>(); - - @Override protected void onAttachView(@NonNull PinnedPullRequestMvp.View view) { - super.onAttachView(view); - if (pullRequests.isEmpty()) { - onReload(); - } - } - - @NonNull @Override public ArrayList getPinnedPullRequest() { - return pullRequests; - } - - @Override public void onReload() { - manageDisposable(PinnedPullRequests.getMyPinnedPullRequests() - .subscribe(repos -> sendToView(view -> view.onNotifyAdapter(repos)), throwable -> - sendToView(view -> view.onNotifyAdapter(null)))); - } - - @Override public void onItemClick(int position, View v, PullRequest item) { - SchemeParser.launchUri(v.getContext(), !InputHelper.isEmpty(item.getHtmlUrl()) ? item.getHtmlUrl() : item.getUrl()); - } - - @Override public void onItemLongClick(int position, View v, PullRequest item) { - if (getView() != null) { - getView().onDeletePinnedPullRequest(item.getId(), position); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposFragment.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposFragment.java deleted file mode 100644 index 7de7aa9f6..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposFragment.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.fastaccess.ui.modules.pinned.repo; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.AbstractPinnedRepos; -import com.fastaccess.data.dao.model.PinnedRepos; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.adapter.PinnedReposAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 25 Mar 2017, 8:04 PM - */ - -public class PinnedReposFragment extends BaseFragment implements PinnedReposMvp.View { - - public static final String TAG = PinnedReposFragment.class.getSimpleName(); - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private PinnedReposAdapter adapter; - - public static PinnedReposFragment newInstance() { - return new PinnedReposFragment(); - } - - @Override public void onNotifyAdapter(@Nullable List items) { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - if (items != null) adapter.insertItems(items); - else adapter.clear(); - } - - @Override public void onDeletePinnedRepo(long id, int position) { - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), - Bundler.start().put(BundleConstant.YES_NO_EXTRA, true) - .put(BundleConstant.EXTRA, position) - .put(BundleConstant.ID, id) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - adapter = new PinnedReposAdapter(getPresenter().getPinnedRepos(), getPresenter()); - stateLayout.setEmptyText(R.string.empty_pinned_repos); - recycler.setEmptyView(stateLayout, refresh); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - refresh.setOnRefreshListener(() -> getPresenter().onReload()); - stateLayout.setOnReloadListener(v -> getPresenter().onReload()); - if (savedInstanceState == null) { - stateLayout.showProgress(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public PinnedReposPresenter providePresenter() { - return new PinnedReposPresenter(); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (bundle != null && isOk) { - long id = bundle.getLong(BundleConstant.ID); - int position = bundle.getInt(BundleConstant.EXTRA); - AbstractPinnedRepos.delete(id); - adapter.removeItem(position); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposMvp.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposMvp.java deleted file mode 100644 index b0d1b9ea8..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposMvp.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.fastaccess.ui.modules.pinned.repo; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.PinnedRepos; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 25 Mar 2017, 7:57 PM - */ - -public interface PinnedReposMvp { - - interface View extends BaseMvp.FAView { - void onNotifyAdapter(@Nullable List items); - - void onDeletePinnedRepo(long id, int position); - } - - interface Presenter extends BaseViewHolder.OnItemClickListener { - @NonNull ArrayList getPinnedRepos(); - - void onReload(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposPresenter.java deleted file mode 100644 index a924cb253..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/pinned/repo/PinnedReposPresenter.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fastaccess.ui.modules.pinned.repo; - -import android.support.annotation.NonNull; -import android.view.View; - -import com.fastaccess.data.dao.model.AbstractPinnedRepos; -import com.fastaccess.data.dao.model.PinnedRepos; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 25 Mar 2017, 8:00 PM - */ - -public class PinnedReposPresenter extends BasePresenter implements PinnedReposMvp.Presenter { - private ArrayList pinnedRepos = new ArrayList<>(); - - @Override protected void onAttachView(@NonNull PinnedReposMvp.View view) { - super.onAttachView(view); - if (pinnedRepos.isEmpty()) { - onReload(); - } - } - - @NonNull @Override public ArrayList getPinnedRepos() { - return pinnedRepos; - } - - @Override public void onReload() { - manageDisposable(AbstractPinnedRepos.getMyPinnedRepos() - .subscribe(repos -> sendToView(view -> view.onNotifyAdapter(repos)), throwable -> - sendToView(view -> view.onNotifyAdapter(null)))); - } - - @Override public void onItemClick(int position, View v, PinnedRepos item) { - SchemeParser.launchUri(v.getContext(), item.getPinnedRepo().getHtmlUrl()); - } - - @Override public void onItemLongClick(int position, View v, PinnedRepos item) { - if (getView() != null) { - if (item.getRepoFullName().equalsIgnoreCase("k0shk0sh/FastHub")) { - return; - } - getView().onDeletePinnedRepo(item.getId(), position); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerFragment.java deleted file mode 100644 index 435bcae5e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerFragment.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.fastaccess.ui.modules.profile; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.Logger; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.ViewPagerView; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 8:00 AM - */ - -public class ProfilePagerFragment extends BaseFragment implements ProfilePagerMvp.View { - - public static final String TAG = ProfilePagerFragment.class.getSimpleName(); - - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.pager) ViewPagerView pager; - - public static ProfilePagerFragment newInstance(@NonNull String login) { - ProfilePagerFragment profileView = new ProfilePagerFragment(); - profileView.setArguments(Bundler.start().put(BundleConstant.EXTRA, login).end()); - return profileView; - } - - @Override protected int fragmentLayout() { - return R.layout.tabbed_viewpager; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new RuntimeException("Bundle is null?"); - } - String login = getArguments().getString(BundleConstant.EXTRA); - if (login == null) { - throw new RuntimeException("user is null?"); - } - FragmentsPagerAdapter adapter = new FragmentsPagerAdapter(getChildFragmentManager(), - FragmentPagerAdapterModel.buildForProfile(getContext(), login)); - tabs.setTabGravity(TabLayout.GRAVITY_FILL); - tabs.setTabMode(TabLayout.MODE_SCROLLABLE); - pager.setAdapter(adapter); - tabs.setupWithViewPager(pager); - } - - @NonNull @Override public ProfilePagerPresenter providePresenter() { - return new ProfilePagerPresenter(); - } - - @Override public void onNavigateToFollowers() { - pager.setCurrentItem(4); - } - - @Override public void onNavigateToFollowing() { - pager.setCurrentItem(5); - } - - @Override public void onCheckType(boolean isOrg) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerMvp.java deleted file mode 100644 index cb9032cef..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerMvp.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.ui.modules.profile; - -import com.fastaccess.ui.base.mvp.BaseMvp; - -/** - * Created by Kosh on 03 Dec 2016, 7:59 AM - */ - -public interface ProfilePagerMvp { - - interface View extends BaseMvp.FAView { - void onNavigateToFollowers(); - - void onNavigateToFollowing(); - - void onCheckType(boolean isOrg); - - } - - interface Presenter extends BaseMvp.FAPresenter {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerPresenter.java deleted file mode 100644 index 0710cbcee..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/ProfilePagerPresenter.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.ui.modules.profile; - -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by Kosh on 03 Dec 2016, 8:00 AM - */ - -class ProfilePagerPresenter extends BasePresenter implements ProfilePagerMvp.Presenter {} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersFragment.java deleted file mode 100644 index 2080cdc8c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersFragment.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.fastaccess.ui.modules.profile.followers; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.UsersAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class ProfileFollowersFragment extends BaseFragment implements ProfileFollowersMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private UsersAdapter adapter; - - public static ProfileFollowersFragment newInstance(@NonNull String username) { - ProfileFollowersFragment view = new ProfileFollowersFragment(); - view.setArguments(Bundler.start().put(BundleConstant.EXTRA, username).end()); - return view; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, username is required"); - } - stateLayout.setEmptyText(R.string.no_followers); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - adapter = new UsersAdapter(getPresenter().getFollowers()); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addKeyLineDivider(); - if (getPresenter().getFollowers().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public ProfileFollowersPresenter providePresenter() { - return new ProfileFollowersPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), getArguments().getString(BundleConstant.EXTRA)); - } - return onLoadMore; - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getArguments().getString(BundleConstant.EXTRA)); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersMvp.java deleted file mode 100644 index 24625ec8e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersMvp.java +++ /dev/null @@ -1,36 +0,0 @@ - -package com.fastaccess.ui.modules.profile.followers; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface ProfileFollowersMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getFollowers(); - - void onWorkOffline(@NonNull String login); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersPresenter.java deleted file mode 100644 index a9dfbd4cd..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/followers/ProfileFollowersPresenter.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.fastaccess.ui.modules.profile.followers; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class ProfileFollowersPresenter extends BasePresenter implements ProfileFollowersMvp.Presenter { - - private ArrayList users = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - sendToView(view -> { - if (view.getLoadMore().getParameter() != null) { - onWorkOffline(view.getLoadMore().getParameter()); - } - }); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (parameter == null) { - throw new NullPointerException("Username is null"); - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(ProfileFollowersMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getUserService(isEnterprise()).getFollowers(parameter, page), - response -> { - lastPage = response.getLast(); - if (getCurrentPage() == 1) { - manageDisposable(User.saveUserFollowerList(response.getItems(), parameter)); - } - sendToView(view -> view.onNotifyAdapter(response.getItems(), page)); - }); - return true; - } - - @NonNull @Override public ArrayList getFollowers() { - return users; - } - - @Override public void onWorkOffline(@NonNull String login) { - if (users.isEmpty()) { - manageDisposable(RxHelper.getSingle(User.getUserFollowerList(login)).subscribe(userModels -> - sendToView(view -> view.onNotifyAdapter(userModels, 1)))); - } else { - sendToView(ProfileFollowersMvp.View::hideProgress); - } - } - - @Override public void onItemClick(int position, View v, User item) {} - - @Override public void onItemLongClick(int position, View v, User item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingFragment.java deleted file mode 100644 index 3da3b821f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingFragment.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.fastaccess.ui.modules.profile.following; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.UsersAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class ProfileFollowingFragment extends BaseFragment implements ProfileFollowingMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private UsersAdapter adapter; - - public static ProfileFollowingFragment newInstance(@NonNull String username) { - ProfileFollowingFragment view = new ProfileFollowingFragment(); - view.setArguments(Bundler.start().put(BundleConstant.EXTRA, username).end()); - return view; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, username is required"); - } - stateLayout.setEmptyText(R.string.no_followings); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - adapter = new UsersAdapter(getPresenter().getFollowing()); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addKeyLineDivider(); - if (getPresenter().getFollowing().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public ProfileFollowingPresenter providePresenter() { - return new ProfileFollowingPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), getArguments().getString(BundleConstant.EXTRA)); - } - return onLoadMore; - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getArguments().getString(BundleConstant.EXTRA)); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingMvp.java deleted file mode 100644 index c21fa6945..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingMvp.java +++ /dev/null @@ -1,36 +0,0 @@ - -package com.fastaccess.ui.modules.profile.following; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface ProfileFollowingMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getFollowing(); - - void onWorkOffline(@NonNull String login); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingPresenter.java deleted file mode 100644 index 8f75fd1de..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/following/ProfileFollowingPresenter.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.fastaccess.ui.modules.profile.following; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class ProfileFollowingPresenter extends BasePresenter implements ProfileFollowingMvp.Presenter { - - private ArrayList users = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - sendToView(view -> {//wait view - if (view.getLoadMore().getParameter() != null) { - onWorkOffline(view.getLoadMore().getParameter()); - } - }); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (parameter == null) { - throw new NullPointerException("Username is null"); - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(ProfileFollowingMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getUserService(isEnterprise()).getFollowing(parameter, page), - response -> { - lastPage = response.getLast(); - if (getCurrentPage() == 1) { - manageDisposable(User.saveUserFollowingList(response.getItems(), parameter)); - } - sendToView(view -> view.onNotifyAdapter(response.getItems(), page)); - }); - return true; - } - - @NonNull @Override public ArrayList getFollowing() { - return users; - } - - @Override public void onWorkOffline(@NonNull String login) { - if (users.isEmpty()) { - manageDisposable(RxHelper.getSingle(User.getUserFollowingList(login)).subscribe(userModels -> - sendToView(view -> view.onNotifyAdapter(userModels, 1)))); - } else { - sendToView(ProfileFollowingMvp.View::hideProgress); - } - } - - @Override public void onItemClick(int position, View v, User item) {} - - @Override public void onItemLongClick(int position, View v, User item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsFragment.java deleted file mode 100644 index ab3e18d64..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsFragment.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.fastaccess.ui.modules.profile.gists; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.GistsAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.gists.gist.GistActivity; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -public class ProfileGistsFragment extends BaseFragment implements ProfileGistsMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - - private GistsAdapter adapter; - private OnLoadMore onLoadMore; - - public static ProfileGistsFragment newInstance(@NonNull String login) { - ProfileGistsFragment view = new ProfileGistsFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.IS_ENTERPRISE, Login.getUser().getLogin().equalsIgnoreCase(login)) - .end()); - return view; - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments().getString(BundleConstant.EXTRA) == null) { - throw new NullPointerException("Username is null"); - } - stateLayout.setEmptyText(R.string.no_gists); - refresh.setOnRefreshListener(this); - stateLayout.setOnReloadListener(this); - recycler.setEmptyView(stateLayout, refresh); - adapter = new GistsAdapter(getPresenter().getGists(), true); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addDivider(); - if (getPresenter().getGists().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getArguments().getString(BundleConstant.EXTRA)); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public ProfileGistsPresenter providePresenter() { - return new ProfileGistsPresenter(); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), getArguments().getString(BundleConstant.EXTRA)); - } - return onLoadMore; - } - - @Override public void onStartGistView(@NonNull String gistId) { - startActivityForResult(GistActivity.createIntent(getContext(), gistId, isEnterprise()), BundleConstant.REQUEST_CODE); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK && requestCode == BundleConstant.REQUEST_CODE) { - if (data != null && data.getExtras() != null) { - Gist gistsModel = data.getExtras().getParcelable(BundleConstant.ITEM); - if (gistsModel != null && adapter != null) { - adapter.removeItem(gistsModel); - } - } else { - onRefresh(); - } - } - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsMvp.java deleted file mode 100644 index b8a958f27..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsMvp.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.fastaccess.ui.modules.profile.gists; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 11 Nov 2016, 12:35 PM - */ - -interface ProfileGistsMvp { - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onStartGistView(@NonNull String gistId); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getGists(); - - void onWorkOffline(@NonNull String login); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsPresenter.java deleted file mode 100644 index 44fda497f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/gists/ProfileGistsPresenter.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.fastaccess.ui.modules.profile.gists; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.annimon.stream.Stream; -import com.fastaccess.data.dao.model.Gist; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -class ProfileGistsPresenter extends BasePresenter implements ProfileGistsMvp.Presenter { - private ArrayList gistsModels = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - sendToView(view -> { - if (view.getLoadMore().getParameter() != null) { - onWorkOffline(view.getLoadMore().getParameter()); - } - }); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (parameter == null) { - throw new NullPointerException("Username is null"); - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(ProfileGistsMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getGistService(isEnterprise()).getUserGists(parameter, page), - listResponse -> { - lastPage = listResponse.getLast(); - sendToView(view -> view.onNotifyAdapter(listResponse.getItems(), page)); - manageDisposable(Gist.save(Stream.of(listResponse.getItems()).toList(), parameter)); - }); - return true; - } - - @NonNull @Override public ArrayList getGists() { - return gistsModels; - } - - @Override public void onWorkOffline(@NonNull String login) { - if (gistsModels.isEmpty()) { - manageDisposable(RxHelper.getObservable(Gist.getMyGists(login).toObservable()).subscribe(gistsModels1 -> - sendToView(view -> view.onNotifyAdapter(gistsModels1, 1)))); - } else { - sendToView(ProfileGistsMvp.View::hideProgress); - } - } - - @Override public void onItemClick(int position, View v, Gist item) { - SchemeParser.launchUri(v.getContext(), item.getHtmlUrl()); - } - - @Override public void onItemLongClick(int position, View v, Gist item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewFragment.java deleted file mode 100644 index 75b9ce333..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewFragment.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.fastaccess.ui.modules.profile.org; - -import android.annotation.SuppressLint; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.transition.TransitionManager; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.provider.emoji.EmojiParser; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.profile.org.project.OrgProjectActivity; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; - -import butterknife.BindView; -import butterknife.OnClick; - -import static android.view.View.GONE; - -/** - * Created by Kosh on 04 Apr 2017, 10:47 AM - */ - -public class OrgProfileOverviewFragment extends BaseFragment - implements OrgProfileOverviewMvp.View { - - @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.username) FontTextView username; - @BindView(R.id.description) FontTextView description; - @BindView(R.id.location) FontTextView location; - @BindView(R.id.email) FontTextView email; - @BindView(R.id.link) FontTextView link; - @BindView(R.id.joined) FontTextView joined; - @BindView(R.id.progress) LinearLayout progress; - @BindView(R.id.projects) View projects; - - @State User userModel; - - public static OrgProfileOverviewFragment newInstance(@NonNull String login) { - OrgProfileOverviewFragment view = new OrgProfileOverviewFragment(); - view.setArguments(Bundler.start().put(BundleConstant.EXTRA, login).end()); - return view; - } - - @OnClick(R.id.userInformation) void onOpenAvatar() { - if (userModel != null) ActivityHelper.startCustomTab(getActivity(), userModel.getAvatarUrl()); - } - - @OnClick(R.id.projects) void onOpenProjects() { - OrgProjectActivity.Companion.startActivity(getContext(), getPresenter().getLogin(), isEnterprise()); - } - - @SuppressLint("ClickableViewAccessibility") @Override public void onInitViews(@Nullable User userModel) { - if (getView() != null) { - TransitionManager.beginDelayedTransition((ViewGroup) getView()); - } - if (this.userModel != null) return; - progress.setVisibility(View.GONE); - if (userModel == null) return; - this.userModel = userModel; - username.setText(InputHelper.isEmpty(userModel.getName()) ? userModel.getLogin() : userModel.getName()); - if (userModel.getDescription() != null) { - description.setText(EmojiParser.parseToUnicode(userModel.getDescription())); - description.setVisibility(View.VISIBLE); - } else { - description.setVisibility(GONE); - } - avatarLayout.setUrl(userModel.getAvatarUrl(), null, false, false); - avatarLayout.findViewById(R.id.avatar).setOnTouchListener((v, event) -> { - if (event.getAction() == MotionEvent.ACTION_UP) { - ActivityHelper.startCustomTab(getActivity(), userModel.getAvatarUrl()); - return true; - } - return false; - }); - location.setText(userModel.getLocation()); - email.setText(userModel.getEmail()); - link.setText(userModel.getBlog()); - joined.setText(ParseDateFormat.getTimeAgo(userModel.getCreatedAt())); - - if (!InputHelper.isEmpty(userModel.getLocation())) { - location.setVisibility(View.VISIBLE); - } - if (!InputHelper.isEmpty(userModel.getEmail())) { - email.setVisibility(View.VISIBLE); - } - if (!InputHelper.isEmpty(userModel.getBlog())) { - link.setVisibility(View.VISIBLE); - } - if (!InputHelper.isEmpty(userModel.getCreatedAt())) { - joined.setVisibility(View.VISIBLE); - } - if (!InputHelper.isEmpty(userModel.getEmail())) { - email.setVisibility(View.VISIBLE); - } - projects.setVisibility(userModel.isHasOrganizationProjects() ? View.VISIBLE : View.GONE); - } - - @Override protected int fragmentLayout() { - return R.layout.org_profile_overview_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments()); - } else { - if (userModel != null) { - onInitViews(userModel); - } else { - getPresenter().onFragmentCreated(getArguments()); - } - } - } - - @NonNull @Override public OrgProfileOverviewPresenter providePresenter() { - return new OrgProfileOverviewPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - progress.setVisibility(View.VISIBLE); - } - - @Override public void hideProgress() { - progress.setVisibility(View.GONE); - } - - @Override public void showErrorMessage(@NonNull String message) { - onHideProgress(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - onHideProgress(); - super.showMessage(titleRes, msgRes); - } - - private void onHideProgress() { - hideProgress(); - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewMvp.java deleted file mode 100644 index fa661a15f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewMvp.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.fastaccess.ui.modules.profile.org; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.ui.base.mvp.BaseMvp; - -/** - * Created by Kosh on 03 Dec 2016, 7:59 AM - */ - -public interface OrgProfileOverviewMvp { - - interface View extends BaseMvp.FAView { - void onInitViews(@Nullable User userModel); - } - - interface Presenter extends BaseMvp.FAPresenter { - void onFragmentCreated(@Nullable Bundle bundle); - - void onWorkOffline(@NonNull String login); - - @NonNull String getLogin(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewPresenter.java deleted file mode 100644 index 6b3fb1cfb..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/OrgProfileOverviewPresenter.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fastaccess.ui.modules.profile.org; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by Kosh on 04 Apr 2017, 10:36 AM - */ - -public class OrgProfileOverviewPresenter extends BasePresenter implements OrgProfileOverviewMvp.Presenter { - @com.evernote.android.state.State String login; - - @Override public void onError(@NonNull Throwable throwable) { - if (!InputHelper.isEmpty(login)) { - onWorkOffline(login); - } - super.onError(throwable); - } - - @Override public void onFragmentCreated(@Nullable Bundle bundle) { - if (bundle == null || bundle.getString(BundleConstant.EXTRA) == null) { - throw new NullPointerException("Either bundle or User is null"); - } - login = bundle.getString(BundleConstant.EXTRA); - if (login != null) { - makeRestCall(RestProvider.getOrgService(isEnterprise()).getOrganization(login), - this::onSendUserToView); - } - } - - @Override public void onWorkOffline(@NonNull String login) { - onSendUserToView(User.getUser(login)); - } - - @NonNull @Override public String getLogin() { - return login; - } - - private void onSendUserToView(User userModel) { - sendToView(view -> view.onInitViews(userModel)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersFragment.java deleted file mode 100644 index 027b040f7..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersFragment.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.members; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.UsersAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class OrgMembersFragment extends BaseFragment implements OrgMembersMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private UsersAdapter adapter; - - public static OrgMembersFragment newInstance(@NonNull String username) { - OrgMembersFragment view = new OrgMembersFragment(); - view.setArguments(Bundler.start().put(BundleConstant.EXTRA, username).end()); - return view; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, username is required"); - } - stateLayout.setEmptyText(R.string.no_members); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - adapter = new UsersAdapter(getPresenter().getFollowers()); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addKeyLineDivider(); - if (getPresenter().getFollowers().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public OrgMembersPresenter providePresenter() { - return new OrgMembersPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), getArguments().getString(BundleConstant.EXTRA)); - } - return onLoadMore; - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getArguments().getString(BundleConstant.EXTRA)); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersMvp.java deleted file mode 100644 index 74d030180..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersMvp.java +++ /dev/null @@ -1,36 +0,0 @@ - -package com.fastaccess.ui.modules.profile.org.members; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface OrgMembersMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getFollowers(); - - void onWorkOffline(@NonNull String login); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersPresenter.java deleted file mode 100644 index c771193ce..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/members/OrgMembersPresenter.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.members; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class OrgMembersPresenter extends BasePresenter implements OrgMembersMvp.Presenter { - - private ArrayList users = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (parameter == null) { - throw new NullPointerException("Username is null"); - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(OrgMembersMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getOrgService(isEnterprise()).getOrgMembers(parameter, page), - response -> { - lastPage = response.getLast(); - sendToView(view -> view.onNotifyAdapter(response.getItems(), page)); - }); - return true; - } - - @NonNull @Override public ArrayList getFollowers() { - return users; - } - - @Override public void onWorkOffline(@NonNull String login) { - //TODO - } - - @Override public void onItemClick(int position, View v, User item) {} - - @Override public void onItemLongClick(int position, View v, User item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/project/OrgProjectActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/profile/org/project/OrgProjectActivity.kt deleted file mode 100644 index cd8e9a966..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/project/OrgProjectActivity.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.project - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.support.design.widget.AppBarLayout -import butterknife.BindView -import com.evernote.android.state.State -import com.fastaccess.R -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.repos.projects.RepoProjectsFragmentPager - -/** - * Created by Hashemsergani on 24.09.17. - */ - -class OrgProjectActivity : BaseActivity>() { - - @State var org: String? = null - - @BindView(R.id.appbar) lateinit var appBar: AppBarLayout - - override fun layout(): Int = R.layout.activity_fragment_layout - - override fun isTransparent(): Boolean = true - - override fun canBack(): Boolean = true - - override fun isSecured(): Boolean = false - - override fun providePresenter(): BasePresenter = BasePresenter() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - appBar.elevation = 0f - appBar.stateListAnimator = null - if (savedInstanceState == null) { - org = intent.extras.getString(BundleConstant.ITEM) - val org = org - if (org != null) { - supportFragmentManager.beginTransaction() - .replace(R.id.container, RepoProjectsFragmentPager.newInstance(org), - RepoProjectsFragmentPager.TAG) - .commit() - } - } - toolbar?.apply { subtitle = org } - } - - companion object { - fun startActivity(context: Context, org: String, isEnterprise: Boolean) { - val intent = Intent(context, OrgProjectActivity::class.java) - intent.putExtras(Bundler.start().put(BundleConstant.ITEM, org) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()) - context.startActivity(intent) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposFragment.java deleted file mode 100644 index e00f438a3..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposFragment.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.repos; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.ReposAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.profile.repos.ProfileReposFilterBottomSheetDialog; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class OrgReposFragment extends BaseFragment implements OrgReposMvp.View, - ProfileReposFilterBottomSheetDialog.ProfileReposFilterChangeListener { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private ReposAdapter adapter; - - public static OrgReposFragment newInstance(@NonNull String username) { - OrgReposFragment view = new OrgReposFragment(); - view.setArguments(Bundler.start().put(BundleConstant.EXTRA, username).end()); - return view; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, username is required"); - } - stateLayout.setEmptyText(R.string.no_repos); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - adapter = new ReposAdapter(getPresenter().getRepos(), false); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addDivider(); - if (getPresenter().getRepos().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public OrgReposPresenter providePresenter() { - return new OrgReposPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter()); - } - onLoadMore.setParameter(getArguments().getString(BundleConstant.EXTRA)); - return onLoadMore; - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getArguments().getString(BundleConstant.EXTRA)); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - @Override public void onRepoFilterClicked() { - ProfileReposFilterBottomSheetDialog.newInstance(getPresenter().getFilterOptions()) - .show(getChildFragmentManager(), "ProfileReposFilterBottomSheetDialog"); - } - - @Override public void onFilterApply() { - getPresenter().onFilterApply(getArguments().getString(BundleConstant.EXTRA)); - } - - @Override public void onTypeSelected(String selectedType) { - getPresenter().onTypeSelected(selectedType); - } - - @Override public void onSortOptionSelected(String selectedSortOption) { - //Not supported for org profile - } - - @Override public void onSortDirectionSelected(String selectedSortDirection) { - //Not supported for org profile - } - - @Override - public String getLogin() { - return getArguments().getString(BundleConstant.EXTRA); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposMvp.java deleted file mode 100644 index e37c09033..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposMvp.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.repos; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -public interface OrgReposMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - void onRepoFilterClicked(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getRepos(); - - void onWorkOffline(@NonNull String login); - void onFilterApply(String org); - void onTypeSelected(String selectedType); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposPresenter.java deleted file mode 100644 index ce79f4c22..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/repos/OrgReposPresenter.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.repos; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.FilterOptionsModel; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class OrgReposPresenter extends BasePresenter implements OrgReposMvp.Presenter { - - private ArrayList repos = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - @com.evernote.android.state.State FilterOptionsModel filterOptions = new FilterOptionsModel(); - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - sendToView(view -> { - if (view.getLoadMore().getParameter() != null) { - onWorkOffline(view.getLoadMore().getParameter()); - } - }); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (parameter == null) { - throw new NullPointerException("Username is null"); - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(OrgReposMvp.View::hideProgress); - return false; - } - filterOptions.setOrg(true); - makeRestCall(RestProvider.getOrgService(isEnterprise()).getOrgRepos(parameter, filterOptions.getQueryMap(), page), - repoModelPageable -> { - lastPage = repoModelPageable.getLast(); - if (getCurrentPage() == 1) { - manageDisposable(Repo.saveMyRepos(repoModelPageable.getItems(), parameter)); - } - sendToView(view -> view.onNotifyAdapter(repoModelPageable.getItems(), page)); - }); - return true; - } - - @NonNull @Override public ArrayList getRepos() { - return repos; - } - - @Override public void onWorkOffline(@NonNull String login) { - if (repos.isEmpty()) { - manageDisposable(RxHelper.getObservable(Repo.getMyRepos(login).toObservable()).subscribe(repoModels -> - sendToView(view -> view.onNotifyAdapter(repoModels, 1)))); - } else { - sendToView(OrgReposMvp.View::hideProgress); - } - } - - @Override public void onFilterApply(String org) { - onCallApi(1, org); - } - - @Override public void onTypeSelected(String selectedType) { - filterOptions.setType(selectedType); - } - - @Override public void onItemClick(int position, View v, Repo item) { - SchemeParser.launchUri(v.getContext(), item.getHtmlUrl()); - } - - @Override public void onItemLongClick(int position, View v, Repo item) {} - - @NonNull FilterOptionsModel getFilterOptions() { - return filterOptions; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamFragment.java deleted file mode 100644 index e42019b99..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamFragment.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.teams; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.TeamsModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.TeamsAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class OrgTeamFragment extends BaseFragment implements OrgTeamMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private TeamsAdapter adapter; - - public static OrgTeamFragment newInstance(@NonNull String username) { - OrgTeamFragment view = new OrgTeamFragment(); - view.setArguments(Bundler.start().put(BundleConstant.EXTRA, username).end()); - return view; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, username is required"); - } - stateLayout.setEmptyText(R.string.no_teams); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - adapter = new TeamsAdapter(getPresenter().getTeams()); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addKeyLineDivider(); - if (getPresenter().getTeams().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public OrgTeamPresenter providePresenter() { - return new OrgTeamPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), getArguments().getString(BundleConstant.EXTRA)); - } - return onLoadMore; - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getArguments().getString(BundleConstant.EXTRA)); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamMvp.java deleted file mode 100644 index 642cb2d57..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamMvp.java +++ /dev/null @@ -1,36 +0,0 @@ - -package com.fastaccess.ui.modules.profile.org.teams; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.TeamsModel; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface OrgTeamMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getTeams(); - - void onWorkOffline(@NonNull String login); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamPresenter.java deleted file mode 100644 index decd37e4b..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/OrgTeamPresenter.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.teams; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.TeamsModel; -import com.fastaccess.helper.Logger; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.profile.org.teams.details.TeamPagerActivity; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class OrgTeamPresenter extends BasePresenter implements OrgTeamMvp.Presenter { - - private ArrayList users = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (parameter == null) { - throw new NullPointerException("Username is null"); - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(OrgTeamMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getOrgService(isEnterprise()).getOrgTeams(parameter, page), - response -> { - lastPage = response.getLast(); - sendToView(view -> view.onNotifyAdapter(response.getItems(), page)); - }); - return true; - } - - @NonNull @Override public ArrayList getTeams() { - return users; - } - - @Override public void onWorkOffline(@NonNull String login) { - //TODO - } - - @Override public void onItemClick(int position, View v, TeamsModel item) { - Logger.e(item.getUrl()); - TeamPagerActivity.startActivity(v.getContext(), item.getId(), item.getName()); - } - - @Override public void onItemLongClick(int position, View v, TeamsModel item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/TeamPagerActivity.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/TeamPagerActivity.java deleted file mode 100644 index cde1dfdd4..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/TeamPagerActivity.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.teams.details; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; - -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.widgets.ViewPagerView; - -import net.grandcentrix.thirtyinch.TiPresenter; - -import butterknife.BindView; -import com.evernote.android.state.State; - -/** - * Created by Kosh on 03 Apr 2017, 10:08 PM - */ - -public class TeamPagerActivity extends BaseActivity { - - @State long id; - @State String name; - - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.tabbedPager) ViewPagerView pager; - - public static void startActivity(@NonNull Context context, long id, @NonNull String name) { - Intent intent = new Intent(context, TeamPagerActivity.class); - intent.putExtras(Bundler - .start() - .put(BundleConstant.ID, id) - .put(BundleConstant.EXTRA, name) - .end()); - context.startActivity(intent); - } - - @Override protected int layout() { - return R.layout.tabbed_pager_layout; - } - - @Override protected boolean isTransparent() { - return false; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } - - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState == null) { - id = getIntent().getExtras().getLong(BundleConstant.ID); - name = getIntent().getExtras().getString(BundleConstant.EXTRA); - } - setTitle(name); - if (id <= 0) { - finish(); - return; - } - FragmentsPagerAdapter adapter = new FragmentsPagerAdapter(getSupportFragmentManager(), - FragmentPagerAdapterModel.buildForTeam(this, id)); - pager.setAdapter(adapter); - tabs.setTabGravity(TabLayout.GRAVITY_FILL); - tabs.setTabMode(TabLayout.MODE_FIXED); - tabs.setupWithViewPager(pager); - tabs.setPaddingRelative(0, 0, 0, 0); - tabs.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager) { - @Override public void onTabReselected(TabLayout.Tab tab) { - super.onTabReselected(tab); - onScrollTop(tab.getPosition()); - } - }); - } - - @Override public void onScrollTop(int index) { - if (pager == null || pager.getAdapter() == null) return; - Fragment fragment = (BaseFragment) pager.getAdapter().instantiateItem(pager, index); - if (fragment instanceof BaseFragment) { - ((BaseFragment) fragment).onScrollTop(index); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersFragment.java deleted file mode 100644 index 007ebf3df..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersFragment.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.teams.details.members; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.UsersAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class TeamMembersFragment extends BaseFragment implements TeamMembersMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private UsersAdapter adapter; - - public static TeamMembersFragment newInstance(@NonNull Long id) { - TeamMembersFragment view = new TeamMembersFragment(); - view.setArguments(Bundler.start().put(BundleConstant.EXTRA, id).end()); - return view; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, username is required"); - } - stateLayout.setEmptyText(R.string.no_members); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - adapter = new UsersAdapter(getPresenter().getFollowers()); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addKeyLineDivider(); - if (getPresenter().getFollowers().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public TeamMembersPresenter providePresenter() { - return new TeamMembersPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), getArguments().getLong(BundleConstant.EXTRA)); - } - return onLoadMore; - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getArguments().getLong(BundleConstant.EXTRA)); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersMvp.java deleted file mode 100644 index c31eb2223..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersMvp.java +++ /dev/null @@ -1,36 +0,0 @@ - -package com.fastaccess.ui.modules.profile.org.teams.details.members; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface TeamMembersMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getFollowers(); - - void onWorkOffline(@NonNull String login); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersPresenter.java deleted file mode 100644 index d4f653c28..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/members/TeamMembersPresenter.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.teams.details.members; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class TeamMembersPresenter extends BasePresenter implements TeamMembersMvp.Presenter { - - private ArrayList users = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable Long parameter) { - if (parameter == null) { - throw new NullPointerException("Username is null"); - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(TeamMembersMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getOrgService(isEnterprise()).getTeamMembers(parameter, page), - response -> { - lastPage = response.getLast(); - sendToView(view -> view.onNotifyAdapter(response.getItems(), page)); - }); - return true; - } - - @NonNull @Override public ArrayList getFollowers() { - return users; - } - - @Override public void onWorkOffline(@NonNull String login) { - //TODO - } - - @Override public void onItemClick(int position, View v, User item) {} - - @Override public void onItemLongClick(int position, View v, User item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposFragment.java deleted file mode 100644 index 61d340e34..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposFragment.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.teams.details.repos; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.ReposAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class TeamReposFragment extends BaseFragment implements TeamReposMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private ReposAdapter adapter; - - public static TeamReposFragment newInstance(long id) { - TeamReposFragment view = new TeamReposFragment(); - view.setArguments(Bundler.start().put(BundleConstant.EXTRA, id).end()); - return view; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, username is required"); - } - stateLayout.setEmptyText(R.string.no_repos); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - adapter = new ReposAdapter(getPresenter().getRepos(), false); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addDivider(); - if (getPresenter().getRepos().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public TeamReposPresenter providePresenter() { - return new TeamReposPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), getArguments().getLong(BundleConstant.EXTRA)); - } - return onLoadMore; - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getArguments().getLong(BundleConstant.EXTRA)); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposMvp.java deleted file mode 100644 index 531dfca4f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposMvp.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.teams.details.repos; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface TeamReposMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getRepos(); - - void onWorkOffline(@NonNull String login); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposPresenter.java deleted file mode 100644 index a66392177..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/org/teams/details/repos/TeamReposPresenter.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.fastaccess.ui.modules.profile.org.teams.details.repos; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class TeamReposPresenter extends BasePresenter implements TeamReposMvp.Presenter { - private ArrayList repos = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable Long parameter) { - if (parameter == null) { - throw new NullPointerException("Username is null"); - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(TeamReposMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getOrgService(isEnterprise()).getTeamRepos(parameter, page), - repoModelPageable -> { - lastPage = repoModelPageable.getLast(); - sendToView(view -> view.onNotifyAdapter(repoModelPageable.getItems(), page)); - }); - return true; - } - - @NonNull @Override public ArrayList getRepos() { - return repos; - } - - @Override public void onWorkOffline(@NonNull String login) { - //TODO - } - - @Override public void onItemClick(int position, View v, Repo item) { - SchemeParser.launchUri(v.getContext(), item.getHtmlUrl()); - } - - @Override public void onItemLongClick(int position, View v, Repo item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewFragment.java deleted file mode 100644 index 4c0969574..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewFragment.java +++ /dev/null @@ -1,319 +0,0 @@ -package com.fastaccess.ui.modules.profile.overview; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.transition.AutoTransition; -import android.support.transition.Transition; -import android.support.transition.TransitionManager; -import android.support.v4.widget.NestedScrollView; -import android.support.v7.widget.CardView; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.LinearLayout; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.provider.emoji.EmojiParser; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.adapter.ProfileOrgsAdapter; -import com.fastaccess.ui.adapter.ProfilePinnedReposAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.profile.ProfilePagerMvp; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontButton; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.contributions.GitHubContributionsView; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.layout_manager.GridManager; - -import java.util.List; - -import butterknife.BindView; -import butterknife.OnClick; -import github.GetPinnedReposQuery; - -import static android.view.View.GONE; -import static android.view.View.VISIBLE; - -/** - * Created by Kosh on 03 Dec 2016, 9:16 AM - */ - -public class ProfileOverviewFragment extends BaseFragment implements ProfileOverviewMvp.View { - - @BindView(R.id.contributionsCaption) FontTextView contributionsCaption; - @BindView(R.id.organizationsCaption) FontTextView organizationsCaption; - @BindView(R.id.userInformation) LinearLayout userInformation; - @BindView(R.id.username) FontTextView username; - @BindView(R.id.fullname) FontTextView fullname; - @BindView(R.id.description) FontTextView description; - @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.organization) FontTextView organization; - @BindView(R.id.location) FontTextView location; - @BindView(R.id.email) FontTextView email; - @BindView(R.id.link) FontTextView link; - @BindView(R.id.joined) FontTextView joined; - @BindView(R.id.following) FontButton following; - @BindView(R.id.followers) FontButton followers; - @BindView(R.id.progress) View progress; - @BindView(R.id.followBtn) Button followBtn; - @BindView(R.id.orgsList) DynamicRecyclerView orgsList; - @BindView(R.id.orgsCard) CardView orgsCard; - @BindView(R.id.parentView) NestedScrollView parentView; - @BindView(R.id.contributionView) GitHubContributionsView contributionView; - @BindView(R.id.contributionCard) CardView contributionCard; - @BindView(R.id.pinnedReposTextView) FontTextView pinnedReposTextView; - @BindView(R.id.pinnedList) DynamicRecyclerView pinnedList; - @BindView(R.id.pinnedReposCard) CardView pinnedReposCard; - @State User userModel; - private ProfilePagerMvp.View profileCallback; - - public static ProfileOverviewFragment newInstance(@NonNull String login) { - ProfileOverviewFragment view = new ProfileOverviewFragment(); - view.setArguments(Bundler.start().put(BundleConstant.EXTRA, login).end()); - return view; - } - - @OnClick({R.id.following, R.id.followers, R.id.followBtn}) void onClick(View view) { - if (view.getId() == R.id.followers) { - profileCallback.onNavigateToFollowers(); - } else if (view.getId() == R.id.following) { - profileCallback.onNavigateToFollowing(); - } else if (view.getId() == R.id.followBtn) { - getPresenter().onFollowButtonClicked(getPresenter().getLogin()); - followBtn.setEnabled(false); - } - } - - @OnClick(R.id.userInformation) void onOpenAvatar() { - if (userModel != null) ActivityHelper.startCustomTab(getActivity(), userModel.getAvatarUrl()); - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof ProfilePagerMvp.View) { - profileCallback = (ProfilePagerMvp.View) getParentFragment(); - } else { - profileCallback = (ProfilePagerMvp.View) context; - } - } - - @Override public void onDetach() { - profileCallback = null; - super.onDetach(); - } - - @Override protected int fragmentLayout() { - return R.layout.profile_overview_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - onInitOrgs(getPresenter().getOrgs()); - onInitPinnedRepos(getPresenter().getNodes()); - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments()); - } else { - if (userModel != null) { - invalidateFollowBtn(); - onInitViews(userModel); - } else { - getPresenter().onFragmentCreated(getArguments()); - } - } - if (isMeOrOrganization()) { - followBtn.setVisibility(GONE); - } - } - - @NonNull @Override public ProfileOverviewPresenter providePresenter() { - return new ProfileOverviewPresenter(); - } - - @SuppressLint("ClickableViewAccessibility") @Override public void onInitViews(@Nullable User userModel) { - progress.setVisibility(GONE); - if (userModel == null) return; - if (profileCallback != null) profileCallback.onCheckType(userModel.isOrganizationType()); - if (getView() != null) { - if (this.userModel == null) { - TransitionManager.beginDelayedTransition((ViewGroup) getView(), - new AutoTransition().addListener(new Transition.TransitionListener() { - - @Override public void onTransitionStart(@NonNull Transition transition) { - - } - - @Override public void onTransitionEnd(@NonNull Transition transition) { - if (contributionView != null) getPresenter().onLoadContributionWidget(contributionView); - } - - @Override public void onTransitionCancel(@NonNull Transition transition) { - - } - - @Override public void onTransitionPause(@NonNull Transition transition) { - - } - - @Override public void onTransitionResume(@NonNull Transition transition) { - - } - })); - } else { - getPresenter().onLoadContributionWidget(contributionView); - } - } - this.userModel = userModel; - followBtn.setVisibility(!isMeOrOrganization() ? VISIBLE : GONE); - username.setText(userModel.getLogin()); - fullname.setText(userModel.getName()); - if (userModel.getBio() != null) { - description.setText(EmojiParser.parseToUnicode(userModel.getBio())); - } else { - description.setVisibility(GONE); - } - avatarLayout.setUrl(userModel.getAvatarUrl(), null, false, false, true); - avatarLayout.findViewById(R.id.avatar).setOnTouchListener((v, event) -> { - if (event.getAction() == MotionEvent.ACTION_UP) { - ActivityHelper.startCustomTab(getActivity(), userModel.getAvatarUrl()); - return true; - } - return false; - }); - organization.setText(userModel.getCompany()); - location.setText(userModel.getLocation()); - email.setText(userModel.getEmail()); - link.setText(userModel.getBlog()); - joined.setText(ParseDateFormat.getTimeAgo(userModel.getCreatedAt())); - if (InputHelper.isEmpty(userModel.getCompany())) { - organization.setVisibility(GONE); - } - if (InputHelper.isEmpty(userModel.getLocation())) { - location.setVisibility(GONE); - } - if (InputHelper.isEmpty(userModel.getEmail())) { - email.setVisibility(GONE); - } - if (InputHelper.isEmpty(userModel.getBlog())) { - link.setVisibility(GONE); - } - if (InputHelper.isEmpty(userModel.getCreatedAt())) { - joined.setVisibility(GONE); - } - followers.setText(SpannableBuilder.builder() - .append(getString(R.string.followers)) - .append(" (") - .bold(String.valueOf(userModel.getFollowers())) - .append(")")); - following.setText(SpannableBuilder.builder() - .append(getString(R.string.following)) - .append(" (") - .bold(String.valueOf(userModel.getFollowing())) - .append(")")); - } - - @Override public void invalidateFollowBtn() { - hideProgress(); - if (isMeOrOrganization()) return; - if (getPresenter().isSuccessResponse()) { - followBtn.setEnabled(true); - followBtn.setActivated(getPresenter().isFollowing()); - followBtn.setText(getPresenter().isFollowing() ? getString(R.string.unfollow) : getString(R.string.follow)); - } - } - - @Override public void onInitContributions(boolean show) { - if (contributionView == null) return; - if (show) { - contributionView.onResponse(); - } - contributionCard.setVisibility(show ? VISIBLE : GONE); - contributionsCaption.setVisibility(show ? VISIBLE : GONE); - } - - @Override public void onInitOrgs(@Nullable List orgs) { - if (orgs != null && !orgs.isEmpty()) { - orgsList.setNestedScrollingEnabled(false); - ProfileOrgsAdapter adapter = new ProfileOrgsAdapter(); - adapter.addItems(orgs); - orgsList.setAdapter(adapter); - orgsCard.setVisibility(VISIBLE); - organizationsCaption.setVisibility(VISIBLE); - ((GridManager) orgsList.getLayoutManager()).setIconSize(getResources().getDimensionPixelSize(R.dimen.header_icon_zie) + getResources() - .getDimensionPixelSize(R.dimen.spacing_xs_large)); - } else { - organizationsCaption.setVisibility(GONE); - orgsCard.setVisibility(GONE); - } - } - - @Override public void onUserNotFound() { - showMessage(R.string.error, R.string.no_user_found); - } - - @Override public void onInitPinnedRepos(@NonNull List nodes) { - if (pinnedReposTextView == null) return; - if (!nodes.isEmpty()) { - pinnedReposTextView.setVisibility(VISIBLE); - pinnedReposCard.setVisibility(VISIBLE); - ProfilePinnedReposAdapter adapter = new ProfilePinnedReposAdapter(nodes); - adapter.setListener(new BaseViewHolder.OnItemClickListener() { - @Override public void onItemClick(int position, View v, GetPinnedReposQuery.Node item) { - SchemeParser.launchUri(getContext(), item.url().toString()); - } - - @Override public void onItemLongClick(int position, View v, GetPinnedReposQuery.Node item) {} - }); - pinnedList.addDivider(); - pinnedList.setAdapter(adapter); - } else { - pinnedReposTextView.setVisibility(GONE); - pinnedReposCard.setVisibility(GONE); - } - } - - @Override public void showProgress(@StringRes int resId) { - progress.setVisibility(VISIBLE); - } - - @Override public void hideProgress() { - progress.setVisibility(GONE); - } - - @Override public void showErrorMessage(@NonNull String message) { - onHideProgress(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - onHideProgress(); - super.showMessage(titleRes, msgRes); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - } - - private void onHideProgress() { - hideProgress(); - } - - private boolean isMeOrOrganization() { - return Login.getUser() != null && Login.getUser().getLogin().equalsIgnoreCase(getPresenter().getLogin()) || - (userModel != null && userModel.getType() != null && !userModel.getType().equalsIgnoreCase("user")); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewMvp.java deleted file mode 100644 index 24016538a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewMvp.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.fastaccess.ui.modules.profile.overview; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.contributions.ContributionsDay; -import com.fastaccess.ui.widgets.contributions.GitHubContributionsView; - -import java.util.ArrayList; -import java.util.List; - -import github.GetPinnedReposQuery; - -/** - * Created by Kosh on 03 Dec 2016, 9:15 AM - */ - -public interface ProfileOverviewMvp { - - interface View extends BaseMvp.FAView { - void onInitViews(@Nullable User userModel); - - void invalidateFollowBtn(); - - void onInitContributions(boolean show); - - void onInitOrgs(@Nullable List orgs); - - void onUserNotFound(); - - void onInitPinnedRepos(@NonNull List nodes); - } - - interface Presenter extends BaseMvp.FAPresenter { - - void onFragmentCreated(@Nullable Bundle bundle); - - void onWorkOffline(@NonNull String login); - - void onCheckFollowStatus(@NonNull String login); - - boolean isSuccessResponse(); - - boolean isFollowing(); - - void onFollowButtonClicked(@NonNull String login); - - void onSendUserToView(@Nullable User userModel); - - void onLoadContributionWidget(@NonNull GitHubContributionsView view); - - @NonNull ArrayList getOrgs(); - - @NonNull ArrayList getContributions(); - - @NonNull ArrayList getNodes(); - - @NonNull String getLogin(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewPresenter.java deleted file mode 100644 index 55f91001a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/overview/ProfileOverviewPresenter.java +++ /dev/null @@ -1,197 +0,0 @@ -package com.fastaccess.ui.modules.profile.overview; - -import android.graphics.Bitmap; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; - -import com.apollographql.apollo.ApolloCall; -import com.apollographql.apollo.rx2.Rx2Apollo; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.ApolloProdivder; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.widgets.contributions.ContributionsDay; -import com.fastaccess.ui.widgets.contributions.ContributionsProvider; -import com.fastaccess.ui.widgets.contributions.GitHubContributionsView; - -import java.util.ArrayList; -import java.util.List; - -import github.GetPinnedReposQuery; -import io.reactivex.Observable; - -/** - * Created by Kosh on 03 Dec 2016, 9:16 AM - */ - -class ProfileOverviewPresenter extends BasePresenter implements ProfileOverviewMvp.Presenter { - @com.evernote.android.state.State boolean isSuccessResponse; - @com.evernote.android.state.State boolean isFollowing; - @com.evernote.android.state.State String login; - private ArrayList userOrgs = new ArrayList<>(); - private ArrayList nodes = new ArrayList<>(); - private ArrayList contributions = new ArrayList<>(); - private static final String URL = "https://github.com/users/%s/contributions"; - - @Override public void onCheckFollowStatus(@NonNull String login) { - if (!TextUtils.equals(login, Login.getUser().getLogin())) { - manageDisposable(RxHelper.getObservable(RestProvider.getUserService(isEnterprise()).getFollowStatus(login)) - .subscribe(booleanResponse -> { - isSuccessResponse = true; - isFollowing = booleanResponse.code() == 204; - sendToView(ProfileOverviewMvp.View::invalidateFollowBtn); - }, Throwable::printStackTrace)); - } - } - - @Override public boolean isSuccessResponse() { - return isSuccessResponse; - } - - @Override public boolean isFollowing() { - return isFollowing; - } - - @Override public void onFollowButtonClicked(@NonNull String login) { - manageDisposable(RxHelper.getObservable(!isFollowing ? RestProvider.getUserService(isEnterprise()).followUser(login) - : RestProvider.getUserService(isEnterprise()).unfollowUser(login)) - .subscribe(booleanResponse -> { - if (booleanResponse.code() == 204) { - isFollowing = !isFollowing; - sendToView(ProfileOverviewMvp.View::invalidateFollowBtn); - } - }, this::onError)); - } - - @Override public void onError(@NonNull Throwable throwable) { - int statusCode = RestProvider.getErrorCode(throwable); - if (statusCode == 404) { - sendToView(ProfileOverviewMvp.View::onUserNotFound); - return; - } - if (!InputHelper.isEmpty(login)) { - onWorkOffline(login); - } - sendToView(ProfileOverviewMvp.View::invalidateFollowBtn); - super.onError(throwable); - } - - @Override public void onFragmentCreated(@Nullable Bundle bundle) { - if (bundle == null || bundle.getString(BundleConstant.EXTRA) == null) { - throw new NullPointerException("Either bundle or User is null"); - } - login = bundle.getString(BundleConstant.EXTRA); - if (login != null) { - makeRestCall(RestProvider.getUserService(isEnterprise()) - .getUser(login) - .doOnComplete(() -> { - loadPinnedRepos(login); - loadOrgs(); - }), userModel -> { - onSendUserToView(userModel); - if (userModel != null) { - userModel.save(userModel); - if (userModel.getType() != null && userModel.getType().equalsIgnoreCase("user")) { - onCheckFollowStatus(login); - } - } - }); - } - } - - @SuppressWarnings("ConstantConditions") private void loadPinnedRepos(@NonNull String login) { - ApolloCall apolloCall = ApolloProdivder.INSTANCE.getApollo(isEnterprise()) - .query(GetPinnedReposQuery.builder() - .login(login) - .build()); - manageDisposable(RxHelper.getObservable(Rx2Apollo.from(apolloCall)) - .filter(dataResponse -> !dataResponse.hasErrors()) - .flatMap(dataResponse -> { - if (dataResponse.data() != null && dataResponse.data().user() != null) { - return Observable.fromIterable(dataResponse.data().user().pinnedRepositories().edges()); - } - return Observable.empty(); - }) - .map(GetPinnedReposQuery.Edge::node) - .toList() - .toObservable() - .subscribe(nodes1 -> { - nodes.clear(); - nodes.addAll(nodes1); - sendToView(view -> view.onInitPinnedRepos(nodes)); - }, Throwable::printStackTrace)); - } - - @Override public void onWorkOffline(@NonNull String login) { - User userModel = User.getUser(login); - if (userModel == null) { - return; - } - onSendUserToView(userModel); - } - - @Override public void onSendUserToView(@Nullable User userModel) { - sendToView(view -> view.onInitViews(userModel)); - } - - @Override public void onLoadContributionWidget(@NonNull GitHubContributionsView gitHubContributionsView) { - if (!isEnterprise()) { - if (contributions == null || contributions.isEmpty()) { - String url = String.format(URL, login); - manageDisposable(RxHelper.getObservable(RestProvider.getContribution().getContributions(url)) - .flatMap(s -> Observable.just(new ContributionsProvider().getContributions(s))) - .subscribe(lists -> { - contributions.clear(); - contributions.addAll(lists); - loadContributions(contributions, gitHubContributionsView); - }, Throwable::printStackTrace)); - } else { - loadContributions(contributions, gitHubContributionsView); - } - } - } - - @NonNull @Override public ArrayList getOrgs() { - return userOrgs; - } - - @NonNull @Override public ArrayList getContributions() { - return contributions; - } - - @NonNull @Override public ArrayList getNodes() { - return nodes; - } - - @NonNull @Override public String getLogin() { - return login; - } - - private void loadContributions(ArrayList contributions, GitHubContributionsView gitHubContributionsView) { - List filter = gitHubContributionsView.getLastContributions(contributions); - if (filter != null && contributions != null) { - Observable bitmapObservable = Observable.just(gitHubContributionsView.drawOnCanvas(filter, contributions)); - manageObservable(bitmapObservable - .doOnNext(bitmap -> sendToView(view -> view.onInitContributions(bitmap != null)))); - } - } - - private void loadOrgs() { - boolean isMe = login.equalsIgnoreCase(Login.getUser() != null ? Login.getUser().getLogin() : ""); - manageDisposable(RxHelper.getObservable(isMe ? RestProvider.getOrgService(isEnterprise()).getMyOrganizations() - : RestProvider.getOrgService(isEnterprise()).getMyOrganizations(login)) - .subscribe(response -> { - if (response != null && response.getItems() != null) { - userOrgs.addAll(response.getItems()); - } - sendToView(view -> view.onInitOrgs(userOrgs)); - }, Throwable::printStackTrace)); - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposFilterBottomSheetDialog.java b/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposFilterBottomSheetDialog.java deleted file mode 100644 index f040bc6d0..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposFilterBottomSheetDialog.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.fastaccess.ui.modules.profile.repos; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.ArrayAdapter; -import android.widget.LinearLayout; -import android.widget.Spinner; - -import com.fastaccess.R; -import com.fastaccess.data.dao.FilterOptionsModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.base.BaseBottomSheetDialog; -import com.fastaccess.ui.modules.profile.org.repos.OrgReposFragment; -import com.fastaccess.ui.modules.profile.org.repos.OrgReposMvp; -import com.fastaccess.ui.modules.search.SearchUserActivity; - -import butterknife.BindView; -import butterknife.OnClick; - -public class ProfileReposFilterBottomSheetDialog extends BaseBottomSheetDialog { - - @BindView(R.id.type_selection) Spinner typeSelectionSpinner; - @BindView(R.id.sort_selection) Spinner sortSelectionSpinner; - @BindView(R.id.filter_sheet_apply_btn) View applyBtn; - @BindView(R.id.sort_direction_selection) Spinner sortDirectionSpinner; - @BindView(R.id.sort_layout) LinearLayout sortLayout; - @BindView(R.id.sort_direction_layout) LinearLayout sortDirectionlayout; - private FilterOptionsModel currentFilterOptions; - - private ProfileReposFilterChangeListener listener; - - public static ProfileReposFilterBottomSheetDialog newInstance(@NonNull FilterOptionsModel currentFilterOptions) { - ProfileReposFilterBottomSheetDialog fragment = new ProfileReposFilterBottomSheetDialog(); - fragment.setArguments(Bundler.start().put(BundleConstant.ITEM, currentFilterOptions).end()); - return fragment; - } - - @Override protected int layoutRes() { - return R.layout.filter_bottom_sheet; - } - - @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - currentFilterOptions = getArguments().getParcelable(BundleConstant.ITEM); - if (currentFilterOptions == null) return; - ArrayAdapter typesAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, - currentFilterOptions.getTypesList()); - ArrayAdapter sortOptionsAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, - currentFilterOptions.getSortOptionList()); - ArrayAdapter sortDirectionAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, - currentFilterOptions.getSortDirectionList()); - typeSelectionSpinner.setAdapter(typesAdapter); - sortSelectionSpinner.setAdapter(sortOptionsAdapter); - sortDirectionSpinner.setAdapter(sortDirectionAdapter); - typeSelectionSpinner.setSelection(currentFilterOptions.getSelectedTypeIndex()); - sortSelectionSpinner.setSelection(currentFilterOptions.getSelectedSortOptionIndex()); - sortDirectionSpinner.setSelection(currentFilterOptions.getSelectedSortDirectionIndex()); - if (currentFilterOptions.isOrg()) { - sortLayout.setVisibility(View.GONE); - sortDirectionlayout.setVisibility(View.GONE); - } - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof OrgReposMvp.View || getParentFragment() instanceof OrgReposMvp.View) { - listener = ((OrgReposFragment) getParentFragment()); - } else { - listener = ((ProfileReposFragment) getParentFragment()); - } - } - - @Override public void onDetach() { - super.onDetach(); - listener = null; - } - - @OnClick(R.id.filter_sheet_apply_btn) public void onApply() { - if (listener != null) { - listener.onTypeSelected((String) typeSelectionSpinner.getSelectedItem()); - listener.onSortOptionSelected((String) sortSelectionSpinner.getSelectedItem()); - listener.onSortDirectionSelected((String) sortDirectionSpinner.getSelectedItem()); - listener.onFilterApply(); - dismiss(); - } - } - - @OnClick(R.id.filter_sheet_reset_btn) public void onReset() { - typeSelectionSpinner.setSelection(0); - sortDirectionSpinner.setSelection(0); - sortSelectionSpinner.setSelection(0); - } - - @OnClick(R.id.filter_sheet_search_btn) public void startSearch() { - if (listener != null) { - Intent intent = SearchUserActivity.Companion.getIntent(getContext(), listener.getLogin(), ""); - startActivity(intent); - } - dismiss(); - } - - public interface ProfileReposFilterChangeListener { - void onFilterApply(); - - void onTypeSelected(String selectedType); - - void onSortOptionSelected(String selectedSortOption); - - void onSortDirectionSelected(String selectedSortDirection); - - String getLogin(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposFragment.java deleted file mode 100644 index 8c3a99686..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposFragment.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.fastaccess.ui.modules.profile.repos; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.ReposAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class ProfileReposFragment extends BaseFragment implements ProfileReposMvp.View, - ProfileReposFilterBottomSheetDialog.ProfileReposFilterChangeListener { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private ReposAdapter adapter; - - public static ProfileReposFragment newInstance(@NonNull String username) { - ProfileReposFragment view = new ProfileReposFragment(); - view.setArguments(Bundler.start().put(BundleConstant.EXTRA, username).end()); - return view; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, username is required"); - } - stateLayout.setEmptyText(R.string.no_repos); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - adapter = new ReposAdapter(getPresenter().getRepos(), false); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addDivider(); - if (getPresenter().getRepos().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public ProfileReposPresenter providePresenter() { - return new ProfileReposPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), getArguments().getString(BundleConstant.EXTRA)); - } - return onLoadMore; - } - - @Override public void onRepoFilterClicked() { - ProfileReposFilterBottomSheetDialog.newInstance(getPresenter().getFilterOptions()) - .show(getChildFragmentManager(), "ProfileReposFilterBottomSheetDialog"); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getArguments().getString(BundleConstant.EXTRA)); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } - - @Override - public void onFilterApply() { - getPresenter().onFilterApply(); - } - - @Override - public void onTypeSelected(String selectedType) { - getPresenter().onTypeSelected(selectedType); - } - - @Override - public void onSortOptionSelected(String selectedSortOption) { - getPresenter().onSortOptionSelected(selectedSortOption); - } - - @Override - public void onSortDirectionSelected(String selectedSortDirection) { - getPresenter().onSortDirectionSelected(selectedSortDirection); - } - - @Override - public String getLogin() { - return getArguments().getString(BundleConstant.EXTRA); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposMvp.java deleted file mode 100644 index d94bf2787..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposMvp.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.fastaccess.ui.modules.profile.repos; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface ProfileReposMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onRepoFilterClicked(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getRepos(); - - void onWorkOffline(@NonNull String login); - void onFilterApply(); - void onTypeSelected(String selectedType); - void onSortOptionSelected(String selectedSortOption); - void onSortDirectionSelected(String selectedSortDirection); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposPresenter.java deleted file mode 100644 index 3581cde1a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/repos/ProfileReposPresenter.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.fastaccess.ui.modules.profile.repos; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import android.view.View; - -import com.fastaccess.data.dao.FilterOptionsModel; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class ProfileReposPresenter extends BasePresenter implements ProfileReposMvp.Presenter { - - private ArrayList repos = new ArrayList<>(); - private int page; - private int previousTotal; - private String username; - private int lastPage = Integer.MAX_VALUE; - private String currentLoggedIn; - private FilterOptionsModel filterOptions = new FilterOptionsModel(); - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - sendToView(view -> { - if (view.getLoadMore().getParameter() != null) { - onWorkOffline(view.getLoadMore().getParameter()); - } - }); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (currentLoggedIn == null) { - currentLoggedIn = Login.getUser().getLogin(); - } - if (parameter == null) { - throw new NullPointerException("Username is null"); - } - username = parameter; - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(ProfileReposMvp.View::hideProgress); - return false; - } - boolean isProfile = TextUtils.equals(currentLoggedIn, username); - filterOptions.setIsPersonalProfile(isProfile); - makeRestCall(isProfile - ? RestProvider.getUserService(isEnterprise()).getRepos(filterOptions.getQueryMap(), page) - : RestProvider.getUserService(isEnterprise()).getRepos(parameter, filterOptions.getQueryMap(), page), - repoModelPageable -> { - lastPage = repoModelPageable.getLast(); - if (getCurrentPage() == 1) { - manageDisposable(Repo.saveMyRepos(repoModelPageable.getItems(), parameter)); - } - sendToView(view -> view.onNotifyAdapter(repoModelPageable.getItems(), page)); - }); - return true; - } - - @NonNull @Override public ArrayList getRepos() { - return repos; - } - - @Override public void onWorkOffline(@NonNull String login) { - if (repos.isEmpty()) { - manageDisposable(RxHelper.getObservable(Repo.getMyRepos(login).toObservable()).subscribe(repoModels -> - sendToView(view -> view.onNotifyAdapter(repoModels, 1)))); - } else { - sendToView(ProfileReposMvp.View::hideProgress); - } - } - - @Override public void onItemClick(int position, View v, Repo item) { - SchemeParser.launchUri(v.getContext(), item.getHtmlUrl()); - } - - @Override public void onItemLongClick(int position, View v, Repo item) {} - - @Override public void onFilterApply() { - onCallApi(1, username); - } - - @Override public void onTypeSelected(String selectedType) { - filterOptions.setType(selectedType); - } - - @Override public void onSortOptionSelected(String selectedSortOption) { - filterOptions.setSort(selectedSortOption); - } - - @Override public void onSortDirectionSelected(String selectedSortDirection) { - filterOptions.setSortDirection(selectedSortDirection); - } - - FilterOptionsModel getFilterOptions() { - return filterOptions; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredFragment.java b/app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredFragment.java deleted file mode 100644 index 39a0541b1..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredFragment.java +++ /dev/null @@ -1,153 +0,0 @@ -package com.fastaccess.ui.modules.profile.starred; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.ReposAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class ProfileStarredFragment extends BaseFragment implements ProfileStarredMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private ReposAdapter adapter; - private RepoPagerMvp.TabsBadgeListener tabsBadgeListener; - - public static ProfileStarredFragment newInstance(@NonNull String username) { - ProfileStarredFragment view = new ProfileStarredFragment(); - view.setArguments(Bundler.start().put(BundleConstant.EXTRA, username).end()); - return view; - } - - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) getParentFragment(); - } else if (context instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) context; - } - } - - @Override public void onDetach() { - tabsBadgeListener = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, username is required"); - } - stateLayout.setEmptyText(R.string.no_starred_repos); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - adapter = new ReposAdapter(getPresenter().getRepos(), true); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addDivider(); - if (getPresenter().getRepos().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public ProfileStarredPresenter providePresenter() { - return new ProfileStarredPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), getArguments().getString(BundleConstant.EXTRA)); - } - return onLoadMore; - } - - @Override public void onUpdateCount(int starredCount) { - if (tabsBadgeListener != null) { - tabsBadgeListener.onSetBadge(3, starredCount); - } - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getArguments().getString(BundleConstant.EXTRA)); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredMvp.java b/app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredMvp.java deleted file mode 100644 index 939bd74a8..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredMvp.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.fastaccess.ui.modules.profile.starred; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface ProfileStarredMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onUpdateCount(int starredCount); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getRepos(); - - void onWorkOffline(@NonNull String login); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredPresenter.java deleted file mode 100644 index 182e710fd..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/profile/starred/ProfileStarredPresenter.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.fastaccess.ui.modules.profile.starred; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class ProfileStarredPresenter extends BasePresenter implements ProfileStarredMvp.Presenter { - - @com.evernote.android.state.State int starredCount = -1; - private ArrayList repos = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - sendToView(view -> { - if (view.getLoadMore().getParameter() != null) { - onWorkOffline(view.getLoadMore().getParameter()); - } - }); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (parameter == null) { - throw new NullPointerException("Username is null"); - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(ProfileStarredMvp.View::hideProgress); - return false; - } - Observable> observable; - if (starredCount == -1) { - observable = Observable.zip(RestProvider.getUserService(isEnterprise()).getStarred(parameter, page), - RestProvider.getUserService(isEnterprise()).getStarredCount(parameter), (repoPageable, count) -> { - if (count != null) { - starredCount = count.getLast(); - } - return repoPageable; - }); - } else { - observable = RestProvider.getUserService(isEnterprise()).getStarred(parameter, page); - } - makeRestCall(observable, repoModelPageable -> { - lastPage = repoModelPageable.getLast(); - if (getCurrentPage() == 1) { - manageDisposable(Repo.saveStarred(repoModelPageable.getItems(), parameter)); - } - sendToView(view -> { - view.onUpdateCount(starredCount); - view.onNotifyAdapter(repoModelPageable.getItems(), page); - }); - }); - return true; - } - - @NonNull @Override public ArrayList getRepos() { - return repos; - } - - @Override public void onWorkOffline(@NonNull String login) { - if (repos.isEmpty()) { - manageDisposable(RxHelper.getObservable(Repo.getStarred(login).toObservable()).subscribe(repoModels -> - sendToView(view -> { - starredCount = -1; - view.onUpdateCount(repoModels != null ? repoModels.size() : 0); - view.onNotifyAdapter(repoModels, 1); - }))); - } else { - sendToView(ProfileStarredMvp.View::hideProgress); - } - } - - @Override public void onItemClick(int position, View v, Repo item) { - SchemeParser.launchUri(v.getContext(), item.getHtmlUrl()); - } - - @Override public void onItemLongClick(int position, View v, Repo item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/DummyFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/DummyFragment.java deleted file mode 100644 index f9833711f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/DummyFragment.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.ui.modules.repos; - -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; - -/** - * Created by Kosh on 11 Mar 2017, 12:10 AM - */ - -public class DummyFragment extends Fragment { - - @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.single_container_layout, container, false); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerActivity.java b/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerActivity.java deleted file mode 100644 index af74edb05..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerActivity.java +++ /dev/null @@ -1,642 +0,0 @@ -package com.fastaccess.ui.modules.repos; - -import android.content.Context; -import android.content.Intent; -import android.content.res.ColorStateList; -import android.graphics.Color; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.FloatingActionButton; -import android.support.transition.TransitionManager; -import android.support.v4.widget.TextViewCompat; -import android.support.v7.widget.RecyclerView; -import android.text.format.Formatter; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.widget.CheckBox; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.LicenseModel; -import com.fastaccess.data.dao.NameParser; -import com.fastaccess.data.dao.model.AbstractPinnedRepos; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AnimHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.TypeFaceHelper; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.colors.ColorsProvider; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.provider.tasks.git.GithubActionService; -import com.fastaccess.ui.adapter.TopicsAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.modules.filter.issues.FilterIssuesActivity; -import com.fastaccess.ui.modules.main.MainActivity; -import com.fastaccess.ui.modules.repos.code.RepoCodePagerFragment; -import com.fastaccess.ui.modules.repos.extras.labels.LabelsDialogFragment; -import com.fastaccess.ui.modules.repos.extras.license.RepoLicenseBottomSheet; -import com.fastaccess.ui.modules.repos.extras.milestone.create.MilestoneDialogFragment; -import com.fastaccess.ui.modules.repos.extras.misc.RepoMiscDialogFragment; -import com.fastaccess.ui.modules.repos.extras.misc.RepoMiscMVp; -import com.fastaccess.ui.modules.repos.issues.RepoIssuesPagerFragment; -import com.fastaccess.ui.modules.repos.pull_requests.RepoPullRequestPagerFragment; -import com.fastaccess.ui.modules.repos.wiki.WikiActivity; -import com.fastaccess.ui.modules.user.UserPagerActivity; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; - -import java.text.NumberFormat; - -import butterknife.BindView; -import butterknife.OnCheckedChanged; -import butterknife.OnClick; -import butterknife.OnLongClick; -import it.sephiroth.android.library.bottomnavigation.BottomNavigation; - -/** - * Created by Kosh on 09 Dec 2016, 4:17 PM - */ - -public class RepoPagerActivity extends BaseActivity implements RepoPagerMvp.View { - - @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.headerTitle) FontTextView title; - @BindView(R.id.size) FontTextView size; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.forkRepo) FontTextView forkRepo; - @BindView(R.id.starRepo) FontTextView starRepo; - @BindView(R.id.watchRepo) FontTextView watchRepo; - @BindView(R.id.license) FontTextView license; - @BindView(R.id.bottomNavigation) BottomNavigation bottomNavigation; - @BindView(R.id.fab) FloatingActionButton fab; - @BindView(R.id.language) FontTextView language; - @BindView(R.id.detailsIcon) View detailsIcon; - @BindView(R.id.tagsIcon) View tagsIcon; - @BindView(R.id.watchRepoImage) ForegroundImageView watchRepoImage; - @BindView(R.id.starRepoImage) ForegroundImageView starRepoImage; - @BindView(R.id.forkRepoImage) ForegroundImageView forkRepoImage; - @BindView(R.id.licenseLayout) View licenseLayout; - @BindView(R.id.watchRepoLayout) View watchRepoLayout; - @BindView(R.id.starRepoLayout) View starRepoLayout; - @BindView(R.id.forkRepoLayout) View forkRepoLayout; - @BindView(R.id.pinImage) ForegroundImageView pinImage; - @BindView(R.id.pinLayout) View pinLayout; - @BindView(R.id.pinText) FontTextView pinText; - @BindView(R.id.filterLayout) View filterLayout; - @BindView(R.id.topicsList) RecyclerView topicsList; - @BindView(R.id.sortByUpdated) CheckBox sortByUpdated; - @BindView(R.id.wikiLayout) View wikiLayout; - @State @RepoPagerMvp.RepoNavigationType int navType; - @State String login; - @State String repoId; - @State int showWhich = -1; - - private NumberFormat numberFormat = NumberFormat.getNumberInstance(); - private boolean userInteracted; - private int accentColor; - private int iconColor; - - public static void startRepoPager(@NonNull Context context, @NonNull NameParser nameParser) { - if (!InputHelper.isEmpty(nameParser.getName()) && !InputHelper.isEmpty(nameParser.getUsername())) { - Intent intent = new Intent(context, RepoPagerActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.ID, nameParser.getName()) - .put(BundleConstant.EXTRA_TWO, nameParser.getUsername()) - .put(BundleConstant.EXTRA_TYPE, RepoPagerMvp.CODE) - .put(BundleConstant.IS_ENTERPRISE, nameParser.isEnterprise()) - .end()); - context.startActivity(intent); - } - } - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, @NonNull String login) { - return createIntent(context, repoId, login, RepoPagerMvp.CODE); - } - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, @NonNull String login, - @RepoPagerMvp.RepoNavigationType int navType) { - return createIntent(context, repoId, login, navType, -1); - } - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, @NonNull String login, - @RepoPagerMvp.RepoNavigationType int navType, int showWhat) { - Intent intent = new Intent(context, RepoPagerActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA_TWO, login) - .put(BundleConstant.EXTRA_TYPE, navType) - .put(BundleConstant.EXTRA_THREE, showWhat) - .end()); - return intent; - } - - @OnLongClick(R.id.date) boolean onShowDateHint() { - showMessage(R.string.creation_date, R.string.creation_date_hint); - return true; - } - - @OnLongClick(R.id.size) boolean onShowLastUpdateDateHint() { - showMessage(R.string.last_updated, R.string.last_updated_hint); - return true; - } - - @OnLongClick(R.id.fab) boolean onFabLongClick() { - if (navType == RepoPagerMvp.ISSUES) { - onAddSelected(); - return true; - } - return false; - } - - @OnClick(R.id.fab) void onFabClicked() { - if (navType == RepoPagerMvp.ISSUES) { - fab.hide(new FloatingActionButton.OnVisibilityChangedListener() { - @Override public void onHidden(FloatingActionButton fab) { - super.onHidden(fab); - if (appbar != null) appbar.setExpanded(false, true); - bottomNavigation.setExpanded(false, true); - AnimHelper.mimicFabVisibility(true, filterLayout, null); - } - }); - } else if (navType == RepoPagerMvp.PULL_REQUEST) { - RepoPullRequestPagerFragment pullRequestPagerView = (RepoPullRequestPagerFragment) AppHelper.getFragmentByTag(getSupportFragmentManager(), - RepoPullRequestPagerFragment.TAG); - if (pullRequestPagerView != null) { - FilterIssuesActivity.startActivity(this, getPresenter().login(), getPresenter().repoId(), false, - pullRequestPagerView.getCurrentItem() == 0, isEnterprise()); - } - } else { - fab.hide(); - } - } - - @OnClick(R.id.add) void onAddIssues() { - hideFilterLayout(); - onAddSelected(); - } - - @OnClick(R.id.search) void onSearch() { - hideFilterLayout(); - onSearchSelected(); - } - - @Override public boolean dispatchTouchEvent(MotionEvent ev) { - if (navType == RepoPagerMvp.ISSUES && filterLayout.isShown()) { - Rect viewRect = ViewHelper.getLayoutPosition(filterLayout); - if (!viewRect.contains((int) ev.getRawX(), (int) ev.getRawY())) { - hideFilterLayout(); - } - } - return super.dispatchTouchEvent(ev); - } - - @OnClick(R.id.detailsIcon) void onTitleClick() { - Repo repoModel = getPresenter().getRepo(); - if (repoModel != null && !InputHelper.isEmpty(repoModel.getDescription())) { - MessageDialogView.newInstance(repoModel.getFullName(), repoModel.getDescription(), false, true) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - } - } - - @OnClick(R.id.tagsIcon) void onTagsClick() { - if (topicsList.getAdapter().getItemCount() > 0) { - TransitionManager.beginDelayedTransition(topicsList); - topicsList.setVisibility(topicsList.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE); - } - } - - @OnClick({R.id.forkRepoLayout, R.id.starRepoLayout, R.id.watchRepoLayout, - R.id.pinLayout, R.id.wikiLayout, R.id.licenseLayout}) void onClick(View view) { - switch (view.getId()) { - case R.id.forkRepoLayout: - MessageDialogView.newInstance(getString(R.string.fork), String.format("%s %s/%s?", getString(R.string.fork), login, repoId), - Bundler.start().put(BundleConstant.EXTRA, true).put(BundleConstant.YES_NO_EXTRA, true).end()) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - break; - case R.id.starRepoLayout: - if (!InputHelper.isEmpty(getPresenter().login()) && !InputHelper.isEmpty(getPresenter().repoId())) { - GithubActionService.startForRepo(this, getPresenter().login(), getPresenter().repoId(), - getPresenter().isStarred() ? GithubActionService.UNSTAR_REPO : GithubActionService.STAR_REPO, isEnterprise()); - getPresenter().onStar(); - } - break; - case R.id.watchRepoLayout: - if (!InputHelper.isEmpty(getPresenter().login()) && !InputHelper.isEmpty(getPresenter().repoId())) { - GithubActionService.startForRepo(this, getPresenter().login(), getPresenter().repoId(), - getPresenter().isWatched() ? GithubActionService.UNWATCH_REPO : GithubActionService.WATCH_REPO, isEnterprise()); - getPresenter().onWatch(); - } - break; - case R.id.pinLayout: - pinLayout.setEnabled(false); - getPresenter().onPinUnpinRepo(); - break; - case R.id.wikiLayout: - ActivityHelper.startReveal(this, WikiActivity.Companion.getWiki(this, repoId, login), wikiLayout); - break; - case R.id.licenseLayout: - if (getPresenter().getRepo() != null) { - LicenseModel licenseModel = getPresenter().getRepo().getLicense(); - String license = !InputHelper.isEmpty(licenseModel.getSpdxId()) ? licenseModel.getSpdxId() : licenseModel.getName(); - RepoLicenseBottomSheet.Companion.newInstance(getPresenter().login(), getPresenter().repoId(), license) - .show(getSupportFragmentManager(), "RepoLicenseBottomSheet"); - } - break; - } - } - - @OnLongClick({R.id.forkRepoLayout, R.id.starRepoLayout, R.id.watchRepoLayout}) boolean onLongClick(View view) { - switch (view.getId()) { - case R.id.forkRepoLayout: - RepoMiscDialogFragment.show(getSupportFragmentManager(), login, repoId, RepoMiscMVp.FORKS); - return true; - case R.id.starRepoLayout: - RepoMiscDialogFragment.show(getSupportFragmentManager(), login, repoId, RepoMiscMVp.STARS); - return true; - case R.id.watchRepoLayout: - RepoMiscDialogFragment.show(getSupportFragmentManager(), login, repoId, RepoMiscMVp.WATCHERS); - return true; - } - return false; - } - - @OnCheckedChanged(R.id.sortByUpdated) void onSortIssues(boolean isChecked) { - RepoIssuesPagerFragment pagerView = (RepoIssuesPagerFragment) AppHelper.getFragmentByTag(getSupportFragmentManager(), - RepoIssuesPagerFragment.TAG); - if (pagerView != null) { - pagerView.onChangeIssueSort(isChecked); - } - hideFilterLayout(); - } - - @Override protected int layout() { - return R.layout.repo_pager_activity; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public RepoPagerPresenter providePresenter() { - return new RepoPagerPresenter(); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState == null) { - if (getIntent() == null || getIntent().getExtras() == null) { - finish(); - return; - } - final Bundle extras = getIntent().getExtras(); - repoId = extras.getString(BundleConstant.ID); - login = extras.getString(BundleConstant.EXTRA_TWO); - navType = extras.getInt(BundleConstant.EXTRA_TYPE); - showWhich = extras.getInt(BundleConstant.EXTRA_THREE); - getPresenter().onUpdatePinnedEntry(repoId, login); - } - getPresenter().onActivityCreate(repoId, login, navType); - setTitle(""); - accentColor = ViewHelper.getAccentColor(this); - iconColor = ViewHelper.getIconColor(this); - if (savedInstanceState == null) { - getSupportFragmentManager() - .beginTransaction() - .add(R.id.container, new DummyFragment(), "DummyFragment") - .commit(); - } - Typeface myTypeface = TypeFaceHelper.getTypeface(); - bottomNavigation.setDefaultTypeface(myTypeface); - fab.setImageTintList(ColorStateList.valueOf(Color.WHITE)); - showHideFab(); - } - - @Override public void onNavigationChanged(@RepoPagerMvp.RepoNavigationType int navType) { - if (navType == RepoPagerMvp.PROFILE) { - getPresenter().onModuleChanged(getSupportFragmentManager(), navType); - bottomNavigation.setSelectedIndex(this.navType, true); - return; - } - this.navType = navType; - //noinspection WrongConstant - try { - if (bottomNavigation.getSelectedIndex() != navType) bottomNavigation.setSelectedIndex(navType, true); - } catch (Exception ignored) {} - showHideFab(); - getPresenter().onModuleChanged(getSupportFragmentManager(), navType); - } - - @Override public void onFinishActivity() { - //do nothing here, github might return 404 if even the repo don't have anything but issues. - } - - @Override public void onInitRepo() { - hideProgress(); - if (getPresenter().getRepo() == null) { - return; - } - switch (showWhich) { - case 1: - onLongClick(watchRepoLayout); - break; - case 2: - onLongClick(starRepoLayout); - break; - case 3: - onLongClick(forkRepoLayout); - break; - case 4: - MilestoneDialogFragment.newInstance(login, repoId) - .show(getSupportFragmentManager(), "MilestoneDialogFragment"); - break; - case 5: - LabelsDialogFragment.newInstance(null, repoId, login) - .show(getSupportFragmentManager(), "LabelsDialogFragment"); - break; - } - showWhich = -1; - setTaskName(getPresenter().getRepo().getFullName()); - Repo repoModel = getPresenter().getRepo(); - if (repoModel.isHasProjects()) { - bottomNavigation.inflateMenu(R.menu.repo_with_project_bottom_nav_menu); - } - bottomNavigation.setOnMenuItemClickListener(getPresenter()); - if (repoModel.getTopics() != null && !repoModel.getTopics().isEmpty()) { - tagsIcon.setVisibility(View.VISIBLE); - topicsList.setAdapter(new TopicsAdapter(repoModel.getTopics())); - } else { - topicsList.setVisibility(View.GONE); - } - onRepoPinned(AbstractPinnedRepos.isPinned(repoModel.getFullName())); - wikiLayout.setVisibility(repoModel.isHasWiki() ? View.VISIBLE : View.GONE); - pinText.setText(R.string.pin); - detailsIcon.setVisibility(InputHelper.isEmpty(repoModel.getDescription()) ? View.GONE : View.VISIBLE); - language.setVisibility(InputHelper.isEmpty(repoModel.getLanguage()) ? View.GONE : View.VISIBLE); - if (!InputHelper.isEmpty(repoModel.getLanguage())) { - language.setText(repoModel.getLanguage()); - language.setTextColor(ColorsProvider.getColorAsColor(repoModel.getLanguage(), language.getContext())); - } - forkRepo.setText(numberFormat.format(repoModel.getForksCount())); - starRepo.setText(numberFormat.format(repoModel.getStargazersCount())); - watchRepo.setText(numberFormat.format(repoModel.getSubsCount())); - if (repoModel.getOwner() != null) { - avatarLayout.setUrl(repoModel.getOwner().getAvatarUrl(), repoModel.getOwner().getLogin(), - repoModel.getOwner().isOrganizationType(), LinkParserHelper.isEnterprise(repoModel.getHtmlUrl())); - } else if (repoModel.getOrganization() != null) { - avatarLayout.setUrl(repoModel.getOrganization().getAvatarUrl(), repoModel.getOrganization().getLogin(), true, - LinkParserHelper.isEnterprise(repoModel.getHtmlUrl())); - } - long repoSize = repoModel.getSize() > 0 ? (repoModel.getSize() * 1000) : repoModel.getSize(); - date.setText(SpannableBuilder.builder() - .append(ParseDateFormat.getTimeAgo(repoModel.getPushedAt())) - .append(" ,") - .append(" ") - .append(Formatter.formatFileSize(this, repoSize))); - size.setVisibility(View.GONE); - title.setText(repoModel.getFullName()); - TextViewCompat.setTextAppearance(title, R.style.TextAppearance_AppCompat_Medium); - title.setTextColor(ViewHelper.getPrimaryTextColor(this)); - if (repoModel.getLicense() != null) { - licenseLayout.setVisibility(View.VISIBLE); - LicenseModel licenseModel = repoModel.getLicense(); - license.setText(!InputHelper.isEmpty(licenseModel.getSpdxId()) ? licenseModel.getSpdxId() : licenseModel.getName()); - } - supportInvalidateOptionsMenu(); - if (!PrefGetter.isRepoGuideShowed()) {} - onRepoWatched(getPresenter().isWatched()); - onRepoStarred(getPresenter().isStarred()); - onRepoForked(getPresenter().isForked()); - } - - @Override public void onRepoWatched(boolean isWatched) { - watchRepoImage.tintDrawableColor(isWatched ? accentColor : iconColor); - onEnableDisableWatch(true); - } - - @Override public void onRepoStarred(boolean isStarred) { - starRepoImage.setImageResource(isStarred ? R.drawable.ic_star_filled : R.drawable.ic_star); - starRepoImage.tintDrawableColor(isStarred ? accentColor : iconColor); - onEnableDisableStar(true); - } - - @Override public void onRepoForked(boolean isForked) { - forkRepoImage.tintDrawableColor(isForked ? accentColor : iconColor); - onEnableDisableFork(true); - } - - @Override public void onRepoPinned(boolean isPinned) { - pinImage.setImageResource(isPinned ? R.drawable.ic_pin_filled : R.drawable.ic_pin); - pinLayout.setEnabled(true); - } - - @Override public void onEnableDisableWatch(boolean isEnabled) { - watchRepoLayout.setEnabled(isEnabled); - } - - @Override public void onEnableDisableStar(boolean isEnabled) { - starRepoLayout.setEnabled(isEnabled); - } - - @Override public void onEnableDisableFork(boolean isEnabled) { - forkRepoLayout.setEnabled(isEnabled); - } - - @Override public void onChangeWatchedCount(boolean isWatched) { - long count = InputHelper.toLong(watchRepo); - watchRepo.setText(numberFormat.format(isWatched ? (count + 1) : (count > 0 ? (count - 1) : 0))); - updatePinnedRepo(); - } - - @Override public void onChangeStarCount(boolean isStarred) { - long count = InputHelper.toLong(starRepo); - starRepo.setText(numberFormat.format(isStarred ? (count + 1) : (count > 0 ? (count - 1) : 0))); - updatePinnedRepo(); - } - - @Override public void onChangeForkCount(boolean isForked) { - long count = InputHelper.toLong(forkRepo); - forkRepo.setText(numberFormat.format(isForked ? (count + 1) : (count > 0 ? (count - 1) : 0))); - updatePinnedRepo(); - } - - @Override public void onUserInteraction() { - super.onUserInteraction(); - userInteracted = true; - } - - @Override public boolean hasUserInteractedWithView() { - return userInteracted; - } - - @Override public void disableIssueTab() { - showMessage(R.string.error, R.string.repo_issues_is_disabled); - bottomNavigation.setMenuItemEnabled(1, false); - bottomNavigation.setSelectedIndex(this.navType, true); - } - - @Override public void openUserProfile() { - UserPagerActivity.startActivity(this, Login.getUser().getLogin(), false, PrefGetter.isEnterprise(), -1); - } - - @Override public void onScrolled(boolean isUp) { - if (fab != null) { - if (isUp) { - fab.hide(); - } else { - fab.show(); - } - } - } - - @Override public boolean isCollaborator() { - return getPresenter().isRepoOwner(); - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.repo_menu, menu); - return super.onCreateOptionsMenu(menu); - } - - @Override public boolean onPrepareOptionsMenu(Menu menu) { - Repo repoModel = getPresenter().getRepo(); - if (repoModel != null && repoModel.isFork() && repoModel.getParent() != null) { - MenuItem menuItem = menu.findItem(R.id.originalRepo); - menuItem.setVisible(true); - menuItem.setTitle(repoModel.getParent().getFullName()); - } -// menu.findItem(R.id.deleteRepo).setVisible(getPresenter().isRepoOwner()); - if (menu.findItem(R.id.deleteRepo) != null) menu.findItem(R.id.deleteRepo).setVisible(false);//removing delete permission. - return super.onPrepareOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - startActivity(new Intent(this, MainActivity.class)); - finish(); - } else if (item.getItemId() == R.id.share) { - if (getPresenter().getRepo() != null) ActivityHelper.shareUrl(this, getPresenter().getRepo().getHtmlUrl()); - return true; - } else if (item.getItemId() == R.id.browser) { - if (getPresenter().getRepo() != null) ActivityHelper.startCustomTab(this, getPresenter().getRepo().getHtmlUrl()); - return true; - } else if (item.getItemId() == R.id.copy) { - if (getPresenter().getRepo() != null) AppHelper.copyToClipboard(this, getPresenter().getRepo().getHtmlUrl()); - return true; - } else if (item.getItemId() == R.id.originalRepo) { - if (getPresenter().getRepo() != null && getPresenter().getRepo().getParent() != null) { - Repo parent = getPresenter().getRepo().getParent(); - SchemeParser.launchUri(this, parent.getHtmlUrl()); - } - return true; - } else if (item.getItemId() == R.id.deleteRepo) { - MessageDialogView.newInstance(getString(R.string.delete_repo), getString(R.string.delete_repo_warning), - Bundler.start().put(BundleConstant.EXTRA_TWO, true) - .put(BundleConstant.YES_NO_EXTRA, true) - .end()).show(getSupportFragmentManager(), MessageDialogView.TAG); - return true; - } - return super.onOptionsItemSelected(item); - } - - @SuppressWarnings("ConstantConditions") @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk && bundle != null) { - boolean isDelete = bundle.getBoolean(BundleConstant.EXTRA_TWO); - boolean fork = bundle.getBoolean(BundleConstant.EXTRA); - if (fork) { - if (getPresenter().login() != null && getPresenter().repoId() != null && !getPresenter().isForked()) { - GithubActionService.startForRepo(this, getPresenter().login(), getPresenter().repoId(), - GithubActionService.FORK_REPO, isEnterprise()); - getPresenter().onFork(); - } - } - if (isDelete) getPresenter().onDeleteRepo(); - } - } - - @Override public void onBackPressed() { - if (navType == RepoPagerMvp.CODE) { - RepoCodePagerFragment codePagerView = (RepoCodePagerFragment) AppHelper.getFragmentByTag(getSupportFragmentManager(), - RepoCodePagerFragment.TAG); - if (codePagerView != null) { - if (codePagerView.canPressBack()) { - super.onBackPressed(); - } else { - codePagerView.onBackPressed(); - return; - } - } - } else if (navType == RepoPagerMvp.ISSUES && filterLayout.isShown()) { - hideFilterLayout(); - return; - } - super.onBackPressed(); - } - - @Override public void onAddSelected() { - RepoIssuesPagerFragment pagerView = (RepoIssuesPagerFragment) AppHelper.getFragmentByTag(getSupportFragmentManager(), - RepoIssuesPagerFragment.TAG); - if (pagerView != null) { - pagerView.onAddIssue(); - } - } - - @Override public void onSearchSelected() { - boolean isOpen = true; - RepoIssuesPagerFragment pagerView = (RepoIssuesPagerFragment) AppHelper.getFragmentByTag(getSupportFragmentManager(), - RepoIssuesPagerFragment.TAG); - if (pagerView != null) { - isOpen = pagerView.getCurrentItem() == 0; - } - FilterIssuesActivity.startActivity(this, getPresenter().login(), getPresenter().repoId(), true, isOpen, isEnterprise()); - } - - private void showHideFab() { - if (navType == RepoPagerMvp.ISSUES) { - fab.setImageResource(R.drawable.ic_menu); - fab.show(); - if (!PrefGetter.isRepoFabHintShowed()) {} - } else if (navType == RepoPagerMvp.PULL_REQUEST) { - fab.setImageResource(R.drawable.ic_search); - fab.show(); - } else { - fab.hide(); - } - } - - private void hideFilterLayout() { - AnimHelper.mimicFabVisibility(false, filterLayout, new FloatingActionButton.OnVisibilityChangedListener() { - @Override public void onHidden(FloatingActionButton actionButton) { - fab.show(); - } - }); - } - - private void updatePinnedRepo() { - getPresenter().updatePinned((int) InputHelper.toLong(forkRepo), (int) InputHelper.toLong(starRepo), (int) InputHelper.toLong(watchRepo)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerMvp.java deleted file mode 100644 index 2125de9fe..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerMvp.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.fastaccess.ui.modules.repos; - -import android.support.annotation.IntDef; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; - -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.filter.chooser.FilterAddChooserListener; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import it.sephiroth.android.library.bottomnavigation.BottomNavigation; - -/** - * Created by Kosh on 09 Dec 2016, 4:16 PM - */ - -public interface RepoPagerMvp { - - int CODE = 0; - int ISSUES = 1; - int PULL_REQUEST = 2; - int PROJECTS = 3; - int PROFILE = 4; - - @IntDef({ - CODE, - ISSUES, - PULL_REQUEST, - PROJECTS, - PROFILE - }) - @Retention(RetentionPolicy.SOURCE) @interface RepoNavigationType {} - - - interface View extends BaseMvp.FAView, FilterAddChooserListener { - - void onNavigationChanged(@RepoNavigationType int navType); - - void onFinishActivity(); - - void onInitRepo(); - - void onRepoWatched(boolean isWatched); - - void onRepoStarred(boolean isStarred); - - void onRepoForked(boolean isForked); - - void onRepoPinned(boolean isPinned); - - void onEnableDisableWatch(boolean isEnabled); - - void onEnableDisableStar(boolean isEnabled); - - void onEnableDisableFork(boolean isEnabled); - - void onChangeWatchedCount(boolean isWatched); - - void onChangeStarCount(boolean isStarred); - - void onChangeForkCount(boolean isForked); - - boolean hasUserInteractedWithView(); - - void disableIssueTab(); - - void openUserProfile(); - - void onScrolled(boolean isUp); - - boolean isCollaborator(); - } - - interface Presenter extends BaseMvp.FAPresenter, BottomNavigation.OnMenuItemSelectionListener { - - void onUpdatePinnedEntry(@NonNull String repoId, @NonNull String login); - - void onActivityCreate(@NonNull String repoId, @NonNull String login, @RepoPagerMvp.RepoNavigationType int navTyp); - - @NonNull String repoId(); - - @NonNull String login(); - - @Nullable Repo getRepo(); - - boolean isWatched(); - - boolean isStarred(); - - boolean isForked(); - - boolean isRepoOwner(); - - void onWatch(); - - void onStar(); - - void onFork(); - - void onCheckWatching(); - - void onCheckStarring(); - - void onWorkOffline(); - - void onModuleChanged(@NonNull FragmentManager fragmentManager, @RepoNavigationType int type); - - void onShowHideFragment(@NonNull FragmentManager fragmentManager, @NonNull Fragment toShow, @NonNull Fragment toHide); - - void onAddAndHide(@NonNull FragmentManager fragmentManager, @NonNull Fragment toAdd, @NonNull Fragment toHide); - - void onDeleteRepo(); - - void onPinUnpinRepo(); - - void updatePinned(int forks, int stars, int watching); - } - - interface TabsBadgeListener { - void onSetBadge(int tabIndex, int count); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerPresenter.java deleted file mode 100644 index 5e38f8e37..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/RepoPagerPresenter.java +++ /dev/null @@ -1,316 +0,0 @@ -package com.fastaccess.ui.modules.repos; - -import android.support.annotation.IdRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.AbstractPinnedRepos; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.PinnedRepos; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.repos.code.RepoCodePagerFragment; -import com.fastaccess.ui.modules.repos.issues.RepoIssuesPagerFragment; -import com.fastaccess.ui.modules.repos.projects.RepoProjectsFragmentPager; -import com.fastaccess.ui.modules.repos.pull_requests.RepoPullRequestPagerFragment; - -import io.reactivex.Observable; - -import static com.fastaccess.helper.ActivityHelper.getVisibleFragment; - -/** - * Created by Kosh on 09 Dec 2016, 4:17 PM - */ - -class RepoPagerPresenter extends BasePresenter implements RepoPagerMvp.Presenter { - @com.evernote.android.state.State boolean isWatched; - @com.evernote.android.state.State boolean isStarred; - @com.evernote.android.state.State boolean isForked; - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State Repo repo; - @com.evernote.android.state.State int navTyp; - @com.evernote.android.state.State boolean isCollaborator; - - private void callApi(int navTyp) { - if (InputHelper.isEmpty(login) || InputHelper.isEmpty(repoId)) return; - makeRestCall(Observable.zip(RestProvider.getRepoService(isEnterprise()).getRepo(login(), repoId()), - RestProvider.getRepoService(isEnterprise()).isCollaborator(login, repoId, Login.getUser().getLogin()), - (repo1, booleanResponse) -> { - isCollaborator = booleanResponse.code() == 204; - return repo1; - }), - repoModel -> { - this.repo = repoModel; - manageDisposable(this.repo.save(repo)); - updatePinned(repoModel); - sendToView(view -> { - view.onInitRepo(); - view.onNavigationChanged(navTyp); - }); - onCheckStarring(); - onCheckWatching(); - }); - } - - @Override public void onError(@NonNull Throwable throwable) { - int code = RestProvider.getErrorCode(throwable); - if (code == 404) { - sendToView(BaseMvp.FAView::onOpenUrlInBrowser); - } else { - onWorkOffline(); - } - super.onError(throwable); - } - - @Override public void onUpdatePinnedEntry(@NonNull String repoId, @NonNull String login) { - manageDisposable(PinnedRepos.updateEntry(login + "/" + repoId)); - } - - @Override public void onActivityCreate(@NonNull String repoId, @NonNull String login, int navTyp) { - this.login = login; - this.repoId = repoId; - this.navTyp = navTyp; - if (getRepo() == null || !isApiCalled()) { - callApi(navTyp); - } else { - sendToView(RepoPagerMvp.View::onInitRepo); - } - } - - @NonNull @Override public String repoId() { - return repoId; - } - - @NonNull @Override public String login() { - return login; - } - - @Nullable @Override public Repo getRepo() { - return repo; - } - - @Override public boolean isWatched() { - return isWatched; - } - - @Override public boolean isStarred() { - return isStarred; - } - - @Override public boolean isForked() { - return isForked; - } - - @Override public boolean isRepoOwner() { - if (getRepo() != null && getRepo().getOwner() != null) { - return getRepo().getOwner().getLogin().equals(Login.getUser().getLogin()) || isCollaborator; - } - return false; - } - - @Override public void onWatch() { - if (getRepo() == null) return; - isWatched = !isWatched; - sendToView(view -> { - view.onRepoWatched(isWatched); - view.onChangeWatchedCount(isWatched); - }); - } - - @Override public void onStar() { - if (getRepo() == null) return; - isStarred = !isStarred; - sendToView(view -> { - view.onRepoStarred(isStarred); - view.onChangeStarCount(isStarred); - }); - } - - @Override public void onFork() { - if (!isForked && getRepo() != null) { - isForked = true; - sendToView(view -> { - view.onRepoForked(isForked); - view.onChangeForkCount(isForked); - }); - } - } - - @Override public void onCheckWatching() { - if (getRepo() != null) { - String login = login(); - String name = repoId(); - manageDisposable(RxHelper.getObservable(RestProvider.getRepoService(isEnterprise()).isWatchingRepo(login, name)) - .doOnSubscribe(disposable -> sendToView(view -> view.onEnableDisableWatch(false))) - .doOnNext(subscriptionModel -> sendToView(view -> view.onRepoWatched(isWatched = subscriptionModel.isSubscribed()))) - .subscribe(o -> {/**/}, throwable -> { - isWatched = false; - sendToView(view -> view.onRepoWatched(isWatched)); - })); - } - } - - @Override public void onCheckStarring() { - if (getRepo() != null) { - String login = login(); - String name = repoId(); - manageDisposable(RxHelper.getObservable(RestProvider.getRepoService(isEnterprise()).checkStarring(login, name)) - .doOnSubscribe(disposable -> sendToView(view -> view.onEnableDisableStar(false))) - .doOnNext(response -> sendToView(view -> view.onRepoStarred(isStarred = response.code() == 204))) - .subscribe(booleanResponse -> {/**/}, throwable -> { - isStarred = false; - sendToView(view -> view.onRepoStarred(isStarred)); - })); - } - } - - @Override public void onWorkOffline() { - if (!InputHelper.isEmpty(login()) && !InputHelper.isEmpty(repoId())) { - manageDisposable(RxHelper.getObservable(Repo.getRepo(repoId, login).toObservable()) - .subscribe(repoModel -> { - repo = repoModel; - if (repo != null) { - sendToView(view -> { - view.onInitRepo(); - view.onNavigationChanged(RepoPagerMvp.CODE); - }); - } else { - callApi(navTyp); - } - }, Throwable::printStackTrace)); - } else { - sendToView(RepoPagerMvp.View::onFinishActivity); - } - } - - @Override public void onModuleChanged(@NonNull FragmentManager fragmentManager, @RepoPagerMvp.RepoNavigationType int type) { - Fragment currentVisible = getVisibleFragment(fragmentManager); - RepoCodePagerFragment codePagerView = (RepoCodePagerFragment) AppHelper.getFragmentByTag(fragmentManager, RepoCodePagerFragment.TAG); - RepoIssuesPagerFragment repoIssuesPagerView = (RepoIssuesPagerFragment) - AppHelper.getFragmentByTag(fragmentManager, RepoIssuesPagerFragment.TAG); - RepoPullRequestPagerFragment pullRequestPagerView = (RepoPullRequestPagerFragment) - AppHelper.getFragmentByTag(fragmentManager, RepoPullRequestPagerFragment.TAG); - RepoProjectsFragmentPager projectsFragmentPager = (RepoProjectsFragmentPager) AppHelper.getFragmentByTag(fragmentManager, - RepoProjectsFragmentPager.Companion.getTAG()); - if (getRepo() == null) { - sendToView(RepoPagerMvp.View::onFinishActivity); - return; - } - if (currentVisible == null) return; - switch (type) { - case RepoPagerMvp.PROFILE: - sendToView(RepoPagerMvp.View::openUserProfile); - case RepoPagerMvp.CODE: - if (codePagerView == null) { - onAddAndHide(fragmentManager, RepoCodePagerFragment.newInstance(repoId(), login(), - getRepo().getHtmlUrl(), getRepo().getUrl(), getRepo().getDefaultBranch()), currentVisible); - } else { - onShowHideFragment(fragmentManager, codePagerView, currentVisible); - } - break; - case RepoPagerMvp.ISSUES: - if ((!getRepo().isHasIssues())) { - sendToView(view -> view.showMessage(R.string.error, R.string.repo_issues_is_disabled)); - break; - } - if (repoIssuesPagerView == null) { - onAddAndHide(fragmentManager, RepoIssuesPagerFragment.newInstance(repoId(), login()), currentVisible); - } else { - onShowHideFragment(fragmentManager, repoIssuesPagerView, currentVisible); - } - break; - case RepoPagerMvp.PULL_REQUEST: - if (pullRequestPagerView == null) { - onAddAndHide(fragmentManager, RepoPullRequestPagerFragment.newInstance(repoId(), login()), currentVisible); - } else { - onShowHideFragment(fragmentManager, pullRequestPagerView, currentVisible); - } - break; - case RepoPagerMvp.PROJECTS: - if (projectsFragmentPager == null) { - onAddAndHide(fragmentManager, RepoProjectsFragmentPager.Companion.newInstance(login(), repoId()), currentVisible); - } else { - onShowHideFragment(fragmentManager, projectsFragmentPager, currentVisible); - } - break; - } - } - - @Override public void onShowHideFragment(@NonNull FragmentManager fragmentManager, @NonNull Fragment toShow, @NonNull Fragment toHide) { - fragmentManager - .beginTransaction() - .hide(toHide) - .show(toShow) - .commit(); - toHide.onHiddenChanged(true); - toShow.onHiddenChanged(false); - } - - @Override public void onAddAndHide(@NonNull FragmentManager fragmentManager, @NonNull Fragment toAdd, @NonNull Fragment toHide) { - fragmentManager - .beginTransaction() - .hide(toHide) - .add(R.id.container, toAdd, toAdd.getClass().getSimpleName()) - .commit(); - - //noinspection ConstantConditions really android? - if (toHide != null) toHide.onHiddenChanged(true); - //noinspection ConstantConditions really android? - if (toAdd != null) toAdd.onHiddenChanged(false); - } - - @Override public void onDeleteRepo() { - if (isRepoOwner()) { - makeRestCall(RestProvider.getRepoService(isEnterprise()).deleteRepo(login, repoId), - booleanResponse -> { - if (booleanResponse.code() == 204) { -// if (repo != null) repo.delete().execute(); - repo = null; - sendToView(RepoPagerMvp.View::onInitRepo); - } - }); - } - } - - @Override public void onPinUnpinRepo() { - if (getRepo() == null) return; - boolean isPinned = AbstractPinnedRepos.pinUpin(getRepo()); - sendToView(view -> view.onRepoPinned(isPinned)); - } - - @Override public void updatePinned(int forks, int stars, int watching) { - this.repo.setStargazersCount(stars); - this.repo.setForksCount(forks); - this.repo.setSubsCount(watching); - updatePinned(repo); - } - - @Override public void onMenuItemSelect(@IdRes int id, int position, boolean fromUser) { - if (id == R.id.issues && (getRepo() != null && !getRepo().isHasIssues())) { - sendToView(RepoPagerMvp.View::disableIssueTab); - return; - } - if (getView() != null && isViewAttached() && fromUser) { - getView().onNavigationChanged(position); - } - } - - @Override public void onMenuItemReselect(@IdRes int id, int position, boolean fromUser) {} - - private void updatePinned(Repo repoModel) { - PinnedRepos pinnedRepos = PinnedRepos.get(repoModel.getFullName()); - if (pinnedRepos != null) { - pinnedRepos.setPinnedRepo(repoModel); - manageObservable(PinnedRepos.update(pinnedRepos).toObservable()); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerFragment.java deleted file mode 100644 index 1e4a5feb8..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerFragment.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.fastaccess.ui.modules.repos.code; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; -import android.view.View; -import android.widget.TextView; - -import com.annimon.stream.Objects; -import com.annimon.stream.Stream; -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.TabsCountStateModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.code.files.paths.RepoFilePathFragment; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.ViewPagerView; - -import java.util.HashSet; - -import butterknife.BindView; - -/** - * Created by Kosh on 31 Dec 2016, 1:36 AM - */ - -public class RepoCodePagerFragment extends BaseFragment implements RepoCodePagerMvp.View { - public static final String TAG = RepoCodePagerFragment.class.getSimpleName(); - - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.pager) ViewPagerView pager; - @State HashSet counts = new HashSet<>(); - - public static RepoCodePagerFragment newInstance(@NonNull String repoId, @NonNull String login, - @NonNull String htmlLink, @NonNull String url, @NonNull String defaultBranch) { - RepoCodePagerFragment view = new RepoCodePagerFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, url) - .put(BundleConstant.EXTRA_THREE, defaultBranch) - .put(BundleConstant.EXTRA_FOUR, htmlLink) - .end()); - return view; - } - - @Override protected int fragmentLayout() { - return R.layout.tabbed_viewpager; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() != null) { - String repoId = getArguments().getString(BundleConstant.ID); - String login = getArguments().getString(BundleConstant.EXTRA); - String url = getArguments().getString(BundleConstant.EXTRA_TWO); - String htmlUrl = getArguments().getString(BundleConstant.EXTRA_FOUR); - String defaultBranch = getArguments().getString(BundleConstant.EXTRA_THREE); - if (InputHelper.isEmpty(repoId) || InputHelper.isEmpty(login) || InputHelper.isEmpty(url) || InputHelper.isEmpty(htmlUrl)) { - return; - } - pager.setAdapter(new FragmentsPagerAdapter(getChildFragmentManager(), - FragmentPagerAdapterModel.buildForRepoCode(getContext(), repoId, login, url, - Objects.toString(defaultBranch, "master"), htmlUrl))); - tabs.setTabMode(TabLayout.MODE_SCROLLABLE); - tabs.setupWithViewPager(pager); - } - if (savedInstanceState != null && !counts.isEmpty()) { - Stream.of(counts).forEach(this::updateCount); - } - tabs.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager) { - @Override public void onTabReselected(TabLayout.Tab tab) { - super.onTabReselected(tab); - onScrollTop(tab.getPosition()); - } - }); - } - - @Override public void onScrollTop(int index) { - if (pager == null || pager.getAdapter() == null) return; - Fragment fragment = (BaseFragment) pager.getAdapter().instantiateItem(pager, index); - if (fragment instanceof BaseFragment) { - ((BaseFragment) fragment).onScrollTop(index); - } - } - - @NonNull @Override public RepoCodePagerPresenter providePresenter() { - return new RepoCodePagerPresenter(); - } - - @Override public boolean canPressBack() { - if (pager.getCurrentItem() != 1) return true; - RepoFilePathFragment pathView = (RepoFilePathFragment) pager.getAdapter().instantiateItem(pager, 1); - return pathView == null || pathView.canPressBack(); - } - - @Override public void onBackPressed() { - if (pager != null && pager.getAdapter() != null) { - RepoFilePathFragment pathView = (RepoFilePathFragment) pager.getAdapter().instantiateItem(pager, 1); - if (pathView != null) { - pathView.onBackPressed(); - } - } - } - - @Override public void onSetBadge(int tabIndex, int count) { - TabsCountStateModel model = new TabsCountStateModel(); - model.setTabIndex(tabIndex); - model.setCount(count); - counts.add(model); - if (tabs != null) { - updateCount(model); - } - } - - private void updateCount(@NonNull TabsCountStateModel model) { - TextView tv = ViewHelper.getTabTextView(tabs, model.getTabIndex()); - tv.setText(SpannableBuilder.builder() - .append(getString(R.string.commits)) - .append(" ") - .append("(") - .bold(String.valueOf(model.getCount())) - .append(")")); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerMvp.java deleted file mode 100644 index 4d92ec913..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerMvp.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.fastaccess.ui.modules.repos.code; - -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; - -/** - * Created by Kosh on 31 Dec 2016, 1:35 AM - */ - -public interface RepoCodePagerMvp { - - interface View extends BaseMvp.FAView, RepoPagerMvp.TabsBadgeListener { - boolean canPressBack(); - - void onBackPressed(); - } - - interface Presenter extends BaseMvp.FAPresenter {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerPresenter.java deleted file mode 100644 index 265101b82..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/RepoCodePagerPresenter.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.ui.modules.repos.code; - -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by Kosh on 31 Dec 2016, 1:36 AM - */ - -class RepoCodePagerPresenter extends BasePresenter implements RepoCodePagerMvp.Presenter {} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsFragment.java deleted file mode 100644 index 1eb82bdd1..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsFragment.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.BranchesModel; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.CommitsAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.extras.branches.pager.BranchesPagerFragment; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class RepoCommitsFragment extends BaseFragment implements RepoCommitsMvp.View { - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @BindView(R.id.branches) FontTextView branches; - private OnLoadMore onLoadMore; - private CommitsAdapter adapter; - private RepoPagerMvp.TabsBadgeListener tabsBadgeListener; - - public static RepoCommitsFragment newInstance(@NonNull String repoId, @NonNull String login, @NonNull String branch) { - return newInstance(repoId, login, branch, null); - } - - public static RepoCommitsFragment newInstance(@NonNull String repoId, @NonNull String login, @NonNull String branch, - @Nullable String path) { - return newInstance(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, branch) - .put(BundleConstant.EXTRA_THREE, path) - .end()); - } - - public static RepoCommitsFragment newInstance(@NonNull Bundle bundle) { - RepoCommitsFragment view = new RepoCommitsFragment(); - view.setArguments(bundle); - return view; - } - - @OnClick(R.id.branches) void onBranchesClicked() { - BranchesPagerFragment.Companion.newInstance(getPresenter().login, getPresenter().repoId) - .show(getChildFragmentManager(), "BranchesFragment"); - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) context; - } else if (getParentFragment() instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) getParentFragment(); - } - } - - @Override public void onDetach() { - tabsBadgeListener = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.commit_with_branch_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, therefore, issues can't be proceeded."); - } - stateLayout.setEmptyText(R.string.no_commits); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - recycler.addKeyLineDivider(); - adapter = new CommitsAdapter(getPresenter().getCommits()); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments()); - } else if (getPresenter().getCommits().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - branches.setText(getPresenter().branch); - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public RepoCommitsPresenter providePresenter() { - return new RepoCommitsPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @SuppressWarnings("unchecked") @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()); - } - return onLoadMore; - } - - @Override public void setBranchesData(@Nullable List branchesData, boolean firstTime) { - } - - @Override public void onShowCommitCount(long sum) { - if (tabsBadgeListener != null) { - tabsBadgeListener.onSetBadge(2, (int) sum); - } - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, null); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - @Override public void onBranchSelected(@NonNull BranchesModel branch) { - String ref = branch.getName(); - branches.setText(ref); - getPresenter().onBranchChanged(ref); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsMvp.java deleted file mode 100644 index ef1c608c1..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsMvp.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.BranchesModel; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.repos.extras.branches.BranchesMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface RepoCommitsMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, - android.view.View.OnClickListener, BranchesMvp.BranchSelectionListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void setBranchesData(@NonNull List branches, boolean firstTime); - - void onShowCommitCount(long sum); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - void onFragmentCreated(@NonNull Bundle bundle); - - @NonNull ArrayList getCommits(); - - void onWorkOffline(); - - void onBranchChanged(@NonNull String branch); - - String getDefaultBranch(); - - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsPresenter.java deleted file mode 100644 index 3aa590582..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/RepoCommitsPresenter.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; -import android.view.View; - -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.repos.code.commit.details.CommitPagerActivity; - -import java.util.ArrayList; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class RepoCommitsPresenter extends BasePresenter implements RepoCommitsMvp.Presenter { - - private ArrayList commits = new ArrayList<>(); - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State String branch; - @com.evernote.android.state.State String path; - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - onWorkOffline(); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable Object parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(RepoCommitsMvp.View::hideProgress); - return false; - } - if (repoId == null || login == null) return false; - Observable> observable = InputHelper.isEmpty(path) - ? RestProvider.getRepoService(isEnterprise()).getCommits(login, repoId, branch, page) - : RestProvider.getRepoService(isEnterprise()).getCommits(login, repoId, branch, path, page); - makeRestCall(observable, response -> { - if (response != null && response.getItems() != null) { - lastPage = response.getLast(); - if (getCurrentPage() == 1) { - manageDisposable(Commit.save(response.getItems(), repoId, login)); - } - } - sendToView(view -> view.onNotifyAdapter(response != null ? response.getItems() : null, page)); - }); - return true; - } - - @Override public void onFragmentCreated(@NonNull Bundle bundle) { - repoId = bundle.getString(BundleConstant.ID); - login = bundle.getString(BundleConstant.EXTRA); - branch = bundle.getString(BundleConstant.EXTRA_TWO); - path = bundle.getString(BundleConstant.EXTRA_THREE); - if (!InputHelper.isEmpty(branch)) { - getCommitCount(branch); - } - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - onCallApi(1, null); - } - } - - @NonNull @Override public ArrayList getCommits() { - return commits; - } - - @Override public void onWorkOffline() { - if (commits.isEmpty()) { - manageDisposable(RxHelper.getObservable(Commit.getCommits(repoId, login).toObservable()) - .subscribe(models -> sendToView(view -> view.onNotifyAdapter(models, 1)))); - } else { - sendToView(BaseMvp.FAView::hideProgress); - } - } - - @Override public void onBranchChanged(@NonNull String branch) { - if (!TextUtils.equals(branch, this.branch)) { - this.branch = branch; - onCallApi(1, null); - getCommitCount(branch); - } - } - - @Override public String getDefaultBranch() { - return branch; - } - - @Override public void onItemClick(int position, View v, Commit item) { - CommitPagerActivity.createIntentForOffline(v.getContext(), item); - } - - @Override public void onItemLongClick(int position, View v, Commit item) {} - - private void getCommitCount(@NonNull String branch) { - manageDisposable(RxHelper.safeObservable(RxHelper.getObservable(RestProvider.getRepoService(isEnterprise()) - .getCommitCounts(login, repoId, branch))) - .subscribe(response -> { - if (response != null) { - sendToView(view -> view.onShowCommitCount(response.getLast())); - } - }, Throwable::printStackTrace)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerActivity.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerActivity.java deleted file mode 100644 index 9df5cb866..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerActivity.java +++ /dev/null @@ -1,295 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.details; - -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.design.widget.CoordinatorLayout; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; -import android.support.v4.view.ViewPager; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.NameParser; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.provider.timeline.HtmlHelper; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; -import com.fastaccess.ui.modules.repos.RepoPagerActivity; -import com.fastaccess.ui.modules.repos.code.commit.details.comments.CommitCommentsFragment; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.ViewPagerView; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; - -import java.util.ArrayList; -import java.util.Date; - -import butterknife.BindView; -import butterknife.OnClick; -import kotlin.text.StringsKt; - -/** - * Created by Kosh on 10 Dec 2016, 9:23 AM - */ - -public class CommitPagerActivity extends BaseActivity implements CommitPagerMvp.View { - - @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.headerTitle) FontTextView title; - @BindView(R.id.size) FontTextView size; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.pager) ViewPagerView pager; - @BindView(R.id.fab) FloatingActionButton fab; - @BindView(R.id.changes) FontTextView changes; - @BindView(R.id.addition) FontTextView addition; - @BindView(R.id.deletion) FontTextView deletion; - @BindView(R.id.coordinatorLayout) CoordinatorLayout coordinatorLayout; - @BindView(R.id.detailsIcon) View detailsIcon; - private CommentEditorFragment commentEditorFragment; - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, @NonNull String login, @NonNull String sha) { - return createIntent(context, repoId, login, sha, false); - } - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, @NonNull String login, - @NonNull String sha, boolean showRepoBtn) { - return createIntent(context, repoId, login, sha, showRepoBtn, false); - } - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, @NonNull String login, - @NonNull String sha, boolean showRepoBtn, - boolean isEnterprise) { - Intent intent = new Intent(context, CommitPagerActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.ID, sha) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, repoId) - .put(BundleConstant.EXTRA_THREE, showRepoBtn) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - return intent; - } - - public static void createIntentForOffline(@NonNull Context context, @NonNull Commit commitModel) { - SchemeParser.launchUri(context, Uri.parse(commitModel.getHtmlUrl())); - } - - @OnClick(R.id.detailsIcon) void onTitleClick() { - if (getPresenter().getCommit() != null && !InputHelper.isEmpty(getPresenter().getCommit().getGitCommit().getMessage())) - MessageDialogView.newInstance(String.format("%s/%s", getPresenter().getLogin(), getPresenter().getRepoId()), - getPresenter().getCommit().getGitCommit().getMessage(), true, false) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - } - - @Override protected int layout() { - return R.layout.commit_pager_activity; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public CommitPagerPresenter providePresenter() { - return new CommitPagerPresenter(); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - fab.hide(); - commentEditorFragment = (CommentEditorFragment) getSupportFragmentManager().findFragmentById(R.id.commentFragment); - setTitle(""); - if (savedInstanceState == null) { - getPresenter().onActivityCreated(getIntent()); - } else { - if (getPresenter().isApiCalled()) onSetup(); - } - if (getPresenter().showToRepoBtn()) showNavToRepoItem(); - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.share_menu, menu); - menu.findItem(R.id.browser).setVisible(true).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - menu.findItem(R.id.copyUrl).setVisible(true).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - menu.findItem(R.id.copySha).setVisible(true).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - menu.findItem(R.id.share).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - return super.onCreateOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - onNavToRepoClicked(); - return true; - } else if (item.getItemId() == R.id.share) { - if (getPresenter().getCommit() != null) ActivityHelper.shareUrl(this, getPresenter().getCommit().getHtmlUrl()); - return true; - } else if (item.getItemId() == R.id.browser) { - if (getPresenter().getCommit() != null) ActivityHelper.startCustomTab(this, getPresenter().getCommit().getHtmlUrl()); - return true; - } else if (item.getItemId() == R.id.copyUrl) { - if (getPresenter().getCommit() != null) AppHelper.copyToClipboard(this, getPresenter().getCommit().getHtmlUrl()); - return true; - } else if (item.getItemId() == R.id.copySha) { - if (getPresenter().getCommit() != null) AppHelper.copyToClipboard(this, getPresenter().getCommit().getSha()); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override public void onSetup() { - hideProgress(); - if (getPresenter().getCommit() == null) { - return; - } - supportInvalidateOptionsMenu(); - Commit commit = getPresenter().getCommit(); - String login = commit.getAuthor() != null ? commit.getAuthor().getLogin() : commit.getGitCommit().getAuthor().getName(); - String avatar = commit.getAuthor() != null ? commit.getAuthor().getAvatarUrl() : null; - Date dateValue = commit.getGitCommit().getAuthor().getDate(); - HtmlHelper.htmlIntoTextView(title, commit.getGitCommit().getMessage(), title.getWidth()); - setTaskName(commit.getLogin() + "/" + commit.getRepoId() + " - Commit " + StringsKt.take(commit.getSha(), 5)); - detailsIcon.setVisibility(View.VISIBLE); - size.setVisibility(View.GONE); - date.setText(SpannableBuilder.builder() - .bold(getPresenter().repoId) - .append(" ") - .append(" ") - .append(ParseDateFormat.getTimeAgo(dateValue))); - avatarLayout.setUrl(avatar, login, false, LinkParserHelper.isEnterprise(commit.getHtmlUrl())); - addition.setText(String.valueOf(commit.getStats() != null ? commit.getStats().getAdditions() : 0)); - deletion.setText(String.valueOf(commit.getStats() != null ? commit.getStats().getDeletions() : 0)); - changes.setText(String.valueOf(commit.getFiles() != null ? commit.getFiles().size() : 0)); - pager.setAdapter(new FragmentsPagerAdapter(getSupportFragmentManager(), FragmentPagerAdapterModel.buildForCommit(this, commit))); - tabs.setupWithViewPager(pager); - pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { - @Override public void onPageSelected(int position) { - super.onPageSelected(position); - hideShowFab(); - } - }); - hideShowFab(); - TabLayout.Tab tabOne = tabs.getTabAt(0); - TabLayout.Tab tabTwo = tabs.getTabAt(1); - if (tabOne != null && commit.getFiles() != null) { - tabOne.setText(getString(R.string.files) + " (" + commit.getFiles().size() + ")"); - } - if (tabTwo != null && commit.getGitCommit() != null && commit.getGitCommit().getCommentCount() > 0) { - tabTwo.setText(getString(R.string.comments) + " (" + commit.getGitCommit().getCommentCount() + ")"); - } - tabs.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager) { - @Override public void onTabReselected(TabLayout.Tab tab) { - super.onTabReselected(tab); - onScrollTop(tab.getPosition()); - } - }); - } - - @Override public void onScrollTop(int index) { - if (pager == null || pager.getAdapter() == null) return; - Fragment fragment = (BaseFragment) pager.getAdapter().instantiateItem(pager, index); - if (fragment instanceof BaseFragment) { - ((BaseFragment) fragment).onScrollTop(index); - } - } - - @Override public void onFinishActivity() { - hideProgress(); - finish(); - } - - @Override public void onAddComment(@NonNull Comment newComment) { - CommitCommentsFragment fragment = getCommitCommentsFragment(); - if (fragment != null) { - fragment.addComment(newComment); - } - } - - @Override public String getLogin() { - return getPresenter().getLogin(); - } - - @Override public String getRepoId() { - return getPresenter().getRepoId(); - } - - @Override public void onBackPressed() { - super.onBackPressed(); - } - - @Override public void onNavToRepoClicked() { - NameParser nameParser = new NameParser(""); - nameParser.setName(getPresenter().getRepoId()); - nameParser.setUsername(getPresenter().getLogin()); - nameParser.setEnterprise(isEnterprise()); - RepoPagerActivity.startRepoPager(this, nameParser); - finish(); - } - - @Override public void onSendActionClicked(@NonNull String text, Bundle bundle) { - CommitCommentsFragment fragment = getCommitCommentsFragment(); - if (fragment != null) { - fragment.onHandleComment(text, bundle); - } - } - - @Override public void onTagUser(@NonNull String username) { - commentEditorFragment.onAddUserName(username); - } - - @Override public void onCreateComment(String text, Bundle bundle) { - - } - - @SuppressWarnings("ConstantConditions") @Override public void onClearEditText() { - if (commentEditorFragment != null && commentEditorFragment.commentText != null) commentEditorFragment.commentText.setText(""); - } - - @NonNull @Override public ArrayList getNamesToTag() { - CommitCommentsFragment fragment = getCommitCommentsFragment(); - if (fragment != null) { - return fragment.getNamesToTags(); - } - return new ArrayList<>(); - } - - private void hideShowFab() { - if (pager.getCurrentItem() == 1) { - getSupportFragmentManager().beginTransaction().show(commentEditorFragment).commit(); - } else { - getSupportFragmentManager().beginTransaction().hide(commentEditorFragment).commit(); - } - } - - private CommitCommentsFragment getCommitCommentsFragment() { - if (pager != null & pager.getAdapter() != null) - return (CommitCommentsFragment) pager.getAdapter().instantiateItem(pager, 1); - return null; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerMvp.java deleted file mode 100644 index eada71e58..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerMvp.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.details; - -import android.content.Intent; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; - -/** - * Created by Kosh on 10 Dec 2016, 9:21 AM - */ - -public interface CommitPagerMvp { - - interface View extends BaseMvp.FAView, CommentEditorFragment.CommentListener { - - void onSetup(); - - void onFinishActivity(); - - void onAddComment(@NonNull Comment newComment); - - String getLogin(); - - String getRepoId(); - } - - interface Presenter extends BaseMvp.FAPresenter { - - @Nullable Commit getCommit(); - - void onActivityCreated(@Nullable Intent intent); - - void onWorkOffline(@NonNull String sha, @NonNull String repoId, @NonNull String login); - - String getLogin(); - - String getRepoId(); - - boolean showToRepoBtn(); - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerPresenter.java deleted file mode 100644 index 1e1a71497..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/CommitPagerPresenter.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.details; - -import android.content.Intent; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.MarkdownModel; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 10 Dec 2016, 9:23 AM - */ - -class CommitPagerPresenter extends BasePresenter implements CommitPagerMvp.Presenter { - @com.evernote.android.state.State Commit commitModel; - @com.evernote.android.state.State String sha; - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State boolean showToRepoBtn; - @com.evernote.android.state.State ArrayList reviewComments = new ArrayList<>(); - - @Nullable @Override public Commit getCommit() { - return commitModel; - } - - @Override public void onError(@NonNull Throwable throwable) { - if (RestProvider.getErrorCode(throwable) == 404) { - sendToView(CommitPagerMvp.View::onFinishActivity); - } else { - onWorkOffline(sha, repoId, login); - } - super.onError(throwable); - } - - @Override public void onActivityCreated(@Nullable Intent intent) { - if (intent != null && intent.getExtras() != null) { - sha = intent.getExtras().getString(BundleConstant.ID); - login = intent.getExtras().getString(BundleConstant.EXTRA); - repoId = intent.getExtras().getString(BundleConstant.EXTRA_TWO); - showToRepoBtn = intent.getExtras().getBoolean(BundleConstant.EXTRA_THREE); - if (commitModel != null) { - sendToView(CommitPagerMvp.View::onSetup); - return; - } else if (!InputHelper.isEmpty(sha) && !InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - makeRestCall(RestProvider.getRepoService(isEnterprise()) - .getCommit(login, repoId, sha) - .flatMap(commit -> { - if (commit.getGitCommit() != null && commit.getGitCommit().getMessage() != null) { - MarkdownModel markdownModel = new MarkdownModel(); - markdownModel.setContext(login + "/" + repoId); - markdownModel.setText(commit.getGitCommit().getMessage()); - return RestProvider.getRepoService(isEnterprise()).convertReadmeToHtml(markdownModel); - } - return Observable.just(commit); - }, (commit, u) -> { - if (!InputHelper.isEmpty(u) && u instanceof String) { - commit.getGitCommit().setMessage(u.toString()); - } - return commit; - }), commit -> { - commitModel = commit; - commitModel.setRepoId(repoId); - commitModel.setLogin(login); - sendToView(CommitPagerMvp.View::onSetup); - manageObservable(commitModel.save(commitModel).toObservable()); - }); - return; - } - } - sendToView(CommitPagerMvp.View::onSetup); - } - - @Override public void onWorkOffline(@NonNull String sha, @NonNull String repoId, @NonNull String login) { - manageDisposable(RxHelper.getObservable(Commit.getCommit(sha, repoId, login)) - .subscribe(commit -> { - commitModel = commit; - sendToView(CommitPagerMvp.View::onSetup); - })); - } - - @Override public String getLogin() { - return login; - } - - @Override public String getRepoId() { - return repoId; - } - - @Override public boolean showToRepoBtn() { - return showToRepoBtn; - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsFragment.java deleted file mode 100644 index c699ac4d3..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsFragment.java +++ /dev/null @@ -1,316 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.details.comments; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.provider.timeline.ReactionsProvider; -import com.fastaccess.ui.adapter.IssuesTimelineAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.editor.EditorActivity; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; -import com.fastaccess.ui.modules.repos.reactions.ReactionsDialogFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -public class CommitCommentsFragment extends BaseFragment implements CommitCommentsMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @State HashMap toggleMap = new LinkedHashMap<>(); - private CommentEditorFragment.CommentListener commentsCallback; - private IssuesTimelineAdapter adapter; - private OnLoadMore onLoadMore; - - public static CommitCommentsFragment newInstance(@NonNull String login, @NonNull String repoId, @NonNull String sha) { - CommitCommentsFragment view = new CommitCommentsFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, sha) - .end()); - return view; - } - - @SuppressWarnings("unchecked") @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof CommentEditorFragment.CommentListener) { - commentsCallback = (CommentEditorFragment.CommentListener) getParentFragment(); - } else if (context instanceof CommentEditorFragment.CommentListener) { - commentsCallback = (CommentEditorFragment.CommentListener) context; - } else { - throw new IllegalArgumentException(String.format("%s or parent fragment must implement CommentEditorFragment.CommentListener", - context.getClass().getSimpleName())); - } - } - - @Override public void onDetach() { - commentsCallback = null; - super.onDetach(); - } - - @Override protected int fragmentLayout() { - return R.layout.fab_micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (savedInstanceState == null) getPresenter().onFragmentCreated(getArguments()); - stateLayout.setEmptyText(R.string.no_comments); - recycler.setEmptyView(stateLayout, refresh); - recycler.setItemViewCacheSize(30); - refresh.setOnRefreshListener(this); - stateLayout.setOnReloadListener(this); - adapter = new IssuesTimelineAdapter(getPresenter().getComments(), this, true, - this, getArguments().getString(BundleConstant.EXTRA), null); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addNormalSpacingDivider(); - if (getPresenter().getComments().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, null); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void onRemove(@NonNull TimelineModel comment) { - hideProgress(); - adapter.removeItem(comment); - } - - @Override public void hideProgress() { - super.hideProgress(); - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public CommitCommentsPresenter providePresenter() { - return new CommitCommentsPresenter(); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter()); - } - return onLoadMore; - } - - @Override public void onEditComment(@NonNull Comment item) { - Intent intent = new Intent(getContext(), EditorActivity.class); - intent.putExtras(Bundler - .start() - .put(BundleConstant.ID, getPresenter().repoId()) - .put(BundleConstant.EXTRA_TWO, getPresenter().login()) - .put(BundleConstant.EXTRA_THREE, getPresenter().sha()) - .put(BundleConstant.EXTRA_FOUR, item.getId()) - .put(BundleConstant.EXTRA, item.getBody()) - .put(BundleConstant.EXTRA_TYPE, BundleConstant.ExtraType.EDIT_COMMIT_COMMENT_EXTRA) - .putStringArrayList("participants", CommentsHelper.getUsersByTimeline(adapter.getData())) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise()) - .end()); - View view = getActivity() != null && getActivity().findViewById(R.id.fab) != null ? getActivity().findViewById(R.id.fab) : recycler; - ActivityHelper.startReveal(this, intent, view, BundleConstant.REQUEST_CODE); - } - - @Override public void onShowDeleteMsg(long id) { - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), - Bundler.start() - .put(BundleConstant.EXTRA, id) - .put(BundleConstant.YES_NO_EXTRA, true) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - - @Override public void onTagUser(@Nullable User user) { - Intent intent = new Intent(getContext(), EditorActivity.class); - intent.putExtras(Bundler - .start() - .put(BundleConstant.ID, getPresenter().repoId()) - .put(BundleConstant.EXTRA_TWO, getPresenter().login()) - .put(BundleConstant.EXTRA_THREE, getPresenter().sha()) - .put(BundleConstant.EXTRA, user != null ? "@" + user.getLogin() : "") - .put(BundleConstant.EXTRA_TYPE, BundleConstant.ExtraType.NEW_COMMIT_COMMENT_EXTRA) - .putStringArrayList("participants", CommentsHelper.getUsersByTimeline(adapter.getData())) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise()) - .end()); - View view = getActivity() != null && getActivity().findViewById(R.id.fab) != null ? getActivity().findViewById(R.id.fab) : recycler; - ActivityHelper.startReveal(this, intent, view, BundleConstant.REQUEST_CODE); - - } - - @Override public void onReply(User user, String message) { - onTagUser(user); - } - - @Override public void showReactionsPopup(@NonNull ReactionTypes reactionTypes, @NonNull String login, @NonNull String repoId, long commentId) { - ReactionsDialogFragment.newInstance(login, repoId, reactionTypes, commentId, ReactionsProvider.COMMIT) - .show(getChildFragmentManager(), "ReactionsDialogFragment"); - } - - @Override public void addComment(@NonNull Comment newComment) { - hideBlockingProgress(); - if (adapter != null) { - adapter.addItem(TimelineModel.constructComment(newComment)); - } - if (commentsCallback != null) commentsCallback.onClearEditText(); - } - - @Override public void onDestroyView() { - recycler.removeOnScrollListener(getLoadMore()); - super.onDestroyView(); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK) { - if (requestCode == BundleConstant.REQUEST_CODE) { - if (data == null) { - onRefresh(); - return; - } - Bundle bundle = data.getExtras(); - if (bundle != null) { - boolean isNew = bundle.getBoolean(BundleConstant.EXTRA); - Comment commentsModel = bundle.getParcelable(BundleConstant.ITEM); - if (commentsModel == null) { - onRefresh(); // shit happens, refresh()? - return; - } - adapter.notifyDataSetChanged(); - if (isNew) { - adapter.addItem(TimelineModel.constructComment(commentsModel)); - recycler.smoothScrollToPosition(adapter.getItemCount()); - } else { - int position = adapter.getItem(TimelineModel.constructComment(commentsModel)); - if (position != -1) { - adapter.swapItem(TimelineModel.constructComment(commentsModel), position); - recycler.smoothScrollToPosition(position); - } else { - adapter.addItem(TimelineModel.constructComment(commentsModel)); - recycler.smoothScrollToPosition(adapter.getItemCount()); - } - } - } else { - onRefresh(); // bundle size is too large? refresh the api - } - } - } - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk) { - getPresenter().onHandleDeletion(bundle); - } - } - - @Override public void onToggle(long position, boolean isCollapsed) { - toggleMap.put(position, isCollapsed); - } - - @Override public boolean isCollapsed(long position) { - Boolean toggle = toggleMap.get(position); - return toggle != null && toggle; - } - - @Override public boolean isPreviouslyReacted(long id, int vId) { - return getPresenter().isPreviouslyReacted(id, vId); - } - - @Override public boolean isCallingApi(long id, int vId) { - return getPresenter().isCallingApi(id, vId); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - @Override public void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } - - @Override public void onHandleComment(@NonNull String text, @Nullable Bundle bundle) { - getPresenter().onHandleComment(text, bundle); - } - - @NonNull @Override public ArrayList getNamesToTags() { - return CommentsHelper.getUsersByTimeline(adapter.getData()); - } - - @Override public void hideBlockingProgress() { - hideProgress(); - super.hideProgress(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsMvp.java deleted file mode 100644 index 09d53ac70..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsMvp.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.details.comments; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.adapter.callback.ReactionsCallback; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 20 Nov 2016, 11:10 AM - */ - -interface CommitCommentsMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, - android.view.View.OnClickListener, OnToggleView, ReactionsCallback { - - void onNotifyAdapter(@Nullable List items, int page); - - void onRemove(@NonNull TimelineModel comment); - - @NonNull OnLoadMore getLoadMore(); - - void onEditComment(@NonNull Comment item); - - void onShowDeleteMsg(long id); - - void onTagUser(@Nullable User user); - - void onReply(User user, String message); - - void showReactionsPopup(@NonNull ReactionTypes reactionTypes, @NonNull String login, @NonNull String repoId, long commentId); - - void addComment(@NonNull Comment newComment); - - void showReload(); - - void onHandleComment(@NonNull String text, @Nullable Bundle bundle); - - @NonNull List getNamesToTags(); - - void hideBlockingProgress(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseMvp.PaginationListener, BaseViewHolder.OnItemClickListener { - - void onFragmentCreated(@Nullable Bundle bundle); - - @NonNull ArrayList getComments(); - - void onHandleDeletion(@Nullable Bundle bundle); - - void onWorkOffline(); - - @NonNull String repoId(); - - @NonNull String login(); - - String sha(); - - boolean isPreviouslyReacted(long commentId, int vId); - - boolean isCallingApi(long id, int vId); - - void onHandleComment(@NonNull String text, @Nullable Bundle bundle); - } - - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsPresenter.java deleted file mode 100644 index f6a6785b1..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/comments/CommitCommentsPresenter.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.details.comments; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.PopupMenu; - -import com.fastaccess.R; -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.provider.timeline.ReactionsProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 11 Nov 2016, 12:36 PM - */ - -class CommitCommentsPresenter extends BasePresenter implements CommitCommentsMvp.Presenter { - private ArrayList comments = new ArrayList<>(); - private ReactionsProvider reactionsProvider; - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String sha; - @com.evernote.android.state.State boolean isCollaborator; - - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - if (page > lastPage || lastPage == 0) { - sendToView(CommitCommentsMvp.View::hideProgress); - return false; - } - if (page == 1) { - manageObservable(RestProvider.getRepoService(isEnterprise()).isCollaborator(login, repoId, - Login.getUser().getLogin()) - .doOnNext(booleanResponse -> isCollaborator = booleanResponse.code() == 204)); - } - setCurrentPage(page); - makeRestCall(RestProvider.getRepoService(isEnterprise()).getCommitComments(login, repoId, sha, page) - .flatMap(listResponse -> { - lastPage = listResponse.getLast(); - return TimelineModel.construct(listResponse.getItems()); - }) - .doOnComplete(() -> { - if (lastPage <= 1) { - sendToView(CommitCommentsMvp.View::showReload); - } - }), - listResponse -> sendToView(view -> view.onNotifyAdapter(listResponse, page))); - return true; - } - - @Override public void onFragmentCreated(@Nullable Bundle bundle) { - if (bundle == null) throw new NullPointerException("Bundle is null?"); - repoId = bundle.getString(BundleConstant.ID); - login = bundle.getString(BundleConstant.EXTRA); - sha = bundle.getString(BundleConstant.EXTRA_TWO); - } - - @NonNull @Override public ArrayList getComments() { - return comments; - } - - @Override public void onHandleDeletion(@Nullable Bundle bundle) { - if (bundle != null) { - long commId = bundle.getLong(BundleConstant.EXTRA, 0); - if (commId != 0) { - makeRestCall(RestProvider.getRepoService(isEnterprise()).deleteComment(login, repoId, commId) - , booleanResponse -> sendToView(view -> { - if (booleanResponse.code() == 204) { - Comment comment = new Comment(); - comment.setId(commId); - view.onRemove(TimelineModel.constructComment(comment)); - } else { - view.showMessage(R.string.error, R.string.error_deleting_comment); - } - })); - } - } - } - - @Override public void onWorkOffline() { - if (comments.isEmpty()) { - manageDisposable(RxHelper.getObservable(Comment.getCommitComments(repoId(), login(), sha).toObservable()) - .flatMap(TimelineModel::construct) - .subscribe(models -> sendToView(view -> view.onNotifyAdapter(models, 1)))); - } else { - sendToView(CommitCommentsMvp.View::hideProgress); - } - } - - @NonNull @Override public String repoId() { - return repoId; - } - - @NonNull @Override public String login() { - return login; - } - - @Override public String sha() { - return sha; - } - - @Override public boolean isPreviouslyReacted(long commentId, int vId) { - return getReactionsProvider().isPreviouslyReacted(commentId, vId); - } - - @Override public boolean isCallingApi(long id, int vId) { - return getReactionsProvider().isCallingApi(id, vId); - } - - @Override public void onHandleComment(@NonNull String text, @Nullable Bundle bundle) { - CommentRequestModel model = new CommentRequestModel(); - model.setBody(text); - manageDisposable(RxHelper.getObservable(RestProvider.getRepoService(isEnterprise()).postCommitComment(login, repoId, sha, model)) - .doOnSubscribe(disposable -> sendToView(view -> view.showBlockingProgress(0))) - .subscribe(comment -> sendToView(view -> view.addComment(comment)), - throwable -> { - onError(throwable); - sendToView(CommitCommentsMvp.View::hideBlockingProgress); - })); - } - - @Override public void onItemClick(int position, View v, TimelineModel timelineModel) { - if (getView() != null) { - Comment item = timelineModel.getComment(); - if (v.getId() == R.id.commentMenu) { - PopupMenu popupMenu = new PopupMenu(v.getContext(), v); - popupMenu.inflate(R.menu.comments_menu); - String username = Login.getUser().getLogin(); - boolean isOwner = CommentsHelper.isOwner(username, login, item.getUser().getLogin()) || isCollaborator; - popupMenu.getMenu().findItem(R.id.delete).setVisible(isOwner); - popupMenu.getMenu().findItem(R.id.edit).setVisible(isOwner); - popupMenu.setOnMenuItemClickListener(item1 -> { - if (getView() == null) return false; - if (item1.getItemId() == R.id.delete) { - getView().onShowDeleteMsg(item.getId()); - } else if (item1.getItemId() == R.id.reply) { - getView().onReply(item.getUser(), item.getBody()); - } else if (item1.getItemId() == R.id.edit) { - getView().onEditComment(item); - } else if (item1.getItemId() == R.id.share) { - ActivityHelper.shareUrl(v.getContext(), item.getHtmlUrl()); - } - return true; - }); - popupMenu.show(); - } else { - onHandleReaction(v.getId(), item.getId()); - } - } - } - - @Override public void onItemLongClick(int position, View v, TimelineModel timelineModel) { - if (v.getId() == R.id.commentMenu) { - Comment item = timelineModel.getComment(); - if (getView() != null) getView().onReply(item.getUser(), item.getBody()); - } else { - ReactionTypes reactionTypes = ReactionTypes.get(v.getId()); - if (reactionTypes != null) { - if (getView() != null) getView().showReactionsPopup(reactionTypes, login, repoId, timelineModel.getComment().getId()); - } else { - onItemClick(position, v, timelineModel); - } - } - } - - @NonNull private ReactionsProvider getReactionsProvider() { - if (reactionsProvider == null) { - reactionsProvider = new ReactionsProvider(); - } - return reactionsProvider; - } - - private void onHandleReaction(int viewId, long id) { - Observable observable = getReactionsProvider().onHandleReaction(viewId, id, login, repoId, ReactionsProvider.COMMIT, isEnterprise()); - if (observable != null) manageObservable(observable); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesFragment.java deleted file mode 100644 index eabef0963..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesFragment.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.details.files; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.CommitFileChanges; -import com.fastaccess.data.dao.CommitFileListModel; -import com.fastaccess.data.dao.CommitFileModel; -import com.fastaccess.data.dao.CommitLinesModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.adapter.CommitFilesAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.main.premium.PremiumActivity; -import com.fastaccess.ui.modules.repos.code.commit.details.CommitPagerMvp; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files.fullscreen.FullScreenFileChangeActivity; -import com.fastaccess.ui.modules.reviews.AddReviewDialogFragment; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 15 Feb 2017, 10:16 PM - */ - -public class CommitFilesFragment extends BaseFragment implements CommitFilesMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @State HashMap toggleMap = new LinkedHashMap<>(); - - private CommitPagerMvp.View viewCallback; - private CommitFilesAdapter adapter; - - public static CommitFilesFragment newInstance(@NonNull String sha, @Nullable CommitFileListModel commitFileModels) { - CommitFilesFragment view = new CommitFilesFragment(); - if (commitFileModels != null) { - CommitFilesSingleton.getInstance().putFiles(sha, commitFileModels); - } - Bundle bundle = Bundler.start().put(BundleConstant.ID, sha).end(); - view.setArguments(bundle); - return view; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof CommitPagerMvp.View) { - viewCallback = (CommitPagerMvp.View) getParentFragment(); - } else if (context instanceof CommitPagerMvp.View) { - viewCallback = (CommitPagerMvp.View) context; - } - } - - @Override public void onDetach() { - viewCallback = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items) { - hideProgress(); - if (items != null) { - adapter.insertItems(items); - } - } - - @Override public void onCommentAdded(@NonNull Comment newComment) { - hideProgress(); - if (viewCallback != null) { - viewCallback.onAddComment(newComment); - } - } - - @Override public void clearAdapter() { - refresh.setRefreshing(true); - adapter.clear(); - } - - @Override public void onOpenForResult(int position, CommitFileChanges model) { - FullScreenFileChangeActivity.Companion.startActivityForResult(this, model, position, true); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == Activity.RESULT_OK) { - if (requestCode == FullScreenFileChangeActivity.Companion.getFOR_RESULT_CODE() && data != null) { - List comments = data.getParcelableArrayListExtra(BundleConstant.ITEM); - if (comments != null && !comments.isEmpty()) { - if (viewCallback != null && !InputHelper.isEmpty(viewCallback.getLogin())) { - getPresenter().onSubmit(viewCallback.getLogin(), viewCallback.getRepoId(), comments.get(0)); - } - } - } - } - super.onActivityResult(requestCode, resultCode, data); - } - - @Override public void hideProgress() { - if (refresh != null) refresh.setRefreshing(false); - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - refresh.setEnabled(false); - stateLayout.setEmptyText(R.string.no_files); - recycler.setEmptyView(stateLayout, refresh); - adapter = new CommitFilesAdapter(getPresenter().changes, this, this); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - if (getPresenter().changes.isEmpty()) getPresenter().onFragmentCreated(getArguments()); - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public CommitFilesPresenter providePresenter() { - return new CommitFilesPresenter(); - } - - @Override public void onToggle(long position, boolean isCollapsed) { - CommitFileChanges model = adapter.getItem((int) position); - if (model == null) return; - if (model.getCommitFileModel().getPatch() == null) { - if ("renamed".equalsIgnoreCase(model.getCommitFileModel().getStatus())) { - SchemeParser.launchUri(getContext(), model.getCommitFileModel().getBlobUrl()); - return; - } - ActivityHelper.startCustomTab(getActivity(), adapter.getItem((int) position).getCommitFileModel().getBlobUrl()); - } - toggleMap.put(position, isCollapsed); - } - - @Override public boolean isCollapsed(long position) { - Boolean toggle = toggleMap.get(position); - return toggle != null && toggle; - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - @Override public void onPatchClicked(int groupPosition, int childPosition, View v, CommitFileModel commit, CommitLinesModel item) { - if (item.getText().startsWith("@@")) return; - if (PrefGetter.isProEnabled()) { - AddReviewDialogFragment.Companion.newInstance(item, Bundler.start() - .put(BundleConstant.ITEM, commit.getBlobUrl()) - .put(BundleConstant.EXTRA, commit.getFilename()) - .end()) - .show(getChildFragmentManager(), "AddReviewDialogFragment"); - } else { - PremiumActivity.Companion.startActivity(getContext()); - } - } - - @Override public void onCommentAdded(@NonNull String comment, @NonNull CommitLinesModel item, Bundle bundle) { - getPresenter().onSubmitComment(comment, item, bundle); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesMvp.java deleted file mode 100644 index 7578a27ec..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesMvp.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.details.files; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.CommitFileChanges; -import com.fastaccess.data.dao.CommitLinesModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files.PullRequestFilesMvp; -import com.fastaccess.ui.modules.reviews.callback.ReviewCommentListener; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.List; - -/** - * Created by Kosh on 20 Nov 2016, 11:10 AM - */ - -interface CommitFilesMvp { - - interface View extends BaseMvp.FAView, OnToggleView, PullRequestFilesMvp.OnPatchClickListener, ReviewCommentListener { - - void onNotifyAdapter(@Nullable List items); - - void onCommentAdded(@NonNull Comment newComment); - - void clearAdapter(); - - void onOpenForResult(int position, CommitFileChanges model); - } - - interface Presenter extends BaseMvp.FAPresenter, BaseViewHolder.OnItemClickListener { - - void onFragmentCreated(@Nullable Bundle bundle); - - void onSubmitComment(@NonNull String comment, @NonNull CommitLinesModel item, @Nullable Bundle bundle); - - void onSubmit(String username, String name, CommentRequestModel commentRequestModel); - } - - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesPresenter.java deleted file mode 100644 index b28ff936c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesPresenter.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.details.files; - -import android.app.Activity; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.MenuInflater; -import android.view.View; -import android.widget.PopupMenu; - -import com.fastaccess.R; -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.CommitFileChanges; -import com.fastaccess.data.dao.CommitFileListModel; -import com.fastaccess.data.dao.CommitFileModel; -import com.fastaccess.data.dao.CommitLinesModel; -import com.fastaccess.data.dao.NameParser; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.code.CodeViewerActivity; - -import java.util.ArrayList; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 15 Feb 2017, 10:10 PM - */ - -class CommitFilesPresenter extends BasePresenter implements CommitFilesMvp.Presenter { - @com.evernote.android.state.State String sha; - ArrayList changes = new ArrayList<>(); - - @Override public void onItemClick(int position, View v, CommitFileChanges model) { - if (v.getId() == R.id.patchList) { - sendToView(view -> view.onOpenForResult(position, model)); - } else if (v.getId() == R.id.open) { - CommitFileModel item = model.getCommitFileModel(); - PopupMenu popup = new PopupMenu(v.getContext(), v); - MenuInflater inflater = popup.getMenuInflater(); - inflater.inflate(R.menu.commit_row_menu, popup.getMenu()); - popup.setOnMenuItemClickListener(item1 -> { - switch (item1.getItemId()) { - case R.id.open: - v.getContext().startActivity(CodeViewerActivity.createIntent(v.getContext(), item.getContentsUrl(), item.getBlobUrl())); - break; - case R.id.share: - ActivityHelper.shareUrl(v.getContext(), item.getBlobUrl()); - break; - case R.id.download: - Activity activity = ActivityHelper.getActivity(v.getContext()); - if (activity == null) break; - if (ActivityHelper.checkAndRequestReadWritePermission(activity)) { - RestProvider.downloadFile(v.getContext(), item.getRawUrl()); - } - break; - case R.id.copy: - AppHelper.copyToClipboard(v.getContext(), item.getBlobUrl()); - break; - } - return true; - }); - popup.show(); - } - } - - @Override public void onItemLongClick(int position, View v, CommitFileChanges item) {} - - @Override public void onFragmentCreated(@Nullable Bundle bundle) { - if (sha == null) { - if (bundle != null) { - sha = bundle.getString(BundleConstant.ID); - } - } - if (!InputHelper.isEmpty(sha)) { - CommitFileListModel commitFiles = CommitFilesSingleton.getInstance().getByCommitId(sha); - if (commitFiles != null) { - manageObservable(Observable.just(commitFiles) - .map(CommitFileChanges::construct) - .doOnSubscribe(disposable -> sendToView(CommitFilesMvp.View::clearAdapter)) - .doOnNext(commitFileChanges -> { - sendToView(view -> view.onNotifyAdapter(commitFileChanges)); - }) - .doOnComplete(() -> sendToView(BaseMvp.FAView::hideProgress))); - } - } else { - throw new NullPointerException("Bundle is null"); - } - } - - @Override public void onSubmitComment(@NonNull String comment, @NonNull CommitLinesModel item, @Nullable Bundle bundle) { - if (bundle != null) { - String blob = bundle.getString(BundleConstant.ITEM); - String path = bundle.getString(BundleConstant.EXTRA); - if (path == null || sha == null) return; - CommentRequestModel commentRequestModel = new CommentRequestModel(); - commentRequestModel.setBody(comment); - commentRequestModel.setPath(path); - commentRequestModel.setPosition(item.getPosition()); - commentRequestModel.setLine(item.getRightLineNo() > 0 ? item.getRightLineNo() : item.getLeftLineNo()); - NameParser nameParser = new NameParser(blob); - onSubmit(nameParser.getUsername(), nameParser.getName(), commentRequestModel); - } - } - - @Override public void onSubmit(String username, String name, CommentRequestModel commentRequestModel) { - makeRestCall(RestProvider.getRepoService(isEnterprise()).postCommitComment(username, name, sha, - commentRequestModel), newComment -> sendToView(view -> view.onCommentAdded(newComment))); - } - - @Override protected void onDestroy() { - CommitFilesSingleton.getInstance().clear(); - super.onDestroy(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesSingleton.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesSingleton.java deleted file mode 100644 index 53d2b166c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/details/files/CommitFilesSingleton.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.details.files; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.CommitFileListModel; - -import java.util.Hashtable; -import java.util.Map; - -/** - * Created by Kosh on 27 Mar 2017, 7:28 PM - * Commits files could be so freaking large, so having this will avoid transactionToLargeException. - */ - -class CommitFilesSingleton { - private static final CommitFilesSingleton SINGLETON = new CommitFilesSingleton(); - - static CommitFilesSingleton getInstance() { - return SINGLETON; - } - - private Map files = new Hashtable<>(); - - private CommitFilesSingleton() {} - - void putFiles(@NonNull String id, @NonNull CommitFileListModel commitFiles) { - clear(); - files.put(id, commitFiles); - } - - @Nullable CommitFileListModel getByCommitId(@NonNull String id) { - return files.get(id); - } - - void clear() { - files.clear(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/history/FileCommitHistoryActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/history/FileCommitHistoryActivity.kt deleted file mode 100644 index 4c81c5433..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/history/FileCommitHistoryActivity.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.history - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.view.MenuItem -import com.evernote.android.state.State -import com.fastaccess.R -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.repos.RepoPagerActivity -import com.fastaccess.ui.modules.repos.code.commit.RepoCommitsFragment - -/** - * Created by Hashemsergani on 02/09/2017. - */ -class FileCommitHistoryActivity : BaseActivity>() { - - @State var login: String? = null - @State var repoId: String? = null - - override fun layout(): Int = R.layout.activity_fragment_layout - - override fun providePresenter(): BasePresenter = BasePresenter() - - override fun isTransparent(): Boolean = true - - override fun canBack(): Boolean = true - - override fun isSecured(): Boolean = false - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - if (savedInstanceState == null && intent != null) { - repoId = intent.extras.getString(BundleConstant.ID) - login = intent.extras.getString(BundleConstant.EXTRA) - supportFragmentManager - .beginTransaction() - .replace(R.id.container, RepoCommitsFragment.newInstance(intent.extras!!), RepoCommitsFragment::class.java.simpleName) - .commit() - } - } - - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - if (item?.itemId == android.R.id.home) { - repoId?.let { - val intent = RepoPagerActivity.createIntent(this, it, login!!) - val bundle = intent.extras - bundle.putBoolean(BundleConstant.IS_ENTERPRISE, isEnterprise) - intent.putExtras(bundle) - startActivity(intent) - finish() - } - return true - } - return super.onOptionsItemSelected(item) - } - - companion object { - fun startActivity(context: Context, login: String, repoId: String, branch: String, path: String, - enterprise: Boolean) { - val intent = Intent(context, FileCommitHistoryActivity::class.java) - intent.putExtras(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, branch) - .put(BundleConstant.EXTRA_THREE, path) - .put(BundleConstant.IS_ENTERPRISE, enterprise) - .end()) - context.startActivity(intent) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/viewer/FullCommitFileActivity.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/viewer/FullCommitFileActivity.java deleted file mode 100644 index 19e53eb49..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/commit/viewer/FullCommitFileActivity.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.commit.viewer; - -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.view.Menu; -import android.view.MenuItem; - -import com.fastaccess.R; -import com.fastaccess.data.dao.CommitFileModel; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.code.CodeViewerActivity; -import com.fastaccess.ui.widgets.DiffLineSpan; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.SpannableBuilder; - -import net.grandcentrix.thirtyinch.TiPresenter; - -import butterknife.BindString; -import butterknife.BindView; -import com.evernote.android.state.State; - -/** - * Created by Kosh on 24 Apr 2017, 2:53 PM - */ - -public class FullCommitFileActivity extends BaseActivity { - @BindView(R.id.textView) FontTextView textView; - - - @State CommitFileModel commitFileModel; - @BindView(R.id.changes) FontTextView changes; - @BindView(R.id.addition) FontTextView addition; - @BindView(R.id.deletion) FontTextView deletion; - @BindView(R.id.status) FontTextView status; - @BindString(R.string.changes) String changesText; - @BindString(R.string.addition) String additionText; - @BindString(R.string.deletion) String deletionText; - @BindString(R.string.status) String statusText; - - public static void start(@NonNull Context context, @NonNull CommitFileModel fileModel) { - Intent starter = new Intent(context, FullCommitFileActivity.class); - starter.putExtras(Bundler.start() - .put(BundleConstant.ITEM, fileModel) - .end()); - context.startActivity(starter); - } - - @Override protected int layout() { - return R.layout.commit_file_full_layout; - } - - @Override protected boolean isTransparent() { - return false; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState == null) { - commitFileModel = getIntent().getExtras().getParcelable(BundleConstant.ITEM); - } - if (commitFileModel == null || commitFileModel.getPatch() == null) { - finish(); - return; - } - changes.setText(SpannableBuilder.builder() - .append(changesText) - .append("\n") - .bold(String.valueOf(commitFileModel.getChanges()))); - addition.setText(SpannableBuilder.builder() - .append(additionText) - .append("\n") - .bold(String.valueOf(commitFileModel.getAdditions()))); - deletion.setText(SpannableBuilder.builder() - .append(deletionText) - .append("\n") - .bold(String.valueOf(commitFileModel.getDeletions()))); - status.setText(SpannableBuilder.builder() - .append(statusText) - .append("\n") - .bold(String.valueOf(commitFileModel.getStatus()))); - setTitle(Uri.parse(commitFileModel.getFilename()).getLastPathSegment()); - textView.setText(DiffLineSpan.getSpannable(commitFileModel.getPatch(), - ViewHelper.getPatchAdditionColor(this), - ViewHelper.getPatchDeletionColor(this), - ViewHelper.getPatchRefColor(this))); - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.commit_row_menu, menu); - return super.onCreateOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.open: - startActivity(CodeViewerActivity.createIntent(this, commitFileModel.getContentsUrl(), commitFileModel.getBlobUrl())); - return true; - case R.id.share: - ActivityHelper.shareUrl(this, commitFileModel.getBlobUrl()); - return true; - case R.id.download: - if (ActivityHelper.checkAndRequestReadWritePermission(this)) { - RestProvider.downloadFile(this, commitFileModel.getRawUrl()); - } - return true; - case R.id.copy: - AppHelper.copyToClipboard(this, commitFileModel.getBlobUrl()); - return true; - default: - return super.onOptionsItemSelected(item); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsFragment.java deleted file mode 100644 index 18f7fbf76..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsFragment.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.contributors; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.UsersAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class RepoContributorsFragment extends BaseFragment implements RepoContributorsMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private UsersAdapter adapter; - - public static RepoContributorsFragment newInstance(@NonNull String repoId, @NonNull String login) { - RepoContributorsFragment view = new RepoContributorsFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .end()); - return view; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, therefore, issues can't be proceeded."); - } - stateLayout.setEmptyText(R.string.no_contributors); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - recycler.addKeyLineDivider(); - adapter = new UsersAdapter(getPresenter().getUsers(), true); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments()); - } else if (getPresenter().getUsers().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public RepoContributorsPresenter providePresenter() { - return new RepoContributorsPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @SuppressWarnings("unchecked") @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()); - } - return onLoadMore; - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getArguments().getString(BundleConstant.EXTRA)); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsMvp.java deleted file mode 100644 index 767ccd6d7..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsMvp.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.contributors; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface RepoContributorsMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - void onFragmentCreated(@NonNull Bundle bundle); - - void onWorkOffline(); - - @NonNull ArrayList getUsers(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsPresenter.java deleted file mode 100644 index 784d8d3bf..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/contributors/RepoContributorsPresenter.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.contributors; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class RepoContributorsPresenter extends BasePresenter implements RepoContributorsMvp.Presenter { - - private ArrayList users = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State String login; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable Object parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(RepoContributorsMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getRepoService(isEnterprise()).getContributors(login, repoId, page), - response -> { - if (response != null) { - lastPage = response.getLast(); - } - sendToView(view -> view.onNotifyAdapter(response != null ? response.getItems() : null, page)); - }); - return true; - } - - @Override public void onFragmentCreated(@NonNull Bundle bundle) { - repoId = bundle.getString(BundleConstant.ID); - login = bundle.getString(BundleConstant.EXTRA); - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - onCallApi(1, null); - } - } - - @Override public void onError(@NonNull Throwable throwable) { - onWorkOffline(); - super.onError(throwable); - } - - @Override public void onWorkOffline() { - sendToView(BaseMvp.FAView::hideProgress); - } - - @NonNull @Override public ArrayList getUsers() { - return users; - } - - @Override public void onItemClick(int position, View v, User item) {} - - @Override public void onItemLongClick(int position, View v, User item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesFragment.java deleted file mode 100644 index 9bff65b5b..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesFragment.java +++ /dev/null @@ -1,253 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.files; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.view.MenuInflater; -import android.view.View; -import android.widget.PopupMenu; - -import com.fastaccess.R; -import com.fastaccess.data.dao.EditRepoFileModel; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.RepoFile; -import com.fastaccess.data.dao.types.FilesType; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.FileHelper; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.markdown.MarkDownProvider; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.adapter.RepoFilesAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.code.CodeViewerActivity; -import com.fastaccess.ui.modules.main.premium.PremiumActivity; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.code.files.activity.RepoFilesActivity; -import com.fastaccess.ui.modules.repos.code.files.paths.RepoFilePathFragment; -import com.fastaccess.ui.modules.repos.git.EditRepoFileActivity; -import com.fastaccess.ui.modules.repos.git.delete.DeleteFileBottomSheetFragment; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import butterknife.BindView; - -/** - * Created by Kosh on 18 Feb 2017, 2:10 AM - */ - -public class RepoFilesFragment extends BaseFragment implements RepoFilesMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private RepoFilesAdapter adapter; - private Login login; - private RepoFilePathFragment parentFragment; - private RepoPagerMvp.View repoCallback; - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof RepoPagerMvp.View) { - repoCallback = (RepoPagerMvp.View) getParentFragment(); - } else if (context instanceof RepoPagerMvp.View) { - repoCallback = (RepoPagerMvp.View) context; - } - } - - @Override public void onDetach() { - repoCallback = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter() { - hideProgress(); - adapter.notifyDataSetChanged(); - } - - @Override public void onItemClicked(@NonNull RepoFile model) { - if (refresh.isRefreshing()) return; - if (model.getType() == FilesType.dir) { - if (getParent() != null) { - getParent().onAppendPath(model); - } - } else { - if (model.getSize() == 0 && InputHelper.isEmpty(model.getDownloadUrl()) && !InputHelper.isEmpty(model.getGitUrl())) { - RepoFilesActivity.startActivity(getContext(), model.getGitUrl().replace("trees/", ""), isEnterprise()); - } else { - String url = InputHelper.isEmpty(model.getDownloadUrl()) ? model.getUrl() : model.getDownloadUrl(); - if (InputHelper.isEmpty(url)) return; - if (model.getSize() > FileHelper.ONE_MB && !MarkDownProvider.isImage(url)) { - MessageDialogView.newInstance(getString(R.string.big_file), getString(R.string.big_file_description), - false, true, Bundler.start() - .put(BundleConstant.EXTRA, model.getDownloadUrl()) - .put(BundleConstant.YES_NO_EXTRA, true) - .end()) - .show(getChildFragmentManager(), "MessageDialogView"); - } else { - CodeViewerActivity.startActivity(getContext(), url, model.getHtmlUrl()); - } - } - } - } - - @Override public void onMenuClicked(int position, @NonNull RepoFile item, View v) { - if (login == null) { - login = Login.getUser(); - } - if (refresh.isRefreshing()) return; - boolean isOwner = login.getLogin().equals(getPresenter().login) || (repoCallback != null && repoCallback.isCollaborator()); - PopupMenu popup = new PopupMenu(getContext(), v); - MenuInflater inflater = popup.getMenuInflater(); - inflater.inflate(R.menu.download_share_menu, popup.getMenu()); - popup.getMenu().findItem(R.id.download).setVisible(item.getType() == FilesType.file); - boolean canOpen = canOpen(item); - popup.getMenu().findItem(R.id.editFile).setVisible(isOwner && item.getType() == FilesType.file && canOpen); - popup.getMenu().findItem(R.id.deleteFile).setVisible(isOwner && item.getType() == FilesType.file); - popup.setOnMenuItemClickListener(item1 -> { - switch (item1.getItemId()) { - case R.id.share: - ActivityHelper.shareUrl(v.getContext(), item.getHtmlUrl()); - break; - case R.id.download: - if (ActivityHelper.checkAndRequestReadWritePermission(getActivity())) { - RestProvider.downloadFile(getContext(), item.getDownloadUrl()); - } - break; - case R.id.copy: - AppHelper.copyToClipboard(v.getContext(), !InputHelper.isEmpty(item.getHtmlUrl()) ? item.getHtmlUrl() : item.getUrl()); - break; - case R.id.editFile: - if (PrefGetter.isProEnabled() || PrefGetter.isAllFeaturesUnlocked()) { - if (canOpen) { - EditRepoFileModel fileModel = new EditRepoFileModel(getPresenter().login, getPresenter().repoId, - item.getPath(), getPresenter().ref, item.getSha(), item.getDownloadUrl(), item.getName(), true); - EditRepoFileActivity.Companion.startForResult(this, fileModel, isEnterprise()); - } - } else { - PremiumActivity.Companion.startActivity(getContext()); - } - break; - case R.id.deleteFile: - if (PrefGetter.isProEnabled() || PrefGetter.isAllFeaturesUnlocked()) { - DeleteFileBottomSheetFragment.Companion.newInstance(position, item.getName()) - .show(getChildFragmentManager(), DeleteFileBottomSheetFragment.class.getSimpleName()); - } else { - PremiumActivity.Companion.startActivity(getContext()); - } - break; - } - return true; - }); - popup.show(); - } - - @Override public void onSetData(@NonNull String login, @NonNull String repoId, @NonNull String path, - @NonNull String ref, boolean clear, @Nullable RepoFile toAppend) { - getPresenter().onInitDataAndRequest(login, repoId, path, ref, clear, toAppend); - } - - @Override public boolean isRefreshing() { - return refresh.isRefreshing(); - } - - @Override public void onUpdateTab(@Nullable RepoFile toAppend) { - getParent().onAppenedtab(toAppend); - } - - @Override protected int fragmentLayout() { - return R.layout.vertical_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - stateLayout.setEmptyText(R.string.no_files); - refresh.setOnRefreshListener(this); - stateLayout.setOnReloadListener(v -> onRefresh()); - recycler.setEmptyView(stateLayout, refresh); - adapter = new RepoFilesAdapter(getPresenter().getFiles()); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - fastScroller.attachRecyclerView(recycler); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public RepoFilesPresenter providePresenter() { - return new RepoFilesPresenter(); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(null); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk && bundle != null) { - String url = bundle.getString(BundleConstant.EXTRA); - if (!InputHelper.isEmpty(url)) { - if (ActivityHelper.checkAndRequestReadWritePermission(getActivity())) { - RestProvider.downloadFile(getContext(), url); - } - } - } - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK && requestCode == EditRepoFileActivity.EDIT_RQ) { - onRefresh(); - } - } - - @Override public void onDelete(@NonNull String message, int position) { - getPresenter().onDeleteFile(message, adapter.getItem(position), getParent() != null ? getParent().getRef() : "master"); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } - - private RepoFilePathFragment getParent() { - if (parentFragment == null) { - parentFragment = (RepoFilePathFragment) getParentFragment(); - } - return parentFragment; - } - - private boolean canOpen(@NonNull RepoFile item) { - return item.getDownloadUrl() != null && !MarkDownProvider.isImage(item.getDownloadUrl()) - && !MarkDownProvider.isArchive(item.getDownloadUrl()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesMvp.java deleted file mode 100644 index f2336720e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesMvp.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.files; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.RepoFile; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.repos.git.delete.DeleteContentFileCallback; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 20 Nov 2016, 11:10 AM - */ - -interface RepoFilesMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, DeleteContentFileCallback { - void onNotifyAdapter(); - - void onItemClicked(@NonNull RepoFile model); - - void onMenuClicked(int position, @NonNull RepoFile model, android.view.View view); - - void onSetData(@NonNull String login, @NonNull String repoId, @NonNull String path, @NonNull String ref, - boolean clear, @Nullable RepoFile toAppend); - - boolean isRefreshing(); - - void onUpdateTab(@Nullable RepoFile toAppend); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener { - - @NonNull ArrayList getFiles(); - - void onWorkOffline(); - - void onCallApi(@Nullable RepoFile toAppend); - - void onInitDataAndRequest(@NonNull String login, @NonNull String repoId, @NonNull String path, - @NonNull String ref, boolean clear, @Nullable RepoFile toAppend); - - @Nullable List getCachedFiles(@NonNull String url, @NonNull String ref); - - void onDeleteFile(@NonNull String message, @NonNull RepoFile item, @NonNull String branch); - } - - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesPresenter.java deleted file mode 100644 index 608ef03b2..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/RepoFilesPresenter.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.files; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.CommitRequestModel; -import com.fastaccess.data.dao.RepoPathsManager; -import com.fastaccess.data.dao.model.RepoFile; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.repos.code.commit.history.FileCommitHistoryActivity; - -import java.util.ArrayList; -import java.util.List; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 15 Feb 2017, 10:10 PM - */ - -class RepoFilesPresenter extends BasePresenter implements RepoFilesMvp.Presenter { - private ArrayList files = new ArrayList<>(); - private RepoPathsManager pathsModel = new RepoPathsManager(); - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String path; - @com.evernote.android.state.State String ref; - - @Override public void onItemClick(int position, View v, RepoFile item) { - if (getView() == null) return; - if (v.getId() != R.id.menu) { - getView().onItemClicked(item); - } else { - getView().onMenuClicked(position, item, v); - } - } - - @Override public void onItemLongClick(int position, View v, RepoFile item) { - FileCommitHistoryActivity.Companion.startActivity(v.getContext(), login, repoId, ref, item.getPath(), isEnterprise()); - } - - @Override public void onError(@NonNull Throwable throwable) { - onWorkOffline(); - super.onError(throwable); - } - - @NonNull @Override public ArrayList getFiles() { - return files; - } - - @Override public void onWorkOffline() { - if ((repoId == null || login == null) || !files.isEmpty()) return; - manageDisposable(RxHelper.getObservable(RepoFile.getFiles(login, repoId).toObservable()) - .flatMap(response -> { - if (response != null) { - return Observable.fromIterable(response) - .filter(repoFile -> repoFile != null && repoFile.getType() != null) - .sorted((repoFile, repoFile2) -> repoFile2.getType().compareTo(repoFile.getType())); - } - return Observable.empty(); - }) - .toList() - .subscribe(models -> { - files.addAll(models); - sendToView(RepoFilesMvp.View::onNotifyAdapter); - })); - } - - @Override public void onCallApi(@Nullable RepoFile toAppend) { - if (repoId == null || login == null) return; - makeRestCall(RestProvider.getRepoService(isEnterprise()).getRepoFiles(login, repoId, path, ref) - .flatMap(response -> { - if (response != null && response.getItems() != null) { - return Observable.fromIterable(response.getItems()) - .filter(repoFile -> repoFile.getType() != null) - .sorted((repoFile, repoFile2) -> repoFile2.getType().compareTo(repoFile.getType())); - } - return Observable.empty(); - }) - .toList().toObservable(), response -> { - files.clear(); - if (response != null) { - manageObservable(RepoFile.save(response, login, repoId)); - pathsModel.setFiles(ref, path, response); - files.addAll(response); - } - sendToView(view -> { - view.onNotifyAdapter(); - view.onUpdateTab(toAppend); - }); - }); - - } - - @Override public void onInitDataAndRequest(@NonNull String login, @NonNull String repoId, @NonNull String path, - @NonNull String ref, boolean clear, @Nullable RepoFile toAppend) { - if (clear) pathsModel.clear(); - this.login = login; - this.repoId = repoId; - this.ref = ref; - this.path = path; - List cachedFiles = getCachedFiles(path, ref); - if (cachedFiles != null && !cachedFiles.isEmpty()) { - files.clear(); - files.addAll(cachedFiles); - sendToView(view -> { - view.onNotifyAdapter(); - view.onUpdateTab(toAppend); - }); - } else { - onCallApi(toAppend); - } - } - - @Nullable @Override public List getCachedFiles(@NonNull String url, @NonNull String ref) { - return pathsModel.getPaths(url, ref); - } - - @Override public void onDeleteFile(@NonNull String message, @NonNull RepoFile item, @NonNull String branch) { - CommitRequestModel body = new CommitRequestModel(message, null, item.getSha(), branch); - makeRestCall(RestProvider.getContentService(isEnterprise()) - .deleteFile(login, repoId, item.getPath(), ref, body), - gitCommitModel -> sendToView(SwipeRefreshLayout.OnRefreshListener::onRefresh)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/activity/RepoFilesActivity.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/activity/RepoFilesActivity.java deleted file mode 100644 index 22dac63b8..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/activity/RepoFilesActivity.java +++ /dev/null @@ -1,167 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.files.activity; - -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.MenuItem; - -import com.annimon.stream.Objects; -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.NameParser; -import com.fastaccess.data.dao.model.AbstractRepo; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.main.MainActivity; -import com.fastaccess.ui.modules.repos.RepoPagerActivity; -import com.fastaccess.ui.modules.repos.code.files.paths.RepoFilePathFragment; - -import net.grandcentrix.thirtyinch.TiPresenter; - -/** - * Created by Kosh on 08 Apr 2017, 4:24 PM - */ - -public class RepoFilesActivity extends BaseActivity { - - @State String login; - @State String repoId; - - public static void startActivity(@NonNull Context context, @NonNull String url, boolean isEnterprise) { - if (!InputHelper.isEmpty(url)) { - Intent intent = ActivityHelper.editBundle(getIntent(context, url), isEnterprise); - context.startActivity(intent); - } - } - - public static Intent getIntent(@NonNull Context context, @NonNull String url) { - boolean isEnterprise = LinkParserHelper.isEnterprise(url); - if (isEnterprise) { - url = url.replace("api/v3/", ""); - if (url.contains("/raw")) { - url = url.replace("/raw", ""); - } - } - Uri uri = Uri.parse(url); - if (uri.getPathSegments() != null && uri.getPathSegments().size() > 3) { - String login = null; - String repoId = null; - String branch = null; - StringBuilder path = new StringBuilder(); - boolean startWithRepo = false; - if (uri.getPathSegments().get(0).equalsIgnoreCase("repos")) { - login = uri.getPathSegments().get(1); - repoId = uri.getPathSegments().get(2); - branch = uri.getQueryParameter("ref"); - startWithRepo = true; - } else if (uri.getPathSegments().get(0).equalsIgnoreCase("repositories")) { - String id = uri.getPathSegments().get(1); - try { - long longRepoId = Long.valueOf(id); - if (longRepoId != 0) { - Repo repo = AbstractRepo.getRepo(longRepoId); - if (repo != null) { - NameParser nameParser = new NameParser(repo.getHtmlUrl()); - if (nameParser.getUsername() != null && nameParser.getName() != null) { - login = nameParser.getUsername(); - repoId = nameParser.getName(); - branch = uri.getQueryParameter("ref"); - } - } - } - } catch (NumberFormatException ignored) { - return new Intent(context, MainActivity.class); - } - } else { - login = uri.getPathSegments().get(0); - repoId = uri.getPathSegments().get(1); - branch = uri.getPathSegments().get(2); - } - for (int i = startWithRepo ? 4 : 3; i < uri.getPathSegments().size() - 1; i++) { - String appendedPath = uri.getPathSegments().get(i); - path.append("/").append(appendedPath); - } - if (!InputHelper.isEmpty(repoId) && !InputHelper.isEmpty(login)) { - Intent intent = new Intent(context, RepoFilesActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, path.toString()) - .put(BundleConstant.EXTRA_THREE, branch) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - return intent; - } - return new Intent(context, MainActivity.class); - } - return new Intent(context, MainActivity.class); - } - - @Override protected int layout() { - return R.layout.toolbar_activity_layout; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } - - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState == null) { - Bundle bundle = getIntent().getExtras(); - login = bundle.getString(BundleConstant.EXTRA); - repoId = bundle.getString(BundleConstant.ID); - String path = bundle.getString(BundleConstant.EXTRA_TWO); - String defaultBranch = Objects.toString(bundle.getString(BundleConstant.EXTRA_THREE), "master"); - getSupportFragmentManager().beginTransaction() - .add(R.id.fragmentContainer, RepoFilePathFragment.newInstance(login, repoId, path, defaultBranch, true), "RepoFilePathFragment") - .commit(); - } - setTitle(String.format("%s/%s", login, repoId)); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - Intent intent = ActivityHelper.editBundle(RepoPagerActivity.createIntent(this, repoId, login), isEnterprise()); - startActivity(intent); - finish(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override public void onBackPressed() { - RepoFilePathFragment filePathView = (RepoFilePathFragment) AppHelper.getFragmentByTag(getSupportFragmentManager(), "RepoFilePathFragment"); - if (filePathView != null) { - if (filePathView.canPressBack()) { - super.onBackPressed(); - } else { - filePathView.onBackPressed(); - return; - } - } - super.onBackPressed(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathFragment.java deleted file mode 100644 index 099a5e39c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathFragment.java +++ /dev/null @@ -1,289 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.files.paths; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v7.widget.RecyclerView; -import android.view.View; - -import com.annimon.stream.Objects; -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.BranchesModel; -import com.fastaccess.data.dao.EditRepoFileModel; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.RepoFile; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.adapter.RepoFilePathsAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.main.premium.PremiumActivity; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.code.files.RepoFilesFragment; -import com.fastaccess.ui.modules.repos.extras.branches.pager.BranchesPagerFragment; -import com.fastaccess.ui.modules.repos.git.EditRepoFileActivity; -import com.fastaccess.ui.modules.search.repos.files.SearchFileActivity; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; - -import java.util.List; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 18 Feb 2017, 2:10 AM - */ - -public class RepoFilePathFragment extends BaseFragment implements RepoFilePathMvp.View { - - @BindView(R.id.recycler) RecyclerView recycler; - @BindView(R.id.toParentFolder) View toParentFolder; - @BindView(R.id.branches) FontTextView branches; - @BindView(R.id.addFile) View addFile; - private RepoPagerMvp.View repoCallback; - - @State String ref; - - private RepoFilePathsAdapter adapter; - private RepoFilesFragment repoFilesView; - - public static RepoFilePathFragment newInstance(@NonNull String login, @NonNull String repoId, @Nullable String path, - @NonNull String defaultBranch) { - return newInstance(login, repoId, path, defaultBranch, false); - } - - public static RepoFilePathFragment newInstance(@NonNull String login, @NonNull String repoId, - @Nullable String path, @NonNull String defaultBranch, - boolean forceAppendPath) { - RepoFilePathFragment view = new RepoFilePathFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, path) - .put(BundleConstant.EXTRA_THREE, defaultBranch) - .put(BundleConstant.EXTRA_FOUR, forceAppendPath) - .end()); - return view; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof RepoPagerMvp.View) { - repoCallback = (RepoPagerMvp.View) getParentFragment(); - } else if (context instanceof RepoPagerMvp.View) { - repoCallback = (RepoPagerMvp.View) context; - } - } - - @Override public void onDetach() { - repoCallback = null; - super.onDetach(); - } - - @OnClick(R.id.addFile) void onAddFile() { - if (PrefGetter.isProEnabled() || PrefGetter.isAllFeaturesUnlocked()) { - RepoFile repoFile = !adapter.isEmpty() ? adapter.getItem(adapter.getItemCount() - 1) : null; - EditRepoFileModel fileModel = new EditRepoFileModel(getPresenter().login, getPresenter().repoId, - repoFile != null ? repoFile.getPath() : "", ref, repoFile != null ? repoFile.getSha() : "", null, null, false); - EditRepoFileActivity.Companion.startForResult(this, fileModel, isEnterprise()); - } else { - PremiumActivity.Companion.startActivity(getContext()); - } - } - - @OnClick(R.id.downloadRepoFiles) void onDownloadRepoFiles() { - if (InputHelper.isEmpty(ref)) { - ref = getPresenter().getDefaultBranch(); - } - if (ActivityHelper.checkAndRequestReadWritePermission(getActivity())) { - MessageDialogView.newInstance(getString(R.string.download), getString(R.string.confirm_message), - Bundler.start() - .put(BundleConstant.YES_NO_EXTRA, true) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - } - - @OnClick(R.id.searchRepoFiles) void onSearchClicked() { - startActivity(SearchFileActivity.createIntent(getContext(), getPresenter().getLogin(), getPresenter().getRepoId(), isEnterprise())); - } - - @OnClick(R.id.toParentFolder) void onBackClicked() { - if (adapter.getItemCount() > 0) { - adapter.clear(); - getRepoFilesView().onSetData(getPresenter().getLogin(), getPresenter().getRepoId(), "", ref, false, null); - } - } - - @OnClick(R.id.branches) void onBranchesClicked() { - BranchesPagerFragment.Companion.newInstance(getPresenter().login, getPresenter().repoId) - .show(getChildFragmentManager(), "BranchesFragment"); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - recycler.smoothScrollToPosition(adapter.getItemCount() - 1); - } - - @Override public void onItemClicked(@NonNull RepoFile model, int position) { - if (getRepoFilesView().isRefreshing()) return; - getRepoFilesView().onSetData(getPresenter().getLogin(), getPresenter().getRepoId(), - Objects.toString(model.getPath(), ""), ref, false, null); - if ((position + 1) < adapter.getItemCount()) { - adapter.subList(position + 1, adapter.getItemCount()); - } - recycler.scrollToPosition(adapter.getItemCount() - 1); - } - - @Override public void onAppendPath(@NonNull RepoFile model) { - getRepoFilesView().onSetData(getPresenter().getLogin(), getPresenter().getRepoId(), - Objects.toString(model.getPath(), ""), ref, false, model); - } - - @Override public void onAppenedtab(@Nullable RepoFile repoFile) { - if (repoFile != null) { - adapter.addItem(repoFile); - recycler.scrollToPosition(adapter.getItemCount() - 1); - } - } - - @Override public void onSendData() { - if (InputHelper.isEmpty(ref)) { - ref = getPresenter().getDefaultBranch(); - } - getRepoFilesView().onSetData(getPresenter().getLogin(), getPresenter().getRepoId(), - Objects.toString(getPresenter().getPath(), ""), ref, false, null); - } - - @Override public boolean canPressBack() { - return adapter == null || adapter.getItemCount() == 0; - } - - @Override public void onBackPressed() { - if (getRepoFilesView().isRefreshing()) return; - if (adapter.getItemCount() > 1) { - adapter.removeItem(adapter.getItemCount() - 1); - RepoFile model = adapter.getItem(adapter.getItemCount() - 1); - getRepoFilesView().onSetData(getPresenter().getLogin(), getPresenter().getRepoId(), - Objects.toString(model.getPath(), ""), ref, false, null); - recycler.scrollToPosition(adapter.getItemCount() - 1); - } else { - onBackClicked(); - } - } - - @Override public void showProgress(@StringRes int resId) {} - - @Override public void hideProgress() {} - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @Override protected int fragmentLayout() { - return R.layout.repo_file_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - adapter = new RepoFilePathsAdapter(getPresenter().getPaths()); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - branches.setText(ref); - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments()); - } else if (getPresenter().getPaths().isEmpty() && !getPresenter().isApiCalled()) { - getPresenter().onFragmentCreated(getArguments()); - } - branches.setText(getPresenter().getDefaultBranch()); - if (Login.getUser().getLogin().equalsIgnoreCase(getPresenter().login) || (repoCallback != null && repoCallback.isCollaborator())) { - addFile.setVisibility(View.VISIBLE); - } - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk && bundle != null) { - boolean isDownload = bundle.getBoolean(BundleConstant.YES_NO_EXTRA); - if (isDownload) { - Uri uri = new Uri.Builder() - .scheme("https") - .authority("github.com") - .appendPath(getPresenter().getLogin()) - .appendPath(getPresenter().getRepoId()) - .appendPath("archive") - .appendPath(ref + ".zip") - .build(); - RestProvider.downloadFile(getContext(), uri.toString()); - } - } - } - - @NonNull @Override public RepoFilePathPresenter providePresenter() { - return new RepoFilePathPresenter(); - } - - @Override public void setUserVisibleHint(boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); - //noinspection ConstantConditions (for this state, it is still null!!!) - if (isSafe() && getRepoFilesView() != null) getRepoFilesView().onHiddenChanged(!isVisibleToUser); - } - - @NonNull public RepoFilesFragment getRepoFilesView() { - if (repoFilesView == null) { - repoFilesView = (RepoFilesFragment) getChildFragmentManager().findFragmentById(R.id.filesFragment); - } - return repoFilesView; - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (repoFilesView != null) repoFilesView.onScrollTop(index); - } - - @Override public void onBranchSelected(@NonNull BranchesModel branch) { - ref = branch.getName(); - branches.setText(ref); - getRepoFilesView().onSetData(getPresenter().getLogin(), getPresenter().getRepoId(), "", ref, true, null); - onBackClicked(); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK && requestCode == EditRepoFileActivity.EDIT_RQ) { - getRepoFilesView().onRefresh(); - } - } - - private void showReload() { - hideProgress(); - } - - @NonNull public String getRef() { - return !InputHelper.isEmpty(ref) ? ref : "master"; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathMvp.java deleted file mode 100644 index ff0decac5..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathMvp.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.files.paths; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.RepoFile; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.repos.extras.branches.BranchesMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 20 Nov 2016, 11:10 AM - */ - -interface RepoFilePathMvp { - - interface View extends BaseMvp.FAView, BranchesMvp.BranchSelectionListener { - void onNotifyAdapter(@Nullable List items, int page); - - void onItemClicked(@NonNull RepoFile model, int position); - - void onAppendPath(@NonNull RepoFile model); - - void onAppenedtab(@Nullable RepoFile repoFile); - - void onSendData(); - - boolean canPressBack(); - - void onBackPressed(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener { - - void onFragmentCreated(@Nullable Bundle bundle); - - @NonNull String getRepoId(); - - @NonNull String getLogin(); - - @Nullable String getPath(); - - @NonNull ArrayList getPaths(); - - String getDefaultBranch(); - } - - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathPresenter.java deleted file mode 100644 index 86b563e70..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/files/paths/RepoFilePathPresenter.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.files.paths; - -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.annimon.stream.Objects; -import com.fastaccess.data.dao.model.RepoFile; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 15 Feb 2017, 10:10 PM - */ - -class RepoFilePathPresenter extends BasePresenter implements RepoFilePathMvp.Presenter { - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String path; - @com.evernote.android.state.State String defaultBranch; - private ArrayList paths = new ArrayList<>(); - - @Override public void onItemClick(int position, View v, RepoFile item) { - if (!item.getPath().equalsIgnoreCase(path)) if (getView() != null) getView().onItemClicked(item, position); - } - - @Override public void onItemLongClick(int position, View v, RepoFile item) {} - - @Override public void onFragmentCreated(@Nullable Bundle bundle) { - if (bundle != null) { - repoId = bundle.getString(BundleConstant.ID); - login = bundle.getString(BundleConstant.EXTRA); - path = Objects.toString(bundle.getString(BundleConstant.EXTRA_TWO), ""); - defaultBranch = Objects.toString(bundle.getString(BundleConstant.EXTRA_THREE), "master"); - boolean forceAppend = bundle.getBoolean(BundleConstant.EXTRA_FOUR); - if (InputHelper.isEmpty(repoId) || InputHelper.isEmpty(login)) { - throw new NullPointerException(String.format("error, repoId(%s) or login(%s) is null", repoId, login)); - } - if (forceAppend && paths.isEmpty()) { - List repoFiles = new ArrayList<>(); - if (!InputHelper.isEmpty(path)) { - Uri uri = Uri.parse(path); - StringBuilder builder = new StringBuilder(); - if (uri.getPathSegments() != null && !uri.getPathSegments().isEmpty()) { - List pathSegments = uri.getPathSegments(); - for (int i = 0; i < pathSegments.size(); i++) { - String name = pathSegments.get(i); - RepoFile file = new RepoFile(); - if (i == 0) { - builder.append(name); - } else { - builder.append("/").append(name); - } - file.setPath(builder.toString()); - file.setName(name); - repoFiles.add(file); - } - } - if (!repoFiles.isEmpty()) { - sendToView(view -> view.onNotifyAdapter(repoFiles, 1)); - } - } - } - sendToView(RepoFilePathMvp.View::onSendData); - } else { - throw new NullPointerException("Bundle is null"); - } - } - - @NonNull @Override public String getRepoId() { - return repoId; - } - - @NonNull @Override public String getLogin() { - return login; - } - - @Nullable @Override public String getPath() { - return path; - } - - @NonNull @Override public ArrayList getPaths() { - return paths; - } - - @Override public String getDefaultBranch() { - return defaultBranch; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerFragment.java deleted file mode 100644 index e678fd8b9..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerFragment.java +++ /dev/null @@ -1,276 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.prettifier; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.design.widget.AppBarLayout; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.widget.ProgressBar; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.prettifier.pretty.PrettifyWebView; - -import butterknife.BindView; -import it.sephiroth.android.library.bottomnavigation.BottomNavigation; - -/** - * Created by Kosh on 28 Nov 2016, 9:27 PM - */ - -public class ViewerFragment extends BaseFragment implements ViewerMvp.View, AppBarLayout.OnOffsetChangedListener { - - public static final String TAG = ViewerFragment.class.getSimpleName(); - - @BindView(R.id.readmeLoader) ProgressBar loader; - @BindView(R.id.webView) PrettifyWebView webView; - @BindView(R.id.stateLayout) StateLayout stateLayout; - private AppBarLayout appBarLayout; - private BottomNavigation bottomNavigation; - private boolean isAppBarMoving; - private boolean isAppBarExpanded = true; - private boolean isAppBarListener; - @State boolean isWrap = PrefGetter.isWrapCode(); - - public static ViewerFragment newInstance(@NonNull String url, @Nullable String htmlUrl) { - return newInstance(url, htmlUrl, false); - } - - public static ViewerFragment newInstance(@NonNull String url, boolean isRepo) { - return newInstance(url, null, isRepo); - } - - public static ViewerFragment newInstance(@NonNull String url, @Nullable String htmlUrl, boolean isRepo) { - return newInstance(Bundler.start() - .put(BundleConstant.ITEM, url) - .put(BundleConstant.EXTRA_TWO, htmlUrl) - .put(BundleConstant.EXTRA, isRepo) - .end()); - } - - private static ViewerFragment newInstance(@NonNull Bundle bundle) { - ViewerFragment fragmentView = new ViewerFragment(); - fragmentView.setArguments(bundle); - return fragmentView; - } - - @Override public void onSetImageUrl(@NonNull String url, boolean isSvg) { - webView.loadImage(url, isSvg); - webView.setOnContentChangedListener(this); - webView.setVisibility(View.VISIBLE); - getActivity().invalidateOptionsMenu(); - } - - @Override public void onSetMdText(@NonNull String text, String baseUrl, boolean replace) { - webView.setVisibility(View.VISIBLE); - loader.setIndeterminate(false); - webView.setGithubContentWithReplace(text, baseUrl, replace); - webView.setOnContentChangedListener(this); - getActivity().invalidateOptionsMenu(); - } - - @Override public void onSetCode(@NonNull String text) { - webView.setVisibility(View.VISIBLE); - loader.setIndeterminate(false); - webView.setSource(text, isWrap); - webView.setOnContentChangedListener(this); - getActivity().invalidateOptionsMenu(); - } - - @Override public void onShowError(@NonNull String msg) { - hideProgress(); - showErrorMessage(msg); - } - - @Override public void onShowError(@StringRes int msg) { - hideProgress(); - onShowError(getString(msg)); - } - - @Override public void onShowMdProgress() { - loader.setIndeterminate(true); - loader.setVisibility(View.VISIBLE); - stateLayout.showProgress(); - } - - @Override public void openUrl(@NonNull String url) { - ActivityHelper.startCustomTab(getActivity(), url); - } - - @Override public void onViewAsCode() { - getPresenter().onLoadContentAsStream(); - } - - @Override public void showProgress(@StringRes int resId) { - onShowMdProgress(); - } - - @Override public void hideProgress() { - loader.setVisibility(View.GONE); - stateLayout.hideProgress(); - if (!getPresenter().isImage()) stateLayout.showReload(getPresenter().downloadedStream() == null ? 0 : 1); - } - - @Override public void showErrorMessage(@NonNull String msgRes) { - hideProgress(); - super.showErrorMessage(msgRes); - } - - @Override public void showMessage(int titleRes, int msgRes) { - hideProgress(); - super.showMessage(titleRes, msgRes); - } - - @Override public void showMessage(@NonNull String titleRes, @NonNull String msgRes) { - hideProgress(); - super.showMessage(titleRes, msgRes); - } - - @Override protected int fragmentLayout() { - return R.layout.general_viewer_layout; - } - - @NonNull @Override public ViewerPresenter providePresenter() { - return new ViewerPresenter(); - } - - @Override public void onContentChanged(int progress) { - if (loader != null) { - loader.setProgress(progress); - if (progress == 100) { - hideProgress(); - if (!getPresenter().isMarkDown() && !getPresenter().isImage()) { - webView.scrollToLine(getPresenter().url()); - } - } - } - } - - @Override public void onScrollChanged(boolean reachedTop, int scroll) { - if (AppHelper.isDeviceAnimationEnabled(getContext())) { - if (getPresenter().isRepo() && appBarLayout != null && bottomNavigation != null && webView != null) { - boolean shouldExpand = webView.getScrollY() == 0; - if (!isAppBarMoving && shouldExpand != isAppBarExpanded) { - isAppBarMoving = true; - isAppBarExpanded = shouldExpand; - bottomNavigation.setExpanded(shouldExpand, true); - appBarLayout.setExpanded(shouldExpand, true); - webView.setNestedScrollingEnabled(shouldExpand); - if (shouldExpand) - webView.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0)); - } - } - } - } - - @Override public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setHasOptionsMenu(true); - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (InputHelper.isEmpty(getPresenter().downloadedStream())) { - getPresenter().onHandleIntent(getArguments()); - } else { - if (getPresenter().isMarkDown()) { - onSetMdText(getPresenter().downloadedStream(), getPresenter().url(), false); - } else { - onSetCode(getPresenter().downloadedStream()); - } - } - getActivity().invalidateOptionsMenu(); - stateLayout.setEmptyText(R.string.no_data); - if (savedInstanceState == null) { - stateLayout.showReload(0); - } - stateLayout.setOnReloadListener(view1 -> getPresenter().onHandleIntent(getArguments())); - if (getPresenter().isRepo()) { - appBarLayout = getActivity().findViewById(R.id.appbar); - bottomNavigation = getActivity().findViewById(R.id.bottomNavigation); - - if (appBarLayout != null && !isAppBarListener) { - appBarLayout.addOnOffsetChangedListener(this); - isAppBarListener = true; - } - } - } - - @Override public void onStart() { - super.onStart(); - if (AppHelper.isDeviceAnimationEnabled(getContext())) { - if (appBarLayout != null && !isAppBarListener) { - appBarLayout.addOnOffsetChangedListener(this); - isAppBarListener = true; - } - } - } - - @Override public void onStop() { - if (AppHelper.isDeviceAnimationEnabled(getContext())) { - if (appBarLayout != null && isAppBarListener) { - appBarLayout.removeOnOffsetChangedListener(this); - isAppBarListener = false; - } - } - super.onStop(); - } - - @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.wrap_menu_option, menu); - menu.findItem(R.id.wrap).setVisible(false); - } - - @Override public void onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); - MenuItem menuItem = menu.findItem(R.id.wrap); - if (menuItem != null) { - if (getPresenter().isMarkDown() || getPresenter().isRepo() || getPresenter().isImage()) { - menuItem.setVisible(false); - } else { - menuItem.setVisible(true).setCheckable(true).setChecked(isWrap); - } - } - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.wrap) { - item.setChecked(!item.isChecked()); - isWrap = item.isChecked(); - showProgress(0); - onSetCode(getPresenter().downloadedStream()); - } - return super.onOptionsItemSelected(item); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (webView != null) webView.scrollTo(0, 0); - } - - @Override public void setUserVisibleHint(boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); - if (!isVisibleToUser && appBarLayout != null) { - appBarLayout.setVisibility(View.VISIBLE); - } - } - - @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { - verticalOffset = Math.abs(verticalOffset); - if (verticalOffset == 0 || verticalOffset == appBarLayout.getTotalScrollRange()) - isAppBarMoving = false; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerMvp.java deleted file mode 100644 index d0662e1d2..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerMvp.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.prettifier; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; - -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.prettifier.pretty.PrettifyWebView; - -/** - * Created by Kosh on 27 Nov 2016, 3:41 PM - */ - -interface ViewerMvp { - - interface View extends BaseMvp.FAView, PrettifyWebView.OnContentChangedListener { - - void onSetImageUrl(@NonNull String url, boolean isSvg); - - void onSetMdText(@NonNull String text, String baseUrl, boolean replace); - - void onSetCode(@NonNull String text); - - void onShowError(@NonNull String msg); - - void onShowError(@StringRes int msg); - - void onShowMdProgress(); - - void openUrl(@NonNull String url); - - void onViewAsCode(); - } - - interface Presenter extends BaseMvp.FAPresenter { - - void onHandleIntent(@Nullable Bundle intent); - - void onLoadContentAsStream(); - - String downloadedStream(); - - boolean isMarkDown(); - - void onWorkOffline(); - - void onWorkOnline(); - - boolean isRepo(); - - boolean isImage(); - - @NonNull String url(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerPresenter.java deleted file mode 100644 index 573659e51..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/prettifier/ViewerPresenter.java +++ /dev/null @@ -1,184 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.prettifier; - -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.webkit.MimeTypeMap; - -import com.fastaccess.R; -import com.fastaccess.data.dao.MarkdownModel; -import com.fastaccess.data.dao.model.ViewerFile; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.markdown.MarkDownProvider; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 27 Nov 2016, 3:43 PM - */ - -class ViewerPresenter extends BasePresenter implements ViewerMvp.Presenter { - private String downloadedStream; - @com.evernote.android.state.State boolean isMarkdown; - @com.evernote.android.state.State boolean isRepo; - @com.evernote.android.state.State boolean isImage; - @com.evernote.android.state.State String url; - @com.evernote.android.state.State String htmlUrl; - - @Override public void onError(@NonNull Throwable throwable) { - throwable.printStackTrace(); - int code = RestProvider.getErrorCode(throwable); - if (code == 404) { - if (!isRepo) { - sendToView(view -> view.onShowError(R.string.no_file_found)); - } - sendToView(BaseMvp.FAView::hideProgress); - } else { - if (code == 406) { - sendToView(view -> { - view.hideProgress(); - view.openUrl(url); - }); - return; - } - onWorkOffline(); - super.onError(throwable); - } - } - - @Override public void onHandleIntent(@Nullable Bundle intent) { - if (intent == null) return; - isRepo = intent.getBoolean(BundleConstant.EXTRA); - url = intent.getString(BundleConstant.ITEM); - htmlUrl = intent.getString(BundleConstant.EXTRA_TWO); - if (!InputHelper.isEmpty(url)) { - if (MarkDownProvider.isArchive(url)) { - sendToView(view -> view.onShowError(R.string.archive_file_detected_error)); - return; - } - if (isRepo) { - url = url.endsWith("/") ? (url + "readme") : (url + "/readme"); - } - onWorkOnline(); - } - } - - @Override public void onLoadContentAsStream() { - boolean isImage = MarkDownProvider.isImage(url) && !"svg".equalsIgnoreCase(MimeTypeMap.getFileExtensionFromUrl(url)); - if (isImage || MarkDownProvider.isArchive(url)) { - return; - } - makeRestCall(RestProvider.getRepoService(isEnterprise()).getFileAsStream(url), - body -> { - downloadedStream = body; - sendToView(view -> view.onSetCode(body)); - }); - } - - @Override public String downloadedStream() { - return downloadedStream; - } - - @Override public boolean isMarkDown() { - return isMarkdown; - } - - @Override public void onWorkOffline() { - if (downloadedStream == null) { - manageDisposable(RxHelper.getObservable(ViewerFile.get(url)) - .subscribe(fileModel -> { - if (fileModel != null) { - isImage = MarkDownProvider.isImage(fileModel.getFullUrl()); - if (isImage) { - sendToView(view -> view.onSetImageUrl(fileModel.getFullUrl(), false)); - } else { - downloadedStream = fileModel.getContent(); - isRepo = fileModel.isRepo(); - isMarkdown = fileModel.isMarkdown(); - sendToView(view -> { - if (isRepo || isMarkdown) { - view.onSetMdText(downloadedStream, fileModel.getFullUrl(), false); - } else { - view.onSetCode(downloadedStream); - } - }); - } - } - }, throwable -> sendToView(view -> view.showErrorMessage(throwable.getMessage())))); - } - } - - @Override public void onWorkOnline() { - isImage = MarkDownProvider.isImage(url); - if (isImage) { - if ("svg".equalsIgnoreCase(MimeTypeMap.getFileExtensionFromUrl(url))) { - makeRestCall(RestProvider.getRepoService(isEnterprise()).getFileAsStream(url), - s -> sendToView(view -> view.onSetImageUrl(s, true))); - return; - } - sendToView(view -> view.onSetImageUrl(url, false)); - return; - } - Observable streamObservable = MarkDownProvider.isMarkdown(url) - ? RestProvider.getRepoService(isEnterprise()).getFileAsHtmlStream(url) - : RestProvider.getRepoService(isEnterprise()).getFileAsStream(url); - Observable observable = isRepo ? RestProvider.getRepoService(isEnterprise()).getReadmeHtml(url) : streamObservable; - makeRestCall(observable, content -> { - downloadedStream = content; - ViewerFile fileModel = new ViewerFile(); - fileModel.setContent(downloadedStream); - fileModel.setFullUrl(url); - fileModel.setRepo(isRepo); - if (isRepo) { - fileModel.setMarkdown(true); - isMarkdown = true; - isRepo = true; - sendToView(view -> view.onSetMdText(downloadedStream, htmlUrl == null ? url : htmlUrl, false)); - } else { - isMarkdown = MarkDownProvider.isMarkdown(url); - if (isMarkdown) { - MarkdownModel model = new MarkdownModel(); - model.setText(downloadedStream); - Uri uri = Uri.parse(url); - StringBuilder baseUrl = new StringBuilder(); - for (String s : uri.getPathSegments()) { - if (!s.equalsIgnoreCase(uri.getLastPathSegment())) { - baseUrl.append("/").append(s); - } - } - model.setContext(baseUrl.toString()); - makeRestCall(RestProvider.getRepoService(isEnterprise()).convertReadmeToHtml(model), string -> { - isMarkdown = true; - downloadedStream = string; - fileModel.setMarkdown(true); - fileModel.setContent(downloadedStream); - manageObservable(fileModel.save(fileModel).toObservable()); - sendToView(view -> view.onSetMdText(downloadedStream, htmlUrl == null ? url : htmlUrl, true)); - }); - return; - } - fileModel.setMarkdown(false); - sendToView(view -> view.onSetCode(downloadedStream)); - } - manageObservable(fileModel.save(fileModel).toObservable()); - }); - } - - @Override public boolean isRepo() { - return isRepo; - } - - @Override public boolean isImage() { - return isImage; - } - - @NonNull @Override public String url() { - return url; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/ReleasesListActivity.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/ReleasesListActivity.java deleted file mode 100644 index 2b3d69e5c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/ReleasesListActivity.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.releases; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.MenuItem; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.NameParser; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.repos.RepoPagerActivity; - -/** - * Created by Kosh on 25 May 2017, 7:13 PM - */ - -public class ReleasesListActivity extends BaseActivity { - - @State String repoId; - @State String login; - - - public static Intent getIntent(@NonNull Context context, @NonNull String username, @NonNull String repoId) { - Intent intent = new Intent(context, ReleasesListActivity.class); - intent.putExtras(Bundler.start().put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, username) - .end()); - return intent; - } - - public static Intent getIntent(@NonNull Context context, @NonNull String username, @NonNull String repoId, - @NonNull String tag, boolean isEnterprise) { - Intent intent = new Intent(context, ReleasesListActivity.class); - intent.putExtras(Bundler.start().put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, username) - .put(BundleConstant.EXTRA_THREE, tag) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - return intent; - } - - public static Intent getIntent(@NonNull Context context, @NonNull String username, @NonNull String repoId, - long id, boolean isEnterprise) { - Intent intent = new Intent(context, ReleasesListActivity.class); - intent.putExtras(Bundler.start().put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, username) - .put(BundleConstant.EXTRA_TWO, id) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - return intent; - } - - @Override protected int layout() { - return R.layout.activity_fragment_layout; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public BasePresenter providePresenter() { - return new BasePresenter(); - } - - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState == null) { - if (getIntent() == null || getIntent().getExtras() == null) { - finish(); - } else { - Bundle bundle = getIntent().getExtras(); - repoId = bundle.getString(BundleConstant.ID); - login = bundle.getString(BundleConstant.EXTRA); - //noinspection ConstantConditions - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.container, RepoReleasesFragment - .newInstance(repoId, login, bundle.getString(BundleConstant.EXTRA_THREE), - bundle.getLong(BundleConstant.EXTRA_TWO))) - .commit(); - - setTaskName(repoId + "/" + login + " " + getString(R.string.releases)); - } - } - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - NameParser parser = new NameParser(""); - parser.setName(repoId); - parser.setUsername(login); - parser.setEnterprise(isEnterprise()); - RepoPagerActivity.startRepoPager(this, parser); - finish(); - return true; - } - return super.onOptionsItemSelected(item); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesFragment.java deleted file mode 100644 index b31c9dffc..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesFragment.java +++ /dev/null @@ -1,197 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.releases; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.fastaccess.R; -import com.fastaccess.data.dao.SimpleUrlsModel; -import com.fastaccess.data.dao.model.Release; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.ReleasesAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.ListDialogView; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.ArrayList; -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class RepoReleasesFragment extends BaseFragment implements RepoReleasesMvp.View { - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private ReleasesAdapter adapter; - - public static RepoReleasesFragment newInstance(@NonNull String repoId, @NonNull String login) { - RepoReleasesFragment view = new RepoReleasesFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .end()); - return view; - } - - public static RepoReleasesFragment newInstance(@NonNull String repoId, @NonNull String login, @Nullable String tag, long id) { - RepoReleasesFragment view = new RepoReleasesFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, id) - .put(BundleConstant.EXTRA_THREE, tag) - .end()); - return view; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, therefore, issues can't be proceeded."); - } - stateLayout.setEmptyText(R.string.no_releases); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - recycler.addDivider(); - adapter = new ReleasesAdapter(getPresenter().getReleases()); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments()); - } else if (getPresenter().getReleases().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public RepoReleasesPresenter providePresenter() { - return new RepoReleasesPresenter(); - } - - @SuppressWarnings("unchecked") @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()); - } - return onLoadMore; - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @Override public void onDownload(@NonNull Release item) { - ArrayList models = new ArrayList<>(); - if (!InputHelper.isEmpty(item.getZipBallUrl())) { - String url = item.getZipBallUrl(); - if (!url.endsWith(".tar.gz")) { - url = url + ".tar.gz"; - } - models.add(new SimpleUrlsModel(getString(R.string.download_as_zip), url)); - } - if (!InputHelper.isEmpty(item.getTarballUrl())) { - models.add(new SimpleUrlsModel(getString(R.string.download_as_tar), item.getTarballUrl())); - } - if (item.getAssets() != null && !item.getAssets().isEmpty()) { - ArrayList mapped = Stream.of(item.getAssets()) - .filter(value -> value != null && value.getBrowserDownloadUrl() != null) - .map(assetsModel -> new SimpleUrlsModel(String.format("%s (%s)", assetsModel.getName(), assetsModel.getDownloadCount()), - assetsModel.getBrowserDownloadUrl())) - .collect(Collectors.toCollection(ArrayList::new)); - if (mapped != null && !mapped.isEmpty()) { - models.addAll(mapped); - } - } - ListDialogView dialogView = new ListDialogView<>(); - dialogView.initArguments(getString(R.string.releases), models); - dialogView.show(getChildFragmentManager(), "ListDialogView"); - } - - @Override public void onShowDetails(@NonNull Release item) { - if (!InputHelper.isEmpty(item.getBody())) { - MessageDialogView.newInstance(!InputHelper.isEmpty(item.getName()) ? item.getName() : item.getTagName(), - item.getBody(), true, false).show(getChildFragmentManager(), MessageDialogView.TAG); - } else { - showErrorMessage(getString(R.string.no_body)); - } - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, null); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onItemSelected(SimpleUrlsModel item) { - if (ActivityHelper.checkAndRequestReadWritePermission(getActivity())) { - RestProvider.downloadFile(getContext(), item.getUrl()); - } - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesMvp.java deleted file mode 100644 index 6eff70fe0..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesMvp.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.releases; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.SimpleUrlsModel; -import com.fastaccess.data.dao.model.Release; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.dialog.ListDialogView; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface RepoReleasesMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, - android.view.View.OnClickListener, ListDialogView.onSimpleItemSelection { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onDownload(@NonNull Release item); - - void onShowDetails(@NonNull Release item); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - void onFragmentCreated(@NonNull Bundle bundle); - - void onWorkOffline(); - - @NonNull ArrayList getReleases(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesPresenter.java deleted file mode 100644 index 31206dd1f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/code/releases/RepoReleasesPresenter.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.fastaccess.ui.modules.repos.code.releases; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.model.Release; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class RepoReleasesPresenter extends BasePresenter implements RepoReleasesMvp.Presenter { - private ArrayList releases = new ArrayList<>(); - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - onWorkOffline(); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable Object parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(RepoReleasesMvp.View::hideProgress); - return false; - } - if (repoId == null || login == null) return false; - makeRestCall(RestProvider.getRepoService(isEnterprise()).getReleases(login, repoId, page), - response -> { - if (response.getItems() == null || response.getItems().isEmpty()) { - makeRestCall(RestProvider.getRepoService(isEnterprise()).getTagReleases(login, repoId, page), this::onResponse); - return; - } - onResponse(response); - }); - return true; - - } - - @Override public void onFragmentCreated(@NonNull Bundle bundle) { - repoId = bundle.getString(BundleConstant.ID); - login = bundle.getString(BundleConstant.EXTRA); - String tag = bundle.getString(BundleConstant.EXTRA_THREE); - long id = bundle.getLong(BundleConstant.EXTRA_TWO, -1); - if (!InputHelper.isEmpty(tag)) { - manageObservable(RestProvider.getRepoService(isEnterprise()).getTagRelease(login, repoId, tag) - .doOnNext(release -> { - if (release != null) { - sendToView(view -> view.onShowDetails(release)); - } - })); - } else if (id > 0) { - manageObservable(RestProvider.getRepoService(isEnterprise()).getRelease(login, repoId, id) - .doOnNext(release -> { - if (release != null) { - sendToView(view -> view.onShowDetails(release)); - } - })); - } - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - onCallApi(1, null); - } - } - - @Override public void onWorkOffline() { - if (releases.isEmpty()) { - manageDisposable(RxHelper.getSingle(Release.get(repoId, login)) - .subscribe(releasesModels -> sendToView(view -> view.onNotifyAdapter(releasesModels, 1)))); - } else { - sendToView(RepoReleasesMvp.View::hideProgress); - } - } - - @NonNull @Override public ArrayList getReleases() { - return releases; - } - - @Override public void onItemClick(int position, View v, Release item) { - if (getView() == null) return; - if (v.getId() == R.id.download) { - getView().onDownload(item); - } else { - getView().onShowDetails(item); - } - } - - @Override public void onItemLongClick(int position, View v, Release item) {} - - private void onResponse(Pageable response) { - lastPage = response.getLast(); - if (getCurrentPage() == 1) { - manageDisposable(Release.save(response.getItems(), repoId, login)); - } - sendToView(view -> view.onNotifyAdapter(response.getItems(), getCurrentPage())); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesDialogFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesDialogFragment.java deleted file mode 100644 index 1a1495003..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesDialogFragment.java +++ /dev/null @@ -1,176 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.assignees; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.adapter.AssigneesAdapter; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 22 Feb 2017, 7:23 PM - */ - -public class AssigneesDialogFragment extends BaseDialogFragment implements AssigneesMvp.View { - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @State HashMap selectionMap; - - private AssigneesAdapter adapter; - private AssigneesMvp.SelectedAssigneesListener callback; - - public static AssigneesDialogFragment newInstance(@NonNull String login, @NonNull String repoId, boolean isAssignees) { - AssigneesDialogFragment fragment = new AssigneesDialogFragment(); - fragment.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, isAssignees) - .end()); - return fragment; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof AssigneesMvp.SelectedAssigneesListener) { - callback = (AssigneesMvp.SelectedAssigneesListener) getParentFragment(); - } else if (context instanceof AssigneesMvp.SelectedAssigneesListener) { - callback = (AssigneesMvp.SelectedAssigneesListener) context; - } else { - throw new IllegalArgumentException("Parent Fragment or Activity must implement AssigneesMvp.SelectedAssigneesListener"); - } - } - - @Override public void onDetach() { - super.onDetach(); - callback = null; - } - - @Override protected int fragmentLayout() { - return R.layout.simple_footer_list_dialog; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (savedInstanceState == null) { - callApi(); - } - refresh.setOnRefreshListener(this::callApi); - stateLayout.setOnReloadListener(v -> callApi()); - boolean isAssinees = getArguments().getBoolean(BundleConstant.EXTRA_TWO); - stateLayout.setEmptyText(isAssinees ? R.string.no_assignees : R.string.no_reviewers); - recycler.setEmptyView(stateLayout, refresh); - recycler.addKeyLineDivider(); - title.setText(isAssinees ? R.string.assignees : R.string.reviewers); - adapter = new AssigneesAdapter(getPresenter().getList(), this); - recycler.setAdapter(adapter); - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public AssigneesPresenter providePresenter() { - return new AssigneesPresenter(); - } - - @Override public boolean isAssigneeSelected(int position) { - return getSelectionMap().get(position) != null; - } - - @Override public void onToggleSelection(int position, boolean select) { - if (select) { - getSelectionMap().put(position, adapter.getItem(position)); - } else { - getSelectionMap().remove(position); - } - adapter.notifyDataSetChanged(); - } - - @OnClick({R.id.cancel, R.id.ok}) public void onClick(View view) { - switch (view.getId()) { - case R.id.cancel: - dismiss(); - break; - case R.id.ok: - ArrayList labels = Stream.of(selectionMap) - .filter(value -> value.getValue() != null) - .map(Map.Entry::getValue) - .collect(Collectors.toCollection(ArrayList::new)); - callback.onSelectedAssignees(labels != null ? labels : new ArrayList<>(), getArguments().getBoolean(BundleConstant.EXTRA_TWO)); - dismiss(); - break; - } - } - - @Override public void onNotifyAdapter(@Nullable List items) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - adapter.insertItems(items); - } - - @Override public void showProgress(@StringRes int resId) { - stateLayout.showProgress(); - refresh.setRefreshing(true); - } - - @Override public void hideProgress() { - stateLayout.hideProgress(); - refresh.setRefreshing(false); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } - - public HashMap getSelectionMap() { - if (selectionMap == null) { - selectionMap = new LinkedHashMap<>(); - } - return selectionMap; - } - - private void callApi() { - //noinspection ConstantConditions - getPresenter().onCallApi(getArguments().getString(BundleConstant.EXTRA), - getArguments().getString(BundleConstant.ID), - getArguments().getBoolean(BundleConstant.EXTRA_TWO)); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesMvp.java deleted file mode 100644 index e1ae37068..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesMvp.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.assignees; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.ui.adapter.AssigneesAdapter; -import com.fastaccess.ui.base.mvp.BaseMvp; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 22 Feb 2017, 7:22 PM - */ - -public interface AssigneesMvp { - - interface SelectedAssigneesListener { - void onSelectedAssignees(@NonNull ArrayList users, boolean isAssignees); - } - - interface View extends BaseMvp.FAView, AssigneesAdapter.OnSelectAssignee { - void onNotifyAdapter(@Nullable List items); - } - - interface Presenter { - void onCallApi(@NonNull String login, @NonNull String repo, boolean isAssignees); - - @NonNull ArrayList getList(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesPresenter.java deleted file mode 100644 index 42694508b..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/assignees/AssigneesPresenter.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.assignees; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 05 Mar 2017, 11:52 AM - */ - -class AssigneesPresenter extends BasePresenter implements AssigneesMvp.Presenter { - private ArrayList users = new ArrayList<>(); - - @Override public void onCallApi(@NonNull String login, @NonNull String repo, boolean isAssignees) { - makeRestCall(isAssignees ? RestProvider.getRepoService(isEnterprise()).getAssignees(login, repo) - : RestProvider.getRepoService(isEnterprise()).getCollaborator(login, repo), - response -> sendToView(view -> view.onNotifyAdapter(response != null ? response.getItems() : null))); - } - - @NonNull @Override public ArrayList getList() { - return users; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesFragment.kt deleted file mode 100644 index adeca4a2e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesFragment.kt +++ /dev/null @@ -1,120 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.branches - -import android.content.Context -import android.os.Bundle -import android.support.v4.widget.SwipeRefreshLayout -import android.view.View -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.BranchesModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.provider.rest.loadmore.OnLoadMore -import com.fastaccess.ui.adapter.BranchesAdapter -import com.fastaccess.ui.base.BaseFragment -import com.fastaccess.ui.modules.repos.extras.branches.pager.BranchesPagerListener -import com.fastaccess.ui.widgets.StateLayout -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller - -/** - * Created by Kosh on 06 Jul 2017, 9:48 PM - */ -class BranchesFragment : BaseFragment(), BranchesMvp.View { - - @BindView(R.id.recycler) lateinit var recycler: DynamicRecyclerView - @BindView(R.id.refresh) lateinit var refresh: SwipeRefreshLayout - @BindView(R.id.stateLayout) lateinit var stateLayout: StateLayout - @BindView(R.id.fastScroller) lateinit var fastScroller: RecyclerViewFastScroller - - private var onLoadMore: OnLoadMore? = null - private var branchCallback: BranchesPagerListener? = null - - private val adapter by lazy { BranchesAdapter(presenter.branches, presenter) } - - override fun onAttach(context: Context) { - super.onAttach(context) - branchCallback = if (parentFragment is BranchesPagerListener) { - parentFragment as BranchesPagerListener - } else context as BranchesPagerListener - } - - override fun onDetach() { - branchCallback = null - super.onDetach() - } - - override fun fragmentLayout(): Int = R.layout.small_grid_refresh_list - - override fun providePresenter(): BranchesPresenter = BranchesPresenter() - - override fun onNotifyAdapter(branches: ArrayList, page: Int) { - hideProgress() - if (page == 1) adapter.insertItems(branches) - else adapter.addItems(branches) - } - - override fun onBranchSelected(item: BranchesModel?) { - branchCallback?.onItemSelect(item!!) - } - - override fun getLoadMore(): OnLoadMore { - if (onLoadMore == null) { - onLoadMore = OnLoadMore(presenter) - } - return onLoadMore!! - } - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - getLoadMore().initialize(presenter.currentPage, presenter.previousTotal) - stateLayout.setEmptyText(R.string.no_branches) - refresh.setOnRefreshListener { presenter.onCallApi(1, null) } - recycler.setEmptyView(stateLayout, refresh) - stateLayout.setOnReloadListener { presenter.onCallApi(1, null) } - recycler.adapter = adapter - recycler.addOnScrollListener(getLoadMore()) - recycler.addDivider() - if (savedInstanceState == null) { - arguments?.let { presenter.onFragmentCreated(it) } - } - fastScroller.attachRecyclerView(recycler) - } - - override fun showProgress(resId: Int) { - refresh.isRefreshing = true - stateLayout.showProgress() - } - - override fun hideProgress() { - refresh.isRefreshing = false - stateLayout.hideProgress() - stateLayout.showReload(adapter.itemCount) - } - - override fun showMessage(titleRes: Int, msgRes: Int) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showMessage(titleRes: String, msgRes: String) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showErrorMessage(msgRes: String) { - hideProgress() - super.showErrorMessage(msgRes) - } - - companion object { - fun newInstance(login: String, repoId: String, branch: Boolean): BranchesFragment { - val fragment = BranchesFragment() - fragment.arguments = Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TYPE, branch) - .end() - return fragment - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesMvp.kt deleted file mode 100644 index d4c515a43..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesMvp.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.branches - -import android.os.Bundle -import com.fastaccess.data.dao.BranchesModel -import com.fastaccess.provider.rest.loadmore.OnLoadMore -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Kosh on 06 Jul 2017, 9:06 PM - */ -interface BranchesMvp { - - interface View : BaseMvp.FAView { - fun onNotifyAdapter(branches: ArrayList, page: Int) - fun onBranchSelected(item: BranchesModel?) - fun getLoadMore(): OnLoadMore - } - - interface Presenter : BaseViewHolder.OnItemClickListener, BaseMvp.PaginationListener { - fun onFragmentCreated(bundle: Bundle) - } - - interface BranchSelectionListener { - fun onBranchSelected(branch: BranchesModel) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesPresenter.kt deleted file mode 100644 index 91e381929..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/BranchesPresenter.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.branches - -import android.os.Bundle -import android.view.View -import com.fastaccess.data.dao.BranchesModel -import com.fastaccess.data.dao.Pageable -import com.fastaccess.helper.BundleConstant -import com.fastaccess.provider.rest.RestProvider -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import io.reactivex.Observable - -/** - * Created by Kosh on 06 Jul 2017, 9:14 PM - */ -class BranchesPresenter : BasePresenter(), BranchesMvp.Presenter { - private var page: Int = 0 - private var previousTotal: Int = 0 - private var lastPage = Integer.MAX_VALUE - @com.evernote.android.state.State var login: String? = null - @com.evernote.android.state.State var repoId: String? = null - @com.evernote.android.state.State var isBranch: Boolean = true - - var branches = ArrayList() - - - override fun onFragmentCreated(bundle: Bundle) { - login = bundle.getString(BundleConstant.EXTRA) - repoId = bundle.getString(BundleConstant.ID) - isBranch = bundle.getBoolean(BundleConstant.EXTRA_TYPE) - if (branches.isEmpty()) { - onCallApi(1, null) - } - } - - private fun callApi(login: String, repoId: String, page: Int) { - val observable = if (!isBranch) RestProvider.getRepoService(isEnterprise) - .getTags(login, repoId, page) else RestProvider.getRepoService(isEnterprise) - .getBranches(login, repoId, page) - return makeRestCall(observable - .flatMap({ t: Pageable? -> - val list = ArrayList() - if (t != null) { - lastPage = t.last - t.items.onEach { - it.isTag = !isBranch - list.add(it) - } - } - return@flatMap Observable.just(list) - }), { items -> sendToView { v -> v.onNotifyAdapter(items, page) } }) - } - - override fun onItemClick(position: Int, v: View?, item: BranchesModel?) { - sendToView({ it.onBranchSelected(item) }) - } - - override fun onItemLongClick(position: Int, v: View?, item: BranchesModel?) {} - - override fun getCurrentPage(): Int = page - - override fun getPreviousTotal(): Int = previousTotal - - override fun setCurrentPage(page: Int) { - this.page = page - } - - override fun setPreviousTotal(previousTotal: Int) { - this.previousTotal = previousTotal - } - - override fun onCallApi(page: Int, parameter: Boolean?): Boolean { - if (login.isNullOrEmpty() || repoId.isNullOrEmpty()) { - sendToView({ it.hideProgress() }) - return false - } - if (page == 1) { - lastPage = Integer.MAX_VALUE - sendToView({ it.getLoadMore().reset() }) - } - if (page > lastPage || lastPage == 0) { - sendToView({ it.hideProgress() }) - return false - } - currentPage = page - callApi(login!!, repoId!!, page) - return true - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/pager/BranchesPagerFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/pager/BranchesPagerFragment.kt deleted file mode 100644 index 5a0046c4d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/pager/BranchesPagerFragment.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.branches.pager - -import android.content.Context -import android.os.Bundle -import android.support.design.widget.TabLayout -import android.support.v4.view.ViewPager -import android.support.v7.widget.Toolbar -import android.view.View -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.BranchesModel -import com.fastaccess.data.dao.FragmentPagerAdapterModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.ui.adapter.FragmentsPagerAdapter -import com.fastaccess.ui.base.BaseDialogFragment -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.repos.extras.branches.BranchesMvp - -/** - * Created by kosh on 15/07/2017. - */ -class BranchesPagerFragment : BaseDialogFragment>(), BranchesPagerListener { - - @BindView(R.id.pager) lateinit var pager: ViewPager - @BindView(R.id.tabs) lateinit var tabs: TabLayout - @BindView(R.id.toolbar) lateinit var toolbar: Toolbar - - private var branchCallback: BranchesMvp.BranchSelectionListener? = null - - override fun onAttach(context: Context) { - super.onAttach(context) - branchCallback = if (parentFragment is BranchesMvp.BranchSelectionListener) { - parentFragment as BranchesMvp.BranchSelectionListener - } else context as BranchesMvp.BranchSelectionListener - } - - override fun onDetach() { - branchCallback = null - super.onDetach() - } - - override fun onItemSelect(branch: BranchesModel) { - branchCallback?.onBranchSelected(branch) - dismiss() - } - - override fun fragmentLayout(): Int = R.layout.branches_tabbed_viewpager - - override fun providePresenter(): BasePresenter = BasePresenter() - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - toolbar.setNavigationIcon(R.drawable.ic_clear) - toolbar.setNavigationOnClickListener { dismiss() } - toolbar.setTitle(R.string.switch_branch) - tabs.setPadding(0, 0, 0, 0) - tabs.tabMode = TabLayout.MODE_FIXED - arguments?.let { - val login = it.getString(BundleConstant.EXTRA) - val repoId = it.getString(BundleConstant.ID) - pager.adapter = FragmentsPagerAdapter(childFragmentManager, FragmentPagerAdapterModel.buildForBranches(context!!, repoId, login)) - tabs.setupWithViewPager(pager) - } - } - - companion object { - fun newInstance(login: String, repoId: String): BranchesPagerFragment { - val fragment = BranchesPagerFragment() - fragment.arguments = Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .end() - return fragment - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/pager/BranchesPagerListener.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/pager/BranchesPagerListener.kt deleted file mode 100644 index b75f775f2..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/branches/pager/BranchesPagerListener.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.branches.pager - -import com.fastaccess.data.dao.BranchesModel - -/** - * Created by kosh on 15/07/2017. - */ -interface BranchesPagerListener { - fun onItemSelect(branch: BranchesModel) -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsDialogFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsDialogFragment.java deleted file mode 100644 index a184090eb..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsDialogFragment.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.labels; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.LabelListModel; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.LabelsAdapter; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.modules.repos.extras.labels.create.CreateLabelDialogFragment; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.ArrayList; -import java.util.List; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 22 Feb 2017, 7:23 PM - */ - -public class LabelsDialogFragment extends BaseDialogFragment implements LabelsMvp.View { - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.add) View add; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @State ArrayList labelModels = new ArrayList<>(); - - private OnLoadMore onLoadMore; - private LabelsAdapter adapter; - private LabelsMvp.SelectedLabelsListener callback; - - public static LabelsDialogFragment newInstance(@Nullable LabelListModel selectedLabels, @NonNull String repo, @NonNull String login) { - LabelsDialogFragment fragment = new LabelsDialogFragment(); - fragment.setArguments(Bundler.start() - .putParcelableArrayList(BundleConstant.EXTRA, selectedLabels) - .put(BundleConstant.EXTRA_TWO, repo) - .put(BundleConstant.EXTRA_THREE, login) - .end()); - return fragment; - } - - @OnClick(R.id.add) void onAddLabel() { - String repo = getArguments().getString(BundleConstant.EXTRA_TWO); - String login = getArguments().getString(BundleConstant.EXTRA_THREE); - if (!InputHelper.isEmpty(repo) && !InputHelper.isEmpty(login)) { - CreateLabelDialogFragment.newInstance(login, repo).show(getChildFragmentManager(), "CreateLabelDialogFragment"); - } - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof LabelsMvp.SelectedLabelsListener) { - callback = (LabelsMvp.SelectedLabelsListener) getParentFragment(); - } else if (context instanceof LabelsMvp.SelectedLabelsListener) { - callback = (LabelsMvp.SelectedLabelsListener) context; - } - } - - @Override public void onDetach() { - super.onDetach(); - callback = null; - } - - @Override protected int fragmentLayout() { - return R.layout.simple_footer_list_dialog; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - stateLayout.setEmptyText(R.string.no_labels); - recycler.setEmptyView(stateLayout, refresh); - refresh.setOnRefreshListener(() -> getPresenter().onCallApi(1, null)); - stateLayout.setOnReloadListener(v -> getPresenter().onCallApi(1, null)); - recycler.addDivider(); - title.setText(R.string.labels); - add.setVisibility(View.VISIBLE); - labelModels = getArguments().getParcelableArrayList(BundleConstant.EXTRA); - if (labelModels == null) { - labelModels = new ArrayList<>(); - } - add.setVisibility(callback == null ? View.GONE : View.VISIBLE); - adapter = new LabelsAdapter(getPresenter().getLabels(), this); - recycler.setAdapter(adapter); - fastScroller.attachRecyclerView(recycler); - recycler.addOnScrollListener(getLoadMore()); - if (getPresenter().getLabels().isEmpty() && !getPresenter().isApiCalled()) { - getPresenter().onCallApi(1, null); - } - } - - @NonNull @Override public LabelsPresenter providePresenter() { - Bundle bundle = getArguments(); - //noinspection ConstantConditions - return new LabelsPresenter(bundle.getString(BundleConstant.EXTRA_THREE), bundle.getString(BundleConstant.EXTRA_TWO)); - } - - @Override public boolean isLabelSelected(LabelModel labelModel) { - return labelModels.indexOf(labelModel) != -1; - } - - @Override public void onToggleSelection(LabelModel labelModel, boolean select) { - if (select) { - labelModels.add(labelModel); - } else { - labelModels.remove(labelModel); - } - adapter.notifyDataSetChanged(); - } - - @SuppressWarnings("unchecked") @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()); - } - return onLoadMore; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void onLabelAdded(@NonNull LabelModel labelModel) { - adapter.addItem(labelModel, 0); - recycler.scrollToPosition(0); - } - - @OnClick({R.id.cancel, R.id.ok}) public void onClick(View view) { - switch (view.getId()) { - case R.id.cancel: - dismiss(); - break; - case R.id.ok: - if (callback != null) callback.onSelectedLabels(labelModels); - dismiss(); - break; - } - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsMvp.java deleted file mode 100644 index 302fb4537..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsMvp.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.labels; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.LabelsAdapter; -import com.fastaccess.ui.base.mvp.BaseMvp; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 22 Feb 2017, 7:22 PM - */ - -public interface LabelsMvp { - - interface SelectedLabelsListener { - void onSelectedLabels(@NonNull ArrayList labels); - } - - interface View extends BaseMvp.FAView, LabelsAdapter.OnSelectLabel { - - @NonNull OnLoadMore getLoadMore(); - - void onNotifyAdapter(@Nullable List items, int page); - - void onLabelAdded(@NonNull LabelModel labelModel); - } - - interface Presenter extends BaseMvp.PaginationListener { - - @NonNull ArrayList getLabels(); - - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsPresenter.java deleted file mode 100644 index ab45ed710..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/LabelsPresenter.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.labels; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 22 Feb 2017, 7:23 PM - */ - -class LabelsPresenter extends BasePresenter implements LabelsMvp.Presenter { - - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - private ArrayList labels = new ArrayList<>(); - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - - LabelsPresenter(@NonNull String login, @NonNull String repoId) { - this.login = login; - this.repoId = repoId; - } - - @NonNull @Override public ArrayList getLabels() { - return labels; - } - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable Object parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - if (page > lastPage || lastPage == 0) { - sendToView(LabelsMvp.View::hideProgress); - return false; - } - setCurrentPage(page); - makeRestCall(RestProvider.getRepoService(isEnterprise()).getLabels(login, repoId, page), response -> { - lastPage = response.getLast(); - sendToView(view -> view.onNotifyAdapter(response.getItems(), page)); - }); - return true; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelDialogFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelDialogFragment.java deleted file mode 100644 index c5ea19d6e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelDialogFragment.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.labels.create; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TextInputLayout; -import android.support.v7.widget.Toolbar; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.ui.adapter.LabelColorsAdapter; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.modules.repos.extras.labels.LabelsMvp; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.Arrays; - -import butterknife.BindView; - -/** - * Created by Kosh on 02 Apr 2017, 5:38 PM - */ - -public class CreateLabelDialogFragment extends BaseDialogFragment implements CreateLabelMvp.View { - - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.name) TextInputLayout name; - @BindView(R.id.description) TextInputLayout description; - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private LabelsMvp.View callback; - - public static CreateLabelDialogFragment newInstance(@NonNull String login, @NonNull String repo) { - CreateLabelDialogFragment fragment = new CreateLabelDialogFragment(); - fragment.setArguments(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repo) - .end()); - return fragment; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof LabelsMvp.View) { - callback = (LabelsMvp.View) getParentFragment(); - } else if (context instanceof LabelsMvp.View) { - callback = (LabelsMvp.View) context; - } - } - - @Override public void onDetach() { - callback = null; - super.onDetach(); - } - - @Override public void onSuccessfullyCreated(@NonNull LabelModel labelModel1) { - hideProgress(); - if (callback != null) callback.onLabelAdded(labelModel1); - dismiss(); - } - - @Override public void onColorSelected(@NonNull String color) { - description.getEditText().setText(color.replaceFirst("#", "")); - } - - @Override protected int fragmentLayout() { - return R.layout.create_label_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - String login = getArguments().getString(BundleConstant.EXTRA); - String repo = getArguments().getString(BundleConstant.ID); - if (login == null || repo == null) { - return; - } - recycler.setAdapter(new LabelColorsAdapter(Arrays.asList(getResources().getStringArray(R.array.label_colors)), getPresenter())); - recycler.addKeyLineDivider(); - toolbar.setTitle(R.string.create_label); - toolbar.setNavigationIcon(R.drawable.ic_clear); - toolbar.setNavigationOnClickListener(item -> dismiss()); - toolbar.inflateMenu(R.menu.add_menu); - toolbar.getMenu().findItem(R.id.add).setIcon(R.drawable.ic_send); - toolbar.setOnMenuItemClickListener(item -> { - boolean emptyColor = InputHelper.isEmpty(description); - boolean emptyName = InputHelper.isEmpty(name); - description.setError(emptyColor ? getString(R.string.required_field) : null); - name.setError(emptyName ? getString(R.string.required_field) : null); - if (!emptyColor && !emptyName) { - getPresenter().onSubmitLabel(InputHelper.toString(name), InputHelper.toString(description), repo, login); - } - return true; - }); - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public CreateLabelPresenter providePresenter() { - return new CreateLabelPresenter(); - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelMvp.java deleted file mode 100644 index df0434d0f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelMvp.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.labels.create; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -/** - * Created by Kosh on 02 Apr 2017, 5:30 PM - */ - -public interface CreateLabelMvp { - - interface View extends BaseMvp.FAView { - void onSuccessfullyCreated(@NonNull LabelModel labelModel1); - - void onColorSelected(@NonNull String color); - } - - interface Presenter extends BaseViewHolder.OnItemClickListener { - void onSubmitLabel(@NonNull String name, @NonNull String color, - @NonNull String repo, @NonNull String login); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelPresenter.java deleted file mode 100644 index f3dd6a1dd..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/labels/create/CreateLabelPresenter.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.labels.create; - -import android.support.annotation.NonNull; -import android.view.View; - -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by Kosh on 02 Apr 2017, 5:35 PM - */ - -public class CreateLabelPresenter extends BasePresenter implements CreateLabelMvp.Presenter { - - @Override public void onItemClick(int position, View v, String item) { - if (getView() != null) { - getView().onColorSelected(item); - } - } - - @Override public void onItemLongClick(int position, View v, String item) {} - - @Override public void onSubmitLabel(@NonNull String name, @NonNull String color, @NonNull String repo, @NonNull String login) { - LabelModel labelModel = new LabelModel(); - labelModel.setColor(color.replaceAll("#", "")); - labelModel.setName(name); - makeRestCall(RestProvider.getRepoService(isEnterprise()) - .addLabel(login, repo, labelModel), - labelModel1 -> sendToView(view -> view.onSuccessfullyCreated(labelModel1))); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicenseBottomSheet.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicenseBottomSheet.kt deleted file mode 100644 index 77f728a5f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicenseBottomSheet.kt +++ /dev/null @@ -1,113 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.license - -import android.os.Bundle -import android.support.annotation.StringRes -import android.view.View -import android.widget.ProgressBar -import android.widget.TextView -import butterknife.BindView -import com.evernote.android.state.State -import com.fastaccess.R -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.ui.base.BaseMvpBottomSheetDialogFragment -import com.fastaccess.ui.widgets.StateLayout -import com.prettifier.pretty.PrettifyWebView - -/** - * Created by Kosh on 30 Jun 2017, 12:38 PM - */ -class RepoLicenseBottomSheet : BaseMvpBottomSheetDialogFragment(), RepoLicenseMvp.View, - PrettifyWebView.OnContentChangedListener { - - @State var content: String? = null - - - @BindView(R.id.stateLayout) lateinit var stateLayout: StateLayout - @BindView(R.id.readmeLoader) lateinit var loader: ProgressBar - @BindView(R.id.webView) lateinit var webView: PrettifyWebView - @BindView(R.id.licenseName) lateinit var licenseName: TextView - - override fun providePresenter(): RepoLicensePresenter = RepoLicensePresenter() - - override fun onLicenseLoaded(license: String) { - this.content = license - if (!license.isNullOrBlank()) { - loader.isIndeterminate = false - val licenseText = license.replace("

    ", "
    ")
    -            webView.setGithubContent("
    $licenseText
    ", null, false) - } else { - hideProgress() - } - } - - override fun fragmentLayout(): Int = R.layout.license_viewer_layout - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - arguments?.let { - val login = it.getString(BundleConstant.EXTRA) - val repo = it.getString(BundleConstant.ID) - val licenseTitle = arguments?.getString(BundleConstant.EXTRA_TWO) - licenseName.text = licenseTitle - if (content.isNullOrBlank() && !presenter.isApiCalled) { - presenter.onLoadLicense(login, repo) - } else { - content?.let { onLicenseLoaded(it) } - } - webView.setOnContentChangedListener(this) - } - } - - override fun onContentChanged(progress: Int) { - val loader: ProgressBar? = loader - loader?.let { - it.progress = progress - if (progress == 100) { - it.visibility = View.GONE - hideProgress() - } - } - } - - override fun showProgress(@StringRes resId: Int) { - loader.visibility = View.VISIBLE - loader.isIndeterminate = true - stateLayout.showProgress() - } - - override fun hideProgress() { - loader.visibility = View.GONE - stateLayout.hideProgress() - } - - override fun showErrorMessage(msgRes: String) { - hideProgress() - super.showErrorMessage(msgRes) - } - - override fun showMessage(titleRes: Int, msgRes: Int) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showMessage(titleRes: String, msgRes: String) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun onScrollChanged(reachedTop: Boolean, scroll: Int) {} - - companion object { - fun newInstance(login: String, repo: String, license: String): RepoLicenseBottomSheet { - val view = RepoLicenseBottomSheet() - view.arguments = Bundler.start() - .put(BundleConstant.ID, repo) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, license) - .end() - return view - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicenseMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicenseMvp.kt deleted file mode 100644 index ca3358361..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicenseMvp.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.license - -import com.fastaccess.ui.base.mvp.BaseMvp - -/** - * Created by Kosh on 30 Jun 2017, 12:32 PM - */ - -interface RepoLicenseMvp { - interface View : BaseMvp.FAView { - fun onLicenseLoaded(license: String) - } - - interface Presenter { - fun onLoadLicense(login: String, repo: String) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicensePresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicensePresenter.kt deleted file mode 100644 index 4db1f0ff1..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/license/RepoLicensePresenter.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.license - -import com.fastaccess.provider.rest.RestProvider -import com.fastaccess.ui.base.mvp.presenter.BasePresenter - -/** - * Created by Kosh on 30 Jun 2017, 12:34 PM - */ -class RepoLicensePresenter : BasePresenter(), RepoLicenseMvp.Presenter { - - override fun onLoadLicense(login: String, repo: String) { - makeRestCall(RestProvider.getRepoService(isEnterprise).getLicense(login, repo), - { license -> sendToView { it.onLicenseLoaded(license) } }) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/locking/LockIssuePrBottomSheetDialog.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/locking/LockIssuePrBottomSheetDialog.kt deleted file mode 100644 index 3a528cec9..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/locking/LockIssuePrBottomSheetDialog.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.locking - -import android.content.Context -import android.os.Bundle -import android.view.View -import com.fastaccess.R -import com.fastaccess.ui.base.BaseBottomSheetDialog -import kotlinx.android.synthetic.main.lock_issue_pr_dialog.* - -/** - * Created by Kosh on 10.02.18. - */ - -class LockIssuePrBottomSheetDialog : BaseBottomSheetDialog() { - - private var lockIssuePrCallback: LockIssuePrCallback? = null - - override fun onAttach(context: Context?) { - super.onAttach(context) - lockIssuePrCallback = when { - parentFragment is LockIssuePrCallback -> parentFragment as LockIssuePrCallback - context is LockIssuePrCallback -> context - else -> null - } - } - - override fun onDetach() { - lockIssuePrCallback = null - super.onDetach() - } - - override fun layoutRes(): Int = R.layout.lock_issue_pr_dialog - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - cancel.setOnClickListener { dismiss() } - ok.setOnClickListener { - lockIssuePrCallback?.onLock(lockReason.selectedItem as String) - dismiss() - } - } - - companion object { - fun newInstance() = LockIssuePrBottomSheetDialog() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/locking/LockIssuePrCallback.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/locking/LockIssuePrCallback.kt deleted file mode 100644 index bb088cb35..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/locking/LockIssuePrCallback.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.locking - -/** - * Created by Kosh on 10.02.18. - */ - -interface LockIssuePrCallback { - fun onLock(reason: String) -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestoneDialogFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestoneDialogFragment.java deleted file mode 100644 index ac723f185..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestoneDialogFragment.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.milestone; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.design.widget.AppBarLayout; -import android.support.v7.widget.Toolbar; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.adapter.MilestonesAdapter; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.extras.milestone.create.CreateMilestoneDialogFragment; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 04 Mar 2017, 9:45 PM - */ - -public class MilestoneDialogFragment extends BaseFragment implements MilestoneMvp.View { - public static final String TAG = MilestoneDialogFragment.class.getSimpleName(); - - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.appbar) AppBarLayout appbar; - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private MilestonesAdapter adapter; - private MilestoneMvp.OnMilestoneSelected onMilestoneSelected; - - public static MilestoneDialogFragment newInstance(@NonNull String login, @NonNull String repo) { - MilestoneDialogFragment fragment = new MilestoneDialogFragment(); - fragment.setArguments(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repo) - .end()); - return fragment; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() != null && getParentFragment() instanceof MilestoneMvp.OnMilestoneSelected) { - onMilestoneSelected = (MilestoneMvp.OnMilestoneSelected) getParentFragment(); - } else if (context instanceof MilestoneMvp.OnMilestoneSelected) { - onMilestoneSelected = (MilestoneMvp.OnMilestoneSelected) context; - } - } - - @Override public void onDetach() { - onMilestoneSelected = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - adapter.insertItems(items); - } - - @Override public void onMilestoneSelected(@NonNull MilestoneModel milestoneModel) { - if (onMilestoneSelected != null) onMilestoneSelected.onMilestoneSelected(milestoneModel); - if (getParentFragment() instanceof BaseDialogFragment) { - ((BaseDialogFragment) getParentFragment()).dismiss(); - } - } - - @Override protected int fragmentLayout() { - return R.layout.milestone_dialog_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - return; - } - String login = getArguments().getString(BundleConstant.EXTRA); - String repo = getArguments().getString(BundleConstant.ID); - if (login == null || repo == null) { - return; - } - stateLayout.setEmptyText(R.string.no_milestones); - toolbar.setTitle(R.string.milestone); - toolbar.setOnMenuItemClickListener(item -> onAddMilestone()); - if (onMilestoneSelected != null) toolbar.inflateMenu(R.menu.add_menu); - toolbar.setNavigationIcon(R.drawable.ic_clear); - toolbar.setNavigationOnClickListener(v -> { - if (getParentFragment() instanceof BaseDialogFragment) { - ((BaseDialogFragment) getParentFragment()).dismiss(); - } - }); - recycler.addDivider(); - adapter = new MilestonesAdapter(getPresenter().getMilestones()); - if (onMilestoneSelected != null) adapter.setListener(getPresenter()); - recycler.setEmptyView(stateLayout, refresh); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - if (savedInstanceState == null || (getPresenter().getMilestones().isEmpty() && !getPresenter().isApiCalled())) { - getPresenter().onLoadMilestones(login, repo); - } - stateLayout.setOnReloadListener(v -> getPresenter().onLoadMilestones(login, repo)); - refresh.setOnRefreshListener(() -> getPresenter().onLoadMilestones(login, repo)); - fastScroller.attachRecyclerView(recycler); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public MilestonePresenter providePresenter() { - return new MilestonePresenter(); - } - - @Override public void onMilestoneAdded(@NonNull MilestoneModel milestoneModel) { - adapter.addItem(milestoneModel, 0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } - - private boolean onAddMilestone() { - //noinspection ConstantConditions - CreateMilestoneDialogFragment.newInstance(getArguments().getString(BundleConstant.EXTRA), getArguments().getString(BundleConstant.ID)) - .show(getChildFragmentManager(), CreateMilestoneDialogFragment.TAG); - return true; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestoneMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestoneMvp.java deleted file mode 100644 index 62590d8b3..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestoneMvp.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.milestone; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.repos.extras.milestone.create.CreateMilestoneMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 04 Mar 2017, 9:38 PM - */ - -public interface MilestoneMvp { - - - interface OnMilestoneSelected { - void onMilestoneSelected(@NonNull MilestoneModel milestoneModel); - } - - interface View extends BaseMvp.FAView, CreateMilestoneMvp.OnMilestoneAdded { - void onNotifyAdapter(@Nullable List items); - - void onMilestoneSelected(@NonNull MilestoneModel milestoneModel); - } - - interface Presenter extends BaseViewHolder.OnItemClickListener { - void onLoadMilestones(@NonNull String login, @NonNull String repo); - - @NonNull ArrayList getMilestones(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestonePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestonePresenter.java deleted file mode 100644 index 6325f9fea..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/MilestonePresenter.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.milestone; - -import android.support.annotation.NonNull; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 04 Mar 2017, 9:41 PM - */ - -public class MilestonePresenter extends BasePresenter implements MilestoneMvp.Presenter { - private ArrayList milestoneModels = new ArrayList<>(); - - @Override public void onItemClick(int position, View v, MilestoneModel item) { - if (getView() != null) getView().onMilestoneSelected(item); - } - - @Override public void onItemLongClick(int position, View v, MilestoneModel item) {} - - @Override public void onLoadMilestones(@NonNull String login, @NonNull String repo) { - makeRestCall(RestProvider.getRepoService(isEnterprise()).getMilestones(login, repo), - response -> { - if (response == null || response.getItems() == null || response.getItems().isEmpty()) { - sendToView(view -> view.showMessage(R.string.error, R.string.no_milestones)); - return; - } - sendToView(view -> view.onNotifyAdapter(response.getItems())); - }); - } - - @NonNull @Override public ArrayList getMilestones() { - return milestoneModels; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneDialogFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneDialogFragment.java deleted file mode 100644 index 735e21bbf..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneDialogFragment.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.milestone.create; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TextInputEditText; -import android.support.design.widget.TextInputLayout; -import android.support.v7.widget.Toolbar; -import android.view.MotionEvent; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.datetimepicker.DatePickerFragmentDialog; -import com.fastaccess.datetimepicker.callback.DatePickerCallback; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.ui.base.BaseDialogFragment; - -import butterknife.BindView; -import butterknife.OnTouch; - -/** - * Created by Kosh on 04 Mar 2017, 10:40 PM - */ - -public class CreateMilestoneDialogFragment extends BaseDialogFragment - implements CreateMilestoneMvp.View, DatePickerCallback { - - public static final String TAG = CreateMilestoneDialogFragment.class.getSimpleName(); - - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.title) TextInputLayout title; - @BindView(R.id.dueOnEditText) TextInputEditText dueOnEditText; - @BindView(R.id.description) TextInputLayout description; - - private CreateMilestoneMvp.OnMilestoneAdded onMilestoneAdded; - - public static CreateMilestoneDialogFragment newInstance(@NonNull String login, @NonNull String repo) { - CreateMilestoneDialogFragment fragment = new CreateMilestoneDialogFragment(); - fragment.setArguments(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repo) - .end()); - return fragment; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof CreateMilestoneMvp.OnMilestoneAdded) { - onMilestoneAdded = (CreateMilestoneMvp.OnMilestoneAdded) getParentFragment(); - } else { - onMilestoneAdded = (CreateMilestoneMvp.OnMilestoneAdded) context; - } - } - - @Override public void onDetach() { - onMilestoneAdded = null; - super.onDetach(); - } - - @Override protected int fragmentLayout() { - return R.layout.create_milestone_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - String login = getArguments().getString(BundleConstant.EXTRA); - String repo = getArguments().getString(BundleConstant.ID); - if (login == null || repo == null) { - return; - } - toolbar.setTitle(R.string.create_milestone); - toolbar.setNavigationIcon(R.drawable.ic_clear); - toolbar.setNavigationOnClickListener(item -> dismiss()); - toolbar.inflateMenu(R.menu.add_menu); - toolbar.getMenu().findItem(R.id.add).setIcon(R.drawable.ic_send); - toolbar.setOnMenuItemClickListener(item -> { - getPresenter().onSubmit(InputHelper.toString(title), InputHelper.toString(dueOnEditText), InputHelper.toString(description), login, repo); - return true; - }); - } - - @NonNull @Override public CreateMilestonePresenter providePresenter() { - return new CreateMilestonePresenter(); - } - - @OnTouch(R.id.dueOnEditText) boolean onTouch(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_UP) { - DatePickerFragmentDialog.newInstance().show(getChildFragmentManager(), "DatePickerFragmentDialog"); - } - return false; - } - - @Override public void onDateSet(long date) { - if (date > 0) { - dueOnEditText.setText(ParseDateFormat.prettifyDate(date)); - } - } - - @Override public void onShowTitleError(boolean isError) { - title.setError(isError ? getString(R.string.required_field) : null); - } - - @Override public void onMilestoneAdded(@NonNull MilestoneModel milestoneModel) { - hideProgress(); - onMilestoneAdded.onMilestoneAdded(milestoneModel); - dismiss(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneMvp.java deleted file mode 100644 index c7d1f696c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestoneMvp.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.milestone.create; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.ui.base.mvp.BaseMvp; - -/** - * Created by Kosh on 04 Mar 2017, 10:47 PM - */ - -public interface CreateMilestoneMvp { - - interface OnMilestoneAdded { - void onMilestoneAdded(@NonNull MilestoneModel milestoneModel); - } - - interface View extends BaseMvp.FAView { - void onShowTitleError(boolean isError); - - void onMilestoneAdded(@NonNull MilestoneModel milestoneModel); - } - - interface Presenter { - void onSubmit(@Nullable String title, @Nullable String dueOn, @Nullable String description, - @NonNull String login, @NonNull String repo); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestonePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestonePresenter.java deleted file mode 100644 index 848e16d85..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/CreateMilestonePresenter.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.milestone.create; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.R; -import com.fastaccess.data.dao.CreateMilestoneModel; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.Date; - -/** - * Created by Kosh on 04 Mar 2017, 10:49 PM - */ - -public class CreateMilestonePresenter extends BasePresenter implements CreateMilestoneMvp.Presenter { - @Override public void onSubmit(@Nullable String title, @Nullable String dueOn, @Nullable String description, - @NonNull String login, @NonNull String repo) { - if (getView() != null) { - boolean isEmptyTitle = InputHelper.isEmpty(title); - getView().onShowTitleError(isEmptyTitle); - if (!isEmptyTitle) { - CreateMilestoneModel createMilestoneModel = new CreateMilestoneModel(); - createMilestoneModel.setTitle(title); - if (!InputHelper.isEmpty(dueOn)) { - Date date = ParseDateFormat.getDateFromString(dueOn); - if (date != null) createMilestoneModel.setDueOn(ParseDateFormat.toGithubDate(date)); - } - if (!InputHelper.isEmpty(description)) { - createMilestoneModel.setDescription(description); - } - makeRestCall(RestProvider.getRepoService(isEnterprise()).createMilestone(login, repo, createMilestoneModel), - milestoneModel -> { - if (milestoneModel != null) { - sendToView(view -> view.onMilestoneAdded(milestoneModel)); - } else { - sendToView(view -> view.showMessage(R.string.error, R.string.error_creating_milestone)); - } - }); - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/MilestoneDialogFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/MilestoneDialogFragment.java deleted file mode 100644 index 05afccb92..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/milestone/create/MilestoneDialogFragment.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.milestone.create; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.repos.extras.milestone.MilestoneMvp; -import com.fastaccess.ui.modules.repos.issues.issue.details.IssuePagerMvp; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.PullRequestPagerMvp; - -import net.grandcentrix.thirtyinch.TiPresenter; - -/** - * Created by Kosh on 04 Mar 2017, 10:58 PM - */ - -public class MilestoneDialogFragment extends BaseDialogFragment implements MilestoneMvp.OnMilestoneSelected { - - private IssuePagerMvp.View issueCallback; - private PullRequestPagerMvp.View pullRequestCallback; - private MilestoneMvp.OnMilestoneSelected milestoneCallback; - - public static MilestoneDialogFragment newInstance(@NonNull String login, @NonNull String repo) { - MilestoneDialogFragment view = new MilestoneDialogFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repo) - .end()); - return view; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof IssuePagerMvp.View) { - issueCallback = (IssuePagerMvp.View) context; - } else if (getParentFragment() instanceof IssuePagerMvp.View) { - issueCallback = (IssuePagerMvp.View) getParentFragment(); - } - if (context instanceof PullRequestPagerMvp.View) { - pullRequestCallback = (PullRequestPagerMvp.View) context; - } else if (getParentFragment() instanceof PullRequestPagerMvp.View) { - pullRequestCallback = (PullRequestPagerMvp.View) getParentFragment(); - } - - if (context instanceof MilestoneMvp.OnMilestoneSelected) { - milestoneCallback = (MilestoneMvp.OnMilestoneSelected) context; - } else if (getParentFragment() instanceof MilestoneMvp.OnMilestoneSelected) { - milestoneCallback = (MilestoneMvp.OnMilestoneSelected) getParentFragment(); - } - } - - @Override public void onDetach() { - super.onDetach(); - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } - - @Override protected int fragmentLayout() { - return R.layout.single_container_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (savedInstanceState == null) { - Bundle bundle = getArguments(); - com.fastaccess.ui.modules.repos.extras.milestone.MilestoneDialogFragment milestoneView = new com.fastaccess.ui.modules.repos.extras - .milestone.MilestoneDialogFragment(); - milestoneView.setArguments(bundle); - getChildFragmentManager() - .beginTransaction() - .replace(R.id.singleContainer, milestoneView, com.fastaccess.ui.modules.repos.extras.milestone.MilestoneDialogFragment.TAG) - .commit(); - } - } - - @Override public void onMilestoneSelected(@NonNull MilestoneModel milestoneModel) { - if (issueCallback != null) issueCallback.onMileStoneSelected(milestoneModel); - if (pullRequestCallback != null) pullRequestCallback.onMileStoneSelected(milestoneModel); - if (milestoneCallback != null) milestoneCallback.onMilestoneSelected(milestoneModel); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscDialogFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscDialogFragment.java deleted file mode 100644 index 477cf3e8d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscDialogFragment.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.misc; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.app.FragmentManager; -import android.support.v4.widget.SwipeRefreshLayout; -import android.support.v7.widget.Toolbar; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.UsersAdapter; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 04 May 2017, 8:41 PM - */ - -public class RepoMiscDialogFragment extends BaseDialogFragment implements RepoMiscMVp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @BindView(R.id.toolbar) Toolbar toolbar; - private OnLoadMore onLoadMore; - private UsersAdapter adapter; - - private static RepoMiscDialogFragment newInstance(@NonNull String owner, @NonNull String repo, @RepoMiscMVp.MiscType int type) { - RepoMiscDialogFragment view = new RepoMiscDialogFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.EXTRA, owner) - .put(BundleConstant.ID, repo) - .put(BundleConstant.EXTRA_TYPE, type) - .end()); - return view; - } - - public static void show(@NonNull FragmentManager fragmentManager, @NonNull String owner, - @NonNull String repo, @RepoMiscMVp.MiscType int type) { - newInstance(owner, repo, type).show(fragmentManager, RepoMiscDialogFragment.class.getName()); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.milestone_dialog_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, username is required"); - } - switch (getPresenter().getType()) { - case RepoMiscMVp.FORKS: - toolbar.setTitle(R.string.forks); - stateLayout.setEmptyText(String.format("%s %s", getString(R.string.no), getString(R.string.forks))); - break; - case RepoMiscMVp.STARS: - toolbar.setTitle(R.string.stars); - stateLayout.setEmptyText(String.format("%s %s", getString(R.string.no), getString(R.string.stars))); - break; - case RepoMiscMVp.WATCHERS: - toolbar.setTitle(R.string.watchers); - stateLayout.setEmptyText(String.format("%s %s", getString(R.string.no), getString(R.string.watchers))); - break; - } - toolbar.setNavigationIcon(R.drawable.ic_clear); - toolbar.setNavigationOnClickListener(v -> dismiss()); - stateLayout.setOnReloadListener(v -> getPresenter().onCallApi(1, null)); - refresh.setOnRefreshListener(() -> getPresenter().onCallApi(1, null)); - recycler.setEmptyView(stateLayout, refresh); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - adapter = new UsersAdapter(getPresenter().getList()); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - recycler.addKeyLineDivider(); - if (getPresenter().getList().isEmpty() && !getPresenter().isApiCalled()) { - getPresenter().onCallApi(1, null); - } - fastScroller.attachRecyclerView(recycler); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter()); - } - return onLoadMore; - } - - @NonNull @Override public RepoMiscPresenter providePresenter() { - return new RepoMiscPresenter(getArguments()); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscMVp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscMVp.java deleted file mode 100644 index 421823f69..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscMVp.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.misc; - -import android.support.annotation.IntDef; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 04 May 2017, 8:30 PM - */ - -public interface RepoMiscMVp { - - int WATCHERS = 0; - int FORKS = 1; - int STARS = 2; - - @IntDef({ - WATCHERS, - FORKS, - STARS - }) - @Retention(RetentionPolicy.SOURCE) @interface MiscType {} - - - interface View extends BaseMvp.FAView { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.PaginationListener, BaseViewHolder.OnItemClickListener { - - @NonNull ArrayList getList(); - - @MiscType int getType(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscPresenter.java deleted file mode 100644 index 69787266e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/misc/RepoMiscPresenter.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.misc; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 04 May 2017, 8:33 PM - */ - -public class RepoMiscPresenter extends BasePresenter implements RepoMiscMVp.Presenter { - - private ArrayList users = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - @com.evernote.android.state.State String owner; - @com.evernote.android.state.State String repo; - @com.evernote.android.state.State @RepoMiscMVp.MiscType int type; - - RepoMiscPresenter(@Nullable Bundle arguments) { - if (arguments == null) return; - if (InputHelper.isEmpty(owner) || InputHelper.isEmpty(repo)) { - owner = arguments.getString(BundleConstant.EXTRA); - repo = arguments.getString(BundleConstant.ID); - type = arguments.getInt(BundleConstant.EXTRA_TYPE); - onCallApi(1, type); - } - } - - @NonNull @Override public ArrayList getList() { - return users; - } - - @Override public int getType() { - return type; - } - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @RepoMiscMVp.MiscType @Nullable Integer parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(RepoMiscMVp.View::hideProgress); - return false; - } - switch (type) { - case RepoMiscMVp.WATCHERS: - makeRestCall(RestProvider.getRepoService(isEnterprise()).getWatchers(owner, repo, page), response -> onResponse(page, response)); - return true; - case RepoMiscMVp.STARS: - makeRestCall(RestProvider.getRepoService(isEnterprise()).getStargazers(owner, repo, page), response -> onResponse(page, response)); - return true; - case RepoMiscMVp.FORKS: - makeRestCall(RestProvider.getRepoService(isEnterprise()).getForks(owner, repo, page) - .flatMap(repoPageable -> { - lastPage = repoPageable.getLast(); - return Observable.fromIterable(repoPageable.getItems()) - .map(Repo::getOwner) - .toList() - .toObservable(); - }), owners -> sendToView(view -> view.onNotifyAdapter(owners, page))); - return true; - } - return false; - } - - private void onResponse(int page, @Nullable Pageable response) { - if (response != null) { - lastPage = response.getLast(); - sendToView(view -> view.onNotifyAdapter(response.getItems(), page)); - } else { - sendToView(BaseMvp.FAView::hideProgress); - } - } - - @Override public void onItemClick(int position, View v, User item) {} - - @Override public void onItemLongClick(int position, View v, User item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupFragment.java deleted file mode 100644 index 6e5b84dae..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupFragment.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.popup; - -import android.graphics.Color; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.AppBarLayout; -import android.support.design.widget.FloatingActionButton; -import android.support.v4.app.FragmentManager; -import android.support.v7.widget.Toolbar; -import android.view.View; -import android.widget.LinearLayout; -import android.widget.ProgressBar; - -import com.fastaccess.R; -import com.fastaccess.data.dao.LabelListModel; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.AnimHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.markdown.MarkDownProvider; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.base.BaseMvpBottomSheetDialogFragment; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontEditText; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.LabelSpan; -import com.fastaccess.ui.widgets.SpannableBuilder; - -import java.util.ArrayList; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 27 May 2017, 12:54 PM - */ - -public class IssuePopupFragment extends BaseMvpBottomSheetDialogFragment - implements IssuePopupMvp.View { - - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.appbar) AppBarLayout appbar; - @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.name) FontTextView name; - @BindView(R.id.body) FontTextView body; - @BindView(R.id.assignee) FontTextView assignee; - @BindView(R.id.assigneeLayout) LinearLayout assigneeLayout; - @BindView(R.id.title) FontTextView title; - @BindView(R.id.labels) FontTextView labels; - @BindView(R.id.labelsLayout) LinearLayout labelsLayout; - @BindView(R.id.milestoneTitle) FontTextView milestoneTitle; - @BindView(R.id.milestoneDescription) FontTextView milestoneDescription; - @BindView(R.id.milestoneLayout) LinearLayout milestoneLayout; - @BindView(R.id.comment) FontEditText comment; - @BindView(R.id.submit) FloatingActionButton submit; - @BindView(R.id.commentSection) LinearLayout commentSection; - @BindView(R.id.progressBar) ProgressBar progressBar; - - public static void showPopup(@NonNull FragmentManager manager, @NonNull Issue issue) { - IssuePopupFragment fragment = new IssuePopupFragment(); - PullsIssuesParser parser = PullsIssuesParser.getForIssue(issue.getHtmlUrl()); - if (parser == null) { - parser = PullsIssuesParser.getForPullRequest(issue.getHtmlUrl()); - } - if (parser == null) return; - fragment.setArguments(getBundle(parser.getLogin(), parser.getRepoId(), issue.getNumber(), issue.getTitle(), issue.getBody(), issue.getUser(), - issue.getAssignee(), issue.getLabels(), issue.getMilestone(), !issue.isLocked())); - fragment.show(manager, ""); - } - - public static void showPopup(@NonNull FragmentManager manager, @NonNull PullRequest pullRequest) { - IssuePopupFragment fragment = new IssuePopupFragment(); - PullsIssuesParser parser = PullsIssuesParser.getForPullRequest(pullRequest.getHtmlUrl()); - if (parser == null) return; - fragment.setArguments(getBundle(parser.getLogin(), parser.getRepoId(), pullRequest.getNumber(), - pullRequest.getTitle(), pullRequest.getBody(), pullRequest.getUser(), - pullRequest.getAssignee(), pullRequest.getLabels(), pullRequest.getMilestone(), !pullRequest.isLocked())); - fragment.show(manager, ""); - } - - @NonNull private static Bundle getBundle(@NonNull String login, @NonNull String repoId, - int number, @NonNull String title, @NonNull String body, - @NonNull User user, @Nullable User assignee, - @Nullable LabelListModel labels, @Nullable MilestoneModel milestone, - boolean canComment) { - return Bundler.start() - .put(BundleConstant.EXTRA_SEVEN, login) - .put(BundleConstant.EXTRA_EIGHT, repoId) - .put(BundleConstant.ID, number) - .put(BundleConstant.EXTRA, title) - .put(BundleConstant.EXTRA_TWO, body) - .put(BundleConstant.EXTRA_THREE, user) - .put(BundleConstant.EXTRA_FOUR, assignee) - .putParcelableArrayList(BundleConstant.EXTRA_FIVE, labels) - .put(BundleConstant.EXTRA_SIX, milestone) - .put(BundleConstant.YES_NO_EXTRA, canComment) - .end(); - } - - @OnClick(R.id.submit) void onSubmit() { - boolean isEmpty = InputHelper.isEmpty(comment); - if (!isEmpty) { - //noinspection ConstantConditions - getPresenter().onSubmit(getArguments().getString(BundleConstant.EXTRA_SEVEN), getArguments().getString(BundleConstant.EXTRA_EIGHT), - getArguments().getInt(BundleConstant.ID), InputHelper.toString(comment)); - } else { - showMessage(R.string.error, R.string.required_field); - } - } - - @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - toolbar.setNavigationIcon(R.drawable.ic_clear); - toolbar.setNavigationOnClickListener(view1 -> dismiss()); - Bundle bundle = getArguments(); - String titleString = bundle.getString(BundleConstant.EXTRA); - String bodyString = bundle.getString(BundleConstant.EXTRA_TWO); - User user = bundle.getParcelable(BundleConstant.EXTRA_THREE); - User assigneeModel = bundle.getParcelable(BundleConstant.EXTRA_FOUR); - ArrayList labelsList = bundle.getParcelableArrayList(BundleConstant.EXTRA_FIVE); - MilestoneModel milestoneModel = bundle.getParcelable(BundleConstant.EXTRA_SIX); - boolean canComment = bundle.getBoolean(BundleConstant.YES_NO_EXTRA); - commentSection.setVisibility(canComment ? View.VISIBLE : View.GONE); - toolbar.setTitle(String.format("#%s", bundle.getInt(BundleConstant.ID))); - title.setText(titleString); - MarkDownProvider.setMdText(body, bodyString); - if (user != null) { - name.setText(user.getLogin()); - avatarLayout.setUrl(user.getAvatarUrl(), user.getLogin(), false, LinkParserHelper.isEnterprise(user.getUrl())); - } - if (assigneeModel == null) { - assigneeLayout.setVisibility(View.GONE); - } else { - assignee.setText(assigneeModel.getLogin()); - } - if (labelsList == null || labelsList.isEmpty()) { - labelsLayout.setVisibility(View.GONE); - } else { - SpannableBuilder builder = SpannableBuilder.builder(); - for (LabelModel label : labelsList) { - int color = Color.parseColor("#" + label.getColor()); - builder.append(" ").append(" " + label.getName() + " ", new LabelSpan(color)); - } - labels.setText(builder); - } - if (milestoneModel == null) { - milestoneLayout.setVisibility(View.GONE); - } else { - milestoneTitle.setText(milestoneModel.getTitle()); - milestoneDescription.setText(milestoneModel.getDescription()); - if (milestoneModel.getDescription() == null) { - milestoneDescription.setVisibility(View.GONE); - } - } - } - - @Override protected int fragmentLayout() { - return R.layout.issue_popup_layout; - } - - @NonNull @Override public IssuePopupPresenter providePresenter() { - return new IssuePopupPresenter(); - } - - @Override public void showMessage(int titleRes, int msgRes) { - hideProgress(); - super.showMessage(titleRes, msgRes); - } - - @Override public void showMessage(@NonNull String titleRes, @NonNull String msgRes) { - hideProgress(); - super.showMessage(titleRes, msgRes); - } - - @Override public void showErrorMessage(@NonNull String msgRes) { - hideProgress(); - super.showErrorMessage(msgRes); - } - - @Override public void showProgress(int resId) { - submit.hide(); - AnimHelper.mimicFabVisibility(true, progressBar, null); - } - - @Override public void hideProgress() { - AnimHelper.mimicFabVisibility(false, progressBar, null); - submit.show(); - } - - @Override public void onSuccessfullySubmitted() { - showMessage(R.string.success, R.string.successfully_submitted); - hideProgress(); - comment.setText(""); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupMvp.java deleted file mode 100644 index 48656dac5..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupMvp.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.popup; - -import android.support.annotation.NonNull; - -import com.fastaccess.ui.base.mvp.BaseMvp; - -/** - * Created by Kosh on 27 May 2017, 1:55 PM - */ - -public interface IssuePopupMvp { - - interface View extends BaseMvp.FAView { - void onSuccessfullySubmitted(); - } - - interface Presenter { - void onSubmit(@NonNull String login, @NonNull String repoId, int issueNumber, @NonNull String text); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupPresenter.java deleted file mode 100644 index 7aa24dab7..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/extras/popup/IssuePopupPresenter.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.fastaccess.ui.modules.repos.extras.popup; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by Kosh on 27 May 2017, 1:56 PM - */ - -public class IssuePopupPresenter extends BasePresenter implements IssuePopupMvp.Presenter { - - @Override public void onSubmit(@NonNull String login, @NonNull String repoId, int issueNumber, @NonNull String text) { - CommentRequestModel requestModel = new CommentRequestModel(); - requestModel.setBody(text); - makeRestCall(RestProvider.getIssueService(isEnterprise()).createIssueComment(login, repoId, issueNumber, requestModel), - comment -> sendToView(IssuePopupMvp.View::onSuccessfullySubmitted)); - } - - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFileActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFileActivity.kt deleted file mode 100644 index 89483a573..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFileActivity.kt +++ /dev/null @@ -1,159 +0,0 @@ -package com.fastaccess.ui.modules.repos.git - -import android.annotation.SuppressLint -import android.app.Activity -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import android.support.design.widget.TextInputLayout -import android.support.v4.app.Fragment -import android.support.v4.app.FragmentManager -import android.view.Menu -import android.view.MenuItem -import android.view.View -import android.widget.EditText -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.EditRepoFileModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.provider.emoji.Emoji -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.widgets.markdown.MarkDownLayout -import com.fastaccess.ui.widgets.markdown.MarkdownEditText - -/** - * Created by kosh on 29/08/2017. - */ -class EditRepoFileActivity : BaseActivity(), EditRepoFileMvp.View { - - @BindView(R.id.markDownLayout) lateinit var markDownLayout: MarkDownLayout - @BindView(R.id.editText) lateinit var editText: MarkdownEditText - @BindView(R.id.description) lateinit var description: TextInputLayout - @BindView(R.id.fileName) lateinit var fileName: TextInputLayout - @BindView(R.id.fileNameHolder) lateinit var fileNameHolder: View - @BindView(R.id.commitHolder) lateinit var commitHolder: View - @BindView(R.id.layoutHolder) lateinit var layoutHolder: View - - - override fun layout(): Int = R.layout.edit_repo_file_layout - - override fun isTransparent(): Boolean = false - - override fun canBack(): Boolean = true - - override fun isSecured(): Boolean = true - - override fun providePresenter(): EditRepoFilePresenter = EditRepoFilePresenter() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - markDownLayout.markdownListener = this - setToolbarIcon(R.drawable.ic_clear) - if (savedInstanceState == null) { - presenter.onInit(intent) - } - val path = presenter.model?.path - if (!path.isNullOrBlank() && presenter.model?.fileName.isNullOrBlank()) { - val name = Uri.parse(path)?.lastPathSegment - title = name - fileName.editText?.setText(name) - } else if (!presenter.model?.fileName.isNullOrBlank()) { - fileName.editText?.setText(presenter.model?.fileName) - fileName.isEnabled = false - title = presenter.model?.fileName - } - toolbar?.let { - it.subtitle = "${presenter.model?.login}/${presenter.model?.repoId}" - } - } - - override fun onSetText(content: String?) { - hideProgress() - editText.setText(content) - } - - override fun onCreateOptionsMenu(menu: Menu): Boolean { - menuInflater.inflate(R.menu.done_menu, menu) - return super.onCreateOptionsMenu(menu) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == R.id.submit) { - val text = editText.text - if (presenter.fileContent == text.toString() && presenter.model?.fileName == fileName.editText?.text.toString()) { - showErrorMessage(getString(R.string.commit_file_required)) - return true - } - presenter.onSubmit(editText.text?.toString(), fileName.editText?.text?.toString(), description.editText?.text?.toString()) - return true - } - return super.onOptionsItemSelected(item) - } - - override fun onPrepareOptionsMenu(menu: Menu): Boolean { - if (menu.findItem(R.id.submit) != null) { - menu.findItem(R.id.submit).isEnabled = true - } - presenter.model?.isEdit?.let { - menu.findItem(R.id.submit).setIcon(R.drawable.ic_done) - } - return super.onPrepareOptionsMenu(menu) - } - - override fun onAppendLink(title: String?, link: String?, isLink: Boolean) { - markDownLayout.onAppendLink(title, link, isLink) - } - - override fun getEditText(): EditText = editText - - override fun getSavedText(): CharSequence? = editText.savedText - - override fun fragmentManager(): FragmentManager = supportFragmentManager - - @SuppressLint("SetTextI18n") - override fun onEmojiAdded(emoji: Emoji?) { - markDownLayout.onEmojiAdded(emoji) - } - - override fun onSetTextError(isEmpty: Boolean) { - editText.error = if (isEmpty) getString(R.string.required_field) else null - } - - override fun onSetDescriptionError(isEmpty: Boolean) { - description.error = if (isEmpty) getString(R.string.required_field) else null - } - - override fun onSetFilenameError(isEmpty: Boolean) { - fileName.error = if (isEmpty) getString(R.string.required_field) else null - } - - override fun onSuccessfullyCommitted() { - setResult(Activity.RESULT_OK) - finish() - } - - companion object { - const val EDIT_RQ = 2017 - - fun startForResult(activity: Activity, model: EditRepoFileModel, isEnterprise: Boolean) { - val bundle = Bundler.start() - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .put(BundleConstant.ITEM, model) - .end() - val intent = Intent(activity, EditRepoFileActivity::class.java) - intent.putExtras(bundle) - activity.startActivityForResult(intent, EDIT_RQ) - } - - fun startForResult(fragment: Fragment, model: EditRepoFileModel, isEnterprise: Boolean) { - val bundle = Bundler.start() - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .put(BundleConstant.ITEM, model) - .end() - val intent = Intent(fragment.context, EditRepoFileActivity::class.java) - intent.putExtras(bundle) - fragment.startActivityForResult(intent, EDIT_RQ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFileMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFileMvp.kt deleted file mode 100644 index 618eedc92..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFileMvp.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.fastaccess.ui.modules.repos.git - -import android.content.Intent -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.modules.editor.emoji.EmojiMvp -import com.fastaccess.ui.modules.editor.popup.EditorLinkImageMvp -import com.fastaccess.ui.widgets.markdown.MarkDownLayout - -/** - * Created by kosh on 29/08/2017. - */ -interface EditRepoFileMvp { - - interface View : BaseMvp.FAView, EditorLinkImageMvp.EditorLinkCallback, - MarkDownLayout.MarkdownListener, EmojiMvp.EmojiCallback { - - fun onSetText(content: String?) - fun onSetTextError(isEmpty: Boolean) - fun onSetDescriptionError(isEmpty: Boolean) - fun onSetFilenameError(isEmpty: Boolean) - fun onSuccessfullyCommitted() - } - - interface Presenter { - fun onInit(intent: Intent?) - fun onSubmit(text: String?, filename: String?, description: String?) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFilePresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFilePresenter.kt deleted file mode 100644 index 77e4f1af1..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/git/EditRepoFilePresenter.kt +++ /dev/null @@ -1,69 +0,0 @@ -package com.fastaccess.ui.modules.repos.git - -import android.content.Intent -import android.util.Base64 -import com.fastaccess.data.dao.CommitRequestModel -import com.fastaccess.data.dao.EditRepoFileModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.provider.rest.RestProvider -import com.fastaccess.ui.base.mvp.presenter.BasePresenter - -/** - * Created by kosh on 29/08/2017. - */ -class EditRepoFilePresenter : BasePresenter(), EditRepoFileMvp.Presenter { - - @com.evernote.android.state.State var model: EditRepoFileModel? = null - var fileContent: String? = null - - var downloadedContent: String? = null - - override fun onInit(intent: Intent?) { - if (downloadedContent.isNullOrBlank()) { - intent?.let { - it.extras?.let { - model = it.getParcelable(BundleConstant.ITEM) - loadContent() - } - } - } else { - sendToView { it.onSetText(downloadedContent) } - } - } - - override fun onSubmit(text: String?, filename: String?, description: String?) { - if (model?.login.isNullOrBlank() || model?.repoId.isNullOrBlank()) return - - sendToView { - it.onSetTextError(text.isNullOrBlank()) - it.onSetFilenameError(filename.isNullOrBlank()) - it.onSetDescriptionError(description.isNullOrBlank()) - } - if (!text.isNullOrBlank() && !description.isNullOrBlank() && !filename.isNullOrBlank()) { - model?.let { - val commitModel = CommitRequestModel(description!!, Base64.encodeToString(text!!.toByteArray(), Base64.DEFAULT), it.sha, it.ref) - val observable = RestProvider.getContentService(isEnterprise).updateCreateFile(it.login, it.repoId, - if (it.path.isNullOrBlank()) { - filename!! - } else { - if (it.path!!.endsWith("/")) { - "${it.path}$filename" - } else { - "${it.path}" - } - }, it.ref, commitModel) - makeRestCall(observable, { sendToView { it.onSuccessfullyCommitted() } }) - } - } - } - - private fun loadContent() { - model?.contentUrl?.let { - makeRestCall(RestProvider.getRepoService(isEnterprise) - .getFileAsStream(it), { - fileContent = it - sendToView({ v -> v.onSetText(it) }) - }) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/git/delete/DeleteContentFileCallback.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/git/delete/DeleteContentFileCallback.kt deleted file mode 100644 index 9713a6472..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/git/delete/DeleteContentFileCallback.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.ui.modules.repos.git.delete - -/** - * Created by Hashemsergani on 02/09/2017. - */ -interface DeleteContentFileCallback { - - fun onDelete(message: String, position: Int) -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/git/delete/DeleteFileBottomSheetFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/git/delete/DeleteFileBottomSheetFragment.kt deleted file mode 100644 index 27f603b12..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/git/delete/DeleteFileBottomSheetFragment.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.fastaccess.ui.modules.repos.git.delete - -import android.content.Context -import android.os.Bundle -import android.support.design.widget.TextInputLayout -import android.view.View -import butterknife.BindView -import butterknife.OnClick -import com.fastaccess.R -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.helper.InputHelper -import com.fastaccess.ui.base.BaseBottomSheetDialog - -/** - * Created by Hashemsergani on 02/09/2017. - */ -class DeleteFileBottomSheetFragment : BaseBottomSheetDialog() { - - @BindView(R.id.description) lateinit var description: TextInputLayout - @BindView(R.id.fileName) lateinit var fileName: TextInputLayout - - private var deleteCallback: DeleteContentFileCallback? = null - - - @OnClick(R.id.delete) fun onDeleteClicked() { - description.error = if (InputHelper.isEmpty(description)) getString(R.string.required_field) else null - if (!InputHelper.isEmpty(description)) { - val position = arguments?.getInt(BundleConstant.EXTRA) - position?.let { - deleteCallback?.onDelete(InputHelper.toString(description), position) - } - dismiss() - } - } - - @OnClick(R.id.cancel) - fun onCancel() = dismiss() - - override fun onAttach(context: Context?) { - super.onAttach(context) - if (parentFragment is DeleteContentFileCallback) { - deleteCallback = parentFragment as DeleteContentFileCallback - } else if (context is DeleteContentFileCallback) { - deleteCallback = context - } - } - - override fun onDetach() { - deleteCallback = null - super.onDetach() - } - - override fun layoutRes(): Int = R.layout.delete_repo_file_layout - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - fileName.isEnabled = false - fileName.editText?.setText(arguments?.getString(BundleConstant.ITEM)) - } - - companion object { - fun newInstance(position: Int, path: String): DeleteFileBottomSheetFragment { - val fragment = DeleteFileBottomSheetFragment() - fragment.arguments = Bundler.start() - .put(BundleConstant.EXTRA, position) - .put(BundleConstant.ITEM, path) - .end() - return fragment - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerFragment.java deleted file mode 100644 index 63a8c1978..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerFragment.java +++ /dev/null @@ -1,154 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; -import android.view.View; -import android.widget.TextView; - -import com.annimon.stream.Stream; -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.TabsCountStateModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.issues.issue.RepoClosedIssuesFragment; -import com.fastaccess.ui.modules.repos.issues.issue.RepoOpenedIssuesFragment; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.ViewPagerView; - -import java.util.HashSet; - -import butterknife.BindView; - -/** - * Created by Kosh on 31 Dec 2016, 1:36 AM - */ - -public class RepoIssuesPagerFragment extends BaseFragment implements RepoIssuesPagerMvp.View { - - public static final String TAG = RepoIssuesPagerFragment.class.getSimpleName(); - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.pager) ViewPagerView pager; - @State HashSet counts = new HashSet<>(); - private RepoPagerMvp.View repoCallback; - - public static RepoIssuesPagerFragment newInstance(@NonNull String repoId, @NonNull String login) { - RepoIssuesPagerFragment view = new RepoIssuesPagerFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .end()); - return view; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof RepoPagerMvp.View) { - repoCallback = (RepoPagerMvp.View) getParentFragment(); - } else if (context instanceof RepoPagerMvp.View) { - repoCallback = (RepoPagerMvp.View) context; - } - } - - @Override public void onDetach() { - repoCallback = null; - super.onDetach(); - } - - @Override protected int fragmentLayout() { - return R.layout.centered_tabbed_viewpager; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - String repoId = getArguments().getString(BundleConstant.ID); - String login = getArguments().getString(BundleConstant.EXTRA); - if (login == null || repoId == null) throw new NullPointerException("repoId || login is null???"); - pager.setAdapter(new FragmentsPagerAdapter(getChildFragmentManager(), - FragmentPagerAdapterModel.buildForRepoIssue(getContext(), login, repoId))); - tabs.setupWithViewPager(pager); - if (savedInstanceState != null && !counts.isEmpty()) { - Stream.of(counts).forEach(this::updateCount); - } - tabs.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager) { - @Override public void onTabReselected(TabLayout.Tab tab) { - super.onTabReselected(tab); - onScrollTop(tab.getPosition()); - } - }); - } - - @NonNull @Override public RepoIssuesPagerPresenter providePresenter() { - return new RepoIssuesPagerPresenter(); - } - - @Override public void onAddIssue() { - if (pager.getCurrentItem() != 0) pager.setCurrentItem(0); - RepoOpenedIssuesFragment repoOpenedIssuesView = (RepoOpenedIssuesFragment) pager.getAdapter().instantiateItem(pager, 0); - repoOpenedIssuesView.onAddIssue(); - } - - @Override public void setCurrentItem(int index, boolean refresh) { - if (pager == null || pager.getAdapter() == null) return; - if (!refresh) pager.setCurrentItem(index, true); - if (index == 1 && refresh) { - RepoClosedIssuesFragment closedIssues = (RepoClosedIssuesFragment) pager.getAdapter().instantiateItem(pager, 1); - if (closedIssues != null) closedIssues.onRefresh(); - } else if (index == 0 && refresh) { - RepoOpenedIssuesFragment openedIssues = (RepoOpenedIssuesFragment) pager.getAdapter().instantiateItem(pager, 0); - if (openedIssues != null) openedIssues.onRefresh(); - } - } - - @Override public int getCurrentItem() { - return pager != null ? pager.getCurrentItem() : 0; - } - - @Override public void onScrolled(boolean isUp) { - if (repoCallback != null) repoCallback.onScrolled(isUp); - } - - @Override public void onSetBadge(int tabIndex, int count) { - TabsCountStateModel model = new TabsCountStateModel(); - model.setTabIndex(tabIndex); - model.setCount(count); - counts.add(model); - if (tabs != null) { - updateCount(model); - } - } - - @Override public void onChangeIssueSort(boolean isLastUpdated) { - if (pager == null || pager.getAdapter() == null) return; - RepoClosedIssuesFragment closedIssues = (RepoClosedIssuesFragment) pager.getAdapter().instantiateItem(pager, 1); - if (closedIssues != null) closedIssues.onRefresh(isLastUpdated); - RepoOpenedIssuesFragment openedIssues = (RepoOpenedIssuesFragment) pager.getAdapter().instantiateItem(pager, 0); - if (openedIssues != null) openedIssues.onRefresh(isLastUpdated); - } - - @Override public void onScrollTop(int index) { - if (pager == null || pager.getAdapter() == null) return; - Fragment fragment = (BaseFragment) pager.getAdapter().instantiateItem(pager, index); - if (fragment instanceof BaseFragment) { - ((BaseFragment) fragment).onScrollTop(index); - } - } - - private void updateCount(@NonNull TabsCountStateModel model) { - TextView tv = ViewHelper.getTabTextView(tabs, model.getTabIndex()); - tv.setText(SpannableBuilder.builder() - .append(model.getTabIndex() == 0 ? getString(R.string.opened) : getString(R.string.closed)) - .append(" ") - .append("(") - .bold(String.valueOf(model.getCount())) - .append(")")); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerMvp.java deleted file mode 100644 index 2fc218cbd..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerMvp.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues; - -import android.support.annotation.IntRange; - -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; - -/** - * Created by Kosh on 31 Dec 2016, 1:35 AM - */ - -public interface RepoIssuesPagerMvp { - - interface View extends BaseMvp.FAView, RepoPagerMvp.TabsBadgeListener { - void onAddIssue(); - - void setCurrentItem(int index, boolean refresh); - - void onChangeIssueSort(boolean isLastUpdated); - - @IntRange(from = 0, to = 1) int getCurrentItem(); - - void onScrolled(boolean isUp); - } - - interface Presenter extends BaseMvp.FAPresenter {} - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerPresenter.java deleted file mode 100644 index e5683fb23..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/RepoIssuesPagerPresenter.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues; - -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by Kosh on 31 Dec 2016, 1:36 AM - */ - -class RepoIssuesPagerPresenter extends BasePresenter implements RepoIssuesPagerMvp.Presenter {} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssueActivity.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssueActivity.java deleted file mode 100644 index 1b121fec4..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssueActivity.java +++ /dev/null @@ -1,417 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.create; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.graphics.Color; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TextInputLayout; -import android.support.transition.TransitionManager; -import android.support.v4.app.Fragment; -import android.support.v7.app.AlertDialog; -import android.view.MotionEvent; -import android.view.View; -import android.widget.LinearLayout; -import android.widget.Toast; - -import com.danielstone.materialaboutlibrary.ConvenienceBuilder; -import com.evernote.android.state.State; -import com.fastaccess.App; -import com.fastaccess.BuildConfig; -import com.fastaccess.R; -import com.fastaccess.data.dao.LabelListModel; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.markdown.MarkDownProvider; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.modules.editor.EditorActivity; -import com.fastaccess.ui.modules.repos.extras.assignees.AssigneesDialogFragment; -import com.fastaccess.ui.modules.repos.extras.labels.LabelsDialogFragment; -import com.fastaccess.ui.modules.repos.extras.milestone.create.MilestoneDialogFragment; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.LabelSpan; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; - -import java.util.ArrayList; - -import butterknife.BindView; -import butterknife.OnClick; -import butterknife.OnTouch; -import es.dmoral.toasty.Toasty; - -/** - * Created by Kosh on 19 Feb 2017, 12:33 PM - */ - -public class CreateIssueActivity extends BaseActivity implements CreateIssueMvp.View { - - @BindView(R.id.title) TextInputLayout title; - @BindView(R.id.description) FontTextView description; - @BindView(R.id.submit) View submit; - @BindView(R.id.issueMiscLayout) LinearLayout issueMiscLayout; - @BindView(R.id.assignee) FontTextView assignee; - @BindView(R.id.labels) FontTextView labels; - @BindView(R.id.milestoneTitle) FontTextView milestoneTitle; - @BindView(R.id.milestoneDescription) FontTextView milestoneDescription; - - @State String repoId; - @State String login; - @State Issue issue; - @State PullRequest pullRequest; - @State boolean isFeedback; - @State ArrayList labelModels = new ArrayList<>(); - @State MilestoneModel milestoneModel; - @State ArrayList users = new ArrayList<>(); - - private AlertDialog alertDialog; - private CharSequence savedText; - - public static void startForResult(@NonNull Fragment fragment, @NonNull String login, @NonNull String repoId, boolean isEnterprise) { - Intent intent = new Intent(fragment.getContext(), CreateIssueActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA_TWO, login.equalsIgnoreCase("k0shk0sh") && repoId.equalsIgnoreCase("FastHub")) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - View view = fragment.getActivity() != null ? fragment.getActivity().findViewById(R.id.fab) : null; - if (view != null) { - ActivityHelper.startReveal(fragment, intent, view, BundleConstant.REQUEST_CODE); - } else { - fragment.startActivityForResult(intent, BundleConstant.REQUEST_CODE); - } - } - - - public static void startForResult(@NonNull Activity activity, @NonNull String login, @NonNull String repoId, - @Nullable Issue issueModel, boolean isEnterprise) { - if (issueModel != null) { - Intent intent = new Intent(activity, CreateIssueActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repoId) - .put(BundleConstant.ITEM, issueModel) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - View view = activity.findViewById(R.id.fab); - if (view != null) { - startForResult(activity, intent, view); - } else { - activity.startActivityForResult(intent, BundleConstant.REQUEST_CODE); - } - } - } - - public static void startForResult(@NonNull Activity activity, @NonNull String login, @NonNull String repoId, - @Nullable PullRequest pullRequestModel, boolean isEnterprise) { - if (pullRequestModel != null) { - Intent intent = new Intent(activity, CreateIssueActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repoId) - .put(BundleConstant.ITEM, pullRequestModel) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()); - View view = activity.findViewById(R.id.fab); - if (view != null) { - startForResult(activity, intent, view); - } else { - activity.startActivityForResult(intent, BundleConstant.REQUEST_CODE); - } - } - } - - @NonNull public static Intent getIntent(@NonNull Context context, @NonNull String login, @NonNull String repoId, boolean isFeedback) { - Intent intent = new Intent(context, CreateIssueActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA_TWO, isFeedback) - .end()); - return intent; - } - - @NonNull public static Intent startForResult(@NonNull Activity activity) { - String login = "k0shk0sh"; // FIXME: 23/02/2017 hardcoded - String repoId = "FastHub";// FIXME: 23/02/2017 hardcoded - Intent intent = new Intent(activity, CreateIssueActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA_TWO, true) - .end()); - return intent; - } - - public static void startForResult(@NonNull Activity activity, @NonNull Intent intent, @NonNull View view) { - ActivityHelper.startReveal(activity, intent, view, BundleConstant.REQUEST_CODE); - } - - @Override public void onSetCode(@NonNull CharSequence charSequence) { - this.savedText = charSequence; - MarkDownProvider.setMdText(description, InputHelper.toString(savedText)); - } - - @Override public void onTitleError(boolean isEmptyTitle) { - title.setError(isEmptyTitle ? getString(R.string.required_field) : null); - } - - @Override public void onDescriptionError(boolean isEmptyDesc) { - description.setError(isEmptyDesc ? getString(R.string.required_field) : null); - } - - @Override public void onSuccessSubmission(Issue issueModel) { - hideProgress(); - Intent intent = new Intent(); - intent.putExtras(Bundler.start() - .put(BundleConstant.ITEM, issueModel) - .end()); - setResult(RESULT_OK, intent); - finish(); - showMessage(R.string.success, R.string.successfully_submitted); - } - - @Override public void onSuccessSubmission(PullRequest issueModel) { - hideProgress(); - Intent intent = new Intent(); - intent.putExtras(Bundler.start() - .put(BundleConstant.ITEM, issueModel) - .end()); - setResult(RESULT_OK, intent); - finish(); - showMessage(R.string.success, R.string.successfully_submitted); - } - - @Override public void onShowUpdate() { - hideProgress(); - Toasty.error(App.getInstance(), getString(R.string.new_version)).show(); - ConvenienceBuilder.createRateOnClickAction(this).onClick(); - finish(); - } - - @Override public void onShowIssueMisc() { - TransitionManager.beginDelayedTransition(findViewById(R.id.parent)); - issueMiscLayout.setVisibility(getPresenter().isCollaborator() ? View.VISIBLE : View.GONE); - //TODO - } - - @NonNull @Override public CreateIssuePresenter providePresenter() { - return new CreateIssuePresenter(); - } - - @Override protected int layout() { - return R.layout.create_issue_layout; - } - - @Override protected boolean isTransparent() { - return false; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState == null) { - Bundle bundle = getIntent().getExtras(); - login = bundle.getString(BundleConstant.EXTRA); - repoId = bundle.getString(BundleConstant.ID); - isFeedback = bundle.getBoolean(BundleConstant.EXTRA_TWO); - if (bundle.getParcelable(BundleConstant.ITEM) != null) { - if (bundle.getParcelable(BundleConstant.ITEM) instanceof Issue) { - issue = bundle.getParcelable(BundleConstant.ITEM); - setTitle(getString(R.string.update_issue)); - } else if (bundle.getParcelable(BundleConstant.ITEM) instanceof PullRequest) { - pullRequest = bundle.getParcelable(BundleConstant.ITEM); - setTitle(getString(R.string.update_pull_request)); - } - } - if (issue != null) { - Logger.e(issue.getLabels(), issue.getMilestone(), issue.getAssignees()); - if (issue.getLabels() != null) { - onSelectedLabels(new ArrayList<>(issue.getLabels())); - } - if (issue.getAssignees() != null) { - onSelectedAssignees(new ArrayList<>(issue.getAssignees()), false); - } - if (issue.getMilestone() != null) { - milestoneModel = issue.getMilestone(); - onMilestoneSelected(milestoneModel); - } - if (!InputHelper.isEmpty(issue.getTitle())) { - if (title.getEditText() != null) title.getEditText().setText(issue.getTitle()); - } - if (!InputHelper.isEmpty(issue.getBody())) { - onSetCode(issue.getBody()); - } - } - if (pullRequest != null) { - if (pullRequest.getLabels() != null) { - onSelectedLabels(new ArrayList<>(pullRequest.getLabels())); - } - if (pullRequest.getAssignees() != null) { - users.addAll(pullRequest.getAssignees()); - onSelectedAssignees(new ArrayList<>(pullRequest.getAssignees()), false); - } - if (pullRequest.getMilestone() != null) { - milestoneModel = pullRequest.getMilestone(); - onMilestoneSelected(milestoneModel); - } - if (!InputHelper.isEmpty(pullRequest.getTitle())) { - if (title.getEditText() != null) title.getEditText().setText(pullRequest.getTitle()); - } - if (!InputHelper.isEmpty(pullRequest.getBody())) { - onSetCode(pullRequest.getBody()); - } - } - } - getPresenter().checkAuthority(login, repoId); - if (isFeedback || ("k0shk0sh".equalsIgnoreCase(login) && repoId.equalsIgnoreCase("FastHub"))) { - Toasty.info(App.getInstance(), getString(R.string.report_issue_warning), Toast.LENGTH_LONG).show(); - setTitle(R.string.submit_feedback); - getPresenter().onCheckAppVersion(); - } - if (BuildConfig.DEBUG && isFeedback) { - alertDialog = new AlertDialog.Builder(this) - .setTitle("You are currently using a debug build") - .setMessage("If you have found a bug, please report it on slack." + "\n" + - "Feature requests can be submitted here." + "\n" + "Happy Testing") - .setPositiveButton(android.R.string.ok, null) - .show(); - } - if (toolbar != null) toolbar.setSubtitle(login + "/" + repoId); - setTaskName(login + "/" + repoId + " - " + (isFeedback ? getString(R.string.submit_feedback) : getString(R.string.create_issue))); - } - - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - AppHelper.hideKeyboard(title); - getPresenter().onActivityForResult(resultCode, requestCode, data); - } - - @Override public void onBackPressed() { - if (InputHelper.isEmpty(title)) { - super.onBackPressed(); - } else { - ViewHelper.hideKeyboard(title); - MessageDialogView.newInstance(getString(R.string.close), getString(R.string.unsaved_data_warning), - Bundler.start().put("primary_extra", getString(R.string.discard)).put("secondary_extra", getString(R.string.cancel)) - .put(BundleConstant.EXTRA, true).end()).show(getSupportFragmentManager(), MessageDialogView.TAG); - } - } - - @Override protected void onDestroy() { - if (alertDialog != null && alertDialog.isShowing()) { - alertDialog.dismiss(); - } - super.onDestroy(); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk && bundle != null) { - finish(); - } - } - - @OnTouch(R.id.description) boolean onTouch(MotionEvent event) { - if (isFeedback && InputHelper.isEmpty(savedText)) { - savedText = AppHelper.getFastHubIssueTemplate(isEnterprise()); - } - if (event.getAction() == MotionEvent.ACTION_UP) { - Intent intent = new Intent(this, EditorActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, InputHelper.toString(savedText)) - .put(BundleConstant.EXTRA_TYPE, BundleConstant.ExtraType.FOR_RESULT_EXTRA) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise()) - .end()); - ActivityHelper.startReveal(this, intent, submit, BundleConstant.REQUEST_CODE); - return true; - } - return false; - } - - @OnClick(R.id.submit) public void onClick() { - getPresenter().onSubmit(InputHelper.toString(title), savedText, login, repoId, issue, pullRequest, labelModels, milestoneModel, users); - } - - @OnClick({R.id.addAssignee, R.id.addLabels, R.id.addMilestone}) public void onViewClicked(View view) { - switch (view.getId()) { - case R.id.addAssignee: - AssigneesDialogFragment.newInstance(login, repoId, false) - .show(getSupportFragmentManager(), "AssigneesDialogFragment"); - break; - case R.id.addLabels: - LabelListModel labelModels = new LabelListModel(); - labelModels.addAll(this.labelModels); - LabelsDialogFragment.newInstance(labelModels, repoId, login) - .show(getSupportFragmentManager(), "LabelsDialogFragment"); - break; - case R.id.addMilestone: - MilestoneDialogFragment.newInstance(login, repoId) - .show(getSupportFragmentManager(), "MilestoneDialogFragment"); - break; - } - } - - @Override public void onSelectedLabels(@NonNull ArrayList labelModels) { - this.labelModels.clear(); - this.labelModels.addAll(labelModels); - SpannableBuilder builder = SpannableBuilder.builder(); - for (int i = 0; i < labelModels.size(); i++) { - LabelModel labelModel = labelModels.get(i); - int color = Color.parseColor("#" + labelModel.getColor()); - if (i > 0) { - builder.append(" ").append(" " + labelModel.getName() + " ", new LabelSpan(color)); - } else { - builder.append(labelModel.getName() + " ", new LabelSpan(color)); - } - } - this.labels.setText(builder); - } - - @Override public void onMilestoneSelected(@NonNull MilestoneModel milestoneModel) { - Logger.e(milestoneModel.getTitle(), milestoneModel.getDescription(), milestoneModel.getNumber()); - this.milestoneModel = milestoneModel; - milestoneTitle.setText(milestoneModel.getTitle()); - if (!InputHelper.isEmpty(milestoneModel.getDescription())) { - milestoneDescription.setText(milestoneModel.getDescription()); - milestoneDescription.setVisibility(View.VISIBLE); - } else { - milestoneDescription.setText(""); - milestoneDescription.setVisibility(View.GONE); - } - } - - @Override public void onSelectedAssignees(@NonNull ArrayList users, boolean isAssignees) { - this.users.clear(); - this.users.addAll(users); - SpannableBuilder builder = SpannableBuilder.builder(); - for (int i = 0; i < users.size(); i++) { - User user = users.get(i); - builder.append(user.getLogin()); - if (i != users.size() - 1) { - builder.append(", "); - } - } - assignee.setText(builder); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssueMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssueMvp.java deleted file mode 100644 index 7740da182..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssueMvp.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.create; - -import android.content.Intent; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.repos.extras.assignees.AssigneesMvp; -import com.fastaccess.ui.modules.repos.extras.labels.LabelsMvp; -import com.fastaccess.ui.modules.repos.extras.milestone.MilestoneMvp; - -import java.util.ArrayList; - -/** - * Created by Kosh on 19 Feb 2017, 12:12 PM - */ - -public interface CreateIssueMvp { - - interface View extends BaseMvp.FAView, LabelsMvp.SelectedLabelsListener, AssigneesMvp.SelectedAssigneesListener, - MilestoneMvp.OnMilestoneSelected { - void onSetCode(@NonNull CharSequence charSequence); - - void onTitleError(boolean isEmptyTitle); - - void onDescriptionError(boolean isEmptyDesc); - - void onSuccessSubmission(Issue issueModel); - - void onSuccessSubmission(PullRequest issueModel); - - void onShowUpdate(); - - void onShowIssueMisc(); - } - - interface Presenter extends BaseMvp.FAPresenter { - - void checkAuthority(@NonNull String login, @NonNull String repoId); - - void onActivityForResult(int resultCode, int requestCode, Intent intent); - - void onSubmit(@NonNull String title, @NonNull CharSequence description, @NonNull String login, - @NonNull String repo, @Nullable Issue issueModel, @Nullable PullRequest pullRequestModel, - @Nullable ArrayList labels, @Nullable MilestoneModel milestoneModel, - @Nullable ArrayList users); - - void onCheckAppVersion(); - - boolean isCollaborator(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssuePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssuePresenter.java deleted file mode 100644 index 4452103f6..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/create/CreateIssuePresenter.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.create; - -import android.app.Activity; -import android.content.Intent; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.fastaccess.BuildConfig; -import com.fastaccess.R; -import com.fastaccess.data.dao.CreateIssueModel; -import com.fastaccess.data.dao.IssueRequestModel; -import com.fastaccess.data.dao.LabelListModel; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.UsersListModel; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 19 Feb 2017, 12:18 PM - */ - -public class CreateIssuePresenter extends BasePresenter implements CreateIssueMvp.Presenter { - - @com.evernote.android.state.State boolean isCollaborator; - - - @Override public void checkAuthority(@NonNull String login, @NonNull String repoId) { - manageViewDisposable(RxHelper.getObservable(RestProvider.getRepoService(isEnterprise()). - isCollaborator(login, repoId, Login.getUser().getLogin())) - .subscribe(booleanResponse -> { - isCollaborator = booleanResponse.code() == 204; - sendToView(CreateIssueMvp.View::onShowIssueMisc); - }, Throwable::printStackTrace)); - } - - @Override public void onActivityForResult(int resultCode, int requestCode, Intent intent) { - if (resultCode == Activity.RESULT_OK && requestCode == BundleConstant.REQUEST_CODE) { - if (intent != null && intent.getExtras() != null) { - CharSequence charSequence = intent.getExtras().getCharSequence(BundleConstant.EXTRA); - if (!InputHelper.isEmpty(charSequence)) { - sendToView(view -> view.onSetCode(charSequence)); - } - } - } - } - - @Override public void onSubmit(@NonNull String title, @NonNull CharSequence description, @NonNull String login, - @NonNull String repo, @Nullable Issue issue, @Nullable PullRequest pullRequestModel, - @Nullable ArrayList labels, @Nullable MilestoneModel milestoneModel, - @Nullable ArrayList users) { - - boolean isEmptyTitle = InputHelper.isEmpty(title); - if (getView() != null) { - getView().onTitleError(isEmptyTitle); - } - if (!isEmptyTitle) { - if (issue == null && pullRequestModel == null) { - CreateIssueModel createIssue = new CreateIssueModel(); - createIssue.setBody(InputHelper.toString(description)); - createIssue.setTitle(title); - if (isCollaborator) { - if (labels != null && !labels.isEmpty()) { - createIssue.setLabels(Stream.of(labels).map(LabelModel::getName).collect(Collectors.toCollection(ArrayList::new))); - } - if (users != null && !users.isEmpty()) { - createIssue.setAssignees(Stream.of(users).map(User::getLogin).collect(Collectors.toCollection(ArrayList::new))); - } - if (milestoneModel != null) { - createIssue.setMilestone((long) milestoneModel.getNumber()); - } - } - makeRestCall(RestProvider.getIssueService(isEnterprise()).createIssue(login, repo, createIssue), - issueModel -> { - if (issueModel != null) { - sendToView(view -> view.onSuccessSubmission(issueModel)); - } else { - sendToView(view -> view.showMessage(R.string.error, R.string.error_creating_issue)); - } - }, false); - } else { - if (issue != null) { - issue.setBody(InputHelper.toString(description)); - issue.setTitle(title); - int number = issue.getNumber(); - if (isCollaborator) { - if (labels != null) { - LabelListModel labelModels = new LabelListModel(); - labelModels.addAll(labels); - issue.setLabels(labelModels); - } - if (milestoneModel != null) { - issue.setMilestone(milestoneModel); - } - if (users != null) { - UsersListModel usersListModel = new UsersListModel(); - usersListModel.addAll(users); - issue.setAssignees(usersListModel); - } - } - IssueRequestModel requestModel = IssueRequestModel.clone(issue, false); - makeRestCall(RestProvider.getIssueService(isEnterprise()).editIssue(login, repo, number, requestModel), - issueModel -> { - if (issueModel != null) { - sendToView(view -> view.onSuccessSubmission(issueModel)); - } else { - sendToView(view -> view.showMessage(R.string.error, R.string.error_creating_issue)); - } - }, false); - } - if (pullRequestModel != null) { - int number = pullRequestModel.getNumber(); - pullRequestModel.setBody(InputHelper.toString(description)); - pullRequestModel.setTitle(title); - if (isCollaborator) { - if (labels != null) { - LabelListModel labelModels = new LabelListModel(); - labelModels.addAll(labels); - pullRequestModel.setLabels(labelModels); - } - if (milestoneModel != null) { - pullRequestModel.setMilestone(milestoneModel); - } - if (users != null) { - UsersListModel usersListModel = new UsersListModel(); - usersListModel.addAll(users); - pullRequestModel.setAssignees(usersListModel); - } - } - IssueRequestModel requestModel = IssueRequestModel.clone(pullRequestModel, false); - makeRestCall(RestProvider.getPullRequestService(isEnterprise()).editPullRequest(login, repo, number, requestModel) - .flatMap(pullRequest1 -> RestProvider.getIssueService(isEnterprise()).getIssue(login, repo, number), - (pullRequest1, issueReaction) -> {//hack to get reactions from issue api - if (issueReaction != null) { - pullRequest1.setReactions(issueReaction.getReactions()); - } - return pullRequest1; - }), pr -> { - if (pr != null) { - sendToView(view -> view.onSuccessSubmission(pr)); - } else { - sendToView(view -> view.showMessage(R.string.error, R.string.error_creating_issue)); - } - }, false); - } - } - } - - } - - @Override public void onCheckAppVersion() { - makeRestCall(RestProvider.getRepoService(false).getLatestRelease("k0shk0sh", "FastHub"), - release -> { - if (release != null) { - if (!BuildConfig.VERSION_NAME.contains(release.getTagName())) { - sendToView(CreateIssueMvp.View::onShowUpdate); - } else { - sendToView(BaseMvp.FAView::hideProgress); - } - } - }, false); - } - - @Override public boolean isCollaborator() { - return isCollaborator; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoClosedIssuesFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoClosedIssuesFragment.java deleted file mode 100644 index d2efa78dc..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoClosedIssuesFragment.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.issue; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.IssuesAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.extras.popup.IssuePopupFragment; -import com.fastaccess.ui.modules.repos.issues.RepoIssuesPagerMvp; -import com.fastaccess.ui.modules.repos.issues.issue.details.IssuePagerActivity; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class RepoClosedIssuesFragment extends BaseFragment implements RepoIssuesMvp.View { - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private IssuesAdapter adapter; - private RepoPagerMvp.TabsBadgeListener tabsBadgeListener; - private RepoIssuesPagerMvp.View pagerCallback; - - public static RepoClosedIssuesFragment newInstance(@NonNull String repoId, @NonNull String login) { - RepoClosedIssuesFragment view = new RepoClosedIssuesFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .end()); - return view; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof RepoIssuesPagerMvp.View) { - pagerCallback = (RepoIssuesPagerMvp.View) getParentFragment(); - } else if (context instanceof RepoIssuesPagerMvp.View) { - pagerCallback = (RepoIssuesPagerMvp.View) context; - } - if (getParentFragment() instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) getParentFragment(); - } else if (context instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) context; - } - } - - @Override public void onDetach() { - pagerCallback = null; - tabsBadgeListener = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, therefore, issues can't be proceeded."); - } - stateLayout.setEmptyText(R.string.no_issues); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - adapter = new IssuesAdapter(getPresenter().getIssues(), true); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments(), IssueState.closed); - } else if (getPresenter().getIssues().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public RepoIssuesPresenter providePresenter() { - return new RepoIssuesPresenter(); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK) { - if (requestCode == RepoIssuesMvp.ISSUE_REQUEST_CODE && data != null) { - boolean isClose = data.getExtras().getBoolean(BundleConstant.EXTRA); - boolean isOpened = data.getExtras().getBoolean(BundleConstant.EXTRA_TWO); - if (isClose) { - onRefresh(); - } else if (isOpened) { - if (pagerCallback != null) pagerCallback.setCurrentItem(0, true); - onRefresh(); - } //else ignore! - } - } - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()) { - @Override public void onScrolled(boolean isUp) { - super.onScrolled(isUp); - if (pagerCallback != null) pagerCallback.onScrolled(isUp); - } - }; - } - onLoadMore.setParameter(IssueState.closed); - return onLoadMore; - } - - @Override public void onAddIssue() { - //DO NOTHING - } - - @Override public void onUpdateCount(int totalCount) { - if (tabsBadgeListener != null) tabsBadgeListener.onSetBadge(1, totalCount); - } - - @Override public void onOpenIssue(@NonNull PullsIssuesParser parser) { - startActivityForResult(IssuePagerActivity.createIntent(getContext(), parser.getRepoId(), parser.getLogin(), - parser.getNumber(), false, isEnterprise()), RepoIssuesMvp.ISSUE_REQUEST_CODE); - } - - @Override public void onRefresh(boolean isLastUpdated) { - getPresenter().onSetSortBy(isLastUpdated); - getPresenter().onCallApi(1, IssueState.closed); - } - - @Override public void onShowIssuePopup(@NonNull Issue item) { - IssuePopupFragment.showPopup(getChildFragmentManager(), item); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, IssueState.closed); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoIssuesMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoIssuesMvp.java deleted file mode 100644 index 5b42cb88d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoIssuesMvp.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.issue; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface RepoIssuesMvp { - - int ISSUE_REQUEST_CODE = 1002; - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onAddIssue(); - - void onUpdateCount(int totalCount); - - void onOpenIssue(@NonNull PullsIssuesParser parser); - - void onRefresh(boolean isLastUpdated); - - void onShowIssuePopup(@NonNull Issue item); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - void onFragmentCreated(@NonNull Bundle bundle, @NonNull IssueState issueState); - - void onWorkOffline(); - - @NonNull ArrayList getIssues(); - - @NonNull String repoId(); - - @NonNull String login(); - - void onSetSortBy(boolean isLastUpdated); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoIssuesPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoIssuesPresenter.java deleted file mode 100644 index 6159c5501..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoIssuesPresenter.java +++ /dev/null @@ -1,184 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.issue; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.annimon.stream.Stream; -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RepoQueryProvider; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; -import java.util.List; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class RepoIssuesPresenter extends BasePresenter implements RepoIssuesMvp.Presenter { - - private ArrayList issues = new ArrayList<>(); - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State IssueState issueState; - @com.evernote.android.state.State boolean isLastUpdated; - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - onWorkOffline(); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable IssueState parameter) { - if (parameter == null) { - sendToView(RepoIssuesMvp.View::hideProgress); - return false; - } - this.issueState = parameter; - if (page == 1) { - onCallCountApi(issueState); - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - if (page > lastPage || lastPage == 0) { - sendToView(RepoIssuesMvp.View::hideProgress); - return false; - } - String sortBy = "created"; - if (isLastUpdated) { - sortBy = "updated"; - } - setCurrentPage(page); - String finalSortBy = sortBy; - makeRestCall(RestProvider.getIssueService(isEnterprise()) - .getRepositoryIssues(login, repoId, parameter.name(), sortBy, page) - .flatMap(issues -> { - lastPage = issues.getLast(); - List filtered = Stream.of(issues.getItems()) - .filter(issue -> issue.getPullRequest() == null) - .toList(); - if (filtered != null) { - if (filtered.size() < 10 && issues.getNext() > 1) { - setCurrentPage(getCurrentPage() + 1); - return grabMoreIssues(filtered, parameter.name(), finalSortBy, getCurrentPage()); - } - return Observable.just(filtered); - } - return Observable.just(new ArrayList()); - }) - .doOnNext(filtered -> { - if (getCurrentPage() == 1) { - Issue.save(filtered, repoId, login); - } - }), - issues -> sendToView(view -> view.onNotifyAdapter(issues, page))); - return true; - } - - @Override public void onFragmentCreated(@NonNull Bundle bundle, @NonNull IssueState issueState) { - repoId = bundle.getString(BundleConstant.ID); - login = bundle.getString(BundleConstant.EXTRA); - this.issueState = issueState; - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - onCallApi(1, issueState); - } - } - - @Override public void onWorkOffline() { - if (issues.isEmpty()) { - manageDisposable(RxHelper.getSingle(Issue.getIssues(repoId, login, issueState)) - .subscribe(issueModel -> sendToView(view -> { - view.onNotifyAdapter(issueModel, 1); - view.onUpdateCount(issueModel.size()); - }))); - } else { - sendToView(BaseMvp.FAView::hideProgress); - } - } - - @NonNull @Override public ArrayList getIssues() { - return issues; - } - - @NonNull @Override public String repoId() { - return repoId; - } - - @NonNull @Override public String login() { - return login; - } - - @Override public void onSetSortBy(boolean isLastUpdated) { - this.isLastUpdated = isLastUpdated; - } - - @Override public void onItemClick(int position, View v, Issue item) { - PullsIssuesParser parser = PullsIssuesParser.getForIssue(item.getHtmlUrl()); - if (parser != null && getView() != null) { - getView().onOpenIssue(parser); - } - } - - @Override public void onItemLongClick(int position, View v, Issue item) { - if (getView() != null) getView().onShowIssuePopup(item); - } - - private void onCallCountApi(@NonNull IssueState issueState) { - manageDisposable(RxHelper.getObservable(RestProvider.getIssueService(isEnterprise()) - .getIssuesWithCount(RepoQueryProvider.getIssuesPullRequestQuery(login, repoId, issueState, false), 1)) - .subscribe(pullRequestPageable -> sendToView(view -> view.onUpdateCount(pullRequestPageable.getTotalCount())), - Throwable::printStackTrace)); - } - - private Observable> grabMoreIssues(@NonNull List issues, @NonNull String state, @NonNull String sortBy, int page) { - return RestProvider.getIssueService(isEnterprise()).getRepositoryIssues(login, repoId, state, sortBy, page) - .flatMap(issuePageable -> { - if (issuePageable != null) { - lastPage = issuePageable.getLast(); - List filtered = Stream.of(issuePageable.getItems()) - .filter(issue -> issue.getPullRequest() == null) - .toList(); - if (filtered != null) { - issues.addAll(filtered); - if (issues.size() < 10 && issuePageable.getNext() > 1 && this.issues.size() < 10) { - setCurrentPage(getCurrentPage() + 1); - return grabMoreIssues(issues, state, sortBy, getCurrentPage()); - } - issues.addAll(filtered); - return Observable.just(issues); - } - } - return Observable.just(issues); - }); - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoOpenedIssuesFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoOpenedIssuesFragment.java deleted file mode 100644 index 875262c06..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/RepoOpenedIssuesFragment.java +++ /dev/null @@ -1,219 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.issue; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.IssuesAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.extras.popup.IssuePopupFragment; -import com.fastaccess.ui.modules.repos.issues.RepoIssuesPagerMvp; -import com.fastaccess.ui.modules.repos.issues.create.CreateIssueActivity; -import com.fastaccess.ui.modules.repos.issues.issue.details.IssuePagerActivity; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class RepoOpenedIssuesFragment extends BaseFragment implements RepoIssuesMvp.View { - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private IssuesAdapter adapter; - private RepoIssuesPagerMvp.View pagerCallback; - private RepoPagerMvp.TabsBadgeListener tabsBadgeListener; - - public static RepoOpenedIssuesFragment newInstance(@NonNull String repoId, @NonNull String login) { - RepoOpenedIssuesFragment view = new RepoOpenedIssuesFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .end()); - return view; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof RepoIssuesPagerMvp.View) { - pagerCallback = (RepoIssuesPagerMvp.View) getParentFragment(); - } else if (context instanceof RepoIssuesPagerMvp.View) { - pagerCallback = (RepoIssuesPagerMvp.View) context; - } - if (getParentFragment() instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) getParentFragment(); - } else if (context instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) context; - } - } - - @Override public void onDetach() { - pagerCallback = null; - tabsBadgeListener = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, therefore, issues can't be proceeded."); - } - stateLayout.setEmptyText(R.string.no_issues); - recycler.setEmptyView(stateLayout, refresh); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - adapter = new IssuesAdapter(getPresenter().getIssues(), true); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments(), IssueState.open); - } else if (getPresenter().getIssues().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK) { - if (requestCode == BundleConstant.REQUEST_CODE) { - onRefresh(); - if (pagerCallback != null) pagerCallback.setCurrentItem(0, false); - } else if (requestCode == RepoIssuesMvp.ISSUE_REQUEST_CODE && data != null) { - boolean isClose = data.getExtras().getBoolean(BundleConstant.EXTRA); - boolean isOpened = data.getExtras().getBoolean(BundleConstant.EXTRA_TWO); - if (isClose) { - if (pagerCallback != null) pagerCallback.setCurrentItem(1, true); - onRefresh(); - } else if (isOpened) { - onRefresh(); - } //else ignore! - } - } - } - - @NonNull @Override public RepoIssuesPresenter providePresenter() { - return new RepoIssuesPresenter(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()) { - @Override public void onScrolled(boolean isUp) { - super.onScrolled(isUp); - if (pagerCallback != null) pagerCallback.onScrolled(isUp); - } - }; - } - onLoadMore.setParameter(IssueState.open); - return onLoadMore; - } - - @Override public void onAddIssue() { - String login = getPresenter().login(); - String repoId = getPresenter().repoId(); - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - CreateIssueActivity.startForResult(this, login, repoId, isEnterprise()); - } - } - - @Override public void onUpdateCount(int totalCount) { - if (tabsBadgeListener != null) tabsBadgeListener.onSetBadge(0, totalCount); - } - - @Override public void onOpenIssue(@NonNull PullsIssuesParser parser) { - startActivityForResult(IssuePagerActivity.createIntent(getContext(), parser.getRepoId(), parser.getLogin(), - parser.getNumber(), false, isEnterprise()), RepoIssuesMvp.ISSUE_REQUEST_CODE); - } - - @Override public void onRefresh(boolean isLastUpdated) { - getPresenter().onSetSortBy(isLastUpdated); - getPresenter().onCallApi(1, IssueState.open); - } - - @Override public void onShowIssuePopup(@NonNull Issue item) { - IssuePopupFragment.showPopup(getChildFragmentManager(), item); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, IssueState.open); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerActivity.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerActivity.java deleted file mode 100644 index ca1081be2..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerActivity.java +++ /dev/null @@ -1,462 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.issue.details; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.TabLayout; -import android.support.v4.content.ContextCompat; -import android.support.v4.view.ViewPager; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.PinnedIssues; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.ParseDateFormat; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; -import com.fastaccess.ui.modules.main.premium.PremiumActivity; -import com.fastaccess.ui.modules.repos.RepoPagerActivity; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.extras.assignees.AssigneesDialogFragment; -import com.fastaccess.ui.modules.repos.extras.labels.LabelsDialogFragment; -import com.fastaccess.ui.modules.repos.extras.locking.LockIssuePrBottomSheetDialog; -import com.fastaccess.ui.modules.repos.extras.milestone.create.MilestoneDialogFragment; -import com.fastaccess.ui.modules.repos.issues.create.CreateIssueActivity; -import com.fastaccess.ui.modules.repos.issues.issue.details.timeline.IssueTimelineFragment; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.ViewPagerView; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; - -import java.util.ArrayList; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 10 Dec 2016, 9:23 AM - */ - -public class IssuePagerActivity extends BaseActivity implements IssuePagerMvp.View { - - @BindView(R.id.startGist) ForegroundImageView startGist; - @BindView(R.id.forkGist) ForegroundImageView forkGist; - @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.headerTitle) FontTextView title; - @BindView(R.id.size) FontTextView size; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.pager) ViewPagerView pager; - @BindView(R.id.fab) FloatingActionButton fab; - @BindView(R.id.detailsIcon) View detailsIcon; - @State boolean isClosed; - @State boolean isOpened; - private CommentEditorFragment commentEditorFragment; - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, @NonNull String login, int number) { - return createIntent(context, repoId, login, number, false); - - } - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, - @NonNull String login, int number, boolean showToRepoBtn) { - return createIntent(context, repoId, login, number, showToRepoBtn, false); - - } - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, - @NonNull String login, int number, boolean showToRepoBtn, - boolean isEnterprise) { - return createIntent(context, repoId, login, number, showToRepoBtn, isEnterprise, 0); - - } - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, - @NonNull String login, int number, boolean showToRepoBtn, - boolean isEnterprise, long commentId) { - Intent intent = new Intent(context, IssuePagerActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.ID, number) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, repoId) - .put(BundleConstant.EXTRA_THREE, showToRepoBtn) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .put(BundleConstant.EXTRA_SIX, commentId) - .end()); - return intent; - - } - - @OnClick(R.id.detailsIcon) void onTitleClick() { - if (getPresenter().getIssue() != null && !InputHelper.isEmpty(getPresenter().getIssue().getTitle())) - MessageDialogView.newInstance(String.format("%s/%s", getPresenter().getLogin(), getPresenter().getRepoId()), - getPresenter().getIssue().getTitle(), false, true) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - } - - @Override protected int layout() { - return R.layout.issue_pager_activity; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public IssuePagerPresenter providePresenter() { - return new IssuePagerPresenter(); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - commentEditorFragment = (CommentEditorFragment) getSupportFragmentManager().findFragmentById(R.id.commentFragment); - tabs.setVisibility(View.GONE); - if (savedInstanceState == null) { - getPresenter().onActivityCreated(getIntent()); - } else { - if (getPresenter().getIssue() != null) onSetupIssue(false); - } - startGist.setVisibility(View.GONE); - forkGist.setVisibility(View.GONE); - fab.hide(); - if (getPresenter().showToRepoBtn()) showNavToRepoItem(); - } - - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK && data != null) { - if (requestCode == BundleConstant.REQUEST_CODE) { - Bundle bundle = data.getExtras(); - if (bundle != null) { - Issue issueModel = bundle.getParcelable(BundleConstant.ITEM); - if (issueModel != null) { - getPresenter().onUpdateIssue(issueModel); - } - } - } - } - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.issue_menu, menu); - menu.findItem(R.id.closeIssue).setVisible(getPresenter().isOwner()); - menu.findItem(R.id.lockIssue).setVisible(getPresenter().isRepoOwner() || getPresenter().isCollaborator); - menu.findItem(R.id.labels).setVisible(getPresenter().isRepoOwner() || getPresenter().isCollaborator); - return super.onCreateOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - onNavToRepoClicked(); - return true; - } - Issue issueModel = getPresenter().getIssue(); - if (issueModel == null) return false; - if (item.getItemId() == R.id.share) { - ActivityHelper.shareUrl(this, getPresenter().getIssue().getHtmlUrl()); - return true; - } else if (item.getItemId() == R.id.closeIssue) { - MessageDialogView.newInstance( - issueModel.getState() == IssueState.open ? getString(R.string.close_issue) : getString(R.string.re_open_issue), - getString(R.string.confirm_message), Bundler.start().put(BundleConstant.EXTRA, true) - .put(BundleConstant.YES_NO_EXTRA, true).end()) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - return true; - } else if (item.getItemId() == R.id.lockIssue) { - if (!getPresenter().isLocked()) { - LockIssuePrBottomSheetDialog.Companion - .newInstance() - .show(getSupportFragmentManager(), MessageDialogView.TAG); - } else { - MessageDialogView.newInstance(getString(R.string.unlock_issue), getString(R.string.unlock_issue_details), - Bundler.start().put(BundleConstant.EXTRA_TWO, true) - .put(BundleConstant.YES_NO_EXTRA, true) - .end()) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - } - return true; - } else if (item.getItemId() == R.id.labels) { - LabelsDialogFragment.newInstance(getPresenter().getIssue() != null ? getPresenter().getIssue().getLabels() : null, - getPresenter().getRepoId(), getPresenter().getLogin()) - .show(getSupportFragmentManager(), "LabelsDialogFragment"); - return true; - } else if (item.getItemId() == R.id.edit) { - CreateIssueActivity.startForResult(this, getPresenter().getLogin(), getPresenter().getRepoId(), - getPresenter().getIssue(), isEnterprise()); - return true; - } else if (item.getItemId() == R.id.milestone) { - MilestoneDialogFragment.newInstance(getPresenter().getLogin(), getPresenter().getRepoId()) - .show(getSupportFragmentManager(), "MilestoneDialogFragment"); - return true; - } else if (item.getItemId() == R.id.assignees) { - AssigneesDialogFragment.newInstance(getPresenter().getLogin(), getPresenter().getRepoId(), true) - .show(getSupportFragmentManager(), "AssigneesDialogFragment"); - return true; - } else if (item.getItemId() == R.id.subscribe) { - getPresenter().onSubscribeOrMute(false); - return true; - } else if (item.getItemId() == R.id.mute) { - getPresenter().onSubscribeOrMute(true); - return true; - } else if (item.getItemId() == R.id.browser) { - ActivityHelper.startCustomTab(this, issueModel.getHtmlUrl()); - return true; - } else if (item.getItemId() == R.id.pinUnpin) { - if (PrefGetter.isProEnabled()) { - getPresenter().onPinUnpinIssue(); - } else { - PremiumActivity.Companion.startActivity(this); - } - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override public boolean onPrepareOptionsMenu(Menu menu) { - MenuItem closeIssue = menu.findItem(R.id.closeIssue); - MenuItem lockIssue = menu.findItem(R.id.lockIssue); - MenuItem milestone = menu.findItem(R.id.milestone); - MenuItem labels = menu.findItem(R.id.labels); - MenuItem assignees = menu.findItem(R.id.assignees); - MenuItem edit = menu.findItem(R.id.edit); - MenuItem editMenu = menu.findItem(R.id.editMenu); - MenuItem pinUnpin = menu.findItem(R.id.pinUnpin); - boolean isOwner = getPresenter().isOwner(); - boolean isLocked = getPresenter().isLocked(); - boolean isCollaborator = getPresenter().isCollaborator(); - boolean isRepoOwner = getPresenter().isRepoOwner(); - editMenu.setVisible(isOwner || isCollaborator || isRepoOwner); - milestone.setVisible(isCollaborator || isRepoOwner); - labels.setVisible(isCollaborator || isRepoOwner); - assignees.setVisible(isCollaborator || isRepoOwner); - edit.setVisible(isCollaborator || isRepoOwner || isOwner); - lockIssue.setVisible(isRepoOwner || isCollaborator); - labels.setVisible(getPresenter().isRepoOwner() || isCollaborator); - closeIssue.setVisible(isOwner || isCollaborator); - if (getPresenter().getIssue() != null) { - boolean isPinned = PinnedIssues.isPinned(getPresenter().getIssue().getId()); - pinUnpin.setIcon(isPinned ? ContextCompat.getDrawable(this, R.drawable.ic_pin_filled) - : ContextCompat.getDrawable(this, R.drawable.ic_pin)); - closeIssue.setTitle(getPresenter().getIssue().getState() == IssueState.closed ? getString(R.string.re_open) : getString(R.string.close)); - lockIssue.setTitle(isLocked ? getString(R.string.unlock_issue) : getString(R.string.lock_issue)); - } - return super.onPrepareOptionsMenu(menu); - } - - @Override public void onSetupIssue(boolean isUpdate) { - hideProgress(); - if (getPresenter().getIssue() == null) { - return; - } - onUpdateMenu(); - Issue issueModel = getPresenter().getIssue(); - setTaskName(issueModel.getRepoId() + " - " + issueModel.getTitle()); - setTitle(String.format("#%s", issueModel.getNumber())); - if (getSupportActionBar() != null) { - getSupportActionBar().setSubtitle(issueModel.getRepoId()); - } - updateViews(issueModel); - if (isUpdate) { - IssueTimelineFragment issueDetailsView = getIssueTimelineFragment(); - if (issueDetailsView != null && getPresenter().getIssue() != null) { - issueDetailsView.onUpdateHeader(); - } - } else { - if (pager.getAdapter() == null) { - Logger.e(getPresenter().commentId); - pager.setAdapter(new FragmentsPagerAdapter(getSupportFragmentManager(), FragmentPagerAdapterModel - .buildForIssues(this, getPresenter().commentId))); - } else { - onUpdateTimeline(); - } - } - if (!getPresenter().isLocked() || getPresenter().isOwner()) { - pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { - @Override public void onPageSelected(int position) { - super.onPageSelected(position); - hideShowFab(); - } - }); - } - hideShowFab(); - } - - @Override public void showSuccessIssueActionMsg(boolean isClose) { - hideProgress(); - if (isClose) { - isOpened = false; - isClosed = true; - showMessage(getString(R.string.success), getString(R.string.success_closed)); - } else { - isOpened = true; - isClosed = false; - showMessage(getString(R.string.success), getString(R.string.success_re_opened)); - } - } - - @Override public void showErrorIssueActionMsg(boolean isClose) { - hideProgress(); - if (isClose) { - showMessage(getString(R.string.error), getString(R.string.error_closing_issue)); - } else { - showMessage(getString(R.string.error), getString(R.string.error_re_opening_issue)); - } - } - - @Override public void onUpdateTimeline() { - IssueTimelineFragment issueDetailsView = getIssueTimelineFragment(); - if (issueDetailsView != null && getPresenter().getIssue() != null) { - issueDetailsView.onRefresh(); - } - } - - @Override public void onUpdateMenu() { - invalidateOptionsMenu(); - } - - @Override public void onMileStoneSelected(@NonNull MilestoneModel milestoneModel) { - getPresenter().onPutMilestones(milestoneModel); - } - - @Override public void onFinishActivity() { - hideProgress(); - finish(); - } - - @Nullable @Override public Issue getData() { - return getPresenter().getIssue(); - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk) { - getPresenter().onHandleConfirmDialog(bundle); - } - } - - @Override public void onSelectedLabels(@NonNull ArrayList labels) { - getPresenter().onPutLabels(labels); - } - - @Override public void onSelectedAssignees(@NonNull ArrayList users, boolean isAssignee) { - getPresenter().onPutAssignees(users); - } - - @Override public void onNavToRepoClicked() { - Intent intent = ActivityHelper.editBundle(RepoPagerActivity.createIntent(this, getPresenter().getRepoId(), - getPresenter().getLogin(), RepoPagerMvp.ISSUES), isEnterprise()); - startActivity(intent); - finish(); - } - - @Override public void onBackPressed() { - super.onBackPressed(); - } - - @Override public void finish() { - Intent intent = new Intent(); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, isClosed) - .put(BundleConstant.EXTRA_TWO, isOpened) - .end()); - setResult(RESULT_OK, intent); - super.finish(); - } - - @Override public void onSendActionClicked(@NonNull String text, @Nullable Bundle bundle) { - IssueTimelineFragment fragment = getIssueTimelineFragment(); - if (fragment != null) { - fragment.onHandleComment(text, bundle); - } - } - - @Override public void onTagUser(@NonNull String username) { - commentEditorFragment.onAddUserName(username); - } - - @Override public void onCreateComment(String text, Bundle bundle) {} - - @SuppressWarnings("ConstantConditions") @Override public void onClearEditText() { - if (commentEditorFragment != null && commentEditorFragment.commentText != null) commentEditorFragment.commentText.setText(""); - } - - @NonNull @Override public ArrayList getNamesToTag() { - IssueTimelineFragment fragment = getIssueTimelineFragment(); - if (fragment != null) { - return fragment.getNamesToTag(); - } - return new ArrayList<>(); - } - - @Override public void onLock(@NonNull String reason) { - getPresenter().onLockUnlockIssue(reason); - } - - private IssueTimelineFragment getIssueTimelineFragment() { - if (pager == null || pager.getAdapter() == null) return null; - return (IssueTimelineFragment) pager.getAdapter().instantiateItem(pager, 0); - } - - private void hideShowFab() { - if (getPresenter().isLocked() && !getPresenter().isOwner()) { - getSupportFragmentManager().beginTransaction().hide(commentEditorFragment).commit(); - return; - } - getSupportFragmentManager().beginTransaction().show(commentEditorFragment).commit(); - } - - private void updateViews(@NonNull Issue issueModel) { - User userModel = issueModel.getUser(); - title.setText(issueModel.getTitle()); - detailsIcon.setVisibility(View.VISIBLE); - if (userModel != null) { - size.setVisibility(View.GONE); - String username; - CharSequence parsedDate; - if (issueModel.getState() == IssueState.closed) { - username = issueModel.getClosedBy() != null ? issueModel.getClosedBy().getLogin() : "N/A"; - parsedDate = issueModel.getClosedAt() != null ? ParseDateFormat.getTimeAgo(issueModel.getClosedAt()) : "N/A"; - } else { - parsedDate = ParseDateFormat.getTimeAgo(issueModel.getCreatedAt()); - username = issueModel.getUser() != null ? issueModel.getUser().getLogin() : "N/A"; - } - date.setText(SpannableBuilder.builder() - .append(ContextCompat.getDrawable(this, - issueModel.getState() == IssueState.open ? R.drawable.ic_issue_opened_small : R.drawable.ic_issue_closed_small)) - .append(" ") - .append(getString(issueModel.getState().getStatus())) - .append(" ").append(getString(R.string.by)).append(" ").append(username).append(" ") - .append(parsedDate)); - avatarLayout.setUrl(userModel.getAvatarUrl(), userModel.getLogin(), false, - LinkParserHelper.isEnterprise(issueModel.getHtmlUrl())); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerMvp.java deleted file mode 100644 index 1b75f173f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerMvp.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.issue.details; - -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; -import com.fastaccess.ui.modules.repos.extras.assignees.AssigneesMvp; -import com.fastaccess.ui.modules.repos.extras.labels.LabelsMvp; -import com.fastaccess.ui.modules.repos.extras.locking.LockIssuePrCallback; - -import java.util.ArrayList; - -/** - * Created by Kosh on 10 Dec 2016, 9:21 AM - */ - -public interface IssuePagerMvp { - - interface View extends BaseMvp.FAView, LabelsMvp.SelectedLabelsListener, - AssigneesMvp.SelectedAssigneesListener, IssuePrCallback, - CommentEditorFragment.CommentListener, LockIssuePrCallback { - void onSetupIssue(boolean isUpdate); - - void showSuccessIssueActionMsg(boolean isClose); - - void showErrorIssueActionMsg(boolean isClose); - - void onUpdateTimeline(); - - void onUpdateMenu(); - - void onMileStoneSelected(@NonNull MilestoneModel milestoneModel); - - void onFinishActivity(); - } - - interface Presenter extends BaseMvp.FAPresenter { - - @Nullable Issue getIssue(); - - void onActivityCreated(@Nullable Intent intent); - - void onWorkOffline(long issueNumber, @NonNull String repoId, @NonNull String login); - - boolean isOwner(); - - boolean isRepoOwner(); - - boolean isLocked(); - - boolean isCollaborator(); - - boolean showToRepoBtn(); - - void onHandleConfirmDialog(@Nullable Bundle bundle); - - void onOpenCloseIssue(); - - void onLockUnlockIssue(String reason); - - void onPutMilestones(@NonNull MilestoneModel milestone); - - void onPutLabels(@NonNull ArrayList labels); - - void onPutAssignees(@NonNull ArrayList users); - - String getLogin(); - - String getRepoId(); - - void onUpdateIssue(@NonNull Issue issueModel); - - void onSubscribeOrMute(boolean mute); - - void onPinUnpinIssue(); - } - - interface IssuePrCallback { - @Nullable T getData(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerPresenter.java deleted file mode 100644 index bd44d5c00..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/IssuePagerPresenter.java +++ /dev/null @@ -1,290 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.issue.details; - -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.fastaccess.R; -import com.fastaccess.data.dao.AssigneesRequestModel; -import com.fastaccess.data.dao.IssueRequestModel; -import com.fastaccess.data.dao.LabelListModel; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.LockIssuePrModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.NotificationSubscriptionBodyModel; -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.UsersListModel; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.PinnedIssues; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.data.service.IssueService; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -import io.reactivex.Observable; -import retrofit2.Response; - -/** - * Created by Kosh on 10 Dec 2016, 9:23 AM - */ - -class IssuePagerPresenter extends BasePresenter implements IssuePagerMvp.Presenter { - @com.evernote.android.state.State Issue issueModel; - @com.evernote.android.state.State int issueNumber; - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State boolean isCollaborator; - @com.evernote.android.state.State boolean showToRepoBtn; - @com.evernote.android.state.State long commentId; - - @Nullable @Override public Issue getIssue() { - return issueModel; - } - - @Override public void onError(@NonNull Throwable throwable) { - if (RestProvider.getErrorCode(throwable) == 404) { - sendToView(BaseMvp.FAView::onOpenUrlInBrowser); - } else { - onWorkOffline(issueNumber, login, repoId); - } - super.onError(throwable); - } - - @Override public void onActivityCreated(@Nullable Intent intent) { - Logger.e(isEnterprise()); - if (intent != null && intent.getExtras() != null) { - issueModel = intent.getExtras().getParcelable(BundleConstant.ITEM); - issueNumber = intent.getExtras().getInt(BundleConstant.ID); - login = intent.getExtras().getString(BundleConstant.EXTRA); - repoId = intent.getExtras().getString(BundleConstant.EXTRA_TWO); - showToRepoBtn = intent.getExtras().getBoolean(BundleConstant.EXTRA_THREE); - commentId = intent.getExtras().getLong(BundleConstant.EXTRA_SIX); - if (issueModel != null) { - issueNumber = issueModel.getNumber(); - sendToView(view -> view.onSetupIssue(false)); - return; - } else if (issueNumber > 0 && !InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - getIssueFromApi(); - return; - } - } - sendToView(view -> view.onSetupIssue(false)); - } - - @Override public void onWorkOffline(long issueNumber, @NonNull String repoId, @NonNull String login) { - if (issueModel == null) { - manageDisposable(RxHelper.getObservable(Issue.getIssueByNumber((int) issueNumber, repoId, login)) - .subscribe(issueModel1 -> { - if (issueModel1 != null) { - issueModel = issueModel1; - sendToView(view -> view.onSetupIssue(false)); - } - })); - } else { - sendToView(BaseMvp.FAView::hideProgress); - } - } - - @Override public boolean isOwner() { - if (getIssue() == null) return false; - User userModel = getIssue() != null ? getIssue().getUser() : null; - Login me = Login.getUser(); - PullsIssuesParser parser = PullsIssuesParser.getForIssue(getIssue().getHtmlUrl()); - return (userModel != null && userModel.getLogin().equalsIgnoreCase(me.getLogin())) - || (parser != null && parser.getLogin().equalsIgnoreCase(me.getLogin())); - } - - @Override public boolean isRepoOwner() { - if (getIssue() == null) return false; - Login me = Login.getUser(); - return TextUtils.equals(login, me.getLogin()); - } - - @Override public boolean isLocked() { - return getIssue() != null && getIssue().isLocked(); - } - - @Override public boolean isCollaborator() { - return isCollaborator; - } - - @Override public boolean showToRepoBtn() { - return showToRepoBtn; - } - - @Override public void onHandleConfirmDialog(@Nullable Bundle bundle) { - if (bundle != null) { - boolean proceedCloseIssue = bundle.getBoolean(BundleConstant.EXTRA); - boolean proceedLockUnlock = bundle.getBoolean(BundleConstant.EXTRA_TWO); - if (proceedCloseIssue) { - onOpenCloseIssue(); - } else if (proceedLockUnlock) { - onLockUnlockIssue(null); - } - } - } - - @Override public void onOpenCloseIssue() { - Issue currentIssue = getIssue(); - if (currentIssue != null) { - IssueRequestModel requestModel = IssueRequestModel.clone(currentIssue, true); - manageDisposable(RxHelper.getObservable(RestProvider.getIssueService(isEnterprise()).editIssue(login, repoId, - issueNumber, requestModel)) - .doOnSubscribe(disposable -> sendToView(view -> view.showProgress(0))) - .subscribe(issue -> { - if (issue != null) { - sendToView(view -> view.showSuccessIssueActionMsg(currentIssue.getState() == IssueState.open)); - issue.setRepoId(issueModel.getRepoId()); - issue.setLogin(issueModel.getLogin()); - issueModel = issue; - sendToView(view -> view.onSetupIssue(false)); - } - }, this::onError)); - } - } - - @Override public void onLockUnlockIssue(String reason) { - Issue currentIssue = getIssue(); - if (currentIssue == null) return; - String login = getLogin(); - String repoId = getRepoId(); - int number = currentIssue.getNumber(); - LockIssuePrModel model = null; - if (!isLocked() && !InputHelper.isEmpty(reason)) { - model = new LockIssuePrModel(true, reason); - } - IssueService issueService = RestProvider.getIssueService(isEnterprise()); - Observable> observable = RxHelper - .getObservable(model == null - ? issueService.unlockIssue(login, repoId, number) : - issueService.lockIssue(model, login, repoId, number)); - makeRestCall(observable, booleanResponse -> { - int code = booleanResponse.code(); - if (code == 204) { - issueModel.setLocked(!isLocked()); - sendToView(view -> view.onSetupIssue(true)); - } - sendToView(IssuePagerMvp.View::hideProgress); - }); - - } - - @Override public void onPutMilestones(@NonNull MilestoneModel milestone) { - issueModel.setMilestone(milestone); - IssueRequestModel issueRequestModel = IssueRequestModel.clone(issueModel, false); - makeRestCall(RestProvider.getIssueService(isEnterprise()).editIssue(login, repoId, issueNumber, issueRequestModel), - issue -> { - this.issueModel.setMilestone(issue.getMilestone()); - manageObservable(issue.save(issueModel).toObservable()); - sendToView(view -> updateTimeline(view, R.string.labels_added_successfully)); - }); - - } - - @Override public void onPutLabels(@NonNull ArrayList labels) { - makeRestCall(RestProvider.getIssueService(isEnterprise()).putLabels(login, repoId, issueNumber, - Stream.of(labels).filter(value -> value != null && value.getName() != null) - .map(LabelModel::getName).collect(Collectors.toList())), - labelModels -> { - sendToView(view -> updateTimeline(view, R.string.labels_added_successfully)); - LabelListModel listModel = new LabelListModel(); - listModel.addAll(labels); - issueModel.setLabels(listModel); - manageObservable(issueModel.save(issueModel).toObservable()); - }); - } - - @Override public void onPutAssignees(@NonNull ArrayList users) { - AssigneesRequestModel assigneesRequestModel = new AssigneesRequestModel(); - ArrayList assignees = new ArrayList<>(); - Stream.of(users).forEach(userModel -> assignees.add(userModel.getLogin())); - assigneesRequestModel.setAssignees(assignees.isEmpty() ? Stream.of(issueModel.getAssignees()).map(User::getLogin).toList() : assignees); - makeRestCall(!assignees.isEmpty() ? - RestProvider.getIssueService(isEnterprise()).putAssignees(login, repoId, issueNumber, assigneesRequestModel) : - RestProvider.getIssueService(isEnterprise()).deleteAssignees(login, repoId, issueNumber, assigneesRequestModel), - issue -> { - UsersListModel assignee = new UsersListModel(); - assignee.addAll(users); - issueModel.setAssignees(assignee); - manageObservable(issueModel.save(issueModel).toObservable()); - sendToView(view -> updateTimeline(view, R.string.assignee_added)); - } - ); - } - - @Override public String getLogin() { - return login; - } - - @Override public String getRepoId() { - return repoId; - } - - @Override public void onUpdateIssue(@NonNull Issue issue) { - this.issueModel.setBody(issue.getBody()); - this.issueModel.setBodyHtml(issue.getBodyHtml()); - this.issueModel.setTitle(issue.getTitle()); - this.issueModel.setLogin(login); - this.issueModel.setRepoId(repoId); - manageObservable(issueModel.save(issueModel).toObservable()); - sendToView(view -> view.onSetupIssue(true)); - } - - @Override public void onSubscribeOrMute(boolean mute) { - if (getIssue() == null) return; - makeRestCall(mute ? RestProvider.getNotificationService(isEnterprise()).subscribe(getIssue().getId(), - new NotificationSubscriptionBodyModel(false, true)) - : RestProvider.getNotificationService(isEnterprise()).subscribe(getIssue().getId(), - new NotificationSubscriptionBodyModel(true, false)), - booleanResponse -> { - if (booleanResponse.code() == 204 || booleanResponse.code() == 200) { - sendToView(view -> view.showMessage(R.string.success, R.string.successfully_submitted)); - } else { - sendToView(view -> view.showMessage(R.string.error, R.string.network_error)); - } - }); - } - - @Override public void onPinUnpinIssue() { - if (getIssue() == null) return; - PinnedIssues.pinUpin(getIssue()); - sendToView(IssuePagerMvp.View::onUpdateMenu); - } - - private void getIssueFromApi() { - Login loginUser = Login.getUser(); - if (loginUser == null) return; - makeRestCall(RxHelper.getObservable(Observable.zip(RestProvider.getIssueService(isEnterprise()).getIssue(login, repoId, issueNumber), - RestProvider.getRepoService(isEnterprise()).isCollaborator(login, repoId, loginUser.getLogin()), - (issue, booleanResponse) -> { - isCollaborator = booleanResponse.code() == 204; - return issue; - })), this::setupIssue); - } - - private void setupIssue(Issue issue) { - issueModel = issue; - issueModel.setRepoId(repoId); - issueModel.setLogin(login); - sendToView(view -> view.onSetupIssue(false)); - manageDisposable(PinnedIssues.updateEntry(issue.getId())); - } - - private void updateTimeline(IssuePagerMvp.View view, int assignee_added) { - view.showMessage(R.string.success, assignee_added); - view.onUpdateTimeline(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelineFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelineFragment.java deleted file mode 100644 index 3c83d3926..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelineFragment.java +++ /dev/null @@ -1,372 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.issue.details.timeline; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.Logger; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.provider.timeline.ReactionsProvider; -import com.fastaccess.ui.adapter.IssuesTimelineAdapter; -import com.fastaccess.ui.adapter.viewholder.TimelineCommentsViewHolder; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.editor.EditorActivity; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; -import com.fastaccess.ui.modules.repos.issues.issue.details.IssuePagerMvp; -import com.fastaccess.ui.modules.repos.reactions.ReactionsDialogFragment; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 31 Mar 2017, 7:35 PM - */ - -public class IssueTimelineFragment extends BaseFragment implements IssueTimelineMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @State HashMap toggleMap = new LinkedHashMap<>(); - private IssuesTimelineAdapter adapter; - private OnLoadMore onLoadMore; - private IssuePagerMvp.IssuePrCallback issueCallback; - private CommentEditorFragment.CommentListener commentsCallback; - - @NonNull public static IssueTimelineFragment newInstance(long commentId) { - IssueTimelineFragment fragment = new IssueTimelineFragment(); - fragment.setArguments(Bundler.start().put(BundleConstant.ID, commentId).end()); - return fragment; - } - - @SuppressWarnings("unchecked") @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof IssuePagerMvp.IssuePrCallback) { - issueCallback = (IssuePagerMvp.IssuePrCallback) getParentFragment(); - } else if (context instanceof IssuePagerMvp.IssuePrCallback) { - issueCallback = (IssuePagerMvp.IssuePrCallback) context; - } else { - throw new IllegalArgumentException(String.format("%s or parent fragment must implement IssuePagerMvp.IssuePrCallback", - context.getClass().getSimpleName())); - } - if (getParentFragment() instanceof CommentEditorFragment.CommentListener) { - commentsCallback = (CommentEditorFragment.CommentListener) getParentFragment(); - } else if (context instanceof CommentEditorFragment.CommentListener) { - commentsCallback = (CommentEditorFragment.CommentListener) context; - } else { - throw new IllegalArgumentException(String.format("%s or parent fragment must implement CommentEditorFragment.CommentListener", - context.getClass().getSimpleName())); - } - } - - @Override public void onDetach() { - issueCallback = null; - commentsCallback = null; - super.onDetach(); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getIssue()); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null) { - adapter.subList(1, adapter.getItemCount()); - return; - } - if (page == 1) { - adapter.subList(1, adapter.getItemCount()); - } - adapter.addItems(items); - Logger.e(adapter.getItemCount()); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter()); - } - onLoadMore.setParameter(getIssue()); - return onLoadMore; - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getIssue() == null) { - throw new NullPointerException("Issue went missing!!!"); - } - - getPresenter().setCommentId(getCommentId()); - if (issueCallback != null && issueCallback.getData() != null) { - adapter = new IssuesTimelineAdapter(getPresenter().getEvents(), this, true, - this, issueCallback.getData().getLogin(), issueCallback.getData().getUser().getLogin()); - } else { - adapter = new IssuesTimelineAdapter(getPresenter().getEvents(), this, true, - this, "", ""); - } - recycler.setVerticalScrollBarEnabled(false); - stateLayout.setEmptyText(R.string.no_events); - recycler.setEmptyView(stateLayout, refresh); - refresh.setOnRefreshListener(this); - stateLayout.setOnReloadListener(this); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - fastScroller.setVisibility(View.VISIBLE); - fastScroller.attachRecyclerView(recycler); - recycler.addDivider(TimelineCommentsViewHolder.class); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null) { - onSetHeader(TimelineModel.constructHeader(getIssue())); - onRefresh(); - } else if (getPresenter().getEvents().isEmpty() || getPresenter().getEvents().size() == 1) { - onRefresh(); - } - } - - @NonNull @Override public IssueTimelinePresenter providePresenter() { - return new IssueTimelinePresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @Override public void onEditComment(@NonNull Comment item) { - if (getIssue() == null) return; - Intent intent = new Intent(getContext(), EditorActivity.class); - intent.putExtras(Bundler - .start() - .put(BundleConstant.ID, getIssue().getRepoId()) - .put(BundleConstant.EXTRA_TWO, getIssue().getLogin()) - .put(BundleConstant.EXTRA_THREE, getIssue().getNumber()) - .put(BundleConstant.EXTRA_FOUR, item.getId()) - .put(BundleConstant.EXTRA, item.getBody()) - .put(BundleConstant.EXTRA_TYPE, BundleConstant.ExtraType.EDIT_ISSUE_COMMENT_EXTRA) - .putStringArrayList("participants", CommentsHelper.getUsersByTimeline(adapter.getData())) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise()) - .end()); - View view = getActivity() != null && getActivity().findViewById(R.id.fab) != null ? getActivity().findViewById(R.id.fab) : recycler; - ActivityHelper.startReveal(this, intent, view, BundleConstant.REQUEST_CODE); - } - - @Override public void onRemove(@NonNull TimelineModel timelineModel) { - hideProgress(); - adapter.removeItem(timelineModel); - } - - @Override public void onStartNewComment(String text) { - onTagUser(null); - } - - @Override public void onShowDeleteMsg(long id) { - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), - Bundler.start() - .put(BundleConstant.EXTRA, id) - .put(BundleConstant.YES_NO_EXTRA, true) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - - @Override public void onTagUser(@Nullable User user) { - if (commentsCallback != null) if (user != null) { - commentsCallback.onTagUser(user.getLogin()); - } - } - - @Override public void onReply(User user, String message) { - if (getIssue() == null) return; - Intent intent = new Intent(getContext(), EditorActivity.class); - intent.putExtras(Bundler - .start() - .put(BundleConstant.ID, getIssue().getRepoId()) - .put(BundleConstant.EXTRA_TWO, getIssue().getLogin()) - .put(BundleConstant.EXTRA_THREE, getIssue().getNumber()) - .put(BundleConstant.EXTRA, "@" + user.getLogin()) - .put(BundleConstant.EXTRA_TYPE, BundleConstant.ExtraType.NEW_ISSUE_COMMENT_EXTRA) - .putStringArrayList("participants", CommentsHelper.getUsersByTimeline(adapter.getData())) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise()) - .put("message", message) - .end()); - View view = getActivity() != null && getActivity().findViewById(R.id.fab) != null ? getActivity().findViewById(R.id.fab) : recycler; - ActivityHelper.startReveal(this, intent, view, BundleConstant.REQUEST_CODE); - - } - - @Override public void showReactionsPopup(@NonNull ReactionTypes type, @NonNull String login, - @NonNull String repoId, long idOrNumber, boolean isHeader) { - ReactionsDialogFragment.newInstance(login, repoId, type, idOrNumber, isHeader ? ReactionsProvider.HEADER : ReactionsProvider.COMMENT) - .show(getChildFragmentManager(), "ReactionsDialogFragment"); - } - - @Override public void onSetHeader(@NonNull TimelineModel timelineModel) { - if (adapter != null) { - if (adapter.isEmpty()) { - adapter.addItem(timelineModel, 0); - } else { - adapter.swapItem(timelineModel, 0); - } - } - } - - @Nullable @Override public Issue getIssue() { - return issueCallback.getData(); - } - - @Override public void onUpdateHeader() { - if (getIssue() == null) return; - onSetHeader(TimelineModel.constructHeader(getIssue())); - } - - @Override public void onHandleComment(@NonNull String text, @Nullable Bundle bundle) { - getPresenter().onHandleComment(text, bundle); - } - - @Override public void addNewComment(@NonNull TimelineModel timelineModel) { - onHideBlockingProgress(); - adapter.addItem(timelineModel); - if (commentsCallback != null) commentsCallback.onClearEditText(); - } - - @NonNull @Override public ArrayList getNamesToTag() { - return CommentsHelper.getUsersByTimeline(adapter.getData()); - } - - @Override public void onHideBlockingProgress() { - hideProgress(); - super.hideProgress(); - } - - @Override public long getCommentId() { - return getArguments() != null ? getArguments().getLong(BundleConstant.ID) : 0; - } - - @Override public void addComment(@Nullable TimelineModel timelineModel, int index) { - if (timelineModel != null) { - adapter.addItem(timelineModel, 1); - recycler.smoothScrollToPosition(1); - } else if (index != -1) { - recycler.smoothScrollToPosition(index + 1); - if ((index + 1) > adapter.getItemCount()) { - showMessage(R.string.error, R.string.comment_is_too_far_to_paginate); - } - } - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK) { - if (requestCode == BundleConstant.REQUEST_CODE) { - if (data == null) { - onRefresh(); - return; - } - Bundle bundle = data.getExtras(); - if (bundle != null) { - boolean isNew = bundle.getBoolean(BundleConstant.EXTRA); - Comment commentsModel = bundle.getParcelable(BundleConstant.ITEM); - if (commentsModel == null) { - onRefresh(); // shit happens, refresh()? - return; - } - adapter.notifyDataSetChanged(); - if (isNew) { - adapter.addItem(TimelineModel.constructComment(commentsModel)); - recycler.smoothScrollToPosition(adapter.getItemCount()); - } else { - int position = adapter.getItem(TimelineModel.constructComment(commentsModel)); - if (position != -1) { - adapter.swapItem(TimelineModel.constructComment(commentsModel), position); - recycler.smoothScrollToPosition(position); - } else { - adapter.addItem(TimelineModel.constructComment(commentsModel)); - recycler.smoothScrollToPosition(adapter.getItemCount()); - } - } - } else { - onRefresh(); // bundle size is too large? refresh the api - } - } - } - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk) { - getPresenter().onHandleDeletion(bundle); - } - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onToggle(long position, boolean isCollapsed) { - toggleMap.put(position, isCollapsed); - } - - @Override public boolean isCollapsed(long position) { - Boolean toggle = toggleMap.get(position); - return toggle != null && toggle; - } - - @Override public boolean isPreviouslyReacted(long id, int vId) { - return getPresenter().isPreviouslyReacted(id, vId); - } - - @Override public boolean isCallingApi(long id, int vId) { - return getPresenter().isCallingApi(id, vId); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelineMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelineMvp.java deleted file mode 100644 index 77d709402..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelineMvp.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.issue.details.timeline; - -import android.os.Bundle; -import android.support.annotation.IdRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.provider.timeline.ReactionsProvider; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.adapter.callback.ReactionsCallback; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 31 Mar 2017, 7:15 PM - */ - -public interface IssueTimelineMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener, - OnToggleView, ReactionsCallback { - - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onEditComment(@NonNull Comment item); - - void onRemove(@NonNull TimelineModel timelineModel); - - void onStartNewComment(String text); - - void onShowDeleteMsg(long id); - - void onTagUser(@Nullable User user); - - void onReply(User user, String message); - - void showReactionsPopup(@NonNull ReactionTypes type, @NonNull String login, @NonNull String repoId, long idOrNumber, boolean isHeadre); - - void onSetHeader(@NonNull TimelineModel timelineModel); - - @Nullable Issue getIssue(); - - void onUpdateHeader(); - - void onHandleComment(String text, @Nullable Bundle bundle); - - void addNewComment(@NonNull TimelineModel timelineModel); - - @NonNull ArrayList getNamesToTag(); - - void onHideBlockingProgress(); - - long getCommentId(); - - void addComment(@Nullable TimelineModel timelineModel, int index); - } - - interface Presenter extends BaseMvp.FAPresenter, BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - boolean isPreviouslyReacted(long commentId, int vId); - - @NonNull ArrayList getEvents(); - - void onWorkOffline(); - - void onHandleDeletion(@Nullable Bundle bundle); - - void onHandleReaction(@IdRes int viewId, long id, @ReactionsProvider.ReactionType int reactionType); - - boolean isCallingApi(long id, int vId); - - void onHandleComment(@NonNull String text, @Nullable Bundle bundle); - - void setCommentId(long commentId); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelinePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelinePresenter.java deleted file mode 100644 index 153fbd1fa..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/issues/issue/details/timeline/IssueTimelinePresenter.java +++ /dev/null @@ -1,328 +0,0 @@ -package com.fastaccess.ui.modules.repos.issues.issue.details.timeline; - -import android.app.Activity; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.PopupMenu; - -import com.fastaccess.R; -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.timeline.GenericEvent; -import com.fastaccess.data.dao.timeline.SourceModel; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.provider.timeline.ReactionsProvider; -import com.fastaccess.provider.timeline.TimelineConverter; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.filter.issues.FilterIssuesActivity; -import com.fastaccess.ui.modules.repos.issues.create.CreateIssueActivity; - -import java.util.ArrayList; -import java.util.List; - -import io.reactivex.Observable; -import lombok.Getter; - -/** - * Created by Kosh on 31 Mar 2017, 7:17 PM - */ - -@Getter public class IssueTimelinePresenter extends BasePresenter implements IssueTimelineMvp.Presenter { - private ArrayList timeline = new ArrayList<>(); - private ReactionsProvider reactionsProvider; - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - @com.evernote.android.state.State boolean isCollaborator; - private long commentId; - - @Override public boolean isPreviouslyReacted(long commentId, int vId) { - return getReactionsProvider().isPreviouslyReacted(commentId, vId); - } - - @Override public void onItemClick(int position, View v, TimelineModel item) { - if (getView() != null) { - Issue issue = getView().getIssue(); - if (issue == null) return; - if (item.getType() == TimelineModel.COMMENT) { - if (v.getId() == R.id.commentMenu) { - PopupMenu popupMenu = new PopupMenu(v.getContext(), v); - popupMenu.inflate(R.menu.comments_menu); - String username = Login.getUser().getLogin(); - boolean isOwner = CommentsHelper.isOwner(username, issue.getLogin(), item.getComment().getUser().getLogin()) || isCollaborator; - popupMenu.getMenu().findItem(R.id.delete).setVisible(isOwner); - popupMenu.getMenu().findItem(R.id.edit).setVisible(isOwner); - popupMenu.setOnMenuItemClickListener(item1 -> { - if (getView() == null) return false; - if (item1.getItemId() == R.id.delete) { - getView().onShowDeleteMsg(item.getComment().getId()); - } else if (item1.getItemId() == R.id.reply) { - getView().onReply(item.getComment().getUser(), item.getComment().getBody()); - } else if (item1.getItemId() == R.id.edit) { - getView().onEditComment(item.getComment()); - } else if (item1.getItemId() == R.id.share) { - ActivityHelper.shareUrl(v.getContext(), item.getComment().getHtmlUrl()); - } - return true; - }); - popupMenu.show(); - } else { - onHandleReaction(v.getId(), item.getComment().getId(), ReactionsProvider.COMMENT); - } - } else if (item.getType() == TimelineModel.EVENT) { - GenericEvent issueEventModel = item.getGenericEvent(); - if (issueEventModel.getCommitUrl() != null) { - SchemeParser.launchUri(v.getContext(), Uri.parse(issueEventModel.getCommitUrl())); - } else if (issueEventModel.getLabel() != null) { - FilterIssuesActivity.startActivity(v, issue.getLogin(), issue.getRepoId(), true, - true, isEnterprise(), "label:\"" + issueEventModel.getLabel().getName() + "\""); - } else if (issueEventModel.getMilestone() != null) { - FilterIssuesActivity.startActivity(v, issue.getLogin(), issue.getRepoId(), true, - true, isEnterprise(), "milestone:\"" + issueEventModel.getMilestone().getTitle() + "\""); - } else if (issueEventModel.getAssignee() != null) { - FilterIssuesActivity.startActivity(v, issue.getLogin(), issue.getRepoId(), true, - true, isEnterprise(), "assignee:\"" + issueEventModel.getAssignee().getLogin() + "\""); - } else { - SourceModel sourceModel = issueEventModel.getSource(); - if (sourceModel != null) { - if (sourceModel.getCommit() != null) { - SchemeParser.launchUri(v.getContext(), sourceModel.getCommit().getUrl()); - } else if (sourceModel.getPullRequest() != null) { - SchemeParser.launchUri(v.getContext(), sourceModel.getPullRequest().getUrl()); - } else if (sourceModel.getIssue() != null) { - SchemeParser.launchUri(v.getContext(), sourceModel.getIssue().getHtmlUrl()); - } else if (sourceModel.getRepository() != null) { - SchemeParser.launchUri(v.getContext(), sourceModel.getRepository().getUrl()); - } - } - } - } else if (item.getType() == TimelineModel.HEADER) { - if (v.getId() == R.id.commentMenu) { - PopupMenu popupMenu = new PopupMenu(v.getContext(), v); - popupMenu.inflate(R.menu.comments_menu); - String username = Login.getUser().getLogin(); - boolean isOwner = CommentsHelper.isOwner(username, item.getIssue().getLogin(), - item.getIssue().getUser().getLogin()) || isCollaborator; - popupMenu.getMenu().findItem(R.id.edit).setVisible(isOwner); - popupMenu.setOnMenuItemClickListener(item1 -> { - if (getView() == null) return false; - if (item1.getItemId() == R.id.reply) { - getView().onReply(item.getIssue().getUser(), item.getIssue().getBody()); - } else if (item1.getItemId() == R.id.edit) { - Activity activity = ActivityHelper.getActivity(v.getContext()); - if (activity == null) return false; - CreateIssueActivity.startForResult(activity, - item.getIssue().getLogin(), item.getIssue().getRepoId(), item.getIssue(), isEnterprise()); - } else if (item1.getItemId() == R.id.share) { - ActivityHelper.shareUrl(v.getContext(), item.getIssue().getHtmlUrl()); - } - return true; - }); - popupMenu.show(); - } else { - onHandleReaction(v.getId(), item.getIssue().getNumber(), ReactionsProvider.HEADER); - } - } - } - } - - @Override public void onItemLongClick(int position, View v, TimelineModel item) { - if (getView() == null) return; - if (item.getType() == TimelineModel.COMMENT || item.getType() == TimelineModel.HEADER) { - if (v.getId() == R.id.commentMenu && item.getType() == TimelineModel.COMMENT) { - Comment comment = item.getComment(); - if (getView() != null) getView().onReply(comment.getUser(), comment.getBody()); - } else { - if (getView().getIssue() == null) return; - Issue issue = getView().getIssue(); - String login = issue.getLogin(); - String repoId = issue.getRepoId(); - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - ReactionTypes type = ReactionTypes.get(v.getId()); - if (type != null) { - if (item.getType() == TimelineModel.HEADER) { - getView().showReactionsPopup(type, login, repoId, item.getIssue().getNumber(), true); - } else { - getView().showReactionsPopup(type, login, repoId, item.getComment().getId(), false); - } - } else { - onItemClick(position, v, item); - } - } - } - } else { - onItemClick(position, v, item); - } - } - - @NonNull @Override public ArrayList getEvents() { - return timeline; - } - - @Override public void onWorkOffline() { - //TODO - } - - @Override public void onHandleDeletion(@Nullable Bundle bundle) { - if (bundle != null) { - long commId = bundle.getLong(BundleConstant.EXTRA, 0); - if (commId != 0) { - if (getView() == null || getView().getIssue() == null) return; - Issue issue = getView().getIssue(); - makeRestCall(RestProvider.getIssueService(isEnterprise()).deleteIssueComment(issue.getLogin(), issue.getRepoId(), commId), - booleanResponse -> sendToView(view -> { - if (booleanResponse.code() == 204) { - Comment comment = new Comment(); - comment.setId(commId); - view.onRemove(TimelineModel.constructComment(comment)); - } else { - view.showMessage(R.string.error, R.string.error_deleting_comment); - } - })); - } - } - } - - @Override public void onHandleReaction(int viewId, long id, @ReactionsProvider.ReactionType int reactionType) { - if (getView() == null || getView().getIssue() == null) return; - Issue issue = getView().getIssue(); - String login = issue.getLogin(); - String repoId = issue.getRepoId(); - Observable observable = getReactionsProvider().onHandleReaction(viewId, id, login, repoId, reactionType, isEnterprise()); - if (observable != null) manageObservable(observable); - } - - @Override public boolean isCallingApi(long id, int vId) { - return getReactionsProvider().isCallingApi(id, vId); - } - - @Override public void onHandleComment(@NonNull String text, @Nullable Bundle bundle) { - if (getView() == null) return; - Issue issue = getView().getIssue(); - if (issue != null) { - if (bundle == null) { - CommentRequestModel commentRequestModel = new CommentRequestModel(); - commentRequestModel.setBody(text); - manageDisposable(RxHelper.getObservable(RestProvider.getIssueService(isEnterprise()).createIssueComment(issue.getLogin(), issue - .getRepoId(), - issue.getNumber(), commentRequestModel)) - .doOnSubscribe(disposable -> sendToView(view -> view.showBlockingProgress(0))) - .subscribe(comment -> sendToView(view -> view.addNewComment(TimelineModel.constructComment(comment))), - throwable -> { - onError(throwable); - sendToView(IssueTimelineMvp.View::onHideBlockingProgress); - })); - } - } - } - - @Override public void setCommentId(long commentId) { - this.commentId = commentId; - } - - @NonNull private ReactionsProvider getReactionsProvider() { - if (reactionsProvider == null) { - reactionsProvider = new ReactionsProvider(); - } - return reactionsProvider; - } - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable Issue parameter) { - if (parameter == null) { - sendToView(BaseMvp.FAView::hideProgress); - return false; - } - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - if (page > lastPage || lastPage == 0) { - sendToView(IssueTimelineMvp.View::hideProgress); - return false; - } - setCurrentPage(page); - String login = parameter.getLogin(); - String repoId = parameter.getRepoId(); - if (page == 1) { - manageObservable(RestProvider.getRepoService(isEnterprise()).isCollaborator(login, repoId, - Login.getUser().getLogin()) - .doOnNext(booleanResponse -> isCollaborator = booleanResponse.code() == 204)); - } - int number = parameter.getNumber(); - Observable> observable = RestProvider.getIssueService(isEnterprise()) - .getTimeline(login, repoId, number, page) - .flatMap(response -> { - if (response != null) { - lastPage = response.getLast(); - } - return TimelineConverter.INSTANCE.convert(response != null ? response.getItems() : null); - }) - .toList() - .toObservable(); - makeRestCall(observable, timeline -> { - sendToView(view -> view.onNotifyAdapter(timeline, page)); - loadComment(page, commentId, login, repoId, timeline); - }); - return true; - } - - private void loadComment(int page, long commentId, String login, String repoId, List timeline) { - if (page == 1 && commentId > 0) { - Observable observable = Observable.create(source -> { - int index = -1; - if (timeline != null) { - for (int i = 0; i < timeline.size(); i++) { - TimelineModel timelineModel = timeline.get(i); - if (timelineModel.getComment() != null) { - if (timelineModel.getComment().getId() == commentId) { - index = i; - break; - } - } - } - } - TimelineModel timelineModel = new TimelineModel(); - timelineModel.setPosition(index); - source.onNext(timelineModel); - source.onComplete(); - }); - manageObservable(observable.doOnNext(timelineModel -> sendToView(view -> { - if (timelineModel.getComment() != null) { - view.addComment(timelineModel, -1); - } else { - view.addComment(null, timelineModel.getPosition()); - } - }))); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/RepoProjectsFragmentPager.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/RepoProjectsFragmentPager.kt deleted file mode 100644 index b6b3ccf6e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/RepoProjectsFragmentPager.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.fastaccess.ui.modules.repos.projects - -import android.os.Bundle -import android.support.design.widget.TabLayout -import android.view.View -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.FragmentPagerAdapterModel -import com.fastaccess.data.dao.TabsCountStateModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.helper.ViewHelper -import com.fastaccess.ui.adapter.FragmentsPagerAdapter -import com.fastaccess.ui.base.BaseFragment -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.repos.RepoPagerMvp -import com.fastaccess.ui.widgets.SpannableBuilder -import com.fastaccess.ui.widgets.ViewPagerView - -/** - * Created by kosh on 09/09/2017. - */ -class RepoProjectsFragmentPager : BaseFragment>(), RepoPagerMvp.TabsBadgeListener { - - @BindView(R.id.tabs) lateinit var tabs: TabLayout - @BindView(R.id.pager) lateinit var pager: ViewPagerView - private var counts: HashSet? = null - - override fun fragmentLayout(): Int = R.layout.centered_tabbed_viewpager - - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(outState) - if (counts?.isNotEmpty() == true) { - outState.putSerializable("counts", counts) - } - } - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - pager.adapter = FragmentsPagerAdapter(childFragmentManager, FragmentPagerAdapterModel.buildForRepoProjects(context!!, - arguments!!.getString(BundleConstant.ID), arguments!!.getString(BundleConstant.EXTRA))) - tabs.setupWithViewPager(pager) - if (savedInstanceState != null) { - @Suppress("UNCHECKED_CAST") - counts = savedInstanceState.getSerializable("counts") as? HashSet? - counts?.let { - if (!it.isEmpty()) it.onEach { updateCount(it) } - } - } else { - counts = hashSetOf() - } - } - - override fun providePresenter(): BasePresenter = BasePresenter() - - override fun onSetBadge(tabIndex: Int, count: Int) { - val model = TabsCountStateModel() - model.tabIndex = tabIndex - model.count = count - counts?.add(model) - tabs.let { updateCount(model) } - } - - private fun updateCount(model: TabsCountStateModel) { - val tv = ViewHelper.getTabTextView(tabs, model.tabIndex) - tv.text = SpannableBuilder.builder() - .append(if (model.tabIndex == 0) getString(R.string.opened) else getString(R.string.closed)) - .append(" ") - .append("(") - .bold(model.count.toString()) - .append(")") - } - - companion object { - val TAG = RepoProjectsFragmentPager::class.java.simpleName - fun newInstance(login: String, repoId: String? = null): RepoProjectsFragmentPager { - val fragment = RepoProjectsFragmentPager() - fragment.arguments = Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .end() - return fragment - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnFragment.kt deleted file mode 100644 index 9e4d421c5..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnFragment.kt +++ /dev/null @@ -1,260 +0,0 @@ -package com.fastaccess.ui.modules.repos.projects.columns - -import android.content.Context -import android.os.Bundle -import android.support.annotation.StringRes -import android.support.v4.widget.SwipeRefreshLayout -import android.view.View -import butterknife.BindView -import butterknife.OnClick -import com.fastaccess.R -import com.fastaccess.data.dao.ProjectCardModel -import com.fastaccess.data.dao.ProjectColumnModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.helper.Logger -import com.fastaccess.helper.PrefGetter -import com.fastaccess.provider.rest.loadmore.OnLoadMore -import com.fastaccess.ui.adapter.ColumnCardAdapter -import com.fastaccess.ui.base.BaseFragment -import com.fastaccess.ui.modules.main.premium.PremiumActivity -import com.fastaccess.ui.modules.repos.projects.crud.ProjectCurdDialogFragment -import com.fastaccess.ui.modules.repos.projects.details.ProjectPagerMvp -import com.fastaccess.ui.widgets.FontTextView -import com.fastaccess.ui.widgets.StateLayout -import com.fastaccess.ui.widgets.dialog.MessageDialogView -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller - -/** - * Created by Hashemsergani on 11.09.17. - */ -class ProjectColumnFragment : BaseFragment(), ProjectColumnMvp.View { - - @BindView(R.id.recycler) lateinit var recycler: DynamicRecyclerView - @BindView(R.id.refresh) lateinit var refresh: SwipeRefreshLayout - @BindView(R.id.stateLayout) lateinit var stateLayout: StateLayout - @BindView(R.id.fastScroller) lateinit var fastScroller: RecyclerViewFastScroller - @BindView(R.id.columnName) lateinit var columnName: FontTextView - @BindView(R.id.editColumnHolder) lateinit var editColumnHolder: View - @BindView(R.id.editColumn) lateinit var editColumn: View - @BindView(R.id.addCard) lateinit var addCard: View - @BindView(R.id.deleteColumn) lateinit var deleteColumn: View - - private var onLoadMore: OnLoadMore? = null - private val adapter by lazy { ColumnCardAdapter(presenter.getCards(), isOwner()) } - private var pageCallback: ProjectPagerMvp.DeletePageListener? = null - - - override fun onAttach(context: Context?) { - super.onAttach(context) - pageCallback = when { - parentFragment is ProjectPagerMvp.DeletePageListener -> parentFragment as ProjectPagerMvp.DeletePageListener - context is ProjectPagerMvp.DeletePageListener -> context - else -> null - } - } - - override fun onDetach() { - pageCallback = null - super.onDetach() - } - - @OnClick(R.id.editColumn) fun onEditColumn() { - if (canEdit()) { - ProjectCurdDialogFragment.newInstance(getColumn().name) - .show(childFragmentManager, ProjectCurdDialogFragment.TAG) - } - } - - @OnClick(R.id.deleteColumn) fun onDeleteColumn() { - if (canEdit()) { - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), - false, MessageDialogView.getYesNoBundle(context!!)) - .show(childFragmentManager, MessageDialogView.TAG) - } - } - - @OnClick(R.id.addCard) fun onAddCard() { - if (canEdit()) { - ProjectCurdDialogFragment.newInstance(isCard = true) - .show(childFragmentManager, ProjectCurdDialogFragment.TAG) - } - } - - override fun onNotifyAdapter(items: List?, page: Int) { - hideProgress() - if (items == null || items.isEmpty()) { - adapter.clear() - return - } - if (page <= 1) { - adapter.insertItems(items) - } else { - adapter.addItems(items) - } - } - - override fun getLoadMore(): OnLoadMore { - if (onLoadMore == null) { - onLoadMore = OnLoadMore(presenter) - } - onLoadMore!!.parameter = getColumn().id - return onLoadMore!! - } - - override fun providePresenter(): ProjectColumnPresenter = ProjectColumnPresenter() - - override fun fragmentLayout(): Int = R.layout.project_columns_layout - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - val column = getColumn() - columnName.text = column.name - refresh.setOnRefreshListener { presenter.onCallApi(1, column.id) } - stateLayout.setOnReloadListener { presenter.onCallApi(1, column.id) } - stateLayout.setEmptyText(R.string.no_cards) - recycler.setEmptyView(stateLayout, refresh) - getLoadMore().initialize(presenter.currentPage, presenter.previousTotal) - adapter.listener = presenter - recycler.adapter = adapter - recycler.addOnScrollListener(getLoadMore()) - fastScroller.attachRecyclerView(recycler) - if (presenter.getCards().isEmpty() && !presenter.isApiCalled) { - presenter.onCallApi(1, column.id) - } - addCard.visibility = if(isOwner()) View.VISIBLE else View.GONE - deleteColumn.visibility = if(isOwner()) View.VISIBLE else View.GONE - editColumn.visibility = if(isOwner()) View.VISIBLE else View.GONE - } - - override fun showProgress(@StringRes resId: Int) { - refresh.isRefreshing = true - stateLayout.showProgress() - } - - override fun hideProgress() { - refresh.isRefreshing = false - stateLayout.hideProgress() - } - - override fun showErrorMessage(message: String) { - showReload() - super.showErrorMessage(message) - } - - override fun showMessage(titleRes: Int, msgRes: Int) { - showReload() - super.showMessage(titleRes, msgRes) - } - - override fun onScrollTop(index: Int) { - super.onScrollTop(index) - recycler.scrollToPosition(0) - } - - override fun onDestroyView() { - recycler.removeOnScrollListener(getLoadMore()) - super.onDestroyView() - } - - override fun onCreatedOrEdited(text: String, isCard: Boolean, position: Int) { - Logger.e(text, isCard, position) - if (!isCard) { - columnName.text = text - presenter.onEditOrDeleteColumn(text, getColumn()) - } else { - if (position == -1) { - presenter.createCard(text, getColumn().id) - } else { - presenter.editCard(text, adapter.getItem(position), position) - } - } - } - - override fun onMessageDialogActionClicked(isOk: Boolean, bundle: Bundle?) { - super.onMessageDialogActionClicked(isOk, bundle) - if (isOk) { - if (bundle != null) { - if (bundle.containsKey(BundleConstant.ID)) { - val position = bundle.getInt(BundleConstant.ID) - presenter.onDeleteCard(position, adapter.getItem(position)) - } else { - presenter.onEditOrDeleteColumn(null, getColumn()) - } - } else { - presenter.onEditOrDeleteColumn(null, getColumn()) - } - } - } - - override fun deleteColumn() { - pageCallback?.onDeletePage(getColumn()) - hideBlockingProgress() - } - - override fun showBlockingProgress() { - super.showProgress(0) - } - - override fun hideBlockingProgress() { - super.hideProgress() - } - - override fun isOwner(): Boolean = arguments!!.getBoolean(BundleConstant.EXTRA) - - override fun onDeleteCard(position: Int) { - if (canEdit()) { - val yesNoBundle = MessageDialogView.getYesNoBundle(context!!) - yesNoBundle.putInt(BundleConstant.ID, position) - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), - false, yesNoBundle).show(childFragmentManager, MessageDialogView.TAG) - } - } - - override fun onEditCard(note: String?, position: Int) { - if (canEdit()) { - ProjectCurdDialogFragment.newInstance(note, true, position) - .show(childFragmentManager, ProjectCurdDialogFragment.TAG) - } - } - - override fun addCard(it: ProjectCardModel) { - hideBlockingProgress() - adapter.addItem(it, 0) - } - - override fun updateCard(response: ProjectCardModel, position: Int) { - hideBlockingProgress() - adapter.swapItem(response, position) - } - - override fun onRemoveCard(position: Int) { - hideBlockingProgress() - adapter.removeItem(position) - } - - private fun showReload() { - hideProgress() - stateLayout.showReload(adapter.itemCount) - } - - private fun getColumn(): ProjectColumnModel = arguments!!.getParcelable(BundleConstant.ITEM) - - private fun canEdit(): Boolean = if (PrefGetter.isProEnabled() || PrefGetter.isAllFeaturesUnlocked()) { - true - } else { - PremiumActivity.startActivity(context!!) - false - } - - companion object { - fun newInstance(column: ProjectColumnModel, isCollaborator: Boolean): ProjectColumnFragment { - val fragment = ProjectColumnFragment() - fragment.arguments = Bundler.start() - .put(BundleConstant.ITEM, column) - .put(BundleConstant.EXTRA, isCollaborator) - .end() - return fragment - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnMvp.kt deleted file mode 100644 index ddab0e47a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnMvp.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.fastaccess.ui.modules.repos.projects.columns - -import com.fastaccess.data.dao.ProjectCardModel -import com.fastaccess.data.dao.ProjectColumnModel -import com.fastaccess.provider.rest.loadmore.OnLoadMore -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.modules.repos.projects.crud.ProjectCurdDialogFragment -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Hashemsergani on 11.09.17. - */ - -interface ProjectColumnMvp { - interface View : BaseMvp.FAView, ProjectCurdDialogFragment.OnProjectEditedCallback { - fun onNotifyAdapter(items: List?, page: Int) - fun getLoadMore(): OnLoadMore - fun deleteColumn() - fun showBlockingProgress() - fun hideBlockingProgress() - fun isOwner(): Boolean - fun onDeleteCard(position: Int) - fun onEditCard(note: String?, position: Int) - fun addCard(it: ProjectCardModel) - fun updateCard(response: ProjectCardModel, position: Int) - fun onRemoveCard(position: Int) - } - - interface Presenter : BaseViewHolder.OnItemClickListener, BaseMvp.PaginationListener { - fun getCards(): ArrayList - fun onEditOrDeleteColumn(text: String? = null, column: ProjectColumnModel) - fun onDeleteCard(position: Int, card: ProjectCardModel) - fun createCard(text: String, columnId: Long) - fun editCard(text: String, card: ProjectCardModel, position: Int) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnPresenter.kt deleted file mode 100644 index cdfde9c69..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/columns/ProjectColumnPresenter.kt +++ /dev/null @@ -1,180 +0,0 @@ -package com.fastaccess.ui.modules.repos.projects.columns - -import android.view.View -import android.widget.PopupMenu -import com.fastaccess.R -import com.fastaccess.data.dao.ProjectCardModel -import com.fastaccess.data.dao.ProjectColumnModel -import com.fastaccess.helper.ActivityHelper -import com.fastaccess.helper.AppHelper -import com.fastaccess.helper.Logger -import com.fastaccess.helper.RxHelper -import com.fastaccess.provider.rest.RestProvider -import com.fastaccess.provider.scheme.SchemeParser -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import java.util.* - -/** - * Created by Hashemsergani on 11.09.17. - */ - -class ProjectColumnPresenter : BasePresenter(), ProjectColumnMvp.Presenter { - - private val projects = ArrayList() - private var page: Int = 0 - private var previousTotal: Int = 0 - private var lastPage = Integer.MAX_VALUE - - override fun onItemClick(position: Int, v: View, item: ProjectCardModel) { - if (v.id == R.id.editCard) { - view?.let { - val popupMenu = PopupMenu(v.context, v) - popupMenu.inflate(R.menu.project_card_menu) - popupMenu.menu.findItem(R.id.share).isVisible = !item.contentUrl.isNullOrBlank() - popupMenu.menu.findItem(R.id.copy).isVisible = !item.contentUrl.isNullOrBlank() - popupMenu.menu.findItem(R.id.edit).isVisible = it.isOwner() && !item.note.isNullOrBlank() - popupMenu.menu.findItem(R.id.delete).isVisible = it.isOwner() && !item.note.isNullOrBlank() - popupMenu.setOnMenuItemClickListener { - when (it.itemId) { - R.id.edit -> sendToView { it.onEditCard(item.note, position) } - R.id.delete -> sendToView { it.onDeleteCard(position) } - R.id.share -> if (!item.contentUrl.isNullOrBlank()) { - ActivityHelper.shareUrl(v.context, item.contentUrl) - } - R.id.copy -> if (!item.contentUrl.isNullOrBlank()) { - AppHelper.copyToClipboard(v.context, item.contentUrl) - } - } - return@setOnMenuItemClickListener true - } - popupMenu.show() - } - } else { - if (!item.contentUrl.isNullOrBlank()) { - SchemeParser.launchUri(v.context, item.contentUrl) - } - } - } - - override fun onItemLongClick(position: Int, v: View?, item: ProjectCardModel?) {} - - override fun getCards(): ArrayList = projects - - override fun getCurrentPage(): Int = page - - override fun getPreviousTotal(): Int = previousTotal - - override fun setCurrentPage(page: Int) { - this.page = page - } - - override fun setPreviousTotal(previousTotal: Int) { - this.previousTotal = previousTotal - } - - override fun onCallApi(page: Int, parameter: Long?): Boolean { - if (page == 1) { - lastPage = Integer.MAX_VALUE - sendToView { view -> view.getLoadMore().reset() } - } - if (page > lastPage || lastPage == 0) { - sendToView({ it.hideProgress() }) - return false - } - currentPage = page - makeRestCall(RestProvider.getProjectsService(isEnterprise).getProjectCards(parameter!!, page), - { response -> - lastPage = response.last - Logger.e(response.items as List?) - sendToView({ it.onNotifyAdapter(response.items, page) }) - }) - return true - } - - override fun onEditOrDeleteColumn(text: String?, column: ProjectColumnModel) { - if (text.isNullOrBlank()) { - manageDisposable(RxHelper.getObservable(RestProvider.getProjectsService(isEnterprise).deleteColumn(column.id)) - .doOnSubscribe { - showBlockingProgress() - } - .subscribe({ - if (it.code() == 204) { - sendToView { it.deleteColumn() } - } else { - sendToView { it.showMessage(R.string.error, R.string.network_error) } - } - }, { - hideBlockingProgress() - onError(it) - })) - } else { - val body = ProjectColumnModel() - body.name = text - manageDisposable(RxHelper.getObservable(RestProvider.getProjectsService(isEnterprise).updateColumn(column.id, body)) - .doOnSubscribe { - showBlockingProgress() - } - .subscribe({ - hideBlockingProgress() - }, { - hideBlockingProgress() - onError(it) - })) - } - } - - override fun onDeleteCard(position: Int, card: ProjectCardModel) { - manageDisposable(RxHelper.getObservable(RestProvider.getProjectsService(isEnterprise).deleteCard(card.id.toLong())) - .doOnSubscribe { - showBlockingProgress() - } - .subscribe({ - if (it.code() == 204) { - sendToView { it.onRemoveCard(position) } - } else { - sendToView { it.showMessage(R.string.error, R.string.network_error) } - } - }, { - hideBlockingProgress() - onError(it) - })) - } - - override fun createCard(text: String, columnId: Long) { - val body = ProjectCardModel() - body.note = text - manageDisposable(RxHelper.getObservable(RestProvider.getProjectsService(isEnterprise).createCard(columnId, body)) - .doOnSubscribe { - showBlockingProgress() - } - .subscribe({ response -> - sendToView { it.addCard(response) } - }, { - hideBlockingProgress() - onError(it) - })) - } - - override fun editCard(text: String, card: ProjectCardModel, position: Int) { - val body = ProjectCardModel() - body.note = text - manageDisposable(RxHelper.getObservable(RestProvider.getProjectsService(isEnterprise).updateCard(card.id.toLong(), body)) - .doOnSubscribe { - showBlockingProgress() - } - .subscribe({ response -> - sendToView { it.updateCard(response, position) } - }, { - hideBlockingProgress() - onError(it) - })) - } - - private fun showBlockingProgress() { - sendToView({ v -> v.showBlockingProgress() }) - } - - private fun hideBlockingProgress() { - sendToView({ v -> v.hideBlockingProgress() }) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/crud/ProjectCurdDialogFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/crud/ProjectCurdDialogFragment.kt deleted file mode 100644 index 35889f577..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/crud/ProjectCurdDialogFragment.kt +++ /dev/null @@ -1,120 +0,0 @@ -package com.fastaccess.ui.modules.repos.projects.crud - -import android.annotation.SuppressLint -import android.content.Context -import android.os.Bundle -import android.support.v4.app.FragmentManager -import android.support.v7.widget.Toolbar -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.WindowManager -import android.widget.EditText -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.helper.InputHelper -import com.fastaccess.provider.emoji.Emoji -import com.fastaccess.ui.base.BaseDialogFragment -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.editor.emoji.EmojiMvp -import com.fastaccess.ui.modules.editor.popup.EditorLinkImageMvp -import com.fastaccess.ui.widgets.markdown.MarkDownLayout -import com.fastaccess.ui.widgets.markdown.MarkdownEditText - -/** - * Created by Hashemsergani on 15.09.17. - */ - -class ProjectCurdDialogFragment : BaseDialogFragment>(), - EditorLinkImageMvp.EditorLinkCallback, MarkDownLayout.MarkdownListener, EmojiMvp.EmojiCallback { - - @BindView(R.id.editText) lateinit var editText: MarkdownEditText - @BindView(R.id.toolbar) lateinit var toolbar: Toolbar - @BindView(R.id.markDownLayout) lateinit var markDownLayout: MarkDownLayout - - private var onProjectEditedCallback: OnProjectEditedCallback? = null - - override fun onAttach(context: Context) { - super.onAttach(context) - onProjectEditedCallback = when { - parentFragment is OnProjectEditedCallback -> parentFragment as OnProjectEditedCallback - context is OnProjectEditedCallback -> context - else -> throw NullPointerException("${context::class.java.simpleName} most implement OnProjectEditedCallback") - } - } - - override fun onDetach() { - onProjectEditedCallback = null - super.onDetach() - } - - override fun fragmentLayout(): Int = R.layout.edit_project_column_note_layout - - override fun providePresenter(): BasePresenter = BasePresenter() - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN) - return super.onCreateView(inflater, container, savedInstanceState) - } - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - markDownLayout.markdownListener = this - toolbar.inflateMenu(R.menu.done_menu) - toolbar.menu.findItem(R.id.submit)?.setIcon(R.drawable.ic_done) - toolbar.setNavigationIcon(R.drawable.ic_clear) - toolbar.setNavigationOnClickListener { dismiss() } - val position: Int = arguments!!.getInt(BundleConstant.ID, -1) - val isCard: Boolean = arguments!!.getBoolean(BundleConstant.EXTRA) - if (savedInstanceState == null) { - editText.setText(arguments?.getString(BundleConstant.ITEM) ?: "") - } - toolbar.setOnMenuItemClickListener { - if (it.itemId == R.id.submit) { - val isEmpty = editText.text.isNullOrBlank() - editText.error = if (isEmpty) getString(R.string.required_field) else null - if (!isEmpty) { - onProjectEditedCallback?.onCreatedOrEdited(InputHelper.toString(editText), isCard, position) - dismiss() - } - } - return@setOnMenuItemClickListener true - } - } - - override fun getEditText(): EditText = editText - - override fun fragmentManager(): FragmentManager = childFragmentManager - - override fun getSavedText(): CharSequence? = editText.savedText - - override fun onAppendLink(title: String?, link: String?, isLink: Boolean) { - markDownLayout.onAppendLink(title, link, isLink) - } - - @SuppressLint("SetTextI18n") - override fun onEmojiAdded(emoji: Emoji?) { - markDownLayout.onEmojiAdded(emoji) - } - - companion object { - val TAG = ProjectCurdDialogFragment::class.java.simpleName!! - - fun newInstance(text: String? = null, isCard: Boolean = false, position: Int = -1): ProjectCurdDialogFragment { - val fragment = ProjectCurdDialogFragment() - fragment.arguments = Bundler.start() - .put(BundleConstant.ITEM, text) - .put(BundleConstant.EXTRA, isCard) - .put(BundleConstant.ID, position) - .end() - return fragment - } - } - - interface OnProjectEditedCallback { - fun onCreatedOrEdited(text: String, isCard: Boolean, position: Int) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerActivity.kt deleted file mode 100644 index 0c572e444..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerActivity.kt +++ /dev/null @@ -1,151 +0,0 @@ -package com.fastaccess.ui.modules.repos.projects.details - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.support.v4.view.ViewPager -import android.view.MenuItem -import android.view.View -import butterknife.BindView -import com.airbnb.lottie.LottieAnimationView -import com.evernote.android.state.State -import com.fastaccess.R -import com.fastaccess.data.dao.FragmentPagerAdapterModel -import com.fastaccess.data.dao.NameParser -import com.fastaccess.data.dao.ProjectColumnModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.ui.adapter.FragmentsPagerAdapter -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.modules.repos.RepoPagerActivity -import com.fastaccess.ui.modules.user.UserPagerActivity -import com.fastaccess.ui.widgets.CardsPagerTransformerBasic - -/** - * Created by Hashemsergani on 11.09.17. - */ - -class ProjectPagerActivity : BaseActivity(), ProjectPagerMvp.View { - - @BindView(R.id.pager) lateinit var pager: ViewPager - @BindView(R.id.loading) lateinit var loading: LottieAnimationView - @State var isProgressShowing = false - - override fun canBack(): Boolean = true - - override fun isSecured(): Boolean = false - - override fun providePresenter(): ProjectPagerPresenter = ProjectPagerPresenter() - - override fun onInitPager(list: List) { - hideProgress() - pager.adapter = FragmentsPagerAdapter(supportFragmentManager, FragmentPagerAdapterModel - .buildForProjectColumns(list, presenter.viewerCanUpdate)) - } - - override fun showMessage(titleRes: Int, msgRes: Int) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showMessage(titleRes: String, msgRes: String) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showErrorMessage(msgRes: String) { - hideProgress() - super.showErrorMessage(msgRes) - } - - override fun showProgress(resId: Int) { - isProgressShowing = true - loading.visibility = View.VISIBLE - loading.playAnimation() - } - - override fun hideProgress() { - isProgressShowing = false - loading.cancelAnimation() - loading.visibility = View.GONE - } - - override fun layout(): Int = R.layout.projects_activity_layout - - override fun isTransparent(): Boolean = true - - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - return when (item?.itemId) { - android.R.id.home -> { - val repoId = presenter.repoId - if (repoId != null && !repoId.isNullOrBlank()) { - if (!presenter.login.isBlank()) { - val nameParse = NameParser("") - nameParse.name = presenter.repoId - nameParse.username = presenter.login - nameParse.isEnterprise = isEnterprise - RepoPagerActivity.startRepoPager(this, nameParse) - } - } else if (!presenter.login.isBlank()) { - UserPagerActivity.startActivity(this, presenter.login, true, isEnterprise, 0) - } - finish() - true - } - else -> super.onOptionsItemSelected(item) - } - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - if (isProgressShowing) { - showProgress(0) - } else { - hideProgress() - } - pager.clipToPadding = false - val partialWidth = resources.getDimensionPixelSize(R.dimen.spacing_xs_large) - val pageMargin = resources.getDimensionPixelSize(R.dimen.spacing_normal) - val pagerPadding = partialWidth + pageMargin - pager.pageMargin = pageMargin - pager.setPageTransformer(true, CardsPagerTransformerBasic(4, 10)) - pager.setPadding(pagerPadding, pagerPadding, pagerPadding, pagerPadding) - - if (savedInstanceState == null) { - presenter.onActivityCreated(intent) - } else if (presenter.getColumns().isEmpty() && !presenter.isApiCalled) { - presenter.onRetrieveColumns() - } else { - onInitPager(presenter.getColumns()) - } - if (presenter.repoId.isNullOrBlank()) { - toolbar?.subtitle = presenter.login - } else { - toolbar?.subtitle = "${presenter.login}/${presenter.repoId}" - } - } - - override fun onDeletePage(model: ProjectColumnModel) { - presenter.getColumns().remove(model) - onInitPager(presenter.getColumns()) - } - - companion object { - fun startActivity(context: Context, login: String, repoId: String? = null, projectId: Long, isEnterprise: Boolean = false) { - context.startActivity(getIntent(context, login, repoId, projectId, isEnterprise)) - } - - fun getIntent(context: Context, login: String, repoId: String? = null, projectId: Long, isEnterprise: Boolean = false): Intent { - val intent = Intent(context, ProjectPagerActivity::class.java) - intent.putExtras(Bundler.start() - .put(BundleConstant.ID, projectId) - .put(BundleConstant.ITEM, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .end()) - return intent - } - - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerMvp.kt deleted file mode 100644 index 636bdb9a0..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerMvp.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.fastaccess.ui.modules.repos.projects.details - -import android.content.Intent -import com.fastaccess.data.dao.ProjectColumnModel -import com.fastaccess.ui.base.mvp.BaseMvp - -/** - * Created by Hashemsergani on 11.09.17. - */ -interface ProjectPagerMvp { - - interface View : BaseMvp.FAView, DeletePageListener { - fun onInitPager(list: List) - } - - interface Presenter { - fun onActivityCreated(intent: Intent?) - - fun onRetrieveColumns() - - fun getColumns(): ArrayList - } - - interface DeletePageListener { - fun onDeletePage(model: ProjectColumnModel) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerPresenter.kt deleted file mode 100644 index aec7c5aba..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/details/ProjectPagerPresenter.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.fastaccess.ui.modules.repos.projects.details - -import android.content.Intent -import com.fastaccess.R -import com.fastaccess.data.dao.Pageable -import com.fastaccess.data.dao.ProjectColumnModel -import com.fastaccess.data.dao.model.Login -import com.fastaccess.helper.BundleConstant -import com.fastaccess.provider.rest.RestProvider -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import io.reactivex.Observable -import io.reactivex.functions.BiFunction -import retrofit2.Response - -/** - * Created by Hashemsergani on 11.09.17. - */ -class ProjectPagerPresenter : BasePresenter(), ProjectPagerMvp.Presenter { - - private val columns = arrayListOf() - @com.evernote.android.state.State var projectId: Long = -1 - @com.evernote.android.state.State var repoId: String? = null - @com.evernote.android.state.State var login: String = "" - @com.evernote.android.state.State var viewerCanUpdate: Boolean = false - - override fun onError(throwable: Throwable) { - val code = RestProvider.getErrorCode(throwable) - if (code == 404) { - sendToView { it.onOpenUrlInBrowser() } - } - super.onError(throwable) - } - - override fun getColumns(): ArrayList = columns - - override fun onRetrieveColumns() { - val repoId = repoId - if (repoId != null && !repoId.isNullOrBlank()) { - makeRestCall(Observable.zip(RestProvider.getProjectsService(isEnterprise).getProjectColumns(projectId), - RestProvider.getRepoService(isEnterprise).isCollaborator(login, repoId, Login.getUser().login), - BiFunction { items: Pageable, response: Response -> - viewerCanUpdate = response.code() == 204 - return@BiFunction items - }) - .flatMap { - if (it.items != null) { - return@flatMap Observable.just(it.items) - } - return@flatMap Observable.just(listOf()) - }, - { t -> - columns.clear() - columns.addAll(t) - sendToView { it.onInitPager(columns) } - }) - } else { - makeRestCall(RestProvider.getProjectsService(isEnterprise).getProjectColumns(projectId) - .flatMap { - if (it.items != null) { - return@flatMap Observable.just(it.items) - } - return@flatMap Observable.just(listOf()) - }, - { t -> - columns.clear() - columns.addAll(t) - sendToView { it.onInitPager(columns) } - }) - } - } - - override fun onActivityCreated(intent: Intent?) { - intent?.let { - it.extras?.let { - projectId = it.getLong(BundleConstant.ID) - repoId = it.getString(BundleConstant.ITEM) - login = it.getString(BundleConstant.EXTRA) - } - } - if (columns.isEmpty()) { - if (projectId > 0) - onRetrieveColumns() - else - sendToView { it.showMessage(R.string.error, R.string.unexpected_error) } - } else { - sendToView { it.onInitPager(columns) } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectFragment.kt deleted file mode 100644 index 3fb414dc3..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectFragment.kt +++ /dev/null @@ -1,145 +0,0 @@ -package com.fastaccess.ui.modules.repos.projects.list - -import android.content.Context -import android.os.Bundle -import android.support.annotation.StringRes -import android.support.v4.widget.SwipeRefreshLayout -import android.view.View -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.types.IssueState -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.provider.rest.loadmore.OnLoadMore -import com.fastaccess.ui.adapter.ProjectsAdapter -import com.fastaccess.ui.base.BaseFragment -import com.fastaccess.ui.modules.repos.RepoPagerMvp -import com.fastaccess.ui.widgets.StateLayout -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller -import github.RepoProjectsOpenQuery - -/** - * Created by kosh on 09/09/2017. - */ - -class RepoProjectFragment : BaseFragment(), RepoProjectMvp.View { - - @BindView(R.id.recycler) lateinit var recycler: DynamicRecyclerView - @BindView(R.id.refresh) lateinit var refresh: SwipeRefreshLayout - @BindView(R.id.stateLayout) lateinit var stateLayout: StateLayout - @BindView(R.id.fastScroller) lateinit var fastScroller: RecyclerViewFastScroller - private var onLoadMore: OnLoadMore? = null - private val adapter by lazy { ProjectsAdapter(presenter.getProjects()) } - private var badgeListener: RepoPagerMvp.TabsBadgeListener? = null - - override fun onAttach(context: Context?) { - super.onAttach(context) - if (parentFragment is RepoPagerMvp.TabsBadgeListener) { - badgeListener = parentFragment as RepoPagerMvp.TabsBadgeListener - } else if (context is RepoPagerMvp.TabsBadgeListener) { - badgeListener = context - } - } - - override fun onDetach() { - badgeListener = null - super.onDetach() - } - - override fun providePresenter(): RepoProjectPresenter = RepoProjectPresenter() - - override fun onNotifyAdapter(items: List?, page: Int) { - hideProgress() - if (items == null || items.isEmpty()) { - adapter.clear() - return - } - if (page <= 1) { - adapter.insertItems(items) - } else { - adapter.addItems(items) - } - } - - override fun onChangeTotalCount(count: Int) { - badgeListener?.onSetBadge(if (getState() == IssueState.open) 0 else 1, count) - } - - override fun getLoadMore(): OnLoadMore { - if (onLoadMore == null) { - onLoadMore = OnLoadMore(presenter) - } - onLoadMore!!.parameter = getState() - return onLoadMore!! - } - - override fun fragmentLayout(): Int = R.layout.micro_grid_refresh_list - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - stateLayout.setEmptyText(R.string.no_projects) - stateLayout.setOnReloadListener({ presenter.onCallApi(1, getState()) }) - refresh.setOnRefreshListener({ presenter.onCallApi(1, getState()) }) - recycler.setEmptyView(stateLayout, refresh) - getLoadMore().initialize(presenter.currentPage, presenter - .previousTotal) - adapter.listener = presenter - recycler.adapter = adapter - recycler.addDivider() - recycler.addOnScrollListener(getLoadMore()) - fastScroller.attachRecyclerView(recycler) - if (presenter.getProjects().isEmpty() && !presenter.isApiCalled) { - presenter.onFragmentCreate(arguments) - presenter.onCallApi(1, getState()) - } - } - - override fun showProgress(@StringRes resId: Int) { - refresh.isRefreshing = true - stateLayout.showProgress() - } - - override fun hideProgress() { - refresh.isRefreshing = false - stateLayout.hideProgress() - } - - override fun showErrorMessage(message: String) { - showReload() - super.showErrorMessage(message) - } - - override fun showMessage(titleRes: Int, msgRes: Int) { - showReload() - super.showMessage(titleRes, msgRes) - } - - override fun onScrollTop(index: Int) { - super.onScrollTop(index) - recycler?.scrollToPosition(0) - } - - override fun onDestroyView() { - recycler.removeOnScrollListener(getLoadMore()) - super.onDestroyView() - } - - private fun showReload() { - hideProgress() - stateLayout.showReload(adapter.itemCount) - } - - private fun getState(): IssueState = arguments!!.getSerializable(BundleConstant.EXTRA_TYPE) as IssueState - - companion object { - fun newInstance(login: String, repoId: String? = null, state: IssueState): RepoProjectFragment { - val fragment = RepoProjectFragment() - fragment.arguments = Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TYPE, state) - .end() - return fragment - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectMvp.kt deleted file mode 100644 index 59db03396..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectMvp.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.fastaccess.ui.modules.repos.projects.list - -import android.os.Bundle -import com.fastaccess.data.dao.types.IssueState -import com.fastaccess.provider.rest.loadmore.OnLoadMore -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder -import github.RepoProjectsOpenQuery -import java.util.* - -/** - * Created by kosh on 09/09/2017. - */ -interface RepoProjectMvp { - - interface View : BaseMvp.FAView { - fun onNotifyAdapter(items: List?, page: Int) - fun getLoadMore(): OnLoadMore - fun onChangeTotalCount(count: Int) - } - - interface Presenter : BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - fun onFragmentCreate(bundle: Bundle?) - - fun getProjects(): ArrayList - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectPresenter.kt deleted file mode 100644 index 90b7d8d54..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/projects/list/RepoProjectPresenter.kt +++ /dev/null @@ -1,222 +0,0 @@ -package com.fastaccess.ui.modules.repos.projects.list - -import android.os.Bundle -import android.view.View -import com.apollographql.apollo.rx2.Rx2Apollo -import com.fastaccess.data.dao.types.IssueState -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Logger -import com.fastaccess.provider.rest.ApolloProdivder -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.repos.projects.details.ProjectPagerActivity -import github.OrgProjectsClosedQuery -import github.OrgProjectsOpenQuery -import github.RepoProjectsClosedQuery -import github.RepoProjectsOpenQuery -import io.reactivex.Observable - -/** - * Created by kosh on 09/09/2017. - */ -class RepoProjectPresenter : BasePresenter(), RepoProjectMvp.Presenter { - - private val projects = arrayListOf() - private var page: Int = 0 - private var previousTotal: Int = 0 - private var lastPage = Integer.MAX_VALUE - @com.evernote.android.state.State var login: String = "" - @com.evernote.android.state.State var repoId: String? = null - var count: Int = 0 - val pages = arrayListOf() - - override fun onItemClick(position: Int, v: View, item: RepoProjectsOpenQuery.Node) { - item.databaseId()?.let { - ProjectPagerActivity.startActivity(v.context, login, repoId, it.toLong(), isEnterprise) - } - } - - override fun onItemLongClick(position: Int, v: View?, item: RepoProjectsOpenQuery.Node?) {} - - override fun onFragmentCreate(bundle: Bundle?) { - bundle?.let { - repoId = it.getString(BundleConstant.ID) - login = it.getString(BundleConstant.EXTRA) - } - } - - override fun getProjects(): ArrayList = projects - - override fun getCurrentPage(): Int = page - - override fun getPreviousTotal(): Int = previousTotal - - override fun setCurrentPage(page: Int) { - this.page = page - } - - override fun setPreviousTotal(previousTotal: Int) { - this.previousTotal = previousTotal - } - - override fun onCallApi(page: Int, parameter: IssueState?): Boolean { - if (page == 1) { - lastPage = Integer.MAX_VALUE - sendToView { view -> view.getLoadMore().reset() } - } - if (page > lastPage || lastPage == 0 || parameter == null) { - sendToView({ it.hideProgress() }) - return false - } - currentPage = page - Logger.e(login) - val repoId = repoId - val apollo = ApolloProdivder.getApollo(isEnterprise) - if (repoId != null && !repoId.isNullOrBlank()) { - if (parameter == IssueState.open) { - val query = RepoProjectsOpenQuery.builder() - .name(repoId) - .owner(login) - .page(getPage()) - .build() - makeRestCall(Rx2Apollo.from(apollo.query(query)) - .flatMap { - val list = arrayListOf() - it.data()?.repository()?.let { - it.projects().let { - lastPage = if (it.pageInfo().hasNextPage()) Int.MAX_VALUE else 0 - pages.clear() - count = it.totalCount() - it.edges()?.let { - pages.addAll(it.map { it.cursor() }) - } - it.nodes()?.let { - list.addAll(it) - } - } - } - return@flatMap Observable.just(list) - }, - { - sendToView({ v -> - v.onNotifyAdapter(it, page) - if (page == 1) v.onChangeTotalCount(count) - }) - }) - } else { - val query = RepoProjectsClosedQuery.builder() - .name(repoId) - .owner(login) - .page(getPage()) - .build() - makeRestCall(Rx2Apollo.from(apollo.query(query)) - .flatMap { - val list = arrayListOf() - it.data()?.repository()?.let { - it.projects().let { - lastPage = if (it.pageInfo().hasNextPage()) Int.MAX_VALUE else 0 - pages.clear() - count = it.totalCount() - it.edges()?.let { - pages.addAll(it.map { it.cursor() }) - } - it.nodes()?.let { - val toConvert = arrayListOf() - it.onEach { - val columns = RepoProjectsOpenQuery.Columns(it.columns().__typename(), it.columns().totalCount()) - val node = RepoProjectsOpenQuery.Node(it.__typename(), it.name(), it.number(), it.body(), - it.createdAt(), it.id(), it.viewerCanUpdate(), columns, it.databaseId()) - toConvert.add(node) - } - list.addAll(toConvert) - } - } - } - return@flatMap Observable.just(list) - }, - { - sendToView({ v -> - v.onNotifyAdapter(it, page) - if (page == 1) v.onChangeTotalCount(count) - }) - }) - } - } else { - if (parameter == IssueState.open) { - val query = OrgProjectsOpenQuery.builder() - .owner(login) - .page(getPage()) - .build() - makeRestCall(Rx2Apollo.from(apollo.query(query)) - .flatMap { - val list = arrayListOf() - it.data()?.organization()?.let { - it.projects().let { - lastPage = if (it.pageInfo().hasNextPage()) Int.MAX_VALUE else 0 - pages.clear() - count = it.totalCount() - it.edges()?.let { - pages.addAll(it.map { it.cursor() }) - } - it.nodes()?.let { - val toConvert = arrayListOf() - it.onEach { - val columns = RepoProjectsOpenQuery.Columns(it.columns().__typename(), it.columns().totalCount()) - val node = RepoProjectsOpenQuery.Node(it.__typename(), it.name(), it.number(), it.body(), - it.createdAt(), it.id(), it.viewerCanUpdate(), columns, it.databaseId()) - toConvert.add(node) - } - list.addAll(toConvert) - } - } - } - return@flatMap Observable.just(list) - }, - { - sendToView({ v -> - v.onNotifyAdapter(it, page) - if (page == 1) v.onChangeTotalCount(count) - }) - }) - } else { - val query = OrgProjectsClosedQuery.builder() - .owner(login) - .page(getPage()) - .build() - makeRestCall(Rx2Apollo.from(apollo.query(query)) - .flatMap { - val list = arrayListOf() - it.data()?.organization()?.let { - it.projects().let { - lastPage = if (it.pageInfo().hasNextPage()) Int.MAX_VALUE else 0 - pages.clear() - count = it.totalCount() - it.edges()?.let { - pages.addAll(it.map { it.cursor() }) - } - it.nodes()?.let { - val toConvert = arrayListOf() - it.onEach { - val columns = RepoProjectsOpenQuery.Columns(it.columns().__typename(), it.columns().totalCount()) - val node = RepoProjectsOpenQuery.Node(it.__typename(), it.name(), it.number(), it.body(), - it.createdAt(), it.id(), it.viewerCanUpdate(), columns, it.databaseId()) - toConvert.add(node) - } - list.addAll(toConvert) - } - } - } - return@flatMap Observable.just(list) - }, - { - sendToView({ v -> - v.onNotifyAdapter(it, page) - if (page == 1) v.onChangeTotalCount(count) - }) - }) - } - } - return true - } - - private fun getPage(): String? = if (pages.isNotEmpty()) pages.last() else null -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerFragment.java deleted file mode 100644 index 11bb369f0..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerFragment.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; -import android.view.View; -import android.widget.TextView; - -import com.annimon.stream.Stream; -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.TabsCountStateModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.ViewPagerView; - -import java.util.HashSet; - -import butterknife.BindView; - -/** - * Created by Kosh on 31 Dec 2016, 1:36 AM - */ - -public class RepoPullRequestPagerFragment extends BaseFragment implements - RepoPullRequestPagerMvp.View { - - public static final String TAG = RepoPullRequestPagerFragment.class.getSimpleName(); - - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.pager) ViewPagerView pager; - @State HashSet counts = new HashSet<>(); - private RepoPagerMvp.View repoCallback; - - public static RepoPullRequestPagerFragment newInstance(@NonNull String repoId, @NonNull String login) { - RepoPullRequestPagerFragment view = new RepoPullRequestPagerFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .end()); - return view; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof RepoPagerMvp.View) { - repoCallback = (RepoPagerMvp.View) getParentFragment(); - } else if (context instanceof RepoPagerMvp.View) { - repoCallback = (RepoPagerMvp.View) context; - } - } - - @Override public void onDetach() { - repoCallback = null; - super.onDetach(); - } - - @Override protected int fragmentLayout() { - return R.layout.centered_tabbed_viewpager; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - String repoId = getArguments().getString(BundleConstant.ID); - String login = getArguments().getString(BundleConstant.EXTRA); - if (login == null || repoId == null) throw new NullPointerException("repoId || login is null???"); - pager.setAdapter(new FragmentsPagerAdapter(getChildFragmentManager(), - FragmentPagerAdapterModel.buildForRepoPullRequest(getContext(), login, repoId))); - tabs.setupWithViewPager(pager); - if (savedInstanceState != null && !counts.isEmpty()) { - Stream.of(counts).forEach(this::updateCount); - } - tabs.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager) { - @Override public void onTabReselected(TabLayout.Tab tab) { - super.onTabReselected(tab); - onScrollTop(tab.getPosition()); - } - }); - } - - @Override public void onScrollTop(int index) { - if (pager == null || pager.getAdapter() == null) return; - Fragment fragment = (BaseFragment) pager.getAdapter().instantiateItem(pager, index); - if (fragment instanceof BaseFragment) { - ((BaseFragment) fragment).onScrollTop(index); - } - } - - @NonNull @Override public RepoPullRequestPagerPresenter providePresenter() { - return new RepoPullRequestPagerPresenter(); - } - - @Override public void onSetBadge(int tabIndex, int count) { - TabsCountStateModel model = new TabsCountStateModel(); - model.setTabIndex(tabIndex); - model.setCount(count); - counts.add(model); - if (tabs != null) { - updateCount(model); - } - } - - @Override public int getCurrentItem() { - return pager != null ? pager.getCurrentItem() : 0; - } - - @Override public void onScrolled(boolean isUp) { - if (repoCallback != null) repoCallback.onScrolled(isUp); - } - - private void updateCount(@NonNull TabsCountStateModel model) { - TextView tv = ViewHelper.getTabTextView(tabs, model.getTabIndex()); - tv.setText(SpannableBuilder.builder() - .append(model.getTabIndex() == 0 ? getString(R.string.opened) : getString(R.string.closed)) - .append(" ") - .append("(") - .bold(String.valueOf(model.getCount())) - .append(")")); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerMvp.java deleted file mode 100644 index 1eee1f770..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerMvp.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests; - -import android.support.annotation.IntRange; - -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; - -/** - * Created by Kosh on 31 Dec 2016, 1:35 AM - */ - -public interface RepoPullRequestPagerMvp { - - interface View extends BaseMvp.FAView, RepoPagerMvp.TabsBadgeListener { - @IntRange(from = 0, to = 1) int getCurrentItem(); - - void onScrolled(boolean isUp); - } - - interface Presenter extends BaseMvp.FAPresenter {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerPresenter.java deleted file mode 100644 index 588b69145..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/RepoPullRequestPagerPresenter.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests; - -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by Kosh on 31 Dec 2016, 1:36 AM - */ - -class RepoPullRequestPagerPresenter extends BasePresenter implements RepoPullRequestPagerMvp.Presenter {} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestFragment.java deleted file mode 100644 index b331035c5..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestFragment.java +++ /dev/null @@ -1,201 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.PullRequestAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.extras.popup.IssuePopupFragment; -import com.fastaccess.ui.modules.repos.pull_requests.RepoPullRequestPagerMvp; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.PullRequestPagerActivity; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class RepoPullRequestFragment extends BaseFragment implements RepoPullRequestMvp.View { - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private PullRequestAdapter adapter; - private RepoPullRequestPagerMvp.View pagerCallback; - private RepoPagerMvp.TabsBadgeListener tabsBadgeListener; - - public static RepoPullRequestFragment newInstance(@NonNull String repoId, @NonNull String login, @NonNull IssueState issueState) { - RepoPullRequestFragment view = new RepoPullRequestFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, issueState) - .end()); - return view; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof RepoPullRequestPagerMvp.View) { - pagerCallback = (RepoPullRequestPagerMvp.View) getParentFragment(); - } else if (context instanceof RepoPullRequestPagerMvp.View) { - pagerCallback = (RepoPullRequestPagerMvp.View) context; - } - if (getParentFragment() instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) getParentFragment(); - } else if (context instanceof RepoPagerMvp.TabsBadgeListener) { - tabsBadgeListener = (RepoPagerMvp.TabsBadgeListener) context; - } - } - - @Override public void onDetach() { - tabsBadgeListener = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, therefore, issues can't be proceeded."); - } - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - adapter = new PullRequestAdapter(getPresenter().getPullRequests(), true); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments()); - } else if (getPresenter().getPullRequests().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - stateLayout.setEmptyText(R.string.no_pull_requests); - fastScroller.attachRecyclerView(recycler); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK) { - if (requestCode == RepoPullRequestMvp.PULL_REQUEST_REQUEST_CODE) { - boolean isClose = data.getExtras().getBoolean(BundleConstant.EXTRA); - boolean isOpened = data.getExtras().getBoolean(BundleConstant.EXTRA_TWO); - if (isClose || isOpened) { - onRefresh(); - } - } - } - } - - @NonNull @Override public RepoPullRequestPresenter providePresenter() { - return new RepoPullRequestPresenter(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()) { - @Override public void onScrolled(boolean isUp) { - super.onScrolled(isUp); - if (pagerCallback != null) pagerCallback.onScrolled(isUp); - } - }; - } - onLoadMore.setParameter(getIssueState()); - return onLoadMore; - } - - @Override public void onUpdateCount(int totalCount) { - if (tabsBadgeListener != null) tabsBadgeListener.onSetBadge(getPresenter().getIssueState() == IssueState.open ? 0 : 1, totalCount); - } - - @Override public void onOpenPullRequest(@NonNull PullsIssuesParser parser) { - Intent intent = PullRequestPagerActivity.createIntent(getContext(), parser.getRepoId(), parser.getLogin(), - parser.getNumber(), false, isEnterprise()); - startActivityForResult(intent, RepoPullRequestMvp.PULL_REQUEST_REQUEST_CODE); - } - - @Override public void onShowPullRequestPopup(@NonNull PullRequest item) { - IssuePopupFragment.showPopup(getChildFragmentManager(), item); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getIssueState()); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private IssueState getIssueState() { - return ((IssueState) getArguments().getSerializable(BundleConstant.EXTRA_TWO)); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestMvp.java deleted file mode 100644 index c835e0e58..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestMvp.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface RepoPullRequestMvp { - - int PULL_REQUEST_REQUEST_CODE = 1003; - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onUpdateCount(int totalCount); - - void onOpenPullRequest(@NonNull PullsIssuesParser parser); - - void onShowPullRequestPopup(@NonNull PullRequest item); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - void onFragmentCreated(@NonNull Bundle bundle); - - void onWorkOffline(); - - @NonNull ArrayList getPullRequests(); - - @NonNull IssueState getIssueState(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestPresenter.java deleted file mode 100644 index 42fb9c681..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/RepoPullRequestPresenter.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RepoQueryProvider; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class RepoPullRequestPresenter extends BasePresenter implements RepoPullRequestMvp.Presenter { - - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State IssueState issueState; - private ArrayList pullRequests = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - onWorkOffline(); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable IssueState parameter) { - if (parameter == null) { - sendToView(RepoPullRequestMvp.View::hideProgress); - return false; - } - this.issueState = parameter; - if (page == 1) { - onCallCountApi(issueState); - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(RepoPullRequestMvp.View::hideProgress); - return false; - } - if (repoId == null || login == null) return false; - makeRestCall(RestProvider.getPullRequestService(isEnterprise()).getPullRequests(login, repoId, parameter.name(), page), response -> { - lastPage = response.getLast(); - if (getCurrentPage() == 1) { - manageDisposable(PullRequest.save(response.getItems(), login, repoId)); - } - sendToView(view -> view.onNotifyAdapter(response.getItems(), page)); - }); - return true; - } - - @Override public void onFragmentCreated(@NonNull Bundle bundle) { - repoId = bundle.getString(BundleConstant.ID); - login = bundle.getString(BundleConstant.EXTRA); - issueState = (IssueState) bundle.getSerializable(BundleConstant.EXTRA_TWO); - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - onCallApi(1, issueState); - } - } - - private void onCallCountApi(@NonNull IssueState issueState) { - manageDisposable(RxHelper.getObservable(RestProvider.getPullRequestService(isEnterprise()) - .getPullsWithCount(RepoQueryProvider.getIssuesPullRequestQuery(login, repoId, issueState, true), 0)) - .subscribe(pullRequestPageable -> sendToView(view -> view.onUpdateCount(pullRequestPageable.getTotalCount())), - Throwable::printStackTrace)); - } - - @Override public void onWorkOffline() { - if (pullRequests.isEmpty()) { - manageDisposable(RxHelper.getSingle(PullRequest.getPullRequests(repoId, login, issueState)) - .subscribe(pulls -> sendToView(view -> { - view.onNotifyAdapter(pulls, 1); - view.onUpdateCount(pulls.size()); - }))); - } else { - sendToView(BaseMvp.FAView::hideProgress); - } - } - - @NonNull public ArrayList getPullRequests() { - return pullRequests; - } - - @NonNull @Override public IssueState getIssueState() { - return issueState; - } - - @Override public void onItemClick(int position, View v, PullRequest item) { - PullsIssuesParser parser = PullsIssuesParser.getForPullRequest(item.getHtmlUrl()); - if (parser != null && getView() != null) { - getView().onOpenPullRequest(parser); - } - } - - @Override public void onItemLongClick(int position, View v, PullRequest item) { - if (getView() != null) getView().onShowPullRequestPopup(item); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerActivity.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerActivity.java deleted file mode 100644 index 422498e3c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerActivity.java +++ /dev/null @@ -1,593 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; -import android.support.v4.content.ContextCompat; -import android.support.v4.view.ViewPager; -import android.support.v7.widget.CardView; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.ReviewRequestModel; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.PinnedPullRequests; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AnimHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; -import com.fastaccess.ui.modules.main.premium.PremiumActivity; -import com.fastaccess.ui.modules.repos.RepoPagerActivity; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; -import com.fastaccess.ui.modules.repos.extras.assignees.AssigneesDialogFragment; -import com.fastaccess.ui.modules.repos.extras.labels.LabelsDialogFragment; -import com.fastaccess.ui.modules.repos.extras.locking.LockIssuePrBottomSheetDialog; -import com.fastaccess.ui.modules.repos.extras.milestone.create.MilestoneDialogFragment; -import com.fastaccess.ui.modules.repos.issues.create.CreateIssueActivity; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files.PullRequestFilesFragment; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.timeline.timeline.PullRequestTimelineFragment; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.merge.MergePullRequestDialogFragment; -import com.fastaccess.ui.modules.reviews.changes.ReviewChangesActivity; -import com.fastaccess.ui.widgets.AvatarLayout; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.ViewPagerView; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; - -import java.util.ArrayList; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 10 Dec 2016, 9:23 AM - */ - -public class PullRequestPagerActivity extends BaseActivity - implements PullRequestPagerMvp.View { - - @BindView(R.id.startGist) ForegroundImageView startGist; - @BindView(R.id.forkGist) ForegroundImageView forkGist; - @BindView(R.id.avatarLayout) AvatarLayout avatarLayout; - @BindView(R.id.headerTitle) FontTextView title; - @BindView(R.id.size) FontTextView size; - @BindView(R.id.date) FontTextView date; - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.pager) ViewPagerView pager; - @BindView(R.id.fab) FloatingActionButton fab; - @BindView(R.id.detailsIcon) View detailsIcon; - @BindView(R.id.reviewsCount) FontTextView reviewsCount; - @BindView(R.id.prReviewHolder) CardView prReviewHolder; - @State boolean isClosed; - @State boolean isOpened; - private CommentEditorFragment commentEditorFragment; - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, @NonNull String login, int number) { - return createIntent(context, repoId, login, number, false); - } - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, @NonNull String login, int number, boolean showRepoBtn) { - return createIntent(context, repoId, login, number, showRepoBtn, false); - } - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, @NonNull String login, - int number, boolean showRepoBtn, boolean isEnterprise) { - return createIntent(context, repoId, login, number, showRepoBtn, isEnterprise, 0); - } - - public static Intent createIntent(@NonNull Context context, @NonNull String repoId, @NonNull String login, - int number, boolean showRepoBtn, boolean isEnterprise, long commentId) { - Intent intent = new Intent(context, PullRequestPagerActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.ID, number) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, repoId) - .put(BundleConstant.EXTRA_THREE, showRepoBtn) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .put(BundleConstant.EXTRA_SIX, commentId) - .end()); - return intent; - } - - @OnClick(R.id.detailsIcon) void onTitleClick() { - if (getPresenter().getPullRequest() != null && !InputHelper.isEmpty(getPresenter().getPullRequest().getTitle())) - MessageDialogView.newInstance(String.format("%s/%s", getPresenter().getLogin(), getPresenter().getRepoId()), - getPresenter().getPullRequest().getTitle(), false, true) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - } - - @OnClick(R.id.submitReviews) void onSubmitReviews(View view) { - addPrReview(view); - } - - @OnClick(R.id.cancelReview) void onCancelReviews(View view) { - MessageDialogView.newInstance(getString(R.string.cancel_reviews), getString(R.string.confirm_message), - false, Bundler.start() - .put(BundleConstant.YES_NO_EXTRA, true) - .put(BundleConstant.EXTRA_TYPE, true) - .end()) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - } - - @Override protected int layout() { - return R.layout.issue_pager_activity; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public PullRequestPagerPresenter providePresenter() { - return new PullRequestPagerPresenter(); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - commentEditorFragment = (CommentEditorFragment) getSupportFragmentManager().findFragmentById(R.id.commentFragment); - if (savedInstanceState == null) { - getPresenter().onActivityCreated(getIntent()); - } else { - if (getPresenter().getPullRequest() != null) onSetupIssue(false); - } - fab.hide(); - startGist.setVisibility(View.GONE); - forkGist.setVisibility(View.GONE); - if (getPresenter().showToRepoBtn()) showNavToRepoItem(); - } - - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_OK) { - if (requestCode == BundleConstant.REQUEST_CODE) { - if (data == null) return; - Bundle bundle = data.getExtras(); - PullRequest pullRequest = bundle.getParcelable(BundleConstant.ITEM); - if (pullRequest != null) { - getPresenter().onUpdatePullRequest(pullRequest); - } else { - getPresenter().onRefresh(); - } - } - } - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.pull_request_menu, menu); - menu.findItem(R.id.merge).setVisible(false); - return super.onCreateOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - onNavToRepoClicked(); - return true; - } - PullRequest pullRequest = getPresenter().getPullRequest(); - if (pullRequest == null) return false; - if (item.getItemId() == R.id.share) { - ActivityHelper.shareUrl(this, pullRequest.getHtmlUrl()); - return true; - } else if (item.getItemId() == R.id.closeIssue) { - MessageDialogView.newInstance( - pullRequest.getState() == IssueState.open ? getString(R.string.close_issue) : getString(R.string.re_open_issue), - getString(R.string.confirm_message), Bundler.start().put(BundleConstant.EXTRA, true).end()) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - return true; - } else if (item.getItemId() == R.id.lockIssue) { - if (!getPresenter().isLocked()) { - LockIssuePrBottomSheetDialog.Companion - .newInstance() - .show(getSupportFragmentManager(), MessageDialogView.TAG); - } else { - MessageDialogView.newInstance(getString(R.string.unlock_issue), getString(R.string.unlock_issue_details), - Bundler.start().put(BundleConstant.EXTRA_TWO, true) - .put(BundleConstant.YES_NO_EXTRA, true) - .end()) - .show(getSupportFragmentManager(), MessageDialogView.TAG); - } - return true; - } else if (item.getItemId() == R.id.labels) { - LabelsDialogFragment.newInstance(getPresenter().getPullRequest() != null ? getPresenter().getPullRequest().getLabels() : null, - getPresenter().getRepoId(), getPresenter().getLogin()) - .show(getSupportFragmentManager(), "LabelsDialogFragment"); - return true; - } else if (item.getItemId() == R.id.edit) { - CreateIssueActivity.startForResult(this, getPresenter().getLogin(), getPresenter().getRepoId(), pullRequest, isEnterprise()); - return true; - } else if (item.getItemId() == R.id.milestone) { - MilestoneDialogFragment.newInstance(getPresenter().getLogin(), getPresenter().getRepoId()) - .show(getSupportFragmentManager(), "MilestoneDialogFragment"); - return true; - } else if (item.getItemId() == R.id.assignees) { - AssigneesDialogFragment.newInstance(getPresenter().getLogin(), getPresenter().getRepoId(), true) - .show(getSupportFragmentManager(), "AssigneesDialogFragment"); - return true; - } else if (item.getItemId() == R.id.reviewers) { - AssigneesDialogFragment.newInstance(getPresenter().getLogin(), getPresenter().getRepoId(), false) - .show(getSupportFragmentManager(), "AssigneesDialogFragment"); - return true; - } else if (item.getItemId() == R.id.merge) { - if (getPresenter().getPullRequest() != null) { - String msg = getPresenter().getPullRequest().getTitle(); - MergePullRequestDialogFragment.newInstance(msg).show(getSupportFragmentManager(), "MergePullRequestDialogFragment"); - } - } else if (item.getItemId() == R.id.browser) { - ActivityHelper.startCustomTab(this, pullRequest.getHtmlUrl()); - return true; - } else if (item.getItemId() == R.id.reviewChanges) { - if (PrefGetter.isProEnabled()) { - addPrReview(item.getActionView() == null ? title : item.getActionView()); - } else { - PremiumActivity.Companion.startActivity(this); - } - return true; - } else if (item.getItemId() == R.id.subscribe) { - getPresenter().onSubscribeOrMute(false); - return true; - } else if (item.getItemId() == R.id.mute) { - getPresenter().onSubscribeOrMute(true); - return true; - } else if (item.getItemId() == R.id.pinUnpin) { - if (PrefGetter.isProEnabled()) { - getPresenter().onPinUnpinPullRequest(); - } else { - PremiumActivity.Companion.startActivity(this); - } - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override public boolean onPrepareOptionsMenu(Menu menu) { - MenuItem closeIssue = menu.findItem(R.id.closeIssue); - MenuItem lockIssue = menu.findItem(R.id.lockIssue); - MenuItem milestone = menu.findItem(R.id.milestone); - MenuItem labels = menu.findItem(R.id.labels); - MenuItem assignees = menu.findItem(R.id.assignees); - MenuItem edit = menu.findItem(R.id.edit); - MenuItem editMenu = menu.findItem(R.id.editMenu); - MenuItem merge = menu.findItem(R.id.merge); - MenuItem reviewers = menu.findItem(R.id.reviewers); - MenuItem pinUnpin = menu.findItem(R.id.pinUnpin); - boolean isOwner = getPresenter().isOwner(); - boolean isLocked = getPresenter().isLocked(); - boolean isCollaborator = getPresenter().isCollaborator(); - boolean isRepoOwner = getPresenter().isRepoOwner(); - boolean isMergable = getPresenter().isMergeable(); - merge.setVisible(isMergable && (isRepoOwner || isCollaborator)); - reviewers.setVisible((isRepoOwner || isCollaborator)); - editMenu.setVisible(isOwner || isCollaborator || isRepoOwner); - milestone.setVisible(isCollaborator || isRepoOwner); - labels.setVisible(isCollaborator || isRepoOwner); - assignees.setVisible(isCollaborator || isRepoOwner); - edit.setVisible(isCollaborator || isRepoOwner || isOwner); - if (getPresenter().getPullRequest() != null) { - boolean isPinned = PinnedPullRequests.isPinned(getPresenter().getPullRequest().getId()); - pinUnpin.setIcon(isPinned ? ContextCompat.getDrawable(this, R.drawable.ic_pin_filled) - : ContextCompat.getDrawable(this, R.drawable.ic_pin)); - closeIssue.setVisible(isRepoOwner || (isOwner || isCollaborator) && getPresenter().getPullRequest().getState() == IssueState.open); - lockIssue.setVisible(isRepoOwner || isCollaborator && getPresenter().getPullRequest().getState() == IssueState.open); - closeIssue.setTitle(getPresenter().getPullRequest().getState() == IssueState.closed ? getString(R.string.re_open) : getString(R.string - .close)); - lockIssue.setTitle(isLocked ? getString(R.string.unlock_issue) : getString(R.string.lock_issue)); - } else { - closeIssue.setVisible(false); - lockIssue.setVisible(false); - } - return super.onPrepareOptionsMenu(menu); - } - - @Override public void onSetupIssue(boolean update) { - hideProgress(); - if (getPresenter().getPullRequest() == null) { - return; - } - invalidateOptionsMenu(); - PullRequest pullRequest = getPresenter().getPullRequest(); - setTaskName(pullRequest.getRepoId() + " - " + pullRequest.getTitle()); - updateViews(pullRequest); - if (update) { - PullRequestTimelineFragment issueDetailsView = getPullRequestTimelineFragment(); - if (issueDetailsView != null && getPresenter().getPullRequest() != null) { - issueDetailsView.onUpdateHeader(); - } - } else { - if (pager.getAdapter() == null) { - pager.setAdapter(new FragmentsPagerAdapter(getSupportFragmentManager(), FragmentPagerAdapterModel.buildForPullRequest(this, - pullRequest))); - tabs.setupWithViewPager(pager); - tabs.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager) { - @Override public void onTabReselected(TabLayout.Tab tab) { - super.onTabReselected(tab); - onScrollTop(tab.getPosition()); - } - }); - } else { - onUpdateTimeline(); - } - } - pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { - @Override public void onPageSelected(int position) { - hideShowFab(); - super.onPageSelected(position); - - } - }); - initTabs(pullRequest); - hideShowFab(); - AnimHelper.mimicFabVisibility(getPresenter().hasReviewComments(), prReviewHolder, null); - reviewsCount.setText(String.format("%s", getPresenter().getCommitComment().size())); - } - - @Override public void onScrollTop(int index) { - if (pager == null || pager.getAdapter() == null) return; - Fragment fragment = (BaseFragment) pager.getAdapter().instantiateItem(pager, index); - if (fragment instanceof BaseFragment) { - ((BaseFragment) fragment).onScrollTop(index); - } - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk) { - if (bundle != null) { - if (bundle.getBoolean(BundleConstant.EXTRA_TYPE)) { - hideAndClearReviews(); - return; - } - } - getPresenter().onHandleConfirmDialog(bundle); - } - } - - @Override public void onSelectedLabels(@NonNull ArrayList labels) { - getPresenter().onPutLabels(labels); - } - - @Override public void showSuccessIssueActionMsg(boolean isClose) { - hideProgress(); - if (isClose) { - isOpened = false; - isClosed = true; - showMessage(getString(R.string.success), getString(R.string.success_closed)); - } else { - isOpened = true; - isClosed = false; - showMessage(getString(R.string.success), getString(R.string.success_re_opened)); - } - } - - @Override public void showErrorIssueActionMsg(boolean isClose) { - hideProgress(); - if (isClose) { - showMessage(getString(R.string.error), getString(R.string.error_closing_issue)); - } else { - showMessage(getString(R.string.error), getString(R.string.error_re_opening_issue)); - } - } - - @Override public void onUpdateTimeline() { - supportInvalidateOptionsMenu(); - PullRequestTimelineFragment pullRequestDetailsView = getPullRequestTimelineFragment(); - if (pullRequestDetailsView != null && getPresenter().getPullRequest() != null) { - pullRequestDetailsView.onRefresh(); - } - } - - @Override public void onMileStoneSelected(@NonNull MilestoneModel milestoneModel) { - getPresenter().onPutMilestones(milestoneModel); - } - - @Override public void onFinishActivity() { - hideProgress(); - finish(); - } - - @Override public void onUpdateMenu() { - invalidateOptionsMenu(); - } - - @Override public void onAddComment(CommentRequestModel comment) { - getPresenter().onAddComment(comment); - AnimHelper.mimicFabVisibility(getPresenter().hasReviewComments(), prReviewHolder, null); - reviewsCount.setText(String.format("%s", getPresenter().getCommitComment().size())); - Logger.e(reviewsCount.getText(), prReviewHolder.getVisibility()); - } - - @Override public void onMerge(@NonNull String msg, @NonNull String mergeMethod) { - getPresenter().onMerge(msg, mergeMethod); - } - - @Override public void onNavToRepoClicked() { - Intent intent = ActivityHelper.editBundle(RepoPagerActivity.createIntent(this, getPresenter().getRepoId(), - getPresenter().getLogin(), RepoPagerMvp.PULL_REQUEST), isEnterprise()); - startActivity(intent); - finish(); - } - - @Override public void finish() { - Intent intent = new Intent(); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, isClosed) - .put(BundleConstant.EXTRA_TWO, isOpened) - .end()); - setResult(RESULT_OK, intent); - super.finish(); - } - - @Override public void onSelectedAssignees(@NonNull ArrayList users, boolean isAssignees) { - hideProgress(); - getPresenter().onPutAssignees(users, isAssignees); - } - - @Nullable @Override public PullRequest getData() { - return getPresenter().getPullRequest(); - } - - @Override public void onSendActionClicked(@NonNull String text, Bundle bundle) { - PullRequestTimelineFragment fragment = getPullRequestTimelineFragment(); - if (fragment != null) { - fragment.onHandleComment(text, bundle); - } - } - - private PullRequestTimelineFragment getPullRequestTimelineFragment() { - if (pager == null || pager.getAdapter() == null) return null; - return (PullRequestTimelineFragment) pager.getAdapter().instantiateItem(pager, 0); - } - - @Override public void onTagUser(@NonNull String username) { - commentEditorFragment.onAddUserName(username); - } - - @Override public void onCreateComment(@NonNull String text, @Nullable Bundle bundle) { - commentEditorFragment.onCreateComment(text, bundle); - } - - @Override public void onSuccessfullyReviewed() { - hideAndClearReviews(); - pager.setCurrentItem(0); - } - - @SuppressWarnings("ConstantConditions") @Override public void onClearEditText() { - if (commentEditorFragment != null && commentEditorFragment.commentText != null) commentEditorFragment.commentText.setText(""); - } - - @Override public ArrayList getNamesToTag() { - PullRequestTimelineFragment fragment = getPullRequestTimelineFragment(); - if (fragment != null) { - return fragment.getNamesToTag(); - } - return new ArrayList<>(); - } - - @Override public void onLock(String reason) { - getPresenter().onLockUnlockConversations(reason); - } - - protected void hideAndClearReviews() { - getPresenter().getCommitComment().clear(); - AnimHelper.mimicFabVisibility(false, prReviewHolder, null); - if (pager == null || pager.getAdapter() == null) return; - PullRequestFilesFragment fragment = (PullRequestFilesFragment) pager.getAdapter().instantiateItem(pager, 2); - if (fragment != null) { - fragment.onRefresh(); - } - - } - - private void addPrReview(@NonNull View view) { - PullRequest pullRequest = getPresenter().getPullRequest(); - if (pullRequest == null) return; - User author = pullRequest.getUser() != null ? pullRequest.getUser() : - pullRequest.getHead() != null && pullRequest.getHead().getAuthor() != null ? - pullRequest.getHead().getAuthor() : pullRequest.getUser(); - if (author == null) return; - ReviewRequestModel requestModel = new ReviewRequestModel(); - requestModel.setComments(getPresenter().getCommitComment().isEmpty() ? null : getPresenter().getCommitComment()); - requestModel.setCommitId(pullRequest.getHead().getSha()); - boolean isAuthor = Login.getUser().getLogin().equalsIgnoreCase(author.getLogin()); - ReviewChangesActivity.Companion.startForResult(requestModel, getPresenter().getRepoId(), - getPresenter().getLogin(), pullRequest.getNumber(), isAuthor, isEnterprise(), pullRequest.isMerged() - || pullRequest.getState() == IssueState.closed) - .show(getSupportFragmentManager(), ReviewChangesActivity.class.getSimpleName()); - } - - private void initTabs(@NonNull PullRequest pullRequest) { - TabLayout.Tab tab1 = tabs.getTabAt(0); - TabLayout.Tab tab2 = tabs.getTabAt(1); - TabLayout.Tab tab3 = tabs.getTabAt(2); - if (tab3 != null) { - tab3.setText(SpannableBuilder.builder() - .append(getString(R.string.files)) - .append(" ") - .append("(") - .append(String.valueOf(pullRequest.getChangedFiles())) - .append(")")); - } - if (tab2 != null) { - tab2.setText(SpannableBuilder.builder() - .append(getString(R.string.commits)) - .append(" ") - .append("(") - .append(String.valueOf(pullRequest.getCommits())) - .append(")")); - } - if (tab1 != null) { - tab1.setText(SpannableBuilder.builder() - .append(getString(R.string.details)) - .append(" ") - .append("(") - .append(String.valueOf(pullRequest.getComments())) - .append(")")); - } - } - - private void updateViews(@NonNull PullRequest pullRequest) { - setTitle(String.format("#%s", pullRequest.getNumber())); - if (getSupportActionBar() != null) { - getSupportActionBar().setSubtitle(pullRequest.getRepoId()); - } - date.setText(SpannableBuilder.builder().append(getPresenter().getMergeBy(pullRequest, getApplicationContext()))); - size.setVisibility(View.GONE); - User userModel = pullRequest.getUser(); - if (userModel != null) { - title.setText(SpannableBuilder.builder().append(userModel.getLogin()).append("/").append(pullRequest.getTitle())); - avatarLayout.setUrl(userModel.getAvatarUrl(), userModel.getLogin(), false, - LinkParserHelper.isEnterprise(pullRequest.getUrl())); - } else { - title.setText(SpannableBuilder.builder().append(pullRequest.getTitle())); - } - detailsIcon.setVisibility(View.VISIBLE); - } - - private void hideShowFab() { - if (getPresenter().isLocked() && !getPresenter().isOwner()) { - getSupportFragmentManager().beginTransaction() - .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) - .hide(commentEditorFragment).commit(); - return; - } - if (pager.getCurrentItem() == 0) { - getSupportFragmentManager().beginTransaction().show(commentEditorFragment) - .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) - .commit(); - } else { - getSupportFragmentManager().beginTransaction().hide(commentEditorFragment) - .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) - .commit(); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerMvp.java deleted file mode 100644 index 5e8acfc44..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerMvp.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; -import com.fastaccess.ui.modules.repos.extras.assignees.AssigneesMvp; -import com.fastaccess.ui.modules.repos.extras.labels.LabelsMvp; -import com.fastaccess.ui.modules.repos.extras.locking.LockIssuePrCallback; -import com.fastaccess.ui.modules.repos.issues.issue.details.IssuePagerMvp; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files.PullRequestFilesMvp; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.merge.MergePullReqeustMvp; -import com.fastaccess.ui.modules.reviews.changes.ReviewChangesMvp; -import com.fastaccess.ui.widgets.SpannableBuilder; - -import java.util.ArrayList; - -/** - * Created by Kosh on 10 Dec 2016, 9:21 AM - */ - -public interface PullRequestPagerMvp { - - interface View extends BaseMvp.FAView, LabelsMvp.SelectedLabelsListener, - AssigneesMvp.SelectedAssigneesListener, MergePullReqeustMvp.MergeCallback, - IssuePagerMvp.IssuePrCallback, PullRequestFilesMvp.PatchCallback, - CommentEditorFragment.CommentListener, ReviewChangesMvp.ReviewSubmissionCallback, - LockIssuePrCallback { - - void onSetupIssue(boolean update); - - void showSuccessIssueActionMsg(boolean isClose); - - void showErrorIssueActionMsg(boolean isClose); - - void onUpdateTimeline(); - - void onMileStoneSelected(@NonNull MilestoneModel milestoneModel); - - void onFinishActivity(); - - void onUpdateMenu(); - } - - interface Presenter extends BaseMvp.FAPresenter, PullRequestFilesMvp.CommitCommentCallback { - - @Nullable PullRequest getPullRequest(); - - void onActivityCreated(@Nullable Intent intent); - - void onWorkOffline(); - - boolean isOwner(); - - boolean isRepoOwner(); - - boolean isLocked(); - - boolean isMergeable(); - - boolean showToRepoBtn(); - - void onHandleConfirmDialog(@Nullable Bundle bundle); - - void onOpenCloseIssue(); - - void onLockUnlockConversations(String reason); - - @NonNull SpannableBuilder getMergeBy(@NonNull PullRequest pullRequest, @NonNull Context context); - - void onMerge(String s, String msg); - - void onPutLabels(@NonNull ArrayList labels); - - void onPutMilestones(@NonNull MilestoneModel milestone); - - void onPutAssignees(@NonNull ArrayList users, boolean isAssignee); - - String getLogin(); - - String getRepoId(); - - boolean isCollaborator(); - - void onUpdatePullRequest(@NonNull PullRequest pullRequestModel); - - void onRefresh(); - - void onPinUnpinPullRequest(); - - void onSubscribeOrMute(boolean mute); - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerPresenter.java deleted file mode 100644 index d53b8801a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/PullRequestPagerPresenter.java +++ /dev/null @@ -1,346 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.text.TextUtils; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.fastaccess.R; -import com.fastaccess.data.dao.AssigneesRequestModel; -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.IssueRequestModel; -import com.fastaccess.data.dao.LabelListModel; -import com.fastaccess.data.dao.LabelModel; -import com.fastaccess.data.dao.LockIssuePrModel; -import com.fastaccess.data.dao.MergeRequestModel; -import com.fastaccess.data.dao.MilestoneModel; -import com.fastaccess.data.dao.NotificationSubscriptionBodyModel; -import com.fastaccess.data.dao.PullsIssuesParser; -import com.fastaccess.data.dao.UsersListModel; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.PinnedPullRequests; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.IssueState; -import com.fastaccess.data.service.IssueService; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.widgets.SpannableBuilder; - -import java.util.ArrayList; - -import io.reactivex.Observable; -import retrofit2.Response; - -/** - * Created by Kosh on 10 Dec 2016, 9:23 AM - */ - -class PullRequestPagerPresenter extends BasePresenter implements PullRequestPagerMvp.Presenter { - @com.evernote.android.state.State PullRequest pullRequest; - @com.evernote.android.state.State int issueNumber; - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State boolean isCollaborator; - @com.evernote.android.state.State boolean showToRepoBtn; - @com.evernote.android.state.State ArrayList reviewComments = new ArrayList<>(); - - @Nullable @Override public PullRequest getPullRequest() { - return pullRequest; - } - - @Override public void onError(@NonNull Throwable throwable) { - if (RestProvider.getErrorCode(throwable) == 404) { - sendToView(BaseMvp.FAView::onOpenUrlInBrowser); - } else { - onWorkOffline(); - } - super.onError(throwable); - } - - @Override public void onActivityCreated(@Nullable Intent intent) { - if (intent != null && intent.getExtras() != null) { - issueNumber = intent.getExtras().getInt(BundleConstant.ID); - login = intent.getExtras().getString(BundleConstant.EXTRA); - repoId = intent.getExtras().getString(BundleConstant.EXTRA_TWO); - showToRepoBtn = intent.getExtras().getBoolean(BundleConstant.EXTRA_THREE); - if (pullRequest != null) { - sendToView(view -> view.onSetupIssue(false)); - return; - } else if (issueNumber > 0 && !InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - callApi(); - return; - } - } - sendToView(view -> view.onSetupIssue(false)); - } - - @Override public void onWorkOffline() { - if (pullRequest == null) { - manageDisposable(PullRequest.getPullRequestByNumber(issueNumber, repoId, login) - .subscribe(pullRequestModel -> { - if (pullRequestModel != null) { - pullRequest = pullRequestModel; - sendToView(view -> view.onSetupIssue(false)); - } - })); - } - } - - @Override public boolean isOwner() { - if (getPullRequest() == null) return false; - User userModel = getPullRequest() != null ? getPullRequest().getUser() : null; - Login me = Login.getUser(); - PullsIssuesParser parser = PullsIssuesParser.getForIssue(getPullRequest().getHtmlUrl()); - return (userModel != null && userModel.getLogin().equalsIgnoreCase(me.getLogin())) - || (parser != null && parser.getLogin().equalsIgnoreCase(me.getLogin())); - } - - @Override public boolean isRepoOwner() { - if (getPullRequest() == null) return false; - Login me = Login.getUser(); - return TextUtils.equals(login, me.getLogin()); - } - - @Override public boolean isLocked() { - return getPullRequest() != null && getPullRequest().isLocked(); - } - - @Override public boolean isMergeable() { - return getPullRequest() != null && getPullRequest().isMergeable() && !getPullRequest().isMerged(); - } - - @Override public boolean showToRepoBtn() { - return showToRepoBtn; - } - - @Override public void onHandleConfirmDialog(@Nullable Bundle bundle) { - if (bundle != null) { - boolean proceedCloseIssue = bundle.getBoolean(BundleConstant.EXTRA); - boolean proceedLockUnlock = bundle.getBoolean(BundleConstant.EXTRA_TWO); - if (proceedCloseIssue) { - onOpenCloseIssue(); - } else if (proceedLockUnlock) { - onLockUnlockConversations(null); - } - } - } - - @Override public void onLockUnlockConversations(String reason) { - PullRequest currentPullRequest = getPullRequest(); - if (currentPullRequest == null) return; - IssueService service = RestProvider.getIssueService(isEnterprise()); - LockIssuePrModel model = null; - if (!isLocked() && !InputHelper.isEmpty(reason)) { - model = new LockIssuePrModel(true, reason); - } - Observable> observable = RxHelper - .getObservable(model == null ? service.unlockIssue(login, repoId, issueNumber) : - service.lockIssue(model, login, repoId, issueNumber)); - makeRestCall(observable, booleanResponse -> { - int code = booleanResponse.code(); - if (code == 204) { - pullRequest.setLocked(!isLocked()); - sendToView(view -> view.onSetupIssue(false)); - } - }); - } - - @Override public void onOpenCloseIssue() { - if (getPullRequest() != null) { - IssueRequestModel requestModel = IssueRequestModel.clone(getPullRequest(), true); - manageDisposable(RxHelper.getObservable(RestProvider.getPullRequestService(isEnterprise()).editPullRequest(login, repoId, - issueNumber, requestModel)) - .doOnSubscribe(disposable -> sendToView(view -> view.showProgress(0))) - .subscribe(issue -> { - if (issue != null) { - sendToView(view -> view.showSuccessIssueActionMsg(getPullRequest().getState() == IssueState.open)); - issue.setRepoId(getPullRequest().getRepoId()); - issue.setLogin(getPullRequest().getLogin()); - pullRequest = issue; - sendToView(view -> view.onSetupIssue(false)); - } - }, throwable -> sendToView(view -> view.showErrorIssueActionMsg(getPullRequest().getState() == IssueState.open)))); - } - } - - @NonNull @Override public SpannableBuilder getMergeBy(@NonNull PullRequest pullRequest, @NonNull Context context) { - return PullRequest.getMergeBy(pullRequest, context, false); - } - - @Override public void onPutLabels(@NonNull ArrayList labels) { - makeRestCall(RestProvider.getIssueService(isEnterprise()).putLabels(login, repoId, issueNumber, - Stream.of(labels).filter(value -> value != null && value.getName() != null) - .map(LabelModel::getName).collect(Collectors.toList())), - labelModels -> { - sendToView(view -> updateTimeline(view, R.string.labels_added_successfully)); - LabelListModel listModel = new LabelListModel(); - listModel.addAll(labels); - pullRequest.setLabels(listModel); - manageObservable(pullRequest.save(pullRequest).toObservable()); - }); - } - - @Override public void onPutMilestones(@NonNull MilestoneModel milestone) { - pullRequest.setMilestone(milestone); - IssueRequestModel issueRequestModel = IssueRequestModel.clone(pullRequest, false); - makeRestCall(RestProvider.getPullRequestService(isEnterprise()).editIssue(login, repoId, issueNumber, issueRequestModel), - pr -> { - this.pullRequest.setMilestone(pr.getMilestone()); - manageObservable(pr.save(pullRequest).toObservable()); - sendToView(view -> updateTimeline(view, R.string.labels_added_successfully)); - }); - - } - - @Override public void onPutAssignees(@NonNull ArrayList users, boolean isAssignees) { - AssigneesRequestModel assigneesRequestModel = new AssigneesRequestModel(); - ArrayList assignees = Stream.of(users) - .map(User::getLogin) - .collect(Collectors.toCollection(ArrayList::new)); - if (isAssignees) { - assigneesRequestModel.setAssignees(assignees.isEmpty() ? Stream.of(pullRequest.getAssignees()).map(User::getLogin).toList() : assignees); - makeRestCall(!assignees.isEmpty() ? - RestProvider.getIssueService(isEnterprise()).putAssignees(login, repoId, issueNumber, assigneesRequestModel) : - RestProvider.getIssueService(isEnterprise()).deleteAssignees(login, repoId, issueNumber, assigneesRequestModel), - pullRequestResponse -> { - UsersListModel usersListModel = new UsersListModel(); - usersListModel.addAll(users); - this.pullRequest.setAssignees(usersListModel); - manageObservable(pullRequest.save(pullRequest).toObservable()); - sendToView(view -> updateTimeline(view, R.string.assignee_added)); - } - ); - } else { - assigneesRequestModel.setReviewers(assignees); - makeRestCall(RestProvider.getPullRequestService(isEnterprise()).putReviewers(login, repoId, issueNumber, assigneesRequestModel), - pullRequestResponse -> sendToView(view -> updateTimeline(view, R.string.reviewer_added)) - ); - } - } - - @Override public void onMerge(@NonNull String msg, @NonNull String mergeMethod) { - if (isMergeable() && (isCollaborator() || isRepoOwner())) {//double the checking - if (getPullRequest() == null || getPullRequest().getHead() == null || getPullRequest().getHead().getSha() == null) return; - MergeRequestModel mergeRequestModel = new MergeRequestModel(); - mergeRequestModel.setSha(getPullRequest().getHead().getSha()); - mergeRequestModel.setCommitMessage(msg); - mergeRequestModel.setMergeMethod(mergeMethod.toLowerCase()); - manageDisposable(RxHelper.getObservable(RestProvider.getPullRequestService(isEnterprise()) - .mergePullRequest(login, repoId, issueNumber, mergeRequestModel)) - .doOnSubscribe(disposable -> sendToView(view -> view.showProgress(0))) - .subscribe(mergeResponseModel -> { - if (mergeResponseModel.isMerged()) { - pullRequest.setMerged(true); - sendToView(view -> updateTimeline(view, R.string.success_merge)); - } else { - sendToView(view -> view.showErrorMessage(mergeResponseModel.getMessage())); - } - }, throwable -> sendToView(view -> view.showErrorMessage(throwable.getMessage()))) - ); - } - } - - @Override public String getLogin() { - return login; - } - - @Override public String getRepoId() { - return repoId; - } - - @Override public boolean isCollaborator() { - return isCollaborator; - } - - @Override public void onUpdatePullRequest(@NonNull PullRequest pullRequestModel) { - this.pullRequest.setTitle(pullRequestModel.getTitle()); - this.pullRequest.setBody(pullRequestModel.getBody()); - this.pullRequest.setBodyHtml(pullRequestModel.getBodyHtml()); - this.pullRequest.setLogin(login); - this.pullRequest.setRepoId(repoId); - manageObservable(pullRequest.save(pullRequest).toObservable()); - sendToView(view -> view.onSetupIssue(true)); - } - - @Override public void onRefresh() { - callApi(); - } - - @Override public void onPinUnpinPullRequest() { - if (getPullRequest() == null) return; - PinnedPullRequests.pinUpin(getPullRequest()); - sendToView(PullRequestPagerMvp.View::onUpdateMenu); - } - - @NonNull @Override public ArrayList getCommitComment() { - return reviewComments; - } - - @Override public void onAddComment(@NonNull CommentRequestModel comment) { - int index = reviewComments.indexOf(comment); - if (index != -1) { - reviewComments.set(index, comment); - } else { - reviewComments.add(comment); - } - } - - @Override public boolean hasReviewComments() { - return reviewComments.size() > 0; - } - - @Override public void onSubscribeOrMute(boolean mute) { - if (getPullRequest() == null) return; - makeRestCall(mute ? RestProvider.getNotificationService(isEnterprise()).subscribe(getPullRequest().getId(), - new NotificationSubscriptionBodyModel(false, true)) - : RestProvider.getNotificationService(isEnterprise()).subscribe(getPullRequest().getId(), - new NotificationSubscriptionBodyModel(true, false)), - booleanResponse -> { - if (booleanResponse.code() == 204 || booleanResponse.code() == 200) { - sendToView(view -> view.showMessage(R.string.success, R.string.successfully_submitted)); - } else { - sendToView(view -> view.showMessage(R.string.error, R.string.network_error)); - } - }); - } - - private void callApi() { - Login loggedInUser = Login.getUser(); - if (loggedInUser == null) return; - makeRestCall(RxHelper.getObservable(Observable.zip(RestProvider.getPullRequestService(isEnterprise()) - .getPullRequest(login, repoId, issueNumber), - RestProvider.getRepoService(isEnterprise()).isCollaborator(login, repoId, loggedInUser.getLogin()), - RestProvider.getIssueService(isEnterprise()).getIssue(login, repoId, issueNumber), - (pullRequestModel, booleanResponse, issue) -> { - this.pullRequest = pullRequestModel; - if (issue != null) { - this.pullRequest.setReactions(issue.getReactions()); - this.pullRequest.setTitle(issue.getTitle()); - this.pullRequest.setBody(issue.getBody()); - this.pullRequest.setBodyHtml(issue.getBodyHtml()); - } - this.pullRequest.setLogin(login); - this.pullRequest.setRepoId(repoId); - isCollaborator = booleanResponse.code() == 204; - return pullRequest; - })), pullRequest -> { - sendToView(view -> view.onSetupIssue(false)); - manageDisposable(PinnedPullRequests.updateEntry(pullRequest.getId())); - manageObservable(pullRequest.save(pullRequest).toObservable()); - }); - } - - private void updateTimeline(PullRequestPagerMvp.View view, int assignee_added) { - view.showMessage(R.string.success, assignee_added); - view.onUpdateTimeline(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsFragment.java deleted file mode 100644 index a8dd48f72..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsFragment.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.commits; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.CommitsAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class PullRequestCommitsFragment extends BaseFragment - implements PullRequestCommitsMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private CommitsAdapter adapter; - - public static PullRequestCommitsFragment newInstance(@NonNull String repoId, @NonNull String login, long number) { - PullRequestCommitsFragment view = new PullRequestCommitsFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, number) - .end()); - return view; - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, therefore, PullRequestCommitsFragment can't be proceeded."); - } - stateLayout.setEmptyText(R.string.no_commits); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - adapter = new CommitsAdapter(getPresenter().getCommits()); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments()); - } else if (getPresenter().getCommits().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public PullRequestCommitsPresenter providePresenter() { - return new PullRequestCommitsPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @SuppressWarnings("unchecked") @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()); - } - return onLoadMore; - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, null); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsMvp.java deleted file mode 100644 index 6c9316b91..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsMvp.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.commits; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface PullRequestCommitsMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - void onFragmentCreated(@NonNull Bundle bundle); - - @NonNull ArrayList getCommits(); - - void onWorkOffline(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsPresenter.java deleted file mode 100644 index 28e96c4bc..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/commits/PullRequestCommitsPresenter.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.commits; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.data.dao.model.Commit; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.repos.code.commit.details.CommitPagerActivity; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class PullRequestCommitsPresenter extends BasePresenter implements PullRequestCommitsMvp.Presenter { - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State long number; - private ArrayList commits = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - onWorkOffline(); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable Object parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(PullRequestCommitsMvp.View::hideProgress); - return false; - } - if (repoId == null || login == null) return false; - makeRestCall(RestProvider.getPullRequestService(isEnterprise()).getPullRequestCommits(login, repoId, number, page), - response -> { - lastPage = response.getLast(); - if (getCurrentPage() == 1) { - manageDisposable(Commit.save(response.getItems(), repoId, login, number)); - } - sendToView(view -> view.onNotifyAdapter(response.getItems(), page)); - }); - return true; - } - - @Override public void onFragmentCreated(@NonNull Bundle bundle) { - repoId = bundle.getString(BundleConstant.ID); - login = bundle.getString(BundleConstant.EXTRA); - number = bundle.getLong(BundleConstant.EXTRA_TWO); - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - onCallApi(1, null); - } - } - - @NonNull @Override public ArrayList getCommits() { - return commits; - } - - @Override public void onWorkOffline() { - if (commits.isEmpty()) { - manageDisposable(RxHelper.getSingle(Commit.getCommits(repoId, login, number)) - .subscribe(models -> sendToView(view -> view.onNotifyAdapter(models, 1)))); - } else { - sendToView(BaseMvp.FAView::hideProgress); - } - } - - @Override public void onItemClick(int position, View v, Commit item) { - CommitPagerActivity.createIntentForOffline(v.getContext(), item); - } - - @Override public void onItemLongClick(int position, View v, Commit item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesFragment.java deleted file mode 100644 index 178e505c2..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesFragment.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.CommitFileChanges; -import com.fastaccess.data.dao.CommitFileModel; -import com.fastaccess.data.dao.CommitLinesModel; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.adapter.CommitFilesAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.main.premium.PremiumActivity; -import com.fastaccess.ui.modules.repos.issues.issue.details.IssuePagerMvp; -import com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files.fullscreen.FullScreenFileChangeActivity; -import com.fastaccess.ui.modules.reviews.AddReviewDialogFragment; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class PullRequestFilesFragment extends BaseFragment - implements PullRequestFilesMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @State HashMap toggleMap = new LinkedHashMap<>(); - @BindView(R.id.changes) FontTextView changes; - @BindView(R.id.addition) FontTextView addition; - @BindView(R.id.deletion) FontTextView deletion; - - private PullRequestFilesMvp.PatchCallback viewCallback; - private OnLoadMore onLoadMore; - private CommitFilesAdapter adapter; - private IssuePagerMvp.IssuePrCallback issueCallback; - - public static PullRequestFilesFragment newInstance(@NonNull String repoId, @NonNull String login, long number) { - PullRequestFilesFragment view = new PullRequestFilesFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.EXTRA_TWO, number) - .end()); - return view; - } - - @SuppressWarnings("unchecked") @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof IssuePagerMvp.IssuePrCallback) { - issueCallback = (IssuePagerMvp.IssuePrCallback) getParentFragment(); - } else if (context instanceof IssuePagerMvp.IssuePrCallback) { - issueCallback = (IssuePagerMvp.IssuePrCallback) context; - } else { - throw new IllegalArgumentException(String.format("%s or parent fragment must implement IssuePagerMvp.IssuePrCallback", context.getClass() - .getSimpleName())); - } - if (getParentFragment() instanceof PullRequestFilesMvp.PatchCallback) { - viewCallback = (PullRequestFilesMvp.PatchCallback) getParentFragment(); - } else if (context instanceof PullRequestFilesMvp.PatchCallback) { - viewCallback = (PullRequestFilesMvp.PatchCallback) context; - } - } - - @Override public void onDetach() { - issueCallback = null; - viewCallback = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override protected int fragmentLayout() { - return R.layout.pull_request_files_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getArguments() == null) { - throw new NullPointerException("Bundle is null, therefore, PullRequestFilesFragment can't be proceeded."); - } - setupChanges(); - stateLayout.setEmptyText(R.string.no_commits); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - adapter = new CommitFilesAdapter(getPresenter().getFiles(), this, this); - adapter.setListener(getPresenter()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments()); - } else if (getPresenter().getFiles().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - fastScroller.attachRecyclerView(recycler); - } - - private void setupChanges() { - PullRequest pullRequest = issueCallback.getData(); - if (pullRequest != null) { - addition.setText(String.valueOf(pullRequest.getAdditions())); - deletion.setText(String.valueOf(pullRequest.getDeletions())); - changes.setText(String.valueOf(pullRequest.getChangedFiles())); - } - } - - @NonNull @Override public PullRequestFilesPresenter providePresenter() { - return new PullRequestFilesPresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @SuppressWarnings("unchecked") @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()); - } - return onLoadMore; - } - - @Override public void onOpenForResult(int position, @NonNull CommitFileChanges model) { - FullScreenFileChangeActivity.Companion.startActivityForResult(this, model, position, false); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, null); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onToggle(long position, boolean isCollapsed) { - CommitFileChanges model = adapter.getItem((int) position); - if (model == null) return; - if (model.getCommitFileModel().getPatch() == null) { - if ("renamed".equalsIgnoreCase(model.getCommitFileModel().getStatus())) { - SchemeParser.launchUri(getContext(), model.getCommitFileModel().getBlobUrl()); - return; - } - ActivityHelper.startCustomTab(getActivity(), adapter.getItem((int) position).getCommitFileModel().getBlobUrl()); - } - toggleMap.put(position, isCollapsed); - } - - @Override public boolean isCollapsed(long position) { - Boolean toggle = toggleMap.get(position); - return toggle != null && toggle; - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - @Override public void onPatchClicked(int groupPosition, int childPosition, View v, CommitFileModel commit, CommitLinesModel item) { - if (item.getText().startsWith("@@")) return; - if (PrefGetter.isProEnabled()) { - AddReviewDialogFragment.Companion.newInstance(item, Bundler.start() - .put(BundleConstant.ITEM, commit.getFilename()) - .put(BundleConstant.EXTRA_TWO, groupPosition) - .put(BundleConstant.EXTRA_THREE, childPosition) - .end()) - .show(getChildFragmentManager(), "AddReviewDialogFragment"); - } else { - PremiumActivity.Companion.startActivity(getContext()); - } - } - - @Override public void onCommentAdded(@NonNull String comment, @NonNull CommitLinesModel item, Bundle bundle) { - if (bundle != null) { - String path = bundle.getString(BundleConstant.ITEM); - if (path == null) return; - CommentRequestModel commentRequestModel = new CommentRequestModel(); - commentRequestModel.setBody(comment); - commentRequestModel.setPath(path); - commentRequestModel.setPosition(item.getPosition()); - if (viewCallback != null) viewCallback.onAddComment(commentRequestModel); - int groupPosition = bundle.getInt(BundleConstant.EXTRA_TWO); - int childPosition = bundle.getInt(BundleConstant.EXTRA_THREE); - CommitFileChanges commitFileChanges = adapter.getItem(groupPosition); - List models = commitFileChanges.getLinesModel(); - if (models != null && !models.isEmpty()) { - CommitLinesModel current = models.get(childPosition); - if (current != null) { - current.setHasCommentedOn(true); - } - models.set(childPosition, current); - adapter.notifyItemChanged(groupPosition); - } - } - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == Activity.RESULT_OK) { - if (requestCode == FullScreenFileChangeActivity.Companion.getFOR_RESULT_CODE() && data != null) { - List comments = data.getParcelableArrayListExtra(BundleConstant.ITEM); - if (comments != null && !comments.isEmpty()) { - if (viewCallback != null) { - for (CommentRequestModel comment : comments) { - viewCallback.onAddComment(comment); - } - showMessage(R.string.success, R.string.comments_added_successfully); - } - } - } - } - super.onActivityResult(requestCode, resultCode, data); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesMvp.java deleted file mode 100644 index a75bc1d18..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesMvp.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.CommitFileChanges; -import com.fastaccess.data.dao.CommitFileModel; -import com.fastaccess.data.dao.CommitLinesModel; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.reviews.callback.ReviewCommentListener; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -public interface PullRequestFilesMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener, - OnToggleView, OnPatchClickListener, ReviewCommentListener { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onOpenForResult(int position, @NonNull CommitFileChanges linesModel); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - void onFragmentCreated(@NonNull Bundle bundle); - - @NonNull ArrayList getFiles(); - - void onWorkOffline(); - } - - interface OnPatchClickListener { - void onPatchClicked(int groupPosition, int childPosition, android.view.View v, CommitFileModel commit, CommitLinesModel item); - } - - interface PatchCallback { - void onAddComment(CommentRequestModel comment); - } - - interface CommitCommentCallback { - @NonNull ArrayList getCommitComment(); - - void onAddComment(@NonNull CommentRequestModel comment); - - boolean hasReviewComments(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesPresenter.java deleted file mode 100644 index 4f3d126ef..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/PullRequestFilesPresenter.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files; - -import android.app.Activity; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.MenuInflater; -import android.view.View; -import android.widget.PopupMenu; - -import com.fastaccess.R; -import com.fastaccess.data.dao.CommitFileChanges; -import com.fastaccess.data.dao.CommitFileModel; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.code.CodeViewerActivity; -import com.fastaccess.ui.modules.repos.code.commit.details.CommitPagerActivity; - -import java.util.ArrayList; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class PullRequestFilesPresenter extends BasePresenter implements PullRequestFilesMvp.Presenter { - - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State long number; - private ArrayList files = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public void onError(@NonNull Throwable throwable) { - onWorkOffline(); - super.onError(throwable); - } - - @Override public boolean onCallApi(int page, @Nullable Object parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0) { - sendToView(PullRequestFilesMvp.View::hideProgress); - return false; - } - if (repoId == null || login == null) return false; - makeRestCall(RestProvider.getPullRequestService(isEnterprise()).getPullRequestFiles(login, repoId, number, page) - .flatMap(commitFileModelPageable -> { - if (commitFileModelPageable != null) { - lastPage = commitFileModelPageable.getLast(); - if (commitFileModelPageable.getItems() != null) { - return Observable.just(CommitFileChanges.construct(commitFileModelPageable.getItems())); - } - } - return Observable.empty(); - }), - response -> sendToView(view -> view.onNotifyAdapter(response, page))); - return true; - } - - @Override public void onFragmentCreated(@NonNull Bundle bundle) { - repoId = bundle.getString(BundleConstant.ID); - login = bundle.getString(BundleConstant.EXTRA); - number = bundle.getLong(BundleConstant.EXTRA_TWO); - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - onCallApi(1, null); - } - } - - @NonNull @Override public ArrayList getFiles() { - return files; - } - - @Override public void onWorkOffline() { - sendToView(BaseMvp.FAView::hideProgress); - } - - @Override public void onItemClick(int position, View v, CommitFileChanges model) { - if (v.getId() == R.id.patchList) { - sendToView(view -> view.onOpenForResult(position, model)); - } else if (v.getId() == R.id.open) { - CommitFileModel item = model.getCommitFileModel(); - PopupMenu popup = new PopupMenu(v.getContext(), v); - MenuInflater inflater = popup.getMenuInflater(); - inflater.inflate(R.menu.commit_row_menu, popup.getMenu()); - popup.setOnMenuItemClickListener(item1 -> { - switch (item1.getItemId()) { - case R.id.open: - v.getContext().startActivity(CodeViewerActivity.createIntent(v.getContext(), item.getContentsUrl(), item.getBlobUrl())); - break; - case R.id.share: - ActivityHelper.shareUrl(v.getContext(), item.getBlobUrl()); - break; - case R.id.download: - Activity activity = ActivityHelper.getActivity(v.getContext()); - if (activity == null) break; - if (ActivityHelper.checkAndRequestReadWritePermission(activity)) { - RestProvider.downloadFile(v.getContext(), item.getRawUrl()); - } - break; - case R.id.copy: - AppHelper.copyToClipboard(v.getContext(), item.getBlobUrl()); - break; - } - return true; - }); - popup.show(); - } - } - - @Override public void onItemLongClick(int position, View v, CommitFileChanges item) { - v.getContext().startActivity(CommitPagerActivity.createIntent(v.getContext(), repoId, login, - Uri.parse(item.getCommitFileModel().getContentsUrl()).getQueryParameter("ref"))); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangeActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangeActivity.kt deleted file mode 100644 index 99f13ce3a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangeActivity.kt +++ /dev/null @@ -1,177 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files.fullscreen - -import android.app.Activity -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import android.support.v4.app.Fragment -import android.support.v4.widget.SwipeRefreshLayout -import android.view.Menu -import android.view.MenuItem -import android.view.View -import android.widget.TextView -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.CommentRequestModel -import com.fastaccess.data.dao.CommitFileChanges -import com.fastaccess.data.dao.CommitLinesModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.helper.PrefGetter -import com.fastaccess.ui.adapter.CommitLinesAdapter -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.modules.main.premium.PremiumActivity -import com.fastaccess.ui.modules.reviews.AddReviewDialogFragment -import com.fastaccess.ui.widgets.StateLayout -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller - -/** - * Created by Hashemsergani on 24.09.17. - */ - -class FullScreenFileChangeActivity : BaseActivity(), FullScreenFileChangeMvp.View { - - @BindView(R.id.recycler) lateinit var recycler: DynamicRecyclerView - @BindView(R.id.refresh) lateinit var refresh: SwipeRefreshLayout - @BindView(R.id.stateLayout) lateinit var stateLayout: StateLayout - @BindView(R.id.fastScroller) lateinit var fastScroller: RecyclerViewFastScroller - @BindView(R.id.changes) lateinit var changes: TextView - @BindView(R.id.deletion) lateinit var deletion: TextView - @BindView(R.id.addition) lateinit var addition: TextView - - val commentList = arrayListOf() - - private val adapter by lazy { CommitLinesAdapter(arrayListOf(), this) } - - override fun layout(): Int = R.layout.full_screen_file_changes_layout - - override fun isTransparent(): Boolean = false - - override fun canBack(): Boolean = true - - override fun isSecured(): Boolean = false - - override fun providePresenter(): FullScreenFileChangePresenter = FullScreenFileChangePresenter() - - override fun onNotifyAdapter(model: CommitLinesModel) { - adapter.addItem(model) - } - - override fun showMessage(titleRes: Int, msgRes: Int) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showMessage(titleRes: String, msgRes: String) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showErrorMessage(msgRes: String) { - hideProgress() - super.showErrorMessage(msgRes) - } - - override fun showProgress(resId: Int) { - stateLayout.showProgress() - refresh.isRefreshing = true - } - - override fun hideProgress() { - stateLayout.hideProgress() - refresh.isRefreshing = false - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - refresh.isEnabled = false - recycler.adapter = adapter - val padding = resources.getDimensionPixelSize(R.dimen.spacing_normal) - recycler.setPadding(padding, 0, padding, 0) - fastScroller.attachRecyclerView(recycler) - presenter.onLoad(intent) - presenter.model?.let { model -> - title = Uri.parse(model.commitFileModel.filename).lastPathSegment - addition.text = model.commitFileModel?.additions.toString() - deletion.text = model.commitFileModel?.deletions.toString() - changes.text = model.commitFileModel?.changes.toString() - } - } - - override fun onCreateOptionsMenu(menu: Menu?): Boolean { - menuInflater.inflate(R.menu.done_menu, menu) - menu?.findItem(R.id.submit)?.setIcon(R.drawable.ic_done) - return super.onCreateOptionsMenu(menu) - } - - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - return when (item?.itemId) { - R.id.submit -> { - sendResult() - true - } - else -> super.onOptionsItemSelected(item) - } - } - - override fun onItemClick(position: Int, v: View, item: CommitLinesModel) { - if (item.text.startsWith("@@")) return - val commit = presenter.model?.commitFileModel ?: return - if (PrefGetter.isProEnabled()) { - AddReviewDialogFragment.newInstance(item, Bundler.start() - .put(BundleConstant.ITEM, commit.filename) - .put(BundleConstant.EXTRA_TWO, presenter.position) - .put(BundleConstant.EXTRA_THREE, position) - .end()) - .show(supportFragmentManager, "AddReviewDialogFragment") - } else { - PremiumActivity.startActivity(this) - } - } - - override fun onItemLongClick(position: Int, v: View?, item: CommitLinesModel?) { - - } - - override fun onCommentAdded(comment: String, item: CommitLinesModel, bundle: Bundle?) { - if (bundle != null) { - val path = bundle.getString(BundleConstant.ITEM) ?: return - val commentRequestModel = CommentRequestModel() - commentRequestModel.body = comment - commentRequestModel.path = path - commentRequestModel.position = item.position - commentList.add(commentRequestModel) - val childPosition = bundle.getInt(BundleConstant.EXTRA_THREE) - val current = adapter.getItem(childPosition) - if (current != null) { - current.isHasCommentedOn = true - adapter.swapItem(current, childPosition) - } - if (presenter.isCommit) { - sendResult() - } - } - } - - private fun sendResult() { - val intent = Intent() - intent.putExtras(Bundler.start().putParcelableArrayList(BundleConstant.ITEM, commentList).end()) - setResult(Activity.RESULT_OK, intent) - finish() - } - - - companion object { - val FOR_RESULT_CODE = 1002 - fun startActivityForResult(fragment: Fragment, model: CommitFileChanges, position: Int, isCommit: Boolean = false) { - val intent = Intent(fragment.context, FullScreenFileChangeActivity::class.java) - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, model) - .put(BundleConstant.ITEM, position) - .put(BundleConstant.YES_NO_EXTRA, isCommit) - .end()) - fragment.startActivityForResult(intent, FOR_RESULT_CODE) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangeMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangeMvp.kt deleted file mode 100644 index 398eedff4..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangeMvp.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files.fullscreen - -import android.content.Intent -import com.fastaccess.data.dao.CommitLinesModel -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.modules.reviews.callback.ReviewCommentListener -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Hashemsergani on 24.09.17. - */ - -interface FullScreenFileChangeMvp { - interface View : BaseMvp.FAView, BaseViewHolder.OnItemClickListener, ReviewCommentListener { - fun onNotifyAdapter(model: CommitLinesModel) - } - - interface Presenter { - fun onLoad(intent: Intent) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangePresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangePresenter.kt deleted file mode 100644 index 5e5915f31..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/files/fullscreen/FullScreenFileChangePresenter.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.files.fullscreen - -import android.content.Intent -import com.fastaccess.data.dao.CommitFileChanges -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.RxHelper -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import io.reactivex.Observable - -/** - * Created by Hashemsergani on 24.09.17. - */ -class FullScreenFileChangePresenter : BasePresenter(), FullScreenFileChangeMvp.Presenter { - - var model: CommitFileChanges? = null - var position: Int = -1 - var isCommit: Boolean = false - - override fun onLoad(intent: Intent) { - intent.extras?.let { - position = it.getInt(BundleConstant.ITEM) - model = it.getParcelable(BundleConstant.EXTRA) - isCommit = it.getBoolean(BundleConstant.YES_NO_EXTRA) - } - model?.let { - manageDisposable(RxHelper.getObservable(Observable.fromIterable(it.linesModel)) - .doOnSubscribe({ sendToView { it.showProgress(0) } }) - .flatMap { Observable.just(it) } - .subscribe - ({ - sendToView { v -> v.onNotifyAdapter(it) } - }, { - onError(it) - }, { - sendToView { it.hideProgress() } - })) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelineFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelineFragment.java deleted file mode 100644 index 09cb51ac4..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelineFragment.java +++ /dev/null @@ -1,434 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.timeline.timeline; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.EditReviewCommentModel; -import com.fastaccess.data.dao.ReviewCommentModel; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.ui.adapter.IssuesTimelineAdapter; -import com.fastaccess.ui.adapter.viewholder.TimelineCommentsViewHolder; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.editor.EditorActivity; -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment; -import com.fastaccess.ui.modules.repos.issues.issue.details.IssuePagerMvp; -import com.fastaccess.ui.modules.repos.reactions.ReactionsDialogFragment; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.dialog.MessageDialogView; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 31 Mar 2017, 7:35 PM - */ - -public class PullRequestTimelineFragment extends BaseFragment - implements PullRequestTimelineMvp.View { - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @State HashMap toggleMap = new LinkedHashMap<>(); - private IssuesTimelineAdapter adapter; - private OnLoadMore onLoadMore; - private CommentEditorFragment.CommentListener commentsCallback; - - private IssuePagerMvp.IssuePrCallback issueCallback; - - @NonNull public static PullRequestTimelineFragment newInstance() { - return new PullRequestTimelineFragment(); - } - - @SuppressWarnings("unchecked") @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() instanceof IssuePagerMvp.IssuePrCallback) { - issueCallback = (IssuePagerMvp.IssuePrCallback) getParentFragment(); - } else if (context instanceof IssuePagerMvp.IssuePrCallback) { - issueCallback = (IssuePagerMvp.IssuePrCallback) context; - } else { - throw new IllegalArgumentException(String.format("%s or parent fragment must implement IssuePagerMvp.IssuePrCallback", context.getClass() - .getSimpleName())); - } - if (getParentFragment() instanceof CommentEditorFragment.CommentListener) { - commentsCallback = (CommentEditorFragment.CommentListener) getParentFragment(); - } else if (context instanceof CommentEditorFragment.CommentListener) { - commentsCallback = (CommentEditorFragment.CommentListener) context; - } else { - throw new IllegalArgumentException(String.format("%s or parent fragment must implement CommentEditorFragment.CommentListener", - context.getClass().getSimpleName())); - } - } - - @Override public void onDetach() { - issueCallback = null; - commentsCallback = null; - super.onDetach(); - } - - @Override public void onRefresh() { - getPresenter().onCallApi(1, getPullRequest()); - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (getPullRequest() == null) { - throw new NullPointerException("PullRequest went missing!!!"); - } - boolean isMerged = getPresenter().isMerged(getPullRequest()); - adapter = new IssuesTimelineAdapter(getPresenter().getEvents(), this, true, - this, isMerged, getPresenter(), getPullRequest().getLogin(), getPullRequest().getUser().getLogin()); - stateLayout.setEmptyText(R.string.no_events); - recycler.setEmptyView(stateLayout, refresh); - refresh.setOnRefreshListener(this); - stateLayout.setOnReloadListener(this); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - fastScroller.setVisibility(View.VISIBLE); - fastScroller.attachRecyclerView(recycler); - recycler.addDivider(TimelineCommentsViewHolder.class); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null) { - onSetHeader(new TimelineModel(getPullRequest())); - onRefresh(); - } else if (getPresenter().getEvents().isEmpty() || getPresenter().getEvents().size() == 1) { - onRefresh(); - } - } - - @NonNull @Override public PullRequestTimelinePresenter providePresenter() { - return new PullRequestTimelinePresenter(); - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onToggle(long position, boolean isCollapsed) { - toggleMap.put(position, isCollapsed); - } - - @Override public boolean isCollapsed(long position) { - return toggleMap.get(position) != null && toggleMap.get(position); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null) { - adapter.subList(1, adapter.getItemCount()); - return; - } - if (page == 1) { - adapter.subList(1, adapter.getItemCount()); - } - adapter.addItems(items); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter()); - } - onLoadMore.setParameter(getPullRequest()); - return onLoadMore; - } - - @Override public void onEditComment(@NonNull Comment item) { - Intent intent = new Intent(getContext(), EditorActivity.class); - if (getPullRequest() == null) return; - intent.putExtras(Bundler - .start() - .put(BundleConstant.ID, getPullRequest().getRepoId()) - .put(BundleConstant.EXTRA_TWO, getPullRequest().getLogin()) - .put(BundleConstant.EXTRA_THREE, getPullRequest().getNumber()) - .put(BundleConstant.EXTRA_FOUR, item.getId()) - .put(BundleConstant.EXTRA, item.getBody()) - .put(BundleConstant.EXTRA_TYPE, BundleConstant.ExtraType.EDIT_ISSUE_COMMENT_EXTRA) - .putStringArrayList("participants", CommentsHelper.getUsersByTimeline(adapter.getData())) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise()) - .end()); - View view = getFromView(); - ActivityHelper.startReveal(this, intent, view, BundleConstant.REQUEST_CODE); - } - - @Override public void onEditReviewComment(@NonNull ReviewCommentModel item, int groupPosition, int childPosition) { - EditReviewCommentModel model = new EditReviewCommentModel(); - model.setCommentPosition(childPosition); - model.setGroupPosition(groupPosition); - model.setInReplyTo(item.getId()); - Intent intent = new Intent(getContext(), EditorActivity.class); - if (getPullRequest() == null) return; - intent.putExtras(Bundler - .start() - .put(BundleConstant.ID, getPullRequest().getRepoId()) - .put(BundleConstant.EXTRA_TWO, getPullRequest().getLogin()) - .put(BundleConstant.EXTRA_THREE, getPullRequest().getNumber()) - .put(BundleConstant.EXTRA_FOUR, item.getId()) - .put(BundleConstant.EXTRA, item.getBody()) - .put(BundleConstant.REVIEW_EXTRA, model) - .put(BundleConstant.EXTRA_TYPE, BundleConstant.ExtraType.EDIT_REVIEW_COMMENT_EXTRA) - .putStringArrayList("participants", CommentsHelper.getUsersByTimeline(adapter.getData())) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise()) - .end()); - View view = getFromView(); - ActivityHelper.startReveal(this, intent, view, BundleConstant.REVIEW_REQUEST_CODE); - } - - @Override public void onRemove(@NonNull TimelineModel timelineModel) { - hideProgress(); - adapter.removeItem(timelineModel); - } - - @Override public void onShowDeleteMsg(long id) { - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), - Bundler.start() - .put(BundleConstant.EXTRA, id) - .put(BundleConstant.YES_NO_EXTRA, false) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - - @Override public void onReply(User user, String message) { - Intent intent = new Intent(getContext(), EditorActivity.class); - if (getPullRequest() == null) return; - intent.putExtras(Bundler - .start() - .put(BundleConstant.ID, getPullRequest().getRepoId()) - .put(BundleConstant.EXTRA_TWO, getPullRequest().getLogin()) - .put(BundleConstant.EXTRA_THREE, getPullRequest().getNumber()) - .put(BundleConstant.EXTRA, "@" + user.getLogin()) - .put(BundleConstant.EXTRA_TYPE, BundleConstant.ExtraType.NEW_ISSUE_COMMENT_EXTRA) - .putStringArrayList("participants", CommentsHelper.getUsersByTimeline(adapter.getData())) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise()) - .put("message", message) - .end()); - View view = getFromView(); - ActivityHelper.startReveal(this, intent, view, BundleConstant.REQUEST_CODE); - } - - @Override public void onHandleComment(@NonNull String text, @Nullable Bundle bundle) { - getPresenter().onHandleComment(text, bundle); - } - - @Override public void onReplyOrCreateReview(@Nullable User user, @Nullable String message, - int groupPosition, int childPosition, - @NonNull EditReviewCommentModel model) { - Intent intent = new Intent(getContext(), EditorActivity.class); - if (getPullRequest() == null) return; - intent.putExtras(Bundler - .start() - .put(BundleConstant.ID, getPullRequest().getRepoId()) - .put(BundleConstant.EXTRA_TWO, getPullRequest().getLogin()) - .put(BundleConstant.EXTRA_THREE, getPullRequest().getNumber()) - .put(BundleConstant.EXTRA, user != null ? "@" + user.getLogin() : "") - .put(BundleConstant.REVIEW_EXTRA, model) - .put(BundleConstant.EXTRA_TYPE, BundleConstant.ExtraType.NEW_REVIEW_COMMENT_EXTRA) - .putStringArrayList("participants", CommentsHelper.getUsersByTimeline(adapter.getData())) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise()) - .put("message", message) - .end()); - View view = getFromView(); - ActivityHelper.startReveal(this, intent, view, BundleConstant.REVIEW_REQUEST_CODE); - } - - @Override public void addComment(@NonNull TimelineModel timelineModel) { - onHideBlockingProgress(); - adapter.addItem(timelineModel); - if (commentsCallback != null) commentsCallback.onClearEditText(); - } - - @NonNull @Override public ArrayList getNamesToTag() { - return CommentsHelper.getUsersByTimeline(adapter.getData()); - } - - @Override public void onHideBlockingProgress() { - hideProgress(); - super.hideProgress(); - } - - @Override public void showReactionsPopup(@NonNull ReactionTypes type, @NonNull String login, @NonNull String repoId, - long idOrNumber, int reactionType) { - ReactionsDialogFragment.newInstance(login, repoId, type, idOrNumber, reactionType).show(getChildFragmentManager(), "ReactionsDialogFragment"); - } - - @Override public void onShowReviewDeleteMsg(long commentId, int groupPosition, int commentPosition) { - MessageDialogView.newInstance(getString(R.string.delete), getString(R.string.confirm_message), - Bundler.start() - .put(BundleConstant.EXTRA, commentId) - .put(BundleConstant.YES_NO_EXTRA, true) - .put(BundleConstant.EXTRA_TWO, groupPosition) - .put(BundleConstant.EXTRA_THREE, commentPosition) - .end()) - .show(getChildFragmentManager(), MessageDialogView.TAG); - } - - @Override public void onRemoveReviewComment(int groupPosition, int commentPosition) { - hideProgress(); - TimelineModel timelineModel = adapter.getItem(groupPosition); - if (timelineModel != null && timelineModel.getGroupedReviewModel() != null) { - if (timelineModel.getGroupedReviewModel().getComments() != null) { - timelineModel.getGroupedReviewModel().getComments().remove(commentPosition); - if (timelineModel.getGroupedReviewModel().getComments().isEmpty()) { - adapter.removeItem(groupPosition); - } else { - adapter.notifyItemChanged(groupPosition); - } - } - } - } - - @Override public void onSetHeader(@NonNull TimelineModel timelineModel) { - if (adapter != null) { - if (adapter.isEmpty()) { - adapter.addItem(timelineModel, 0); - } else { - adapter.swapItem(timelineModel, 0); - } - } - } - - @Nullable @Override public PullRequest getPullRequest() { - return issueCallback.getData(); - } - - @Override public void onUpdateHeader() { - if (getPullRequest() == null) return; - onSetHeader(new TimelineModel(getPullRequest())); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == Activity.RESULT_OK) { - if (data == null) { - onRefresh(); - return; - } - Bundle bundle = data.getExtras(); - if (bundle != null) { - boolean isNew = bundle.getBoolean(BundleConstant.EXTRA); - if (requestCode == BundleConstant.REQUEST_CODE) { - Comment commentsModel = bundle.getParcelable(BundleConstant.ITEM); - if (commentsModel == null) { - onRefresh(); // bundle size is too large? refresh the api - return; - } - if (isNew) { - adapter.addItem(TimelineModel.constructComment(commentsModel)); - recycler.smoothScrollToPosition(adapter.getItemCount()); - } else { - int position = adapter.getItem(TimelineModel.constructComment(commentsModel)); - if (position != -1) { - adapter.swapItem(TimelineModel.constructComment(commentsModel), position); - recycler.smoothScrollToPosition(position); - } else { - adapter.addItem(TimelineModel.constructComment(commentsModel)); - recycler.smoothScrollToPosition(adapter.getItemCount()); - } - } - } else if (requestCode == BundleConstant.REVIEW_REQUEST_CODE) { - EditReviewCommentModel commentModel = bundle.getParcelable(BundleConstant.ITEM); - if (commentModel == null) { - onRefresh(); // bundle size is too large? refresh the api - return; - } - TimelineModel timelineModel = adapter.getItem(commentModel.getGroupPosition()); - if (isNew) { - if (timelineModel.getGroupedReviewModel() != null && timelineModel.getGroupedReviewModel().getComments() != null) { - timelineModel.getGroupedReviewModel().getComments().add(commentModel.getCommentModel()); - adapter.notifyItemChanged(commentModel.getGroupPosition()); - } else { - onRefresh(); - } - } else { - if (timelineModel.getGroupedReviewModel() != null && timelineModel.getGroupedReviewModel().getComments() != null) { - timelineModel.getGroupedReviewModel().getComments().set(commentModel.getCommentPosition(), commentModel.getCommentModel - ()); - adapter.notifyItemChanged(commentModel.getGroupPosition()); - } else { - onRefresh(); - } - } - } - } else { - onRefresh(); // bundle size is too large? refresh the api - } - } - } - - @Override public void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle) { - super.onMessageDialogActionClicked(isOk, bundle); - if (isOk) { - getPresenter().onHandleDeletion(bundle); - } - } - - @Override public boolean isPreviouslyReacted(long id, int vId) { - return getPresenter().isPreviouslyReacted(id, vId); - } - - @Override public boolean isCallingApi(long id, int vId) { - return getPresenter().isCallingApi(id, vId); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - @Override public void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } - - private View getFromView() { - return getActivity() != null && getActivity().findViewById(R.id.fab) != null ? getActivity().findViewById(R.id.fab) : recycler; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelineMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelineMvp.java deleted file mode 100644 index b2a4246f5..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelineMvp.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.timeline.timeline; - -import android.os.Bundle; -import android.support.annotation.IdRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.EditReviewCommentModel; -import com.fastaccess.data.dao.ReviewCommentModel; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.provider.timeline.ReactionsProvider; -import com.fastaccess.ui.adapter.callback.OnToggleView; -import com.fastaccess.ui.adapter.callback.ReactionsCallback; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import net.grandcentrix.thirtyinch.callonmainthread.CallOnMainThread; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 31 Mar 2017, 7:15 PM - */ - -public interface PullRequestTimelineMvp { - - interface ReviewCommentCallback { - void onClick(int groupPosition, int commentPosition, @NonNull android.view.View view, @NonNull ReviewCommentModel model); - - void onLongClick(int groupPosition, int commentPosition, @NonNull android.view.View view, @NonNull ReviewCommentModel model); - } - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener, - OnToggleView, ReactionsCallback { - - @CallOnMainThread void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - - void onEditComment(@NonNull Comment item); - - void onEditReviewComment(@NonNull ReviewCommentModel item, int groupPosition, int childPosition); - - void onRemove(@NonNull TimelineModel timelineModel); - - void onShowDeleteMsg(long id); - - void onReply(User user, String message); - - void showReactionsPopup(@NonNull ReactionTypes type, @NonNull String login, @NonNull String repoId, long idOrNumber, @ReactionsProvider - .ReactionType int reactionType); - - void onShowReviewDeleteMsg(long commentId, int groupPosition, int commentPosition); - - void onRemoveReviewComment(int groupPosition, int commentPosition); - - void onSetHeader(@NonNull TimelineModel timelineModel); - - @Nullable PullRequest getPullRequest(); - - void onUpdateHeader(); - - @CallOnMainThread void showReload(); - - void onHandleComment(String text, @Nullable Bundle bundle); - - void onReplyOrCreateReview(@Nullable User user, @Nullable String message, int groupPosition, int childPosition, - @NonNull EditReviewCommentModel model); - - void addComment(@NonNull TimelineModel timelineModel); - - @NonNull ArrayList getNamesToTag(); - - void onHideBlockingProgress(); - } - - interface Presenter extends BaseMvp.FAPresenter, BaseViewHolder.OnItemClickListener, - ReviewCommentCallback, BaseMvp.PaginationListener { - - @NonNull ArrayList getEvents(); - - void onWorkOffline(); - - void onHandleDeletion(@Nullable Bundle bundle); - - boolean isPreviouslyReacted(long commentId, int vId); - - void onHandleReaction(@IdRes int vId, long idOrNumber, @ReactionsProvider.ReactionType int reactionType); - - boolean isMerged(PullRequest pullRequest); - - boolean isCallingApi(long id, int vId); - - void onHandleComment(@NonNull String text, @Nullable Bundle bundle); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelinePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelinePresenter.java deleted file mode 100644 index aa7e72a5f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/details/timeline/timeline/PullRequestTimelinePresenter.java +++ /dev/null @@ -1,456 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.details.timeline.timeline; - -import android.app.Activity; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.SparseArray; -import android.view.View; -import android.widget.PopupMenu; - -import com.fastaccess.R; -import com.fastaccess.data.dao.CommentRequestModel; -import com.fastaccess.data.dao.EditReviewCommentModel; -import com.fastaccess.data.dao.GroupedReviewModel; -import com.fastaccess.data.dao.PullRequestStatusModel; -import com.fastaccess.data.dao.ReviewCommentModel; -import com.fastaccess.data.dao.TimelineModel; -import com.fastaccess.data.dao.model.Comment; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.data.dao.model.PullRequest; -import com.fastaccess.data.dao.timeline.GenericEvent; -import com.fastaccess.data.dao.timeline.SourceModel; -import com.fastaccess.data.dao.types.IssueEventType; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.provider.timeline.ReactionsProvider; -import com.fastaccess.provider.timeline.TimelineConverter; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.filter.issues.FilterIssuesActivity; -import com.fastaccess.ui.modules.repos.issues.create.CreateIssueActivity; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 31 Mar 2017, 7:17 PM - */ - -public class PullRequestTimelinePresenter extends BasePresenter implements PullRequestTimelineMvp.Presenter { - private ArrayList timeline = new ArrayList<>(); - private SparseArray pages = new SparseArray<>(); - private ReactionsProvider reactionsProvider; - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - @com.evernote.android.state.State boolean isCollaborator; - - @Override public void onItemClick(int position, View v, TimelineModel item) { - if (getView() == null) return; - PullRequest pullRequest = getView().getPullRequest(); - if (pullRequest != null) { - if (item.getType() == TimelineModel.COMMENT) { - if (v.getId() == R.id.commentMenu) { - PopupMenu popupMenu = new PopupMenu(v.getContext(), v); - popupMenu.inflate(R.menu.comments_menu); - String username = Login.getUser().getLogin(); - boolean isOwner = CommentsHelper.isOwner(username, pullRequest.getLogin(), item.getComment().getUser().getLogin()) - || isCollaborator; - popupMenu.getMenu().findItem(R.id.delete).setVisible(isOwner); - popupMenu.getMenu().findItem(R.id.edit).setVisible(isOwner); - popupMenu.setOnMenuItemClickListener(item1 -> { - if (getView() == null) return false; - if (item1.getItemId() == R.id.delete) { - getView().onShowDeleteMsg(item.getComment().getId()); - } else if (item1.getItemId() == R.id.reply) { - getView().onReply(item.getComment().getUser(), item.getComment().getBodyHtml()); - } else if (item1.getItemId() == R.id.edit) { - getView().onEditComment(item.getComment()); - } else if (item1.getItemId() == R.id.share) { - ActivityHelper.shareUrl(v.getContext(), item.getComment().getHtmlUrl()); - } - return true; - }); - popupMenu.show(); - } else { - onHandleReaction(v.getId(), item.getComment().getId(), ReactionsProvider.COMMENT); - } - } else if (item.getType() == TimelineModel.EVENT) { - GenericEvent issueEventModel = item.getGenericEvent(); - if (issueEventModel.getCommitUrl() != null) { - SchemeParser.launchUri(v.getContext(), Uri.parse(issueEventModel.getCommitUrl())); - } else if (issueEventModel.getLabel() != null) { - FilterIssuesActivity.startActivity(v, pullRequest.getLogin(), pullRequest.getRepoId(), false, - true, isEnterprise(), "label:\"" + issueEventModel.getLabel().getName() + "\""); - } else if (issueEventModel.getMilestone() != null) { - FilterIssuesActivity.startActivity(v, pullRequest.getLogin(), pullRequest.getRepoId(), false, - true, isEnterprise(), "milestone:\"" + issueEventModel.getMilestone().getTitle() + "\""); - } else if (issueEventModel.getAssignee() != null) { - FilterIssuesActivity.startActivity(v, pullRequest.getLogin(), pullRequest.getRepoId(), false, - true, isEnterprise(), "assignee:\"" + issueEventModel.getAssignee().getLogin() + "\""); - } else if (issueEventModel.getEvent() == IssueEventType.committed) { - SchemeParser.launchUri(v.getContext(), issueEventModel.getUrl().replace("git/", "")); - } else { - SourceModel sourceModel = issueEventModel.getSource(); - if (sourceModel != null) { - if (sourceModel.getCommit() != null) { - SchemeParser.launchUri(v.getContext(), sourceModel.getCommit().getUrl()); - } else if (sourceModel.getPullRequest() != null) { - SchemeParser.launchUri(v.getContext(), sourceModel.getPullRequest().getUrl()); - } else if (sourceModel.getIssue() != null) { - SchemeParser.launchUri(v.getContext(), sourceModel.getIssue().getHtmlUrl()); - } else if (sourceModel.getRepository() != null) { - SchemeParser.launchUri(v.getContext(), sourceModel.getRepository().getUrl()); - } - } - } - } else if (item.getType() == TimelineModel.HEADER) { - if (v.getId() == R.id.commentMenu) { - PopupMenu popupMenu = new PopupMenu(v.getContext(), v); - popupMenu.inflate(R.menu.comments_menu); - String username = Login.getUser().getLogin(); - boolean isOwner = CommentsHelper.isOwner(username, item.getPullRequest().getLogin(), - item.getPullRequest().getUser().getLogin()) || isCollaborator; - popupMenu.getMenu().findItem(R.id.edit).setVisible(isOwner); - popupMenu.setOnMenuItemClickListener(item1 -> { - if (getView() == null) return false; - if (item1.getItemId() == R.id.reply) { - getView().onReply(item.getPullRequest().getUser(), item.getPullRequest().getBodyHtml()); - } else if (item1.getItemId() == R.id.edit) { - Activity activity = ActivityHelper.getActivity(v.getContext()); - if (activity == null) return false; - CreateIssueActivity.startForResult(activity, - item.getPullRequest().getLogin(), item.getPullRequest().getRepoId(), - item.getPullRequest(), isEnterprise()); - } else if (item1.getItemId() == R.id.share) { - ActivityHelper.shareUrl(v.getContext(), item.getPullRequest().getHtmlUrl()); - } - return true; - }); - popupMenu.show(); - } else { - onHandleReaction(v.getId(), item.getPullRequest().getNumber(), ReactionsProvider.HEADER); - } - } else if (item.getType() == TimelineModel.GROUP) { - GroupedReviewModel reviewModel = item.getGroupedReviewModel(); - if (v.getId() == R.id.addCommentPreview) { - if (getView() != null) { - EditReviewCommentModel model = new EditReviewCommentModel(); - model.setCommentPosition(-1); - model.setGroupPosition(position); - model.setInReplyTo(reviewModel.getId()); - getView().onReplyOrCreateReview(null, null, position, -1, model); - - } - } - } - } - } - - @Override public void onItemLongClick(int position, View v, TimelineModel item) { - if (getView() == null || getView().getPullRequest() == null) return; - if (item.getType() == TimelineModel.COMMENT || item.getType() == TimelineModel.HEADER) { - if (v.getId() == R.id.commentMenu && item.getType() == TimelineModel.COMMENT) { - Comment comment = item.getComment(); - if (getView() != null) getView().onReply(comment.getUser(), comment.getBody()); - } else { - PullRequest pullRequest = getView().getPullRequest(); - String login = pullRequest.getLogin(); - String repoId = pullRequest.getRepoId(); - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - ReactionTypes type = ReactionTypes.get(v.getId()); - if (type != null) { - if (item.getType() == TimelineModel.HEADER) { - getView().showReactionsPopup(type, login, repoId, item.getPullRequest().getNumber(), ReactionsProvider.HEADER); - } else { - getView().showReactionsPopup(type, login, repoId, item.getComment().getId(), ReactionsProvider.COMMENT); - } - } else { - onItemClick(position, v, item); - } - } - } - } else { - onItemClick(position, v, item); - } - } - - @NonNull @Override public ArrayList getEvents() { - return timeline; - } - - @Override public void onWorkOffline() { - //TODO - } - - @Override public void onHandleDeletion(@Nullable Bundle bundle) { - if (getView() == null || getView().getPullRequest() == null) return; - if (bundle != null) { - PullRequest pullRequest = getView().getPullRequest(); - String login = pullRequest.getLogin(); - String repoId = pullRequest.getRepoId(); - long commId = bundle.getLong(BundleConstant.EXTRA, 0); - boolean isReviewComment = bundle.getBoolean(BundleConstant.YES_NO_EXTRA); - if (commId != 0 && !isReviewComment) { - makeRestCall(RestProvider.getIssueService(isEnterprise()).deleteIssueComment(login, repoId, commId), - booleanResponse -> sendToView(view -> { - if (booleanResponse.code() == 204) { - Comment comment = new Comment(); - comment.setId(commId); - view.onRemove(TimelineModel.constructComment(comment)); - } else { - view.showMessage(R.string.error, R.string.error_deleting_comment); - } - })); - } else { - int groupPosition = bundle.getInt(BundleConstant.EXTRA_TWO); - int commentPosition = bundle.getInt(BundleConstant.EXTRA_THREE); - makeRestCall(RestProvider.getReviewService(isEnterprise()).deleteComment(login, repoId, commId), - booleanResponse -> sendToView(view -> { - if (booleanResponse.code() == 204) { - view.onRemoveReviewComment(groupPosition, commentPosition); - } else { - view.showMessage(R.string.error, R.string.error_deleting_comment); - } - })); - } - } - } - - @Override public void onHandleReaction(int vId, long idOrNumber, @ReactionsProvider.ReactionType int reactionType) { - if (getView() == null || getView().getPullRequest() == null) return; - PullRequest pullRequest = getView().getPullRequest(); - String login = pullRequest.getLogin(); - String repoId = pullRequest.getRepoId(); - Observable observable = getReactionsProvider().onHandleReaction(vId, idOrNumber, login, repoId, reactionType, isEnterprise()); - if (observable != null) //noinspection unchecked - manageObservable(observable); - } - - @Override public boolean isMerged(PullRequest pullRequest) { - return pullRequest != null && (pullRequest.isMerged() || !InputHelper.isEmpty(pullRequest.getMergedAt())); - } - - @Override public boolean isCallingApi(long id, int vId) { - return getReactionsProvider().isCallingApi(id, vId); - } - - @Override public void onHandleComment(@NonNull String text, @Nullable Bundle bundle) { - if (getView() == null) return; - PullRequest pullRequest = getView().getPullRequest(); - if (pullRequest != null) { - if (bundle == null) { - CommentRequestModel commentRequestModel = new CommentRequestModel(); - commentRequestModel.setBody(text); - manageDisposable(RxHelper.getObservable(RestProvider.getIssueService(isEnterprise()).createIssueComment(pullRequest.getLogin(), - pullRequest.getRepoId(), pullRequest.getNumber(), commentRequestModel)) - .doOnSubscribe(disposable -> sendToView(view -> view.showBlockingProgress(0))) - .subscribe(comment -> sendToView(view -> view.addComment(TimelineModel.constructComment(comment))), - throwable -> { - onError(throwable); - sendToView(PullRequestTimelineMvp.View::onHideBlockingProgress); - })); - } - } - } - - @Override public boolean isPreviouslyReacted(long commentId, int vId) { - return getReactionsProvider().isPreviouslyReacted(commentId, vId); - } - - @NonNull private ReactionsProvider getReactionsProvider() { - if (reactionsProvider == null) { - reactionsProvider = new ReactionsProvider(); - } - return reactionsProvider; - } - - @Override public void onClick(int groupPosition, int commentPosition, @NonNull View v, @NonNull ReviewCommentModel comment) { - if (getView() == null || getView().getPullRequest() == null) return; - if (v.getId() == R.id.commentMenu) { - PopupMenu popupMenu = new PopupMenu(v.getContext(), v); - popupMenu.inflate(R.menu.comments_menu); - String username = Login.getUser().getLogin(); - boolean isOwner = CommentsHelper.isOwner(username, getView().getPullRequest().getLogin(), comment.getUser().getLogin()) || isCollaborator; - popupMenu.getMenu().findItem(R.id.delete).setVisible(isOwner); - popupMenu.getMenu().findItem(R.id.edit).setVisible(isOwner); - popupMenu.setOnMenuItemClickListener(item1 -> { - if (getView() == null) return false; - if (item1.getItemId() == R.id.delete) { - getView().onShowReviewDeleteMsg(comment.getId(), groupPosition, commentPosition); - } else if (item1.getItemId() == R.id.reply) { - EditReviewCommentModel model = new EditReviewCommentModel(); - model.setGroupPosition(groupPosition); - model.setCommentPosition(commentPosition); - model.setInReplyTo(comment.getId()); - getView().onReplyOrCreateReview(comment.getUser(), comment.getBodyHtml(), groupPosition, commentPosition, model); - } else if (item1.getItemId() == R.id.edit) { - getView().onEditReviewComment(comment, groupPosition, commentPosition); - } else if (item1.getItemId() == R.id.share) { - ActivityHelper.shareUrl(v.getContext(), comment.getHtmlUrl()); - } - return true; - }); - popupMenu.show(); - } else { - onHandleReaction(v.getId(), comment.getId(), ReactionsProvider.REVIEW_COMMENT); - } - } - - @Override public void onLongClick(int groupPosition, int commentPosition, @NonNull View v, @NonNull ReviewCommentModel model) { - if (getView() == null || getView().getPullRequest() == null) return; - PullRequest pullRequest = getView().getPullRequest(); - String login = pullRequest.getLogin(); - String repoId = pullRequest.getRepoId(); - if (!InputHelper.isEmpty(login) && !InputHelper.isEmpty(repoId)) { - ReactionTypes type = ReactionTypes.get(v.getId()); - if (type != null) { - getView().showReactionsPopup(type, login, repoId, model.getId(), ReactionsProvider.REVIEW_COMMENT); - } else { - onClick(groupPosition, commentPosition, v, model); - } - } - } - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable PullRequest parameter) { - if (parameter == null) { - sendToView(BaseMvp.FAView::hideProgress); - return false; - } - String login = parameter.getLogin(); - String repoId = parameter.getRepoId(); - int number = parameter.getNumber(); - if (page <= 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - pages.clear(); - } - if (page > lastPage || lastPage == 0) { - sendToView(PullRequestTimelineMvp.View::hideProgress); - return false; - } - if (page == 1) { - manageObservable(RestProvider.getRepoService(isEnterprise()).isCollaborator(login, repoId, - Login.getUser().getLogin()) - .doOnNext(booleanResponse -> isCollaborator = booleanResponse.code() == 204)); - } - setCurrentPage(page); - if (parameter.getHead() != null) { - Observable> observable = Observable.zip( - RestProvider.getIssueService(isEnterprise()).getTimeline(login, repoId, number, page), - RestProvider.getReviewService(isEnterprise()).getPrReviewComments(login, repoId, number), - RestProvider.getPullRequestService(isEnterprise()).getPullStatus(login, repoId, parameter.getHead().getSha()) - .onErrorReturn(throwable -> RestProvider.getPullRequestService(isEnterprise()).getPullStatus(login, repoId, - parameter.getBase().getSha()).blockingFirst(new PullRequestStatusModel())), - (response, comments, status) -> { - if (response != null) { - lastPage = response.getLast(); - List models = TimelineConverter.INSTANCE.convert(response.getItems(), comments); - if (page == 1 && status != null) { - status.setMergable(parameter.isMergeable()); - status.setMergeableState(parameter.getMergeableState()); - if (status.getState() != null) { - models.add(0, new TimelineModel(status)); - } - } - return models; - } else { - return Collections.emptyList(); - } - }); - makeRestCall(observable, timeline -> sendToView(view -> view.onNotifyAdapter(timeline, page))); - return true; - } - return false; - } -// -// @Nullable private Observable getTimelineObservable(Response response, -// boolean isMergeable) { -// if (!response.hasErrors()) { -// PullRequestTimelineQuery.Data data = response.data(); -// if (data != null) { -// PullRequestTimelineQuery.Repository repo = data.repository(); -// PullRequestTimelineQuery.PullRequest pullRequest = repo != null ? repo.pullRequest() : null; -// if (pullRequest != null) { -// PullRequestTimelineQuery.Timeline timeline = pullRequest.timeline(); -// lastPage = timeline.pageInfo().hasNextPage() ? Integer.MAX_VALUE : 0; -// pages.clear(); -// ArrayList models = new ArrayList<>(); -// PullRequestTimelineQuery.PullRequestCommits pullRequestCommits = pullRequest.pullRequestCommits(); -// List commits = pullRequestCommits.pullRequestCommit(); -// if (commits != null && !commits.isEmpty() && page <= 1) { -// PullRequestTimelineQuery.Status status = commits.get(0).commit().status(); -// if (status != null) { -// models.add(new PullRequestTimelineModel(status, isMergeable)); -// } -// } -// List edges = timeline.edges(); -// if (edges != null) { -// Stream.of(edges).forEachIndexed((i, edge) -> pages.append(i, edge.cursor())); -// } -// List nodes = timeline.nodes(); -// if (nodes != null) { -// for (PullRequestTimelineQuery.Node node : nodes) { -// models.add(new PullRequestTimelineModel(node)); -// } -// } -// return RxHelper.getObservable(Observable.fromIterable(models)); -// } -// } -// } -// return null; -// } -// -// @NonNull private PullRequestTimelineQuery getTimelineBuilder(@NonNull String login, @NonNull String repoId, int number, int page) { -// return PullRequestTimelineQuery.builder() -// .owner(login) -// .name(repoId) -// .number(number) -// .page(getPage()) -// .build(); -// } -// -// @Nullable private String getPage() { -// return pages.size() != 0 ? pages.valueAt(pages.size() - 1) : ""; -// } -// -// private void loadEverything(@NonNull String login, @NonNull String repoId, int number, -// @NonNull String sha, boolean isMergeable, int page) { -// PullRequestTimelineQuery query = getTimelineBuilder(login, repoId, number, page); -// ApolloCall apolloCall = App.getInstance().getApolloClient().query(query); -// Observable observable = Rx2Apollo.from(apolloCall) -// .flatMap(response -> { -// Observable models = getTimelineObservable(response, isMergeable); -// return models != null ? models : RxHelper.getObservable(Observable.fromIterable(new ArrayList<>())); -// }); -// makeRestCall(observable.toList().toObservable(), -// pullRequestTimelineModels -> sendToView(view -> view.onNotifyAdapter(pullRequestTimelineModels, page))); -// } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullReqeustMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullReqeustMvp.java deleted file mode 100644 index 9b0e45c5e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullReqeustMvp.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.merge; - -import android.support.annotation.NonNull; - -import com.fastaccess.ui.base.mvp.BaseMvp; - -/** - * Created by Kosh on 18 Mar 2017, 12:11 PM - */ - -public interface MergePullReqeustMvp { - - interface MergeCallback { - void onMerge(@NonNull String msg, @NonNull String mergeMethod); - } - - interface View extends BaseMvp.FAView { - - } - - interface Presenter {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullRequestDialogFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullRequestDialogFragment.java deleted file mode 100644 index 9ee81a7bb..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullRequestDialogFragment.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.merge; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.TextInputLayout; -import android.support.v7.widget.AppCompatSpinner; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.modules.main.premium.PremiumActivity; - -import butterknife.BindView; -import butterknife.OnClick; -import butterknife.OnItemSelected; - -/** - * Created by Kosh on 18 Mar 2017, 12:13 PM - */ - -public class MergePullRequestDialogFragment extends BaseDialogFragment - implements MergePullReqeustMvp.View { - - @BindView(R.id.title) TextInputLayout title; - @BindView(R.id.mergeMethod) AppCompatSpinner mergeMethod; - - private MergePullReqeustMvp.MergeCallback mergeCallback; - - public static MergePullRequestDialogFragment newInstance(@Nullable String title) { - MergePullRequestDialogFragment view = new MergePullRequestDialogFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.EXTRA, title) - .end()); - return view; - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof MergePullReqeustMvp.MergeCallback) { - mergeCallback = (MergePullReqeustMvp.MergeCallback) context; - } else if (getParentFragment() instanceof MergePullReqeustMvp.MergeCallback) { - mergeCallback = (MergePullReqeustMvp.MergeCallback) getParentFragment(); - } - } - - @Override public void onDetach() { - mergeCallback = null; - super.onDetach(); - } - - @Override protected int fragmentLayout() { - return R.layout.merge_dialog_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (savedInstanceState == null) { - String titleMsg = getArguments().getString(BundleConstant.EXTRA); - if (!InputHelper.isEmpty(titleMsg)) { - if (title.getEditText() != null) title.getEditText().setText(titleMsg); - } - } - } - - @NonNull @Override public MergePullRequestPresenter providePresenter() { - return new MergePullRequestPresenter(); - } - - @OnClick({R.id.cancel, R.id.ok}) public void onClick(View view) { - if (view.getId() == R.id.ok) { - boolean isEmpty = InputHelper.isEmpty(title); - title.setError(isEmpty ? getString(R.string.required_field) : null); - if (isEmpty) return; - mergeCallback.onMerge(InputHelper.toString(title), mergeMethod.getSelectedItem().toString().toLowerCase()); - } - dismiss(); - } - - @OnItemSelected(R.id.mergeMethod) void onItemSelect(int position) { - if (position > 0) { - if (!PrefGetter.isProEnabled()) { - mergeMethod.setSelection(0); - PremiumActivity.Companion.startActivity(getContext()); - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullRequestPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullRequestPresenter.java deleted file mode 100644 index ab2f86ae8..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/pull_requests/pull_request/merge/MergePullRequestPresenter.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.ui.modules.repos.pull_requests.pull_request.merge; - -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by Kosh on 18 Mar 2017, 12:13 PM - */ - -public class MergePullRequestPresenter extends BasePresenter implements MergePullReqeustMvp.Presenter {} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogFragment.java b/app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogFragment.java deleted file mode 100644 index 691c7f822..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogFragment.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.fastaccess.ui.modules.repos.reactions; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.design.widget.AppBarLayout; -import android.support.v7.widget.Toolbar; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.provider.timeline.CommentsHelper; -import com.fastaccess.provider.timeline.ReactionsProvider; -import com.fastaccess.ui.adapter.UsersAdapter; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.widgets.AppbarRefreshLayout; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 11 Apr 2017, 11:30 AM - */ - -public class ReactionsDialogFragment extends BaseDialogFragment - implements ReactionsDialogMvp.View { - - @BindView(R.id.toolbar) Toolbar toolbar; - @BindView(R.id.appbar) AppBarLayout appbar; - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) AppbarRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private UsersAdapter adapter; - private OnLoadMore onLoadMore; - - public static ReactionsDialogFragment newInstance(@NonNull String login, @NonNull String repoId, - @NonNull ReactionTypes type, long idOrNumber, - @ReactionsProvider.ReactionType int reactionType) { - ReactionsDialogFragment view = new ReactionsDialogFragment(); - view.setArguments(Bundler.start() - .put(BundleConstant.EXTRA_TYPE, type) - .put(BundleConstant.EXTRA, repoId) - .put(BundleConstant.EXTRA_TWO, login) - .put(BundleConstant.EXTRA_THREE, reactionType) - .put(BundleConstant.ID, idOrNumber) - .end()); - return view; - } - - @Override protected int fragmentLayout() { - return R.layout.milestone_dialog_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - toolbar.setNavigationIcon(R.drawable.ic_clear); - toolbar.setNavigationOnClickListener(v -> dismiss()); - stateLayout.setEmptyText(R.string.no_reactions); - stateLayout.setOnReloadListener(v -> getPresenter().onCallApi(1, null)); - refresh.setOnRefreshListener(() -> getPresenter().onCallApi(1, null)); - recycler.setEmptyView(stateLayout, refresh); - adapter = new UsersAdapter(getPresenter().getUsers()); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - recycler.setAdapter(adapter); - recycler.addOnScrollListener(getLoadMore()); - if (savedInstanceState == null) { - getPresenter().onFragmentCreated(getArguments()); - } - toolbar.setTitle(SpannableBuilder.builder().append(getString(R.string.reactions)) - .append(" ") - .append(CommentsHelper.getEmoji(getPresenter().getReactionType()))); - fastScroller.attachRecyclerView(recycler); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @SuppressWarnings("unchecked") @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore(getPresenter()); - } - return onLoadMore; - } - - @NonNull @Override public ReactionsDialogPresenter providePresenter() { - return new ReactionsDialogPresenter(); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogMvp.java b/app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogMvp.java deleted file mode 100644 index f840e12ba..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogMvp.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.fastaccess.ui.modules.repos.reactions; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 11 Apr 2017, 11:19 AM - */ - -public interface ReactionsDialogMvp { - - interface View extends BaseMvp.FAView { - void onNotifyAdapter(@Nullable List items, int page); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.PaginationListener { - void onFragmentCreated(@Nullable Bundle bundle); - - @NonNull ArrayList getUsers(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogPresenter.java deleted file mode 100644 index 8032c665e..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/reactions/ReactionsDialogPresenter.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.fastaccess.ui.modules.repos.reactions; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; -import com.fastaccess.data.dao.Pageable; -import com.fastaccess.data.dao.ReactionsModel; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.data.dao.types.ReactionTypes; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.timeline.ReactionsProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -import io.reactivex.Observable; - -/** - * Created by Kosh on 11 Apr 2017, 11:20 AM - */ - -public class ReactionsDialogPresenter extends BasePresenter implements ReactionsDialogMvp.Presenter { - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - private ArrayList users = new ArrayList<>(); - @com.evernote.android.state.State String login; - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State long id; - @com.evernote.android.state.State ReactionTypes reactionType; - @com.evernote.android.state.State @ReactionsProvider.ReactionType int reactionTypeMode; - - @Override public void onFragmentCreated(@Nullable Bundle bundle) { - if (bundle != null) { - repoId = bundle.getString(BundleConstant.EXTRA); - login = bundle.getString(BundleConstant.EXTRA_TWO); - id = bundle.getLong(BundleConstant.ID); - reactionType = (ReactionTypes) bundle.getSerializable(BundleConstant.EXTRA_TYPE); - reactionTypeMode = bundle.getInt(BundleConstant.EXTRA_THREE); - onCallApi(1, null); - } - } - - @NonNull @Override public ArrayList getUsers() { - return users; - } - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable Object parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - if (page > lastPage || lastPage == 0 || (login == null || repoId == null || reactionType == null)) { - sendToView(ReactionsDialogMvp.View::hideProgress); - return false; - } - setCurrentPage(page); - Observable> observable = null; - switch (reactionTypeMode) { - case ReactionsProvider.COMMENT: - observable = RestProvider.getReactionsService(isEnterprise()) - .getIssueCommentReaction(login, repoId, id, reactionType.getContent(), page); - break; - case ReactionsProvider.COMMIT: - observable = RestProvider.getReactionsService(isEnterprise()) - .getCommitReaction(login, repoId, id, reactionType.getContent(), page); - break; - case ReactionsProvider.HEADER: - observable = RestProvider.getReactionsService(isEnterprise()) - .getIssueReaction(login, repoId, id, reactionType.getContent(), page); - break; - case ReactionsProvider.REVIEW_COMMENT: - observable = RestProvider.getReactionsService(isEnterprise()) - .getPullRequestReactions(login, repoId, id, reactionType.getContent(), page); - break; - } - if (observable == null) { - throw new NullPointerException("Reaction is null?"); - } - makeRestCall(observable, response -> { - lastPage = response.getLast(); - sendToView(view -> view.onNotifyAdapter(Stream.of(response.getItems()) - .filter(reactionsModel -> reactionsModel.getUser() != null) - .map(ReactionsModel::getUser) - .collect(Collectors.toList()), page)); - }); - return true; - } - - ReactionTypes getReactionType() { - return reactionType; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiActivity.kt deleted file mode 100644 index 409de198a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiActivity.kt +++ /dev/null @@ -1,183 +0,0 @@ -package com.fastaccess.ui.modules.repos.wiki - -import android.content.Context -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import android.support.design.widget.NavigationView -import android.support.v4.widget.DrawerLayout -import android.view.Gravity -import android.view.Menu -import android.view.MenuItem -import android.view.View -import android.widget.ProgressBar -import butterknife.BindView -import com.evernote.android.state.State -import com.fastaccess.R -import com.fastaccess.data.dao.NameParser -import com.fastaccess.data.dao.wiki.WikiContentModel -import com.fastaccess.helper.ActivityHelper -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.provider.scheme.LinkParserHelper -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.modules.repos.RepoPagerActivity -import com.fastaccess.ui.widgets.StateLayout -import com.prettifier.pretty.PrettifyWebView - -/** - * Created by Kosh on 13 Jun 2017, 8:35 PM - */ -class WikiActivity : BaseActivity(), WikiMvp.View { - - @BindView(R.id.wikiSidebar) lateinit var navMenu: NavigationView - @BindView(R.id.drawer) lateinit var drawerLayout: DrawerLayout - @BindView(R.id.progress) lateinit var progressbar: ProgressBar - @BindView(R.id.stateLayout) lateinit var stateLayout: StateLayout - @BindView(R.id.webView) lateinit var webView: PrettifyWebView - - @State var wiki = WikiContentModel(null, null, arrayListOf()) - @State var selectedTitle: String = "Home" - - override fun layout(): Int = R.layout.wiki_activity_layout - - override fun isTransparent(): Boolean = true - - override fun providePresenter(): WikiPresenter = WikiPresenter() - - override fun onLoadContent(wiki: WikiContentModel) { - hideProgress() - this.wiki = wiki - if (wiki.sidebar.isNotEmpty()) { - loadMenu() - } - if (wiki.content != null) { - val baseUrl = Uri.Builder().scheme(LinkParserHelper.PROTOCOL_HTTPS) - .authority(LinkParserHelper.HOST_DEFAULT) - .appendPath(presenter.login) - .appendPath(presenter.repoId) - .appendPath("wiki") - .build() - .toString() - webView.setWikiContent(wiki.content, baseUrl) - } - } - - override fun onSetPage(page: String) { - selectedTitle = page - } - - private fun loadMenu() { - navMenu.menu.clear() - wiki.sidebar.onEach { - navMenu.menu.add(R.id.languageGroup, it.title?.hashCode()!!, Menu.NONE, it.title) - .setCheckable(true) - .isChecked = it.title.toLowerCase() == selectedTitle.toLowerCase() - } - } - - override fun canBack(): Boolean = true - - override fun isSecured(): Boolean = false - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - if (savedInstanceState != null) { - onLoadContent(wiki) - } else { - presenter.onActivityCreated(intent) - } - navMenu.setNavigationItemSelectedListener { - onSidebarClicked(it) - return@setNavigationItemSelectedListener true - } - - toolbar?.subtitle = presenter.login + "/" + presenter.repoId - setTaskName("${presenter.login}/${presenter.repoId} - Wiki - $selectedTitle") - } - - private fun onSidebarClicked(item: MenuItem) { - this.selectedTitle = item.title.toString() - setTaskName("${presenter.login}/${presenter.repoId} - Wiki - $selectedTitle") - closeDrawerLayout() - wiki.sidebar.first { it.title?.toLowerCase() == item.title.toString().toLowerCase() } - .let { presenter.onSidebarClicked(it) } - } - - private fun closeDrawerLayout() { - drawerLayout.closeDrawer(Gravity.END) - } - - override fun onCreateOptionsMenu(menu: Menu?): Boolean { - menuInflater.inflate(R.menu.trending_menu, menu) - menu?.findItem(R.id.menu)?.setIcon(R.drawable.ic_menu) - return super.onCreateOptionsMenu(menu) - } - - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - when (item?.itemId) { - R.id.menu -> { - drawerLayout.openDrawer(Gravity.END) - return true - } - R.id.share -> { - ActivityHelper.shareUrl(this, "${LinkParserHelper.PROTOCOL_HTTPS}://${LinkParserHelper.HOST_DEFAULT}/" + - "${presenter.login}/${presenter.repoId}/wiki/$selectedTitle") - return true - } - android.R.id.home -> { - if (!presenter.login.isNullOrEmpty() && !presenter.repoId.isNullOrEmpty()) { - val nameParse = NameParser("") - nameParse.name = presenter.repoId!! - nameParse.username = presenter.login!! - nameParse.isEnterprise = isEnterprise - RepoPagerActivity.startRepoPager(this, nameParse) - } - finish() - return true - } - else -> return super.onOptionsItemSelected(item) - } - } - - override fun showMessage(titleRes: Int, msgRes: Int) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showMessage(titleRes: String, msgRes: String) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showErrorMessage(msgRes: String) { - hideProgress() - super.showErrorMessage(msgRes) - } - - override fun showProgress(resId: Int) { - progressbar.visibility = View.VISIBLE - stateLayout.showProgress() - } - - override fun hideProgress() { - progressbar.visibility = View.GONE - stateLayout.hideProgress() - } - - companion object { - fun getWiki(context: Context, repoId: String?, username: String?): Intent { - return getWiki(context, repoId, username, null) - } - - fun getWiki(context: Context, repoId: String?, username: String?, page: String?): Intent { - val intent = Intent(context, WikiActivity::class.java) - intent.putExtras(Bundler.start() - .put(BundleConstant.ID, repoId) - .put(BundleConstant.EXTRA, username) - .put(BundleConstant.EXTRA_TWO, page) - .end()) - return intent - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiMvp.kt deleted file mode 100644 index 200915947..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiMvp.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.ui.modules.repos.wiki - -import android.content.Intent -import com.fastaccess.data.dao.wiki.WikiContentModel -import com.fastaccess.data.dao.wiki.WikiSideBarModel -import com.fastaccess.ui.base.mvp.BaseMvp - -/** - * Created by Kosh on 13 Jun 2017, 8:11 PM - */ -interface WikiMvp { - interface View : BaseMvp.FAView { - fun onLoadContent(wiki: WikiContentModel) - fun onSetPage(page: String) - } - - interface Presenter { - fun onActivityCreated(intent: Intent?) - fun onSidebarClicked(sidebar: WikiSideBarModel) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiPresenter.kt deleted file mode 100644 index b1fe3efcf..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/repos/wiki/WikiPresenter.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.fastaccess.ui.modules.repos.wiki - -import android.content.Intent -import com.fastaccess.data.dao.wiki.WikiContentModel -import com.fastaccess.data.dao.wiki.WikiSideBarModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.RxHelper -import com.fastaccess.provider.rest.jsoup.JsoupProvider -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import io.reactivex.Observable -import org.jsoup.Jsoup -import org.jsoup.nodes.Document - -/** - * Created by Kosh on 13 Jun 2017, 8:14 PM - */ -class WikiPresenter : BasePresenter(), WikiMvp.Presenter { - - @com.evernote.android.state.State var repoId: String? = null - @com.evernote.android.state.State var login: String? = null - - override fun onActivityCreated(intent: Intent?) { - if (intent != null) { - val bundle = intent.extras - repoId = bundle.getString(BundleConstant.ID) - login = bundle.getString(BundleConstant.EXTRA) - val page = bundle.getString(BundleConstant.EXTRA_TWO) - if (!page.isNullOrEmpty()) { - sendToView { it.onSetPage(page) } - } - if (!repoId.isNullOrEmpty() && !login.isNullOrEmpty()) { - onSidebarClicked(WikiSideBarModel("Home", "$login/$repoId/wiki" + - if (!page.isNullOrEmpty()) "/$page" else "")) - } - } - } - - override fun onSidebarClicked(sidebar: WikiSideBarModel) { - manageViewDisposable(RxHelper.getObservable(JsoupProvider.getWiki().getWiki(sidebar.link)) - .flatMap { s -> RxHelper.getObservable(getWikiContent(s)) } - .doOnSubscribe { sendToView { it.showProgress(0) } } - .subscribe({ response -> sendToView { view -> view.onLoadContent(response) } }, - { throwable -> onError(throwable) }, { sendToView({ it.hideProgress() }) })) - } - - private fun getWikiContent(body: String?): Observable { - return Observable.fromPublisher { s -> - try { - val document: Document = Jsoup.parse(body, "") - val wikiWrapper = document.select("#wiki-wrapper") - if (wikiWrapper.isNotEmpty()) { - val cloneUrl = wikiWrapper.select(".clone-url") -// val bottomRightBar = wikiWrapper.select(".wiki-custom-sidebar") - if (cloneUrl.isNotEmpty()) { - cloneUrl.remove() - } -// if (bottomRightBar.isNotEmpty()) { -// bottomRightBar.remove() -// } - val headerHtml = wikiWrapper.select(".gh-header .gh-header-meta") - val revision = headerHtml.select("a.history") - if (revision.isNotEmpty()) { - revision.remove() - } - val header = "
    ${headerHtml.html()}
    " - val wikiContent = wikiWrapper.select(".wiki-content") - val content = header + wikiContent.select(".wiki-body").html() - val rightBarList = wikiContent.select(".wiki-pages").select("li") - val sidebarList = arrayListOf() - if (rightBarList.isNotEmpty()) { - rightBarList.onEach { - val sidebarTitle = it.select("a").text() - val sidebarLink = it.select("a").attr("href") - sidebarList.add(WikiSideBarModel(sidebarTitle, sidebarLink)) - } - } - s.onNext(WikiContentModel(content, "", sidebarList)) - } else { - s.onNext(WikiContentModel("

    No Wiki

    ", "", arrayListOf())) - } - } catch (e: Exception) { - e.printStackTrace() - } - s.onComplete() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/reviews/AddReviewDialogFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/reviews/AddReviewDialogFragment.kt deleted file mode 100644 index f98a14f3d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/reviews/AddReviewDialogFragment.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.fastaccess.ui.modules.reviews - -import android.content.Context -import android.graphics.Color -import android.os.Bundle -import android.support.v4.content.ContextCompat -import android.support.v7.widget.Toolbar -import android.view.View -import android.widget.TextView -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.CommitLinesModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.helper.InputHelper -import com.fastaccess.helper.ViewHelper -import com.fastaccess.ui.base.BaseDialogFragment -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment -import com.fastaccess.ui.modules.reviews.callback.ReviewCommentListener -import com.fastaccess.ui.widgets.SpannableBuilder - -/** - * Created by Kosh on 24 Jun 2017, 12:32 PM - */ -class AddReviewDialogFragment : BaseDialogFragment>() { - - @BindView(R.id.toolbar) lateinit var toolbar: Toolbar - @BindView(R.id.text) lateinit var textView: TextView - @BindView(R.id.lineNo) lateinit var lineNo: TextView - - private val commentEditorFragment: CommentEditorFragment? by lazy { - childFragmentManager.findFragmentByTag("CommentEditorFragment") as CommentEditorFragment? - } - private val spacePattern = "\\s+".toRegex() - - private var commentCallback: ReviewCommentListener? = null - - override fun onAttach(context: Context?) { - super.onAttach(context) - commentCallback = if (parentFragment is ReviewCommentListener) { - parentFragment as ReviewCommentListener - } else { - context as ReviewCommentListener - } - } - - override fun onDetach() { - commentCallback = null - super.onDetach() - } - - override fun fragmentLayout(): Int = R.layout.review_comment_dialog_layout - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - if (savedInstanceState == null) { - val fragment = CommentEditorFragment() - fragment.arguments = Bundler.start().put(BundleConstant.YES_NO_EXTRA, true).end() - childFragmentManager.beginTransaction() - .replace(R.id.commentFragmentContainer, fragment, "CommentEditorFragment") - .commitNow() - } - val item = arguments!!.getParcelable(BundleConstant.ITEM) - lineNo.text = SpannableBuilder.builder() - .append(if (item.leftLineNo >= 0) String.format("%s.", item.leftLineNo) else "") - .append(if (item.rightLineNo >= 0) String.format("%s.", item.rightLineNo) else "") - lineNo.visibility = if (InputHelper.isEmpty(lineNo)) View.GONE else View.VISIBLE - - val context = context ?: return - when (item.color) { - CommitLinesModel.ADDITION -> textView.setBackgroundColor(ViewHelper.getPatchAdditionColor(context)) - CommitLinesModel.DELETION -> textView.setBackgroundColor(ViewHelper.getPatchDeletionColor(context)) - CommitLinesModel.PATCH -> textView.setBackgroundColor(ViewHelper.getPatchRefColor(context)) - else -> textView.setBackgroundColor(Color.TRANSPARENT) - } - if (item.noNewLine) { - textView.text = SpannableBuilder.builder().append(item.text.replace(spacePattern, " ")).append(" ") - .append(ContextCompat.getDrawable(context, R.drawable.ic_newline)) - } else { - textView.text = item.text.replace(spacePattern, " ") - } - toolbar.setTitle(R.string.add_comment) - toolbar.setNavigationIcon(R.drawable.ic_clear) - toolbar.setNavigationOnClickListener { dismiss() } - toolbar.inflateMenu(R.menu.add_menu) - toolbar.setOnMenuItemClickListener { - if (commentEditorFragment?.getEditText()?.text.isNullOrEmpty()) { - commentEditorFragment?.getEditText()?.error = getString(R.string.required_field) - } else { - commentEditorFragment?.getEditText()?.error = null - commentCallback?.onCommentAdded(InputHelper.toString(commentEditorFragment?.getEditText()?.text), - item, arguments!!.getBundle(BundleConstant.EXTRA)) - dismiss() - } - return@setOnMenuItemClickListener true - } - } - - override fun providePresenter(): BasePresenter = BasePresenter() - - companion object { - fun newInstance(commitLinesModel: CommitLinesModel, bundle: Bundle? = null): AddReviewDialogFragment { - val dialog = AddReviewDialogFragment() - dialog.arguments = Bundler.start() - .put(BundleConstant.ITEM, commitLinesModel) - .put(BundleConstant.EXTRA, bundle) - .end() - return dialog - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/reviews/callback/ReviewCommentListener.kt b/app/src/main/java/com/fastaccess/ui/modules/reviews/callback/ReviewCommentListener.kt deleted file mode 100644 index 2c9e8ad4a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/reviews/callback/ReviewCommentListener.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.fastaccess.ui.modules.reviews.callback - -import android.os.Bundle -import com.fastaccess.data.dao.CommitLinesModel - -/** - * Created by Kosh on 24 Jun 2017, 12:38 PM - */ -interface ReviewCommentListener { - fun onCommentAdded(comment: String, item: CommitLinesModel, bundle: Bundle?) -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesActivity.kt deleted file mode 100644 index e04b5fc80..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesActivity.kt +++ /dev/null @@ -1,151 +0,0 @@ -package com.fastaccess.ui.modules.reviews.changes - -import android.content.Context -import android.os.Bundle -import android.support.v4.content.ContextCompat -import android.support.v7.widget.Toolbar -import android.view.View -import android.widget.Spinner -import butterknife.BindView -import com.evernote.android.state.State -import com.fastaccess.R -import com.fastaccess.data.dao.ReviewRequestModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.helper.InputHelper -import com.fastaccess.ui.base.BaseDialogFragment -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment - -/** - * Created by Kosh on 25 Jun 2017, 1:25 AM - */ -class ReviewChangesActivity : BaseDialogFragment(), ReviewChangesMvp.View { - - @BindView(R.id.toolbar) lateinit var toolbar: Toolbar - @BindView(R.id.reviewMethod) lateinit var spinner: Spinner - - @State var reviewRequest: ReviewRequestModel? = null - @State var repoId: String? = null - @State var owner: String? = null - @State var number: Long? = null - @State var isClosed: Boolean = false - @State var isAuthor: Boolean = false - - private var subimssionCallback: ReviewChangesMvp.ReviewSubmissionCallback? = null - - private val commentEditorFragment: CommentEditorFragment? by lazy { - childFragmentManager.findFragmentByTag("commentContainer") as CommentEditorFragment? - } - - override fun onAttach(context: Context?) { - super.onAttach(context) - if (parentFragment is ReviewChangesMvp.ReviewSubmissionCallback) { - subimssionCallback = parentFragment as ReviewChangesMvp.ReviewSubmissionCallback - } else if (context is ReviewChangesMvp.ReviewSubmissionCallback) { - subimssionCallback = context - } - } - - override fun onDetach() { - subimssionCallback = null - super.onDetach() - } - - override fun providePresenter(): ReviewChangesPresenter = ReviewChangesPresenter() - - override fun fragmentLayout(): Int = R.layout.add_review_dialog_layout - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - if (savedInstanceState == null) { - val fragment = CommentEditorFragment() - fragment.arguments = Bundler.start().put(BundleConstant.YES_NO_EXTRA, true).end() - childFragmentManager.beginTransaction() - .replace(R.id.commentContainer, fragment, "commentContainer") - .commit() - val bundle = arguments!! - reviewRequest = bundle.getParcelable(BundleConstant.EXTRA) - repoId = bundle.getString(BundleConstant.EXTRA_TWO) - owner = bundle.getString(BundleConstant.EXTRA_THREE) - number = bundle.getLong(BundleConstant.ID) - isClosed = bundle.getBoolean(BundleConstant.EXTRA_FIVE) - isAuthor = bundle.getBoolean(BundleConstant.EXTRA_FOUR) - } - toolbar.navigationIcon = ContextCompat.getDrawable(context!!, R.drawable.ic_clear) - toolbar.inflateMenu(R.menu.done_menu) - toolbar.setNavigationOnClickListener { dismiss() } - toolbar.setOnMenuItemClickListener { - if (it.itemId == R.id.submit) { - if (spinner.selectedItemPosition != 0 && commentEditorFragment?.getEditText()?.text.isNullOrEmpty()) { - commentEditorFragment?.getEditText()?.error = getString(R.string.required_field) - } else { - commentEditorFragment?.getEditText()?.error = null - presenter.onSubmit(reviewRequest!!, repoId!!, owner!!, number!!, InputHelper.toString(commentEditorFragment?.getEditText()?.text) - , spinner.selectedItem as String) - } - } - return@setOnMenuItemClickListener true - } - - if (isAuthor || isClosed) { - spinner.setSelection(2, true) - spinner.isEnabled = false - } - } - - override fun onSuccessfullySubmitted() { - hideProgress() - subimssionCallback?.onSuccessfullyReviewed() - dismiss() - } - - override fun onErrorSubmitting() { - showErrorMessage(getString(R.string.network_error)) - } - - override fun showMessage(titleRes: Int, msgRes: Int) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showMessage(titleRes: String, msgRes: String) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showErrorMessage(msgRes: String) { - hideProgress() - super.showErrorMessage(msgRes) - } - - override fun onSendActionClicked(text: String, bundle: Bundle?) {} - - override fun onTagUser(username: String) {} - - override fun onClearEditText() { - commentEditorFragment?.commentText?.setText("") - } - - override fun getNamesToTag(): ArrayList? { - return arrayListOf() - } - - companion object { - fun startForResult(reviewChanges: ReviewRequestModel, repoId: String, owner: String, number: Long, - isAuthor: Boolean, isEnterprise: Boolean, isClosed: Boolean): ReviewChangesActivity { - val fragment = ReviewChangesActivity() - val bundle = Bundler.start() - .put(BundleConstant.EXTRA, reviewChanges) - .put(BundleConstant.EXTRA_TWO, repoId) - .put(BundleConstant.EXTRA_THREE, owner) - .put(BundleConstant.EXTRA_FOUR, isAuthor) - .put(BundleConstant.ID, number) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .put(BundleConstant.EXTRA_FIVE, isClosed) - .end() - fragment.arguments = bundle - return fragment - } - } - - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesMvp.kt deleted file mode 100644 index 57ff1671c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesMvp.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.fastaccess.ui.modules.reviews.changes - -import com.fastaccess.data.dao.ReviewRequestModel -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.modules.editor.comment.CommentEditorFragment - -/** - * Created by Kosh on 25 Jun 2017, 1:15 AM - */ -interface ReviewChangesMvp { - - interface View : BaseMvp.FAView, CommentEditorFragment.CommentListener { - fun onSuccessfullySubmitted() - fun onErrorSubmitting() - } - - interface Presenter { - fun onSubmit(reviewRequest: ReviewRequestModel, repoId: String, owner: String, number: Long, comment: String, method: String) - } - - interface ReviewSubmissionCallback { - fun onSuccessfullyReviewed() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesPresenter.kt deleted file mode 100644 index 7667fbb45..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/reviews/changes/ReviewChangesPresenter.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.fastaccess.ui.modules.reviews.changes - -import com.fastaccess.data.dao.ReviewRequestModel -import com.fastaccess.provider.rest.RestProvider -import com.fastaccess.ui.base.mvp.presenter.BasePresenter - -/** - * Created by Kosh on 25 Jun 2017, 1:16 AM - */ -class ReviewChangesPresenter : BasePresenter(), ReviewChangesMvp.Presenter { - - override fun onSubmit(reviewRequest: ReviewRequestModel, repoId: String, owner: String, number: Long, comment: String, method: String) { - reviewRequest.body = comment - reviewRequest.event = method.replace(" ", "_").toUpperCase() - makeRestCall(RestProvider.getReviewService(isEnterprise).submitPrReview(owner, repoId, number, reviewRequest), { - if (it.isSuccessful && it.code() == 200) { - sendToView { it.onSuccessfullySubmitted() } - } else { - sendToView { it.onErrorSubmitting() } - } - }, false) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/SearchActivity.java b/app/src/main/java/com/fastaccess/ui/modules/search/SearchActivity.java deleted file mode 100644 index 5339f4ba9..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/SearchActivity.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.fastaccess.ui.modules.search; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.design.widget.AppBarLayout; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; -import android.text.Editable; -import android.view.View; -import android.widget.ArrayAdapter; -import android.widget.TextView; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.TabsCountStateModel; -import com.fastaccess.data.dao.model.SearchHistory; -import com.fastaccess.helper.AnimHelper; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.widgets.FontAutoCompleteEditText; -import com.fastaccess.ui.widgets.ForegroundImageView; -import com.fastaccess.ui.widgets.ViewPagerView; - -import java.text.NumberFormat; -import java.util.HashSet; -import java.util.LinkedHashSet; - -import butterknife.BindView; -import butterknife.OnClick; -import butterknife.OnEditorAction; -import butterknife.OnTextChanged; - -/** - * Created by Kosh on 08 Dec 2016, 8:22 PM - */ - -public class SearchActivity extends BaseActivity implements SearchMvp.View { - - @BindView(R.id.searchEditText) FontAutoCompleteEditText searchEditText; - @BindView(R.id.clear) ForegroundImageView clear; - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.appbar) AppBarLayout appbar; - @BindView(R.id.pager) ViewPagerView pager; - @State HashSet tabsCountSet = new LinkedHashSet<>(); - - private NumberFormat numberFormat = NumberFormat.getNumberInstance(); - private ArrayAdapter adapter; - - - public static Intent getIntent(@NonNull Context context, @Nullable String query) { - Intent intent = new Intent(context, SearchActivity.class); - intent.putExtra("search", query); - return intent; - } - - @OnTextChanged(value = R.id.searchEditText, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) - void onTextChange(Editable s) { - String text = s.toString(); - if (text.length() == 0) { - AnimHelper.animateVisibility(clear, false); - } else { - AnimHelper.animateVisibility(clear, true); - } - } - - @OnClick(R.id.search) void onSearchClicked() { - getPresenter().onSearchClicked(pager, searchEditText); - } - - @OnEditorAction(R.id.searchEditText) boolean onEditor() { - onSearchClicked(); - return true; - } - - @OnClick(value = {R.id.clear}) void onClear(View view) { - if (view.getId() == R.id.clear) { - searchEditText.setText(""); - } - } - - @Override protected int layout() { - return R.layout.search_layout; - } - - @Override protected boolean isTransparent() { - return false; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public SearchPresenter providePresenter() { - return new SearchPresenter(); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle(""); - pager.setAdapter(new FragmentsPagerAdapter(getSupportFragmentManager(), FragmentPagerAdapterModel.buildForSearch(this))); - tabs.setupWithViewPager(pager); - searchEditText.setAdapter(getAdapter()); - searchEditText.setOnItemClickListener((parent, view, position, id) -> getPresenter().onSearchClicked(pager, searchEditText)); - if (!tabsCountSet.isEmpty()) { - setupTab(); - } - if (savedInstanceState == null && getIntent() != null) { - if (getIntent().hasExtra("search")) { - searchEditText.setText(getIntent().getStringExtra("search")); - getPresenter().onSearchClicked(pager, searchEditText); - } - } - tabs.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager) { - @Override public void onTabReselected(TabLayout.Tab tab) { - super.onTabReselected(tab); - onScrollTop(tab.getPosition()); - } - }); - } - - @Override public void onNotifyAdapter(@Nullable SearchHistory query) { - if (query == null) getAdapter().notifyDataSetChanged(); - else getAdapter().add(query); - } - - @Override public void onSetCount(int count, int index) { - TabsCountStateModel model = new TabsCountStateModel(); - model.setCount(count); - model.setTabIndex(index); - tabsCountSet.add(model); - TextView textView = ViewHelper.getTabTextView(tabs, index); - if (index == 0) { - textView.setText(String.format("%s(%s)", getString(R.string.repos), numberFormat.format(count))); - } else if (index == 1) { - textView.setText(String.format("%s(%s)", getString(R.string.users), numberFormat.format(count))); - } else if (index == 2) { - textView.setText(String.format("%s(%s)", getString(R.string.issues), numberFormat.format(count))); - } else if (index == 3) { - textView.setText(String.format("%s(%s)", getString(R.string.code), numberFormat.format(count))); - } - } - - @Override public void onScrollTop(int index) { - if (pager == null || pager.getAdapter() == null) return; - Fragment fragment = (BaseFragment) pager.getAdapter().instantiateItem(pager, index); - if (fragment instanceof BaseFragment) { - ((BaseFragment) fragment).onScrollTop(index); - } - } - - private ArrayAdapter getAdapter() { - if (adapter == null) adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, getPresenter().getHints()); - return adapter; - } - - private void setupTab() { - for (TabsCountStateModel model : tabsCountSet) { - int index = model.getTabIndex(); - int count = model.getCount(); - TextView textView = ViewHelper.getTabTextView(tabs, index); - if (index == 0) { - textView.setText(String.format("%s(%s)", getString(R.string.repos), numberFormat.format(count))); - } else if (index == 1) { - textView.setText(String.format("%s(%s)", getString(R.string.users), numberFormat.format(count))); - } else if (index == 2) { - textView.setText(String.format("%s(%s)", getString(R.string.issues), numberFormat.format(count))); - } else if (index == 3) { - textView.setText(String.format("%s(%s)", getString(R.string.code), numberFormat.format(count))); - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/SearchMvp.java b/app/src/main/java/com/fastaccess/ui/modules/search/SearchMvp.java deleted file mode 100644 index 84d515c88..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/SearchMvp.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.fastaccess.ui.modules.search; - -import android.support.annotation.IntRange; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.view.ViewPager; -import android.widget.AutoCompleteTextView; - -import com.fastaccess.data.dao.model.SearchHistory; -import com.fastaccess.ui.base.mvp.BaseMvp; - -import java.util.ArrayList; - -/** - * Created by Kosh on 08 Dec 2016, 8:19 PM - */ - -public interface SearchMvp { - - interface View extends BaseMvp.FAView { - void onNotifyAdapter(@Nullable SearchHistory query); - - void onSetCount(int count, @IntRange(from = 0, to = 3) int index); - } - - interface Presenter extends BaseMvp.FAPresenter { - - @NonNull ArrayList getHints(); - - void onSearchClicked(@NonNull ViewPager viewPager, @NonNull AutoCompleteTextView editText); - - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/SearchPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/search/SearchPresenter.java deleted file mode 100644 index 4080c4150..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/SearchPresenter.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.fastaccess.ui.modules.search; - -import android.support.annotation.NonNull; -import android.support.v4.view.ViewPager; -import android.widget.AutoCompleteTextView; - -import com.annimon.stream.Stream; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.SearchHistory; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.search.code.SearchCodeFragment; -import com.fastaccess.ui.modules.search.issues.SearchIssuesFragment; -import com.fastaccess.ui.modules.search.repos.SearchReposFragment; -import com.fastaccess.ui.modules.search.users.SearchUsersFragment; - -import java.util.ArrayList; - - -/** - * Created by Kosh on 08 Dec 2016, 8:20 PM - */ -public class SearchPresenter extends BasePresenter implements SearchMvp.Presenter { - private ArrayList hints = new ArrayList<>(); - - @Override protected void onAttachView(@NonNull SearchMvp.View view) { - super.onAttachView(view); - if (hints.isEmpty()) { - manageDisposable(SearchHistory.getHistory() - .subscribe(strings -> { - hints.clear(); - if (strings != null) hints.addAll(strings); - view.onNotifyAdapter(null); - })); - } - } - - @NonNull @Override public ArrayList getHints() { - return hints; - } - - @Override public void onSearchClicked(@NonNull ViewPager viewPager, @NonNull AutoCompleteTextView editText) { - boolean isEmpty = InputHelper.isEmpty(editText) || InputHelper.toString(editText).length() < 2; - editText.setError(isEmpty ? editText.getResources().getString(R.string.minimum_three_chars) : null); - if (!isEmpty) { - editText.dismissDropDown(); - AppHelper.hideKeyboard(editText); - String query = InputHelper.toString(editText); - SearchReposFragment repos = (SearchReposFragment) viewPager.getAdapter().instantiateItem(viewPager, 0); - SearchUsersFragment users = (SearchUsersFragment) viewPager.getAdapter().instantiateItem(viewPager, 1); - SearchIssuesFragment issues = (SearchIssuesFragment) viewPager.getAdapter().instantiateItem(viewPager, 2); - SearchCodeFragment code = (SearchCodeFragment) viewPager.getAdapter().instantiateItem(viewPager, 3); - repos.onQueueSearch(query); - users.onQueueSearch(query); - issues.onQueueSearch(query); - code.onQueueSearch(query, true); - boolean noneMatch = Stream.of(hints).noneMatch(value -> value.getText().equalsIgnoreCase(query)); - if (noneMatch) { - SearchHistory searchHistory = new SearchHistory(query); - manageObservable(searchHistory.save(searchHistory).toObservable()); - sendToView(view -> view.onNotifyAdapter(new SearchHistory(query))); - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/SearchUserActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/search/SearchUserActivity.kt deleted file mode 100644 index d323c4ea2..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/SearchUserActivity.kt +++ /dev/null @@ -1,109 +0,0 @@ -package com.fastaccess.ui.modules.search - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.text.Editable -import android.view.View -import android.widget.CheckBox -import butterknife.BindView -import butterknife.OnClick -import butterknife.OnEditorAction -import butterknife.OnTextChanged -import com.evernote.android.state.State -import com.fastaccess.R -import com.fastaccess.helper.AnimHelper -import com.fastaccess.helper.AppHelper -import com.fastaccess.helper.InputHelper -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.search.repos.SearchReposFragment -import com.fastaccess.ui.widgets.FontAutoCompleteEditText - -class SearchUserActivity : BaseActivity>() { - - @BindView(R.id.forkCheckBox) lateinit var forkCheckBox: CheckBox - @BindView(R.id.clear) lateinit var clear: View - @BindView(R.id.searchEditText) lateinit var searchEditText: FontAutoCompleteEditText - - @State var username = "" - @State var searchTerm = "" - - @OnTextChanged(value = [R.id.searchEditText], callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) - fun onTextChange(str: Editable) { - searchTerm = str.toString() - if (searchTerm.isEmpty()) { - AnimHelper.animateVisibility(clear, false) - } else { - AnimHelper.animateVisibility(clear, true) - } - } - - @OnClick(R.id.search) fun onSearchClicked() { - searchTerm = searchEditText.text.toString() - makeSearch() - } - - @OnClick(R.id.forkCheckBox) fun checkBoxClicked() { - onSearchClicked() - } - - @OnEditorAction(R.id.searchEditText) fun onEditor(): Boolean { - onSearchClicked() - return true - } - - @OnClick(R.id.clear) internal fun onClear(view: View) { - if (view.id == R.id.clear) { - searchEditText.setText("") - } - } - - override fun layout(): Int = R.layout.activity_search_user - - override fun isTransparent(): Boolean = false - - override fun canBack(): Boolean = true - - override fun providePresenter(): BasePresenter = BasePresenter() - - override fun isSecured(): Boolean = false - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - if (savedInstanceState == null) { - val args = intent.extras - username = args.getString(USERNAME) - if (InputHelper.isEmpty(username)) { - finish() - return - } - searchTerm = args.getString(SEARCH_TERM) - supportFragmentManager.beginTransaction() - .replace(R.id.containerFragment, SearchReposFragment.newInstance(), "SearchReposFragment") - .commit() - } - searchEditText.setText(searchTerm) - onSearchClicked() - } - - private fun makeSearch() { - val query = "user:$username $searchTerm fork:${forkCheckBox.isChecked}" - getFragment()?.onQueueSearch(query) - } - - private fun getFragment() = AppHelper.getFragmentByTag(supportFragmentManager, "SearchReposFragment") as? SearchReposFragment? - - companion object { - val USERNAME = "username" - val SEARCH_TERM = "search" - - fun getIntent(context: Context, username: String, searchTerm: String?): Intent { - val intent = Intent(context, SearchUserActivity::class.java) - intent.putExtra(USERNAME, username) - intent.putExtra(SEARCH_TERM, searchTerm) - return intent - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodeFragment.java b/app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodeFragment.java deleted file mode 100644 index 34c13eb7f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodeFragment.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.fastaccess.ui.modules.search.code; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.SearchCodeModel; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.adapter.SearchCodeAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.search.SearchMvp; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class SearchCodeFragment extends BaseFragment implements SearchCodeMvp.View { - - @State String searchQuery = ""; - @State boolean showRepoName; - - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private SearchCodeAdapter adapter; - private SearchMvp.View countCallback; - - public static SearchCodeFragment newInstance() { - return new SearchCodeFragment(); - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof SearchMvp.View) { - countCallback = (SearchMvp.View) context; - } - } - - @Override public void onDetach() { - countCallback = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void onSetTabCount(int count) { - if (countCallback != null) countCallback.onSetCount(count, 3); - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - stateLayout.setEmptyText(R.string.no_search_results); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - adapter = new SearchCodeAdapter(getPresenter().getCodes()); - adapter.showRepoName(showRepoName); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addDivider(); - if (!InputHelper.isEmpty(searchQuery) && getPresenter().getCodes().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - if (InputHelper.isEmpty(searchQuery)) { - stateLayout.showEmptyState(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public SearchCodePresenter providePresenter() { - return new SearchCodePresenter(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @Override public void onSetSearchQuery(@NonNull String query, boolean showRepoName) { - this.searchQuery = query; - this.showRepoName = showRepoName; - getLoadMore().reset(); - adapter.clear(); - adapter.showRepoName(showRepoName); - if (!InputHelper.isEmpty(query)) { - recycler.removeOnScrollListener(getLoadMore()); - recycler.addOnScrollListener(getLoadMore()); - onRefresh(); - } - } - - @Override public void onQueueSearch(@NonNull String query) { - this.searchQuery = query; - if (getView() != null) - onSetSearchQuery(query, false); - } - - @Override public void onQueueSearch(@NonNull String query, boolean showRepoName) { - this.searchQuery = query; - if (getView() != null) - onSetSearchQuery(query, showRepoName); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), searchQuery); - } - onLoadMore.setParameter(searchQuery); - return onLoadMore; - } - - @Override public void onItemClicked(@NonNull SearchCodeModel item) { - if (item.getUrl() != null) { - SchemeParser.launchUri(getContext(), item.getHtmlUrl()); - } else { - showErrorMessage(getString(R.string.no_url)); - } - } - - @Override public void onRefresh() { - if (searchQuery.length() == 0) { - refresh.setRefreshing(false); - return; - } - getPresenter().onCallApi(1, searchQuery); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodeMvp.java b/app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodeMvp.java deleted file mode 100644 index e008303ab..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodeMvp.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.fastaccess.ui.modules.search.code; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.SearchCodeModel; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface SearchCodeMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - void onSetTabCount(int count); - - void onSetSearchQuery(@NonNull String query, boolean showRepoName); - - void onQueueSearch(@NonNull String query); - - void onQueueSearch(@NonNull String query, boolean showRepoName); - - @NonNull OnLoadMore getLoadMore(); - - void onItemClicked(@NonNull SearchCodeModel item); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getCodes(); - - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodePresenter.java deleted file mode 100644 index bde4b8989..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/code/SearchCodePresenter.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.fastaccess.ui.modules.search.code; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.SearchCodeModel; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class SearchCodePresenter extends BasePresenter implements SearchCodeMvp.Presenter { - - private ArrayList codes = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0 || parameter == null) { - sendToView(SearchCodeMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getSearchService(isEnterprise()).searchCode(parameter, page), - response -> { - lastPage = response.getLast(); - sendToView(view -> { - view.onNotifyAdapter(response.isIncompleteResults() ? null : response.getItems(), page); - if (!response.isIncompleteResults()) { - view.onSetTabCount(response.getTotalCount()); - } else { - view.onSetTabCount(0); - view.showMessage(R.string.error, R.string.search_results_warning); - } - }); - }); - return true; - } - - @NonNull @Override public ArrayList getCodes() { - return codes; - } - - @Override public void onItemClick(int position, View v, SearchCodeModel item) { - if (getView() != null) { - getView().onItemClicked(item); - } - } - - @Override public void onItemLongClick(int position, View v, SearchCodeModel item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesFragment.java b/app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesFragment.java deleted file mode 100644 index fb329610f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesFragment.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.fastaccess.ui.modules.search.issues; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.IssuesAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.repos.extras.popup.IssuePopupFragment; -import com.fastaccess.ui.modules.search.SearchMvp; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class SearchIssuesFragment extends BaseFragment implements SearchIssuesMvp.View { - - @State String searchQuery = ""; - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private IssuesAdapter adapter; - private SearchMvp.View countCallback; - - public static SearchIssuesFragment newInstance() { - return new SearchIssuesFragment(); - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof SearchMvp.View) { - countCallback = (SearchMvp.View) context; - } - } - - @Override public void onDetach() { - countCallback = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void onSetTabCount(int count) { - if (countCallback != null) countCallback.onSetCount(count, 2); - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - stateLayout.setEmptyText(R.string.no_search_results); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - adapter = new IssuesAdapter(getPresenter().getIssues(), false, true, true); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addDivider(); - if (!InputHelper.isEmpty(searchQuery) && getPresenter().getIssues().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - if (InputHelper.isEmpty(searchQuery)) { - stateLayout.showEmptyState(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public SearchIssuesPresenter providePresenter() { - return new SearchIssuesPresenter(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - - refresh.setRefreshing(true); - - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @Override public void onSetSearchQuery(@NonNull String query) { - this.searchQuery = query; - getLoadMore().reset(); - adapter.clear(); - if (!InputHelper.isEmpty(query)) { - recycler.removeOnScrollListener(getLoadMore()); - recycler.addOnScrollListener(getLoadMore()); - onRefresh(); - } - } - - @Override public void onQueueSearch(@NonNull String query) { - this.searchQuery = query; - if (getView() != null) - onSetSearchQuery(query); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), searchQuery); - } - onLoadMore.setParameter(searchQuery); - return onLoadMore; - } - - @Override public void onShowPopupDetails(@NonNull Issue item) { - IssuePopupFragment.showPopup(getChildFragmentManager(), item); - } - - @Override public void onRefresh() { - if (searchQuery.length() == 0) { - refresh.setRefreshing(false); - return; - } - getPresenter().onCallApi(1, searchQuery); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesMvp.java b/app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesMvp.java deleted file mode 100644 index 64efcff40..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesMvp.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.fastaccess.ui.modules.search.issues; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface SearchIssuesMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - void onSetTabCount(int count); - - void onSetSearchQuery(@NonNull String query); - - void onQueueSearch(@NonNull String query); - - @NonNull OnLoadMore getLoadMore(); - - void onShowPopupDetails(@NonNull Issue item); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getIssues(); - - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesPresenter.java deleted file mode 100644 index 667179070..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/issues/SearchIssuesPresenter.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.fastaccess.ui.modules.search.issues; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Issue; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class SearchIssuesPresenter extends BasePresenter implements SearchIssuesMvp.Presenter { - - private ArrayList issues = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0 || parameter == null) { - sendToView(SearchIssuesMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getSearchService(isEnterprise()).searchIssues(parameter, page), - response -> { - lastPage = response.getLast(); - sendToView(view -> { - view.onNotifyAdapter(response.isIncompleteResults() ? null : response.getItems(), page); - if (!response.isIncompleteResults()) { - view.onSetTabCount(response.getTotalCount()); - } else { - view.onSetTabCount(0); - view.showMessage(R.string.error, R.string.search_results_warning); - } - }); - }); - return true; - } - - @NonNull @Override public ArrayList getIssues() { - return issues; - } - - @Override public void onItemClick(int position, View v, Issue item) { - SchemeParser.launchUri(v.getContext(), item.getHtmlUrl()); - } - - @Override public void onItemLongClick(int position, View v, Issue item) { - if (getView() != null) getView().onShowPopupDetails(item); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposFragment.java b/app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposFragment.java deleted file mode 100644 index f5856eecb..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposFragment.java +++ /dev/null @@ -1,171 +0,0 @@ -package com.fastaccess.ui.modules.search.repos; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.ReposAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.search.SearchMvp; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class SearchReposFragment extends BaseFragment implements SearchReposMvp.View { - - @State String searchQuery = ""; - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private ReposAdapter adapter; - private SearchMvp.View countCallback; - - public static SearchReposFragment newInstance() { - return new SearchReposFragment(); - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof SearchMvp.View) { - countCallback = (SearchMvp.View) context; - } - } - - @Override public void onDetach() { - countCallback = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void onSetTabCount(int count) { - if (countCallback != null) countCallback.onSetCount(count, 0); - } - - @Override protected int fragmentLayout() { - return R.layout.micro_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - if (savedInstanceState == null) { - stateLayout.hideProgress(); - } - stateLayout.setEmptyText(R.string.no_search_results); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - adapter = new ReposAdapter(getPresenter().getRepos(), true, true); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - if (!InputHelper.isEmpty(searchQuery) && getPresenter().getRepos().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - if (InputHelper.isEmpty(searchQuery)) { - stateLayout.showEmptyState(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public SearchReposPresenter providePresenter() { - return new SearchReposPresenter(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @Override public void onSetSearchQuery(@NonNull String query) { - this.searchQuery = query; - getLoadMore().reset(); - adapter.clear(); - if (!InputHelper.isEmpty(query)) { - recycler.removeOnScrollListener(getLoadMore()); - recycler.addOnScrollListener(getLoadMore()); - onRefresh(); - } - } - - @Override public void onQueueSearch(@NonNull String query) { - this.searchQuery = query; - if (getView() != null) - onSetSearchQuery(query); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), searchQuery); - } - onLoadMore.setParameter(searchQuery); - return onLoadMore; - } - - @Override public void onRefresh() { - if (searchQuery.length() == 0) { - refresh.setRefreshing(false); - return; - } - getPresenter().onCallApi(1, searchQuery); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposMvp.java b/app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposMvp.java deleted file mode 100644 index c0a9abd51..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposMvp.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.fastaccess.ui.modules.search.repos; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface SearchReposMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - void onSetTabCount(int count); - - void onSetSearchQuery(@NonNull String query); - - void onQueueSearch(@NonNull String query); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getRepos(); - - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposPresenter.java deleted file mode 100644 index 6cfc79e41..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/repos/SearchReposPresenter.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.fastaccess.ui.modules.search.repos; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.Repo; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class SearchReposPresenter extends BasePresenter implements SearchReposMvp.Presenter { - - private ArrayList repos = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0 || parameter == null) { - sendToView(SearchReposMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getSearchService(isEnterprise()).searchRepositories(parameter, page), - response -> { - lastPage = response.getLast(); - sendToView(view -> { - view.onNotifyAdapter(response.isIncompleteResults() ? null : response.getItems(), page); - if (!response.isIncompleteResults()) { - view.onSetTabCount(response.getTotalCount()); - } else { - view.onSetTabCount(0); - view.showMessage(R.string.error, R.string.search_results_warning); - } - }); - }); - return true; - } - - @NonNull @Override public ArrayList getRepos() { - return repos; - } - - @Override public void onItemClick(int position, View v, Repo item) { - SchemeParser.launchUri(v.getContext(), item.getHtmlUrl()); - } - - @Override public void onItemLongClick(int position, View v, Repo item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFileActivity.java b/app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFileActivity.java deleted file mode 100644 index 1e1d1a588..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFileActivity.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.fastaccess.ui.modules.search.repos.files; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.AppCompatSpinner; -import android.text.Editable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.helper.AnimHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.modules.search.code.SearchCodeFragment; -import com.fastaccess.ui.widgets.FontEditText; -import com.fastaccess.ui.widgets.ForegroundImageView; - -import butterknife.BindView; -import butterknife.OnClick; -import butterknife.OnEditorAction; -import butterknife.OnItemSelected; -import butterknife.OnTextChanged; -import butterknife.OnTouch; - -public class SearchFileActivity extends BaseActivity implements SearchFileMvp.View { - - @BindView(R.id.searchEditText) FontEditText searchEditText; - @BindView(R.id.clear) ForegroundImageView clear; - @BindView(R.id.searchOptions) AppCompatSpinner searchOptions; - private boolean onSpinnerTouched; - - private SearchCodeFragment searchCodeFragment; - - public static Intent createIntent(@NonNull Context context, @NonNull String login, @NonNull String repoId, boolean isEnterprise) { - Intent intent = new Intent(context, SearchFileActivity.class); - intent.putExtra(BundleConstant.ID, repoId); - intent.putExtra(BundleConstant.EXTRA, login); - intent.putExtra(BundleConstant.IS_ENTERPRISE, isEnterprise); - return intent; - } - - @OnTouch(R.id.searchOptions) boolean onTouch() { - onSpinnerTouched = true; - return false; - } - - @OnItemSelected(R.id.searchOptions) void onOptionSelected() { - if (onSpinnerTouched) { - onSearch(); - } - } - - @OnTextChanged(value = R.id.searchEditText, callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) void onTextChange(Editable s) { - String text = s.toString(); - if (text.length() == 0) { - AnimHelper.animateVisibility(clear, false); - } else { - AnimHelper.animateVisibility(clear, true); - } - } - - @OnEditorAction(R.id.searchEditText) boolean onEditor() { - onSearch(); - return true; - } - - @OnClick(value = {R.id.clear}) void onClear(View view) { - if (view.getId() == R.id.clear) { - searchEditText.setText(""); - } - } - - @OnClick(R.id.search) void onSearchClicked() { - onSearch(); - } - - @Override protected int layout() { - return R.layout.activity_search_file; - } - - @Override protected boolean isTransparent() { - return false; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public SearchFilePresenter providePresenter() { - return new SearchFilePresenter(); - } - - @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getPresenter().onActivityCreated(getIntent().getExtras()); - searchCodeFragment = ((SearchCodeFragment) getSupportFragmentManager().findFragmentById(R.id.filesFragment)); - } - - @Override public void onValidSearchQuery(@NonNull String query) { - searchCodeFragment.onSetSearchQuery(query, false); - } - - private void onSearch() { - getPresenter().onSearchClicked(searchEditText, searchOptions.getSelectedItemPosition() == 0); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFileMvp.java b/app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFileMvp.java deleted file mode 100644 index 622a1f4f0..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFileMvp.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.ui.modules.search.repos.files; - -import android.os.Bundle; -import android.support.annotation.NonNull; - -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.FontEditText; - - -interface SearchFileMvp { - - interface View extends BaseMvp.FAView { - void onValidSearchQuery(@NonNull String query); - } - - interface Presenter extends BaseMvp.FAPresenter { - void onSearchClicked(@NonNull FontEditText editText, boolean inPath); - - void onActivityCreated(Bundle extras); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFilePresenter.java b/app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFilePresenter.java deleted file mode 100644 index fd974684f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/repos/files/SearchFilePresenter.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.fastaccess.ui.modules.search.repos.files; - -import android.os.Bundle; -import android.support.annotation.NonNull; - -import com.fastaccess.R; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.widgets.FontEditText; - -public class SearchFilePresenter extends BasePresenter implements SearchFileMvp.Presenter { - @com.evernote.android.state.State String repoId; - @com.evernote.android.state.State String login; - - @Override protected void onAttachView(@NonNull SearchFileMvp.View view) { - super.onAttachView(view); - } - - @Override public void onSearchClicked(@NonNull FontEditText editText, boolean inPath) { - boolean isEmpty = InputHelper.isEmpty(editText) || InputHelper.toString(editText).length() < 2; - editText.setError(isEmpty ? editText.getResources().getString(R.string.minimum_three_chars) : null); - if (!isEmpty) { - AppHelper.hideKeyboard(editText); - String query = InputHelper.toString(editText); - if (getView() != null && isViewAttached()) getView().onValidSearchQuery(modifyQueryForFileSearch(query, inPath)); - } - } - - @Override public void onActivityCreated(Bundle extras) { - repoId = extras.getString(BundleConstant.ID); - login = extras.getString(BundleConstant.EXTRA); - } - - @NonNull private String modifyQueryForFileSearch(@NonNull String query, boolean inPath) { - //restrict the search to file paths and the current repo user is looking at - return query + "+" + "in:" + (inPath ? "path" : "" + "file") + "+" + "repo:" + login + "/" + repoId; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersFragment.java b/app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersFragment.java deleted file mode 100644 index a1b6e9d56..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersFragment.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.fastaccess.ui.modules.search.users; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.support.v4.widget.SwipeRefreshLayout; -import android.view.View; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.adapter.UsersAdapter; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.search.SearchMvp; -import com.fastaccess.ui.widgets.StateLayout; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 03 Dec 2016, 3:56 PM - */ - -public class SearchUsersFragment extends BaseFragment implements SearchUsersMvp.View { - @State String searchQuery = ""; - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.refresh) SwipeRefreshLayout refresh; - @BindView(R.id.stateLayout) StateLayout stateLayout; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - private OnLoadMore onLoadMore; - private UsersAdapter adapter; - private SearchMvp.View countCallback; - - public static SearchUsersFragment newInstance() { - return new SearchUsersFragment(); - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof SearchMvp.View) { - countCallback = (SearchMvp.View) context; - } - } - - @Override public void onDetach() { - countCallback = null; - super.onDetach(); - } - - @Override public void onNotifyAdapter(@Nullable List items, int page) { - hideProgress(); - if (items == null || items.isEmpty()) { - adapter.clear(); - return; - } - if (page <= 1) { - adapter.insertItems(items); - } else { - adapter.addItems(items); - } - } - - @Override public void onSetTabCount(int count) { - if (countCallback != null) countCallback.onSetCount(count, 1); - } - - @Override protected int fragmentLayout() { - return R.layout.small_grid_refresh_list; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - stateLayout.setEmptyText(R.string.no_search_results); - getLoadMore().initialize(getPresenter().getCurrentPage(), getPresenter().getPreviousTotal()); - stateLayout.setOnReloadListener(this); - refresh.setOnRefreshListener(this); - recycler.setEmptyView(stateLayout, refresh); - adapter = new UsersAdapter(getPresenter().getUsers()); - adapter.setListener(getPresenter()); - recycler.setAdapter(adapter); - recycler.addKeyLineDivider(); - if (savedInstanceState != null) { - if (!InputHelper.isEmpty(searchQuery) && getPresenter().getUsers().isEmpty() && !getPresenter().isApiCalled()) { - onRefresh(); - } - } - if (InputHelper.isEmpty(searchQuery)) { - stateLayout.showEmptyState(); - } - fastScroller.attachRecyclerView(recycler); - } - - @NonNull @Override public SearchUsersPresenter providePresenter() { - return new SearchUsersPresenter(); - } - - @Override public void hideProgress() { - refresh.setRefreshing(false); - stateLayout.hideProgress(); - } - - @Override public void showProgress(@StringRes int resId) { - refresh.setRefreshing(true); - stateLayout.showProgress(); - } - - @Override public void showErrorMessage(@NonNull String message) { - showReload(); - super.showErrorMessage(message); - } - - @Override public void showMessage(int titleRes, int msgRes) { - showReload(); - super.showMessage(titleRes, msgRes); - } - - @Override public void onSetSearchQuery(@NonNull String query) { - this.searchQuery = query; - getLoadMore().reset(); - adapter.clear(); - if (!InputHelper.isEmpty(query)) { - recycler.removeOnScrollListener(getLoadMore()); - recycler.addOnScrollListener(getLoadMore()); - onRefresh(); - } - } - - @Override public void onQueueSearch(@NonNull String query) { - this.searchQuery = query; - if (getView() != null) - onSetSearchQuery(query); - } - - @NonNull @Override public OnLoadMore getLoadMore() { - if (onLoadMore == null) { - onLoadMore = new OnLoadMore<>(getPresenter(), searchQuery); - } - onLoadMore.setParameter(searchQuery); - return onLoadMore; - } - - @Override public void onRefresh() { - if (searchQuery.length() == 0) { - refresh.setRefreshing(false); - return; - } - getPresenter().onCallApi(1, searchQuery); - } - - @Override public void onClick(View view) { - onRefresh(); - } - - @Override public void onScrollTop(int index) { - super.onScrollTop(index); - if (recycler != null) recycler.scrollToPosition(0); - } - - private void showReload() { - hideProgress(); - stateLayout.showReload(adapter.getItemCount()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersMvp.java b/app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersMvp.java deleted file mode 100644 index 9f2661777..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersMvp.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.fastaccess.ui.modules.search.users; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; - -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.loadmore.OnLoadMore; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 03 Dec 2016, 3:45 PM - */ - -interface SearchUsersMvp { - - interface View extends BaseMvp.FAView, SwipeRefreshLayout.OnRefreshListener, android.view.View.OnClickListener { - void onNotifyAdapter(@Nullable List items, int page); - - void onSetTabCount(int count); - - void onSetSearchQuery(@NonNull String query); - - void onQueueSearch(@NonNull String query); - - @NonNull OnLoadMore getLoadMore(); - } - - interface Presenter extends BaseMvp.FAPresenter, - BaseViewHolder.OnItemClickListener, - BaseMvp.PaginationListener { - - @NonNull ArrayList getUsers(); - - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersPresenter.java deleted file mode 100644 index 68704e810..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/search/users/SearchUsersPresenter.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.fastaccess.ui.modules.search.users; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.data.dao.model.User; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import java.util.ArrayList; - -/** - * Created by Kosh on 03 Dec 2016, 3:48 PM - */ - -class SearchUsersPresenter extends BasePresenter implements SearchUsersMvp.Presenter { - - private ArrayList users = new ArrayList<>(); - private int page; - private int previousTotal; - private int lastPage = Integer.MAX_VALUE; - - @Override public int getCurrentPage() { - return page; - } - - @Override public int getPreviousTotal() { - return previousTotal; - } - - @Override public void setCurrentPage(int page) { - this.page = page; - } - - @Override public void setPreviousTotal(int previousTotal) { - this.previousTotal = previousTotal; - } - - @Override public boolean onCallApi(int page, @Nullable String parameter) { - if (page == 1) { - lastPage = Integer.MAX_VALUE; - sendToView(view -> view.getLoadMore().reset()); - } - setCurrentPage(page); - if (page > lastPage || lastPage == 0 || parameter == null) { - sendToView(SearchUsersMvp.View::hideProgress); - return false; - } - makeRestCall(RestProvider.getSearchService(isEnterprise()).searchUsers(parameter, page), - response -> { - lastPage = response.getLast(); - sendToView(view -> { - view.onNotifyAdapter(response.isIncompleteResults() ? null : response.getItems(), page); - if (!response.isIncompleteResults()) { - view.onSetTabCount(response.getTotalCount()); - } else { - view.onSetTabCount(0); - view.showMessage(R.string.error, R.string.search_results_warning); - } - }); - }); - return true; - } - - @NonNull @Override public ArrayList getUsers() { - return users; - } - - @Override public void onItemClick(int position, View v, User item) { - - } - - @Override public void onItemLongClick(int position, View v, User item) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/LanguageBottomSheetDialog.java b/app/src/main/java/com/fastaccess/ui/modules/settings/LanguageBottomSheetDialog.java deleted file mode 100644 index b00b98fef..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/settings/LanguageBottomSheetDialog.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.fastaccess.ui.modules.settings; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.widget.RadioButton; -import android.widget.RadioGroup; - -import com.annimon.stream.Stream; -import com.fastaccess.R; -import com.fastaccess.data.dao.AppLanguageModel; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.ui.base.BaseBottomSheetDialog; -import com.fastaccess.ui.widgets.FontTextView; - -import java.util.List; - -import butterknife.BindView; -import io.reactivex.functions.Action; - -/** - * Created by JediB on 5/12/2017. - */ - -public class LanguageBottomSheetDialog extends BaseBottomSheetDialog { - public interface LanguageDialogListener { - void onLanguageChanged(Action action); - } - - public static final String TAG = LanguageBottomSheetDialog.class.getSimpleName(); - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.picker) RadioGroup radioGroup; - private LanguageDialogListener listener; - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof LanguageDialogListener) { - listener = (LanguageDialogListener) context; - } - } - - @Override public void onDetach() { - listener = null; - super.onDetach(); - } - - @Override protected int layoutRes() { - return R.layout.picker_dialog; - } - - @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - String language = PrefGetter.getAppLanguage(); - String[] values = getResources().getStringArray(R.array.languages_array_values); - List languageModels = Stream.of(getResources().getStringArray(R.array.languages_array)) - .mapIndexed((index, s) -> new AppLanguageModel(values[index], s)) - .sortBy(AppLanguageModel::getLabel) - .toList(); - int padding = getResources().getDimensionPixelSize(R.dimen.spacing_xs_large); - for (int i = 0; i < languageModels.size(); i++) { - RadioButton radioButtonView = new RadioButton(getContext()); - RadioGroup.LayoutParams params = new RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); - radioButtonView.setLayoutParams(params); - AppLanguageModel model = languageModels.get(i); - radioButtonView.setText(model.getLabel()); - radioButtonView.setId(i); - radioButtonView.setTag(model.getValue()); - radioButtonView.setGravity(Gravity.CENTER_VERTICAL); - radioButtonView.setPadding(padding, padding, padding, padding); - radioGroup.addView(radioButtonView); - if (model.getValue().equalsIgnoreCase(language)) radioGroup.check(i); - } - radioGroup.setOnCheckedChangeListener((group, checkedId) -> { - String tag = (String) radioGroup.getChildAt(checkedId).getTag(); - Logger.e(tag); - if (!tag.equalsIgnoreCase(language)) { - PrefGetter.setAppLangauge(tag); - if (listener != null) listener.onLanguageChanged(this::dismiss); - } - }); - - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/SettingsActivity.java b/app/src/main/java/com/fastaccess/ui/modules/settings/SettingsActivity.java deleted file mode 100644 index 50b9a9104..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/settings/SettingsActivity.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.fastaccess.ui.modules.settings; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.widget.ListView; - -import com.fastaccess.R; -import com.fastaccess.data.dao.SettingsModel; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.adapter.SettingsAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.modules.settings.category.SettingsCategoryActivity; -import com.fastaccess.ui.modules.theme.ThemeActivity; -import com.fastaccess.ui.modules.theme.code.ThemeCodeActivity; - -import net.grandcentrix.thirtyinch.TiPresenter; - -import java.util.ArrayList; - -import butterknife.BindView; -import io.reactivex.functions.Action; - -public class SettingsActivity extends BaseActivity implements LanguageBottomSheetDialog.LanguageDialogListener { - - @BindView(R.id.settingsList) ListView settingsList; - - private static int THEME_CHANGE = 32; - private ArrayList settings = new ArrayList<>(); - - @Override protected int layout() { - return R.layout.activity_settings; - } - - @Override protected boolean isTransparent() { - return false; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setToolbarIcon(R.drawable.ic_back); - setTitle(getString(R.string.settings)); - if (savedInstanceState == null) { - setResult(RESULT_CANCELED); - } - settings.add(new SettingsModel(R.drawable.ic_color_lens, getString(R.string.theme_title), SettingsModel.THEME)); - settings.add(new SettingsModel(R.drawable.ic_color_lens, getString(R.string.choose_code_theme), SettingsModel.CODE_THEME)); - settings.add(new SettingsModel(R.drawable.ic_edit, getString(R.string.customization), SettingsModel.CUSTOMIZATION)); - settings.add(new SettingsModel(R.drawable.ic_ring, getString(R.string.notifications), SettingsModel.NOTIFICATION)); - settings.add(new SettingsModel(R.drawable.ic_settings, getString(R.string.behavior), SettingsModel.BEHAVIOR)); - settings.add(new SettingsModel(R.drawable.ic_backup, getString(R.string.backup), SettingsModel.BACKUP)); - settings.add(new SettingsModel(R.drawable.ic_language, getString(R.string.app_language), SettingsModel.LANGUAGE)); - settingsList.setAdapter(new SettingsAdapter(this, settings)); - settingsList.setOnItemClickListener((parent, view, position, id) -> { - SettingsModel settingsModel = (SettingsModel) parent.getItemAtPosition(position); - Intent intent = new Intent(this, SettingsCategoryActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.ITEM, settingsModel.getSettingsType()) - .put(BundleConstant.EXTRA, settingsModel.getTitle()) - .end()); - if (settingsModel.getSettingsType() == SettingsModel.LANGUAGE) { - showLanguageList(); - } else if (settingsModel.getSettingsType() == SettingsModel.THEME) { - ActivityHelper.startReveal(this, new Intent(this, ThemeActivity.class), view, THEME_CHANGE); - } else if (settingsModel.getSettingsType() == SettingsModel.CODE_THEME) { - ActivityHelper.startReveal(this, new Intent(this, ThemeCodeActivity.class), view, THEME_CHANGE); - } else { - ActivityHelper.startReveal(this, intent, view); - } - }); - } - - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == THEME_CHANGE && resultCode == RESULT_OK) { - setResult(resultCode); - finish(); - } - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } - - private void showLanguageList() { - LanguageBottomSheetDialog languageBottomSheetDialog = new LanguageBottomSheetDialog(); - languageBottomSheetDialog.onAttach((Context) this); - languageBottomSheetDialog.show(getSupportFragmentManager(), "LanguageBottomSheetDialog"); - } - - @Override public void onLanguageChanged(Action action) { - try { - action.run();//dismiss dialog avoid leakage - } catch (Exception e) { - e.printStackTrace(); - } - setResult(RESULT_OK); - finish(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/SlackBottomSheetDialog.java b/app/src/main/java/com/fastaccess/ui/modules/settings/SlackBottomSheetDialog.java deleted file mode 100644 index e999d0ca4..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/settings/SlackBottomSheetDialog.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.fastaccess.ui.modules.settings; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.ui.base.BaseBottomSheetDialog; -import com.fastaccess.ui.widgets.FontButton; -import com.fastaccess.ui.widgets.FontTextView; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 01 May 2017, 12:58 AM - */ - -public class SlackBottomSheetDialog extends BaseBottomSheetDialog { - public interface SlackDialogListener { - void onDismissed(); - } - - public static final String TAG = SlackBottomSheetDialog.class.getSimpleName(); - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.message) FontTextView message; - @BindView(R.id.cancel) FontButton cancel; - @BindView(R.id.ok) FontButton ok; - private SlackDialogListener listener; - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (context instanceof SlackDialogListener) { - listener = (SlackDialogListener) context; - } - } - - @Override public void onDetach() { - listener = null; - super.onDetach(); - } - - @Override protected int layoutRes() { - return R.layout.message_dialog; - } - - @OnClick({R.id.cancel, R.id.ok}) public void onViewClicked(View view) { - switch (view.getId()) { - case R.id.ok: - ActivityHelper.startCustomTab(getActivity(), "http://rebrand.ly/fasthub"); - break; - } - if (listener != null) listener.onDismissed(); - dismiss(); - } - - @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - cancel.setText(R.string.no); - ok.setText(R.string.yes); - title.setText(R.string.join_slack); - message.setText(getString(R.string.join_slack_message)); - } - - @Override protected void onHidden() { - if (listener != null) listener.onDismissed(); - super.onHidden(); - } - - @Override protected void onDismissedByScrolling() { - if (listener != null) listener.onDismissed(); - super.onDismissedByScrolling(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryActivity.java b/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryActivity.java deleted file mode 100644 index 8060221f2..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryActivity.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.fastaccess.ui.modules.settings.category; - -import android.os.Bundle; -import android.support.annotation.NonNull; - -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.SettingsModel; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.ui.base.BaseActivity; - -import net.grandcentrix.thirtyinch.TiPresenter; - -public class SettingsCategoryActivity extends BaseActivity implements SettingsCategoryFragment.SettingsCallback { - - @State String title; - @SettingsModel.SettingsType @State int settingsType; - @State boolean needRecreation; - - @Override protected int layout() { - return R.layout.activity_settings_category; - } - - @Override protected boolean isTransparent() { - return false; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setResult(RESULT_CANCELED); - if (savedInstanceState == null) { - Bundle bundle = getIntent().getExtras(); - title = bundle.getString(BundleConstant.EXTRA); - settingsType = bundle.getInt(BundleConstant.ITEM); - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.settingsContainer, new SettingsCategoryFragment(), SettingsCategoryFragment.TAG) - .commit(); - } - setTitle(title); - } - - @NonNull @Override public TiPresenter providePresenter() { - return new SettingsCategoryPresenter(); - } - - @SettingsModel.SettingsType @Override public int getSettingsType() { - return settingsType; - } - - @Override public void onThemeChanged() { - needRecreation = true; - } - - @Override public void onBackPressed() { - if (needRecreation) { - super.onThemeChanged(); - return; - } - super.onBackPressed(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryFragment.java b/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryFragment.java deleted file mode 100644 index 381af82e5..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryFragment.java +++ /dev/null @@ -1,363 +0,0 @@ -package com.fastaccess.ui.modules.settings.category; - -import android.Manifest; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.media.RingtoneManager; -import android.net.Uri; -import android.os.Bundle; -import android.os.Environment; -import android.support.annotation.NonNull; -import android.support.v4.content.ContextCompat; -import android.support.v7.preference.Preference; -import android.support.v7.preference.PreferenceFragmentCompat; -import android.util.Log; -import android.widget.Toast; - -import com.bumptech.glide.Glide; -import com.fastaccess.App; -import com.fastaccess.R; -import com.fastaccess.data.dao.SettingsModel; -import com.fastaccess.data.dao.model.SearchHistory; -import com.fastaccess.helper.FileHelper; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.PrefHelper; -import com.fastaccess.helper.RxHelper; -import com.fastaccess.provider.tasks.notification.NotificationSchedulerJobTask; -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.settings.sound.NotificationSoundBottomSheet; -import com.fastaccess.ui.modules.settings.sound.NotificationSoundMvp; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.lang.reflect.Type; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.Map; - -import es.dmoral.toasty.Toasty; -import io.reactivex.Observable; -import io.reactivex.disposables.CompositeDisposable; - -import static android.app.Activity.RESULT_OK; - -public class SettingsCategoryFragment extends PreferenceFragmentCompat implements - Preference.OnPreferenceChangeListener, NotificationSoundMvp.NotificationSoundListener { - - public static final String TAG = SettingsCategoryFragment.class.getSimpleName(); - - public interface SettingsCallback { - @SettingsModel.SettingsType int getSettingsType(); - } - - private static int PERMISSION_REQUEST_CODE = 128; - private static int RESTORE_REQUEST_CODE = 256; - private static int SOUND_REQUEST_CODE = 257; - - private BaseMvp.FAView callback; - private String appColor; - private String appLanguage; - - private Preference notificationTime; - private Preference notificationRead; - private Preference notificationSound; - private Preference notificationSoundPath; - private SettingsCallback settingsCallback; - private CompositeDisposable disposable = new CompositeDisposable(); - - @Override public void onAttach(Context context) { - super.onAttach(context); - this.callback = (BaseMvp.FAView) context; - this.settingsCallback = (SettingsCallback) context; - appColor = PrefHelper.getString("appColor"); - appLanguage = PrefHelper.getString("app_language"); - } - - @Override public void onDetach() { - callback = null; - settingsCallback = null; - super.onDetach(); - } - - @Override public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - switch (settingsCallback.getSettingsType()) { - case SettingsModel.BACKUP: - addBackup(); - break; - case SettingsModel.BEHAVIOR: - addBehaviour(); - break; - case SettingsModel.CUSTOMIZATION: - addCustomization(); - break; - case SettingsModel.NOTIFICATION: - addNotifications(); - break; - default: - Toast.makeText(App.getInstance(), "You reached the impossible :'(", Toast.LENGTH_SHORT).show(); - } - } - - @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - if (preference.getKey().equalsIgnoreCase("notificationEnabled")) { - if ((boolean) newValue) { - getPreferenceScreen().addPreference(notificationTime); - getPreferenceScreen().addPreference(notificationRead); - getPreferenceScreen().addPreference(notificationSound); - getPreferenceScreen().addPreference(notificationSoundPath); - NotificationSchedulerJobTask.scheduleJob(App.getInstance(), - PrefGetter.getNotificationTaskDuration(), true); - } else { - getPreferenceScreen().removePreference(notificationTime); - getPreferenceScreen().removePreference(notificationRead); - getPreferenceScreen().removePreference(notificationSound); - getPreferenceScreen().removePreference(notificationSoundPath); - NotificationSchedulerJobTask.scheduleJob(App.getInstance(), -1, true); - } - return true; - } else if (preference.getKey().equalsIgnoreCase("notificationTime")) { - NotificationSchedulerJobTask.scheduleJob(App.getInstance(), - PrefGetter.notificationDurationMillis((String) newValue), true); - return true; - } else if (preference.getKey().equalsIgnoreCase("recylerViewAnimation")) { - callback.onThemeChanged(); - return true; - } else if (preference.getKey().equalsIgnoreCase("rect_avatar")) { - callback.onThemeChanged(); - return true; - } else if (preference.getKey().equalsIgnoreCase("appColor")) { - if (newValue.toString().equalsIgnoreCase(appColor)) - return true; - Toasty.warning(App.getInstance(), getString(R.string.change_theme_warning), Toast.LENGTH_LONG).show(); - callback.onThemeChanged(); - return true; - } else if (preference.getKey().equalsIgnoreCase("app_language")) { - if (newValue.toString().equalsIgnoreCase(appLanguage)) - return true; - callback.onThemeChanged(); - return true; - } - return false; - } - - @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (requestCode == PERMISSION_REQUEST_CODE) { - if (permissions[0].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - Map settings = PrefHelper.getAll(); - settings.remove("token"); - String json = new Gson().toJson(settings); - String path = Environment.getExternalStorageDirectory() + File.separator + "FastHub"; - File folder = new File(path); - folder.mkdirs(); - File backup = new File(folder, "backup.json"); - try { - backup.createNewFile(); - FileOutputStream outputStream = new FileOutputStream(backup); - OutputStreamWriter myOutWriter = new OutputStreamWriter(outputStream); - myOutWriter.append(json); - - myOutWriter.close(); - - outputStream.flush(); - outputStream.close(); - } catch (IOException e) { - Log.e(getTag(), "Couldn't backup: " + e.toString()); - } - PrefHelper.set("backed_up", new SimpleDateFormat("MM/dd", Locale.ENGLISH).format(new Date())); - findPreference("backup").setSummary(getString(R.string.backup_summary, getString(R.string.now))); - Toasty.success(App.getInstance(), getString(R.string.backed_up)).show(); - } else { - Toasty.error(App.getInstance(), getString(R.string.permission_failed)).show(); - } - } else if (permissions[0].equals(Manifest.permission.READ_EXTERNAL_STORAGE)) { - if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - showFileChooser(); - } else { - Toasty.error(App.getInstance(), getString(R.string.permission_failed)).show(); - } - } - } - - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == RESULT_OK) { - if (requestCode == RESTORE_REQUEST_CODE) { - restoreData(data); - } else if (requestCode == SOUND_REQUEST_CODE) { - Uri ringtone = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI); - if (notificationSoundPath != null && notificationSoundPath.isVisible()) { - notificationSoundPath.setDefaultValue(ringtone.toString()); - } - } - } - } - - @Override public void onSoundSelected(Uri uri) { - PrefGetter.setNotificationSound(uri); - if (notificationSoundPath != null && notificationSoundPath.isVisible()) - notificationSoundPath.setSummary(FileHelper.getRingtoneName(getContext(), uri)); - } - - @Override public void onDestroyView() { - disposable.clear(); - super.onDestroyView(); - } - - @Override public void onDestroy() { - disposable.clear(); - super.onDestroy(); - } - - private void showFileChooser() { - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.setType("application/json"); - startActivityForResult(Intent.createChooser(intent, getString(R.string.select_backup)), RESTORE_REQUEST_CODE); - } - - private void addBackup() { - addPreferencesFromResource(R.xml.backup_settings); - findPreference("backup").setOnPreferenceClickListener((Preference preference) -> { - if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { - Map preferences = PrefHelper.getAll(); - preferences.remove("token"); - String json = new Gson().toJson(preferences); - String path = FileHelper.PATH; - File folder = new File(path); - folder.mkdirs(); - File backup = new File(folder, "backup.json"); - try { - backup.createNewFile(); - try (FileOutputStream outputStream = new FileOutputStream(backup)) { - try (OutputStreamWriter myOutWriter = new OutputStreamWriter(outputStream)) { - myOutWriter.append(json); - } - } - } catch (IOException e) { - Log.e(getTag(), "Couldn't backup: " + e.toString()); - } - PrefHelper.set("backed_up", new SimpleDateFormat("MM/dd", Locale.ENGLISH).format(new Date())); - Toasty.success(App.getInstance(), getString(R.string.backed_up)).show(); - } else { - requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE); - } - return true; - }); - if (PrefHelper.getString("backed_up") != null) { - findPreference("backup").setSummary(SpannableBuilder.builder() - .append(getString(R.string.backup_summary, PrefHelper.getString("backed_up"))) - .append("\n") - .append(FileHelper.PATH)); - } else { - findPreference("backup").setSummary(""); - } - findPreference("restore").setOnPreferenceClickListener(preference -> { - if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { - showFileChooser(); - } else { - requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE); - } - return true; - }); - } - - private void addCustomization() { - addPreferencesFromResource(R.xml.customization_settings); - findPreference("enable_ads").setVisible(false); - findPreference("recylerViewAnimation").setOnPreferenceChangeListener(this); - findPreference("rect_avatar").setOnPreferenceChangeListener(this); - findPreference("appColor").setOnPreferenceChangeListener(this); - } - - private void addBehaviour() { - addPreferencesFromResource(R.xml.behaviour_settings); - findPreference("clear_search").setOnPreferenceClickListener(preference -> { - callback.showMessage(R.string.success, R.string.deleted); - SearchHistory.deleteAll(); - return true; - }); - findPreference("clear_image_cache").setOnPreferenceClickListener(preference -> { - final Glide glide = Glide.get(App.getInstance()); - disposable.add(RxHelper.getObservable(Observable.fromCallable(() -> { - glide.clearDiskCache(); - return true; - })).subscribe(aBoolean -> { - glide.clearMemory(); - Toasty.info(App.getInstance(), getString(R.string.restart_app_message), Toast.LENGTH_LONG).show(); - })); - return true; - }); - } - - private void addNotifications() { - addPreferencesFromResource(R.xml.notification_settings); - notificationTime = findPreference("notificationTime"); - notificationRead = findPreference("markNotificationAsRead"); - notificationSound = findPreference("notificationSound"); - notificationTime.setOnPreferenceChangeListener(this); - findPreference("notificationEnabled").setOnPreferenceChangeListener(this); - notificationSoundPath = findPreference("notification_sound_path"); - notificationSoundPath.setSummary(FileHelper.getRingtoneName(getContext(), PrefGetter.getNotificationSound())); - notificationSoundPath.setOnPreferenceClickListener(preference -> { - NotificationSoundBottomSheet.Companion.newInstance(FileHelper.getRingtoneName(getContext(), PrefGetter.getNotificationSound())) - .show(getChildFragmentManager(), "NotificationSoundBottomSheet"); - return true; - }); - if (!PrefHelper.getBoolean("notificationEnabled")) { - getPreferenceScreen().removePreference(notificationTime); - getPreferenceScreen().removePreference(notificationRead); - getPreferenceScreen().removePreference(notificationSound); - getPreferenceScreen().removePreference(notificationSoundPath); - } - } - - private void restoreData(Intent data) { - StringBuilder json = new StringBuilder(); - try { - try (InputStream inputStream = getContext().getContentResolver().openInputStream(data.getData())) { - if (inputStream != null) { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { - String line; - while ((line = reader.readLine()) != null) { - json.append(line); - } - } - } - } - } catch (IOException e) { - Toasty.error(App.getInstance(), getString(R.string.error)).show(); - } - if (!InputHelper.isEmpty(json)) { - try { - Gson gson = new Gson(); - Type typeOfHashMap = new TypeToken>() {}.getType(); - Map savedPref = gson.fromJson(json.toString(), typeOfHashMap); - if (savedPref != null && !savedPref.isEmpty()) { - for (Map.Entry stringEntry : savedPref.entrySet()) { - PrefHelper.set(stringEntry.getKey(), stringEntry.getValue()); - } - } - callback.onThemeChanged(); - } catch (Exception ignored) { - Toasty.error(App.getInstance(), getString(R.string.error), Toast.LENGTH_SHORT).show(); - } - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryMvp.java b/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryMvp.java deleted file mode 100644 index 043fe7e3d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryMvp.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.fastaccess.ui.modules.settings.category; - -import com.fastaccess.ui.base.mvp.BaseMvp; - -/** - * Created by JediB on 5/12/2017. - */ - -public interface SettingsCategoryMvp { - interface Presenter extends BaseMvp.FAPresenter { - - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryPresenter.java deleted file mode 100644 index 4b447e733..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/settings/category/SettingsCategoryPresenter.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.ui.modules.settings.category; - -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -/** - * Created by JediB on 5/12/2017. - */ - -class SettingsCategoryPresenter extends BasePresenter implements SettingsCategoryMvp.Presenter{} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundBottomSheet.kt b/app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundBottomSheet.kt deleted file mode 100644 index 34702822c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundBottomSheet.kt +++ /dev/null @@ -1,113 +0,0 @@ -package com.fastaccess.ui.modules.settings.sound - -import android.content.Context -import android.media.MediaPlayer -import android.os.Bundle -import android.view.Gravity -import android.view.View -import android.view.ViewGroup -import android.widget.Button -import android.widget.RadioButton -import android.widget.RadioGroup -import butterknife.BindView -import com.fastaccess.R -import com.fastaccess.data.dao.NotificationSoundModel -import com.fastaccess.helper.BundleConstant -import com.fastaccess.helper.Bundler -import com.fastaccess.ui.base.BaseMvpBottomSheetDialogFragment -import com.fastaccess.ui.widgets.FontTextView - -/** - * Created by kosh on 23/07/2017. - */ -class NotificationSoundBottomSheet : BaseMvpBottomSheetDialogFragment(), NotificationSoundMvp.View { - - @BindView(R.id.title) lateinit var title: FontTextView - @BindView(R.id.picker) lateinit var radioGroup: RadioGroup - @BindView(R.id.ok) lateinit var okButton: Button - - private val padding: Int by lazy { resources.getDimensionPixelSize(R.dimen.spacing_xs_large) } - private var canPlaySound: Boolean = false - private val mediaPlayer = MediaPlayer() - - private var listener: NotificationSoundMvp.NotificationSoundListener? = null - - override fun onAttach(context: Context?) { - super.onAttach(context) - listener = if (parentFragment is NotificationSoundMvp.NotificationSoundListener) { - parentFragment as NotificationSoundMvp.NotificationSoundListener - } else { - context as NotificationSoundMvp.NotificationSoundListener - } - } - - override fun onDetach() { - super.onDetach() - } - - override fun fragmentLayout(): Int = R.layout.picker_dialog - - override fun providePresenter(): NotificationSoundPresenter = NotificationSoundPresenter() - - override fun onAddSound(sound: NotificationSoundModel) { - val radioButtonView = RadioButton(context) - val params = RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - radioButtonView.layoutParams = params - radioButtonView.id = (radioGroup.childCount) - radioButtonView.setPadding(padding, padding, padding, padding) - radioButtonView.gravity = Gravity.CENTER_VERTICAL - radioButtonView.tag = sound - if (sound.isSelected) { - radioButtonView.isChecked = true - } - radioButtonView.text = sound.name - radioGroup.addView(radioButtonView) - } - - override fun onCompleted() { - canPlaySound = true - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - title.text = getString(R.string.sound_chooser_title) - okButton.visibility = View.VISIBLE - presenter.loadSounds(arguments?.getString(BundleConstant.EXTRA)) - okButton.setOnClickListener { - val selectedView: View? = radioGroup.getChildAt(radioGroup.checkedRadioButtonId) - selectedView?.let { - val sound = it.tag as NotificationSoundModel - listener?.onSoundSelected(sound.uri) - } - dismiss() - } - radioGroup.setOnCheckedChangeListener { radioGroup, id -> - if (!canPlaySound) return@setOnCheckedChangeListener - val sound = radioGroup.getChildAt(id).tag as NotificationSoundModel - if (mediaPlayer.isPlaying) mediaPlayer.stop() - mediaPlayer.reset() - mediaPlayer.setDataSource(context, sound.uri) - mediaPlayer.prepare() - mediaPlayer.start() - } - } - - override fun onDestroyView() { - release() - super.onDestroyView() - } - - private fun release() { - if (mediaPlayer.isPlaying) mediaPlayer.stop() - mediaPlayer.release() - } - - companion object { - fun newInstance(default: String? = null): NotificationSoundBottomSheet { - val fragment = NotificationSoundBottomSheet() - fragment.arguments = Bundler.start().put(BundleConstant.EXTRA, default).end() - return fragment - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundMvp.kt deleted file mode 100644 index 7c214e669..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundMvp.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.fastaccess.ui.modules.settings.sound - -import android.net.Uri -import com.fastaccess.data.dao.NotificationSoundModel -import com.fastaccess.ui.base.mvp.BaseMvp - -/** - * Created by kosh on 23/07/2017. - */ - -interface NotificationSoundMvp { - interface View : BaseMvp.FAView { - fun onAddSound(sound: NotificationSoundModel) - fun onCompleted() - } - - interface Presenter { - fun loadSounds(default: String? = null) - } - - interface NotificationSoundListener { - fun onSoundSelected(uri: Uri? = null) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundPresenter.kt deleted file mode 100644 index 40e9114ba..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/settings/sound/NotificationSoundPresenter.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.fastaccess.ui.modules.settings.sound - -import com.fastaccess.App -import com.fastaccess.data.dao.NotificationSoundModel -import com.fastaccess.helper.FileHelper -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import io.reactivex.Observable - -/** - * Created by kosh on 23/07/2017. - */ -class NotificationSoundPresenter : BasePresenter(), NotificationSoundMvp.Presenter { - override fun loadSounds(default: String?) { - manageObservable(Observable.fromPublisher { s -> - val sounds = FileHelper.getNotificationSounds(App.getInstance(), default) - sounds.filterNotNull() - .sortedBy { !it.isSelected } - .onEach { s.onNext(it) } - s.onComplete() - }.doOnNext({ t -> sendToView { it.onAddSound(t) } }) - .doOnComplete { sendToView { it.onCompleted() } }) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/theme/ThemeActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/theme/ThemeActivity.kt deleted file mode 100644 index aade56189..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/theme/ThemeActivity.kt +++ /dev/null @@ -1,101 +0,0 @@ -package com.fastaccess.ui.modules.theme - -import android.animation.Animator -import android.animation.AnimatorListenerAdapter -import android.os.Build -import android.os.Bundle -import android.view.View -import android.view.ViewAnimationUtils -import butterknife.BindView -import butterknife.OnClick -import com.fastaccess.R -import com.fastaccess.data.dao.FragmentPagerAdapterModel -import com.fastaccess.helper.PrefGetter -import com.fastaccess.ui.adapter.FragmentsPagerAdapter -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.main.premium.PremiumActivity -import com.fastaccess.ui.modules.theme.fragment.ThemeFragmentMvp -import com.fastaccess.ui.widgets.CardsPagerTransformerBasic -import com.fastaccess.ui.widgets.ViewPagerView - - -/** - * Created by Kosh on 08 Jun 2017, 10:34 PM - */ - -class ThemeActivity : BaseActivity>(), ThemeFragmentMvp.ThemeListener { - - @BindView(R.id.pager) lateinit var pager: ViewPagerView - @BindView(R.id.parentLayout) lateinit var parentLayout: View - - @OnClick(R.id.premium) fun onOpenPremium() { - PremiumActivity.startActivity(this) - } - - override fun layout(): Int = R.layout.theme_viewpager - - override fun isTransparent(): Boolean = false - - override fun canBack(): Boolean = true - - override fun isSecured(): Boolean = false - - override fun providePresenter(): BasePresenter { - return BasePresenter() - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - pager.adapter = FragmentsPagerAdapter(supportFragmentManager, FragmentPagerAdapterModel.buildForTheme()) - pager.clipToPadding = false - val partialWidth = resources.getDimensionPixelSize(R.dimen.spacing_s_large) - val pageMargin = resources.getDimensionPixelSize(R.dimen.spacing_normal) - val pagerPadding = partialWidth + pageMargin - pager.pageMargin = pageMargin - pager.setPageTransformer(true, CardsPagerTransformerBasic(4, 10)) - pager.setPadding(pagerPadding, pagerPadding, pagerPadding, pagerPadding) - if (savedInstanceState == null) { - val theme = PrefGetter.getThemeType(this) - pager.setCurrentItem(theme - 1, true) - } - } - - override fun onChangePrimaryDarkColor(color: Int, darkIcons: Boolean) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - val view = window.decorView - view.systemUiVisibility = if (darkIcons) View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR else view.systemUiVisibility and View - .SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() - } - val cx = parentLayout.width / 2 - val cy = parentLayout.height / 2 - if (parentLayout.isAttachedToWindow) { - val finalRadius = Math.hypot(cx.toDouble(), cy.toDouble()).toFloat() - val anim = ViewAnimationUtils.createCircularReveal(parentLayout, cx, cy, 0f, finalRadius) - anim.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator?) { - super.onAnimationEnd(animation) - window?.statusBarColor = color - changeNavColor(color) - } - }) - parentLayout.setBackgroundColor(color) - anim.start() - } else { - parentLayout.setBackgroundColor(color) - window.statusBarColor = color - changeNavColor(color) - } - } - - private fun changeNavColor(color: Int) { - window?.navigationBarColor = color - } - - override fun onThemeApplied() { - showMessage(R.string.success, R.string.change_theme_warning) - onThemeChanged() - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodeActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodeActivity.kt deleted file mode 100644 index 29be78a88..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodeActivity.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.fastaccess.ui.modules.theme.code - -import android.app.Activity -import android.os.Bundle -import android.view.View -import android.widget.ProgressBar -import android.widget.Spinner -import butterknife.BindView -import butterknife.OnClick -import butterknife.OnItemSelected -import com.fastaccess.R -import com.fastaccess.helper.PrefGetter -import com.fastaccess.ui.adapter.SpinnerAdapter -import com.fastaccess.ui.base.BaseActivity -import com.prettifier.pretty.PrettifyWebView -import com.prettifier.pretty.helper.CodeThemesHelper - -/** - * Created by Kosh on 21 Jun 2017, 2:01 PM - */ - -class ThemeCodeActivity : BaseActivity(), ThemeCodeMvp.View { - - @BindView(R.id.themesList) lateinit var spinner: Spinner - @BindView(R.id.webView) lateinit var webView: PrettifyWebView - @BindView(R.id.readmeLoader) lateinit var progress: ProgressBar - - override fun layout(): Int = R.layout.theme_code_layout - - override fun isTransparent(): Boolean = false - - override fun canBack(): Boolean = true - - override fun isSecured(): Boolean = false - - override fun providePresenter(): ThemeCodePresenter = ThemeCodePresenter() - - @OnClick(R.id.done) fun onSaveTheme() { - val theme = spinner.selectedItem as String - PrefGetter.setCodeTheme(theme) - setResult(Activity.RESULT_OK) - finish() - } - - override fun onInitAdapter(list: List) { - val adapter = SpinnerAdapter(this, list) - spinner.adapter = adapter - val themePosition = list.indexOf(PrefGetter.getCodeTheme()) - if (themePosition >= 0) spinner.setSelection(themePosition) - } - - @OnItemSelected(R.id.themesList) fun onItemSelect() { - val theme = spinner.selectedItem as String - progress.visibility = View.VISIBLE - webView.setThemeSource(CodeThemesHelper.CODE_EXAMPLE, theme) - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - progress.visibility = View.VISIBLE - webView.setOnContentChangedListener(this) - title = "" - presenter.onLoadThemes() - } - - override fun onContentChanged(p: Int) { - progress.let { - it.progress = p - if (p == 100) it.visibility = View.GONE - } - } - - override fun onScrollChanged(reachedTop: Boolean, scroll: Int) {} -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodeMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodeMvp.kt deleted file mode 100644 index 02b6de67c..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodeMvp.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.fastaccess.ui.modules.theme.code - -import com.fastaccess.ui.base.mvp.BaseMvp -import com.prettifier.pretty.PrettifyWebView - -/** - * Created by Kosh on 22 Jun 2017, 11:50 PM - */ -interface ThemeCodeMvp { - - interface View : BaseMvp.FAView, PrettifyWebView.OnContentChangedListener { - fun onInitAdapter(list: List) - } - - interface Presenter { - fun onLoadThemes() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodePresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodePresenter.kt deleted file mode 100644 index 4f7d0292d..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/theme/code/ThemeCodePresenter.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.fastaccess.ui.modules.theme.code - -import com.fastaccess.helper.RxHelper -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.prettifier.pretty.helper.CodeThemesHelper -import io.reactivex.Observable - -/** - * Created by Kosh on 22 Jun 2017, 11:52 PM - */ - -class ThemeCodePresenter : BasePresenter(), ThemeCodeMvp.Presenter { - - override fun onLoadThemes() { - manageDisposable(RxHelper.getObservable(Observable.just(CodeThemesHelper.listThemes())) - .subscribe({ list -> sendToView { it.onInitAdapter(list) } }, { onError(it) })) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragment.kt deleted file mode 100644 index 0e79bf0b5..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragment.kt +++ /dev/null @@ -1,166 +0,0 @@ -package com.fastaccess.ui.modules.theme.fragment - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.graphics.Color -import android.os.Bundle -import android.support.design.widget.FloatingActionButton -import android.support.v7.widget.Toolbar -import android.view.ContextThemeWrapper -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import butterknife.BindView -import butterknife.ButterKnife -import butterknife.Unbinder -import com.fastaccess.R -import com.fastaccess.helper.* -import com.fastaccess.ui.base.BaseFragment -import com.fastaccess.ui.modules.main.donation.DonateActivity -import com.fastaccess.ui.modules.main.premium.PremiumActivity -import com.fastaccess.ui.widgets.SpannableBuilder - -/** - * Created by Kosh on 08 Jun 2017, 10:53 PM - */ - -class ThemeFragment : BaseFragment(), ThemeFragmentMvp.View { - - @BindView(R.id.apply) lateinit var apply: FloatingActionButton - @BindView(R.id.toolbar) lateinit var toolbar: Toolbar - - private var unbinder: Unbinder? = null - - private val THEME = "appTheme" - private var primaryDarkColor: Int = 0 - private var theme: Int = 0 - private var themeListener: ThemeFragmentMvp.ThemeListener? = null - - override fun onAttach(context: Context?) { - super.onAttach(context) - themeListener = context as ThemeFragmentMvp.ThemeListener - } - - override fun onDetach() { - themeListener = null - super.onDetach() - } - - override fun fragmentLayout(): Int = 0 - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - apply.setOnClickListener { - setTheme() - } - if (isPremiumTheme()) { - toolbar.title = SpannableBuilder.builder().foreground(getString(R.string.premium_theme), Color.RED) - } - toolbar.setNavigationOnClickListener { activity?.onBackPressed() } - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - super.onCreateView(inflater, container, savedInstanceState) - theme = arguments!!.getInt(BundleConstant.ITEM) - val contextThemeWrapper = ContextThemeWrapper(activity, theme) - primaryDarkColor = ViewHelper.getPrimaryDarkColor(contextThemeWrapper) - val localInflater = inflater.cloneInContext(contextThemeWrapper) - val view = localInflater.inflate(R.layout.theme_layout, container, false)!! - unbinder = ButterKnife.bind(this, view) - return view - } - - override fun providePresenter(): ThemeFragmentPresenter { - return ThemeFragmentPresenter() - } - - override fun setUserVisibleHint(isVisibleToUser: Boolean) { - super.setUserVisibleHint(isVisibleToUser) - if (isVisibleToUser) { - if (themeListener != null) { - themeListener!!.onChangePrimaryDarkColor(primaryDarkColor, theme == R.style.ThemeLight) - } - } - } - - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (resultCode == Activity.RESULT_OK) { - val productKey = data?.getStringExtra(BundleConstant.ITEM) - productKey?.let { - when (it) { - getString(R.string.amlod_theme_purchase) -> setTheme(getString(R.string.amlod_theme_mode)) - getString(R.string.midnight_blue_theme_purchase) -> setTheme(getString(R.string.mid_night_blue_theme_mode)) - getString(R.string.theme_bluish_purchase) -> setTheme(getString(R.string.bluish_theme)) - } - } - } - } - - companion object { - fun newInstance(style: Int): ThemeFragment { - val fragment = ThemeFragment() - fragment.arguments = Bundler.start() - .put(BundleConstant.ITEM, style) - .end() - return fragment - } - } - - private fun setTheme() { - when (theme) { - R.style.ThemeLight -> setTheme(getString(R.string.light_theme_mode)) - R.style.ThemeDark -> setTheme(getString(R.string.dark_theme_mode)) - R.style.ThemeAmlod -> applyAmlodTheme() - R.style.ThemeBluish -> applyBluishTheme() - R.style.ThemeMidnight -> applyMidnightTheme() - } - } - - private fun applyBluishTheme() { - if (!isGoogleSupported()) return - if (PrefGetter.isBluishEnabled() || PrefGetter.isProEnabled()) { - setTheme(getString(R.string.bluish_theme)) - } else { - DonateActivity.start(this, getString(R.string.theme_bluish_purchase)) - } - } - - private fun applyAmlodTheme() { - if (!isGoogleSupported()) return - if (PrefGetter.isAmlodEnabled() || PrefGetter.isProEnabled()) { - setTheme(getString(R.string.amlod_theme_mode)) - } else { - DonateActivity.start(this, getString(R.string.amlod_theme_purchase)) - } - } - - private fun applyMidnightTheme() { - if (!isGoogleSupported()) return - if (PrefGetter.isProEnabled() || PrefGetter.isAllFeaturesUnlocked()) { - setTheme(getString(R.string.mid_night_blue_theme_mode)) - } else { - PremiumActivity.startActivity(context!!) - } - } - - private fun setTheme(theme: String) { - PrefHelper.set(THEME, theme) - themeListener?.onThemeApplied() - } - - private fun isPremiumTheme(): Boolean = theme != R.style.ThemeLight && theme != R.style.ThemeDark - - private fun isGoogleSupported(): Boolean { - if (AppHelper.isGoogleAvailable(context!!)) { - return true - } - showErrorMessage(getString(R.string.common_google_play_services_unsupported_text)) - return false - } - - override fun onDestroyView() { - super.onDestroyView() - unbinder?.unbind() - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragmentMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragmentMvp.kt deleted file mode 100644 index f22c59586..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragmentMvp.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.fastaccess.ui.modules.theme.fragment - -import android.support.annotation.ColorInt - -import com.fastaccess.ui.base.mvp.BaseMvp - -/** - * Created by Kosh on 08 Jun 2017, 10:52 PM - */ - -interface ThemeFragmentMvp { - - interface ThemeListener { - fun onChangePrimaryDarkColor(@ColorInt color: Int, darkIcons: Boolean) - - fun onThemeApplied() - } - - interface View : BaseMvp.FAView - - interface Presenter -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragmentPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragmentPresenter.kt deleted file mode 100644 index d6980c928..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/theme/fragment/ThemeFragmentPresenter.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.fastaccess.ui.modules.theme.fragment - -import com.fastaccess.ui.base.mvp.presenter.BasePresenter - -/** - * Created by Kosh on 08 Jun 2017, 10:52 PM - */ - -class ThemeFragmentPresenter : BasePresenter(), ThemeFragmentMvp.Presenter diff --git a/app/src/main/java/com/fastaccess/ui/modules/trending/TrendingActivity.kt b/app/src/main/java/com/fastaccess/ui/modules/trending/TrendingActivity.kt deleted file mode 100644 index 2f924b411..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/trending/TrendingActivity.kt +++ /dev/null @@ -1,239 +0,0 @@ -package com.fastaccess.ui.modules.trending - -import android.content.Context -import android.content.Intent -import android.graphics.drawable.GradientDrawable -import android.os.Bundle -import android.os.Handler -import android.support.annotation.ColorInt -import android.support.design.widget.NavigationView -import android.support.v4.widget.DrawerLayout -import android.text.Editable -import android.view.Gravity -import android.view.Menu -import android.view.MenuItem -import android.view.View -import android.widget.TextView -import butterknife.BindView -import butterknife.OnClick -import butterknife.OnEditorAction -import butterknife.OnTextChanged -import com.evernote.android.state.State -import com.fastaccess.R -import com.fastaccess.helper.* -import com.fastaccess.provider.scheme.LinkParserHelper -import com.fastaccess.ui.base.BaseActivity -import com.fastaccess.ui.modules.main.MainActivity -import com.fastaccess.ui.modules.trending.fragment.TrendingFragment -import com.fastaccess.ui.widgets.FontEditText - - -/** - * Created by Kosh on 30 May 2017, 10:57 PM - */ - -class TrendingActivity : BaseActivity(), TrendingMvp.View { - private var trendingFragment: TrendingFragment? = null - - @BindView(R.id.navMenu) lateinit var navMenu: NavigationView - @BindView(R.id.daily) lateinit var daily: TextView - @BindView(R.id.weekly) lateinit var weekly: TextView - @BindView(R.id.monthly) lateinit var monthly: TextView - @BindView(R.id.drawer) lateinit var drawerLayout: DrawerLayout - @BindView(R.id.clear) lateinit var clear: View - @BindView(R.id.searchEditText) lateinit var searchEditText: FontEditText - - - @State var selectedTitle: String = "All Language" - - @OnTextChanged(value = [R.id.searchEditText], callback = OnTextChanged.Callback.AFTER_TEXT_CHANGED) fun onTextChange(s: Editable) { - val text = s.toString() - if (text.isEmpty()) { - AnimHelper.animateVisibility(clear, false) - } else { - AnimHelper.animateVisibility(clear, true) - } - } - - @OnEditorAction(R.id.searchEditText) fun onSearch(): Boolean { - presenter.onFilterLanguage(InputHelper.toString(searchEditText)) - ViewHelper.hideKeyboard(searchEditText) - return true - } - - @OnClick(R.id.daily) fun onDailyClicked() { - Logger.e() - daily.isSelected = true - weekly.isSelected = false - monthly.isSelected = false - setValues() - } - - @OnClick(R.id.weekly) fun onWeeklyClicked() { - weekly.isSelected = true - daily.isSelected = false - monthly.isSelected = false - setValues() - } - - @OnClick(R.id.monthly) fun onMonthlyClicked() { - monthly.isSelected = true - weekly.isSelected = false - daily.isSelected = false - setValues() - } - - @OnClick(R.id.clear) fun onClearSearch() { - ViewHelper.hideKeyboard(searchEditText) - searchEditText.setText("") - onClearMenu() - presenter.onLoadLanguage() - } - - override fun layout(): Int = R.layout.trending_activity_layout - - override fun isTransparent(): Boolean = true - - override fun canBack(): Boolean = true - - override fun isSecured(): Boolean = false - - override fun providePresenter(): TrendingPresenter = TrendingPresenter() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - navMenu.itemIconTintList = null - trendingFragment = supportFragmentManager.findFragmentById(R.id.trendingFragment) as TrendingFragment? - navMenu.setNavigationItemSelectedListener({ item -> - closeDrawerLayout() - onItemClicked(item) - }) - setupIntent(savedInstanceState) - if (savedInstanceState == null) { - presenter.onLoadLanguage() - } else { - Handler().postDelayed({ - Logger.e(searchEditText.text) - if (InputHelper.isEmpty(searchEditText)) { //searchEditText.text is always empty even tho there is a text in it !!!!!!! - presenter.onLoadLanguage() - } else { - presenter.onFilterLanguage(InputHelper.toString(searchEditText)) - } - }, 300) - } - onSelectTrending() - } - - override fun onCreateOptionsMenu(menu: Menu?): Boolean { - menuInflater.inflate(R.menu.trending_menu, menu) - return super.onCreateOptionsMenu(menu) - } - - override fun onOptionsItemSelected(item: MenuItem?): Boolean { - return when (item?.itemId) { - R.id.menu -> { - drawerLayout.openDrawer(Gravity.END) - true - } - R.id.share -> { - ActivityHelper.shareUrl(this, "${LinkParserHelper.PROTOCOL_HTTPS}://${LinkParserHelper.HOST_DEFAULT}" + - "/trending/$selectedTitle") - return true - } - android.R.id.home -> { - startActivity(Intent(this, MainActivity::class.java)) - finish() - true - } - else -> super.onOptionsItemSelected(item) - } - } - - override fun onAppend(title: String, color: Int) { - navMenu.menu.add(R.id.languageGroup, title.hashCode(), Menu.NONE, title) - .setCheckable(true) - .setIcon(createOvalShape(color)) - .isChecked = title.toLowerCase() == selectedTitle.toLowerCase() - } - - override fun onClearMenu() { - navMenu.menu.clear() - } - - private fun onItemClicked(item: MenuItem?): Boolean { - selectedTitle = when (item?.title.toString()) { - "All Language" -> "" - else -> item?.title.toString() - } - Logger.e(selectedTitle) - setValues() - return true - } - - private fun closeDrawerLayout() { - drawerLayout.closeDrawer(Gravity.END) - } - - private fun setValues() { - closeDrawerLayout() - Logger.e(selectedTitle, getSince()) - trendingFragment?.onSetQuery(selectedTitle, getSince()) - } - - private fun getSince(): String { - return when { - daily.isSelected -> "daily" - weekly.isSelected -> "weekly" - monthly.isSelected -> "monthly" - else -> "daily" - } - } - - private fun setupIntent(savedInstanceState: Bundle?) { - if (savedInstanceState == null) { - if (intent != null && intent.extras != null) { - val bundle = intent.extras - if (bundle != null) { - val lang: String = bundle.getString(BundleConstant.EXTRA) - val query: String? = bundle.getString(BundleConstant.EXTRA_TWO) - if (!lang.isEmpty()) { - selectedTitle = lang - } - if (query.isNullOrEmpty()) { - daily.isSelected = true - } else { - when (query?.toLowerCase()) { - "daily" -> daily.isSelected = true - "weekly" -> weekly.isSelected = true - "monthly" -> monthly.isSelected = true - } - } - } else { - daily.isSelected = true - } - } else { - daily.isSelected = true - } - setValues() - } - } - - private fun createOvalShape(@ColorInt color: Int): GradientDrawable { - val drawable = GradientDrawable() - drawable.shape = GradientDrawable.OVAL - drawable.setSize(24, 24) - drawable.setColor(color) - return drawable - } - - companion object { - fun getTrendingIntent(context: Context, lang: String?, query: String?): Intent { - val intent = Intent(context, TrendingActivity::class.java) - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, lang) - .put(BundleConstant.EXTRA_TWO, query) - .end()) - return intent - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/trending/TrendingMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/trending/TrendingMvp.kt deleted file mode 100644 index dbd68d5c3..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/trending/TrendingMvp.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.fastaccess.ui.modules.trending - -import android.support.annotation.ColorInt -import com.fastaccess.ui.base.mvp.BaseMvp - -/** - * Created by Kosh on 30 May 2017, 10:51 PM - */ - -interface TrendingMvp { - interface View : BaseMvp.FAView { - fun onAppend(title: String, @ColorInt color: Int) - fun onClearMenu() - } - - interface Presenter { - fun onLoadLanguage() - - fun onFilterLanguage(key: String) - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/trending/TrendingPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/trending/TrendingPresenter.kt deleted file mode 100644 index f6d44553f..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/trending/TrendingPresenter.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.fastaccess.ui.modules.trending - -import android.graphics.Color -import com.fastaccess.helper.RxHelper -import com.fastaccess.provider.colors.ColorsProvider -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import io.reactivex.Observable - -/** - * Created by Kosh on 30 May 2017, 10:55 PM - */ - -class TrendingPresenter : BasePresenter(), TrendingMvp.Presenter { - override fun onFilterLanguage(key: String) { - manageObservable(RxHelper.getObservable(Observable.fromIterable(ColorsProvider.languages())) - .doOnSubscribe { sendToView { it.onClearMenu() } } - .filter { it.toLowerCase().contains(key.toLowerCase()) } - .doOnNext { sendWithColor(it) }) - } - - private fun sendWithColor(t: String) { - val color = ColorsProvider.getColor(t) - if (color != null) { - try { - val lanColor = Color.parseColor(color.color) - sendToView { it.onAppend(t, lanColor) } - } catch (e: Exception) { - e.printStackTrace() - sendToView { it.onAppend(t, Color.LTGRAY) } - } - } else { - sendToView { it.onAppend(t, Color.LTGRAY) } - } - } - - override fun onLoadLanguage() { - manageObservable(RxHelper.getObservable(Observable.fromIterable(ColorsProvider.languages())) - .doOnNext { sendWithColor(it) }) - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragment.kt b/app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragment.kt deleted file mode 100644 index ad4d0d775..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragment.kt +++ /dev/null @@ -1,90 +0,0 @@ -package com.fastaccess.ui.modules.trending.fragment - -import android.os.Bundle -import android.support.v4.widget.SwipeRefreshLayout -import android.view.View -import butterknife.BindView -import com.evernote.android.state.State -import com.fastaccess.R -import com.fastaccess.data.dao.TrendingModel -import com.fastaccess.ui.adapter.TrendingAdapter -import com.fastaccess.ui.base.BaseFragment -import com.fastaccess.ui.widgets.StateLayout -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller - -/** - * Created by Kosh on 30 May 2017, 11:37 PM - */ - -class TrendingFragment : BaseFragment(), TrendingFragmentMvp.View { - - @BindView(R.id.recycler) lateinit var recycler: DynamicRecyclerView - @BindView(R.id.refresh) lateinit var refresh: SwipeRefreshLayout - @BindView(R.id.stateLayout) lateinit var stateLayout: StateLayout - @BindView(R.id.fastScroller) lateinit var fastScroller: RecyclerViewFastScroller - - private val adapter by lazy { TrendingAdapter(presenter.getTendingList()) } - - @State var lang: String = "" - @State var since: String = "" - - override fun providePresenter(): TrendingFragmentPresenter = TrendingFragmentPresenter() - - override fun fragmentLayout(): Int = R.layout.small_grid_refresh_list - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - stateLayout.setEmptyText(R.string.no_trending) - recycler.setEmptyView(stateLayout, refresh) - refresh.setOnRefreshListener { onCallApi() } - stateLayout.setOnReloadListener { onCallApi() } - adapter.listener = presenter - recycler.adapter = adapter - fastScroller.attachRecyclerView(recycler) - } - - override fun onNotifyAdapter(items: TrendingModel) { - adapter.addItem(items) - } - - override fun onSetQuery(lang: String, since: String) { - this.lang = lang - this.since = since - adapter.clear() - presenter.onCallApi(lang, since) - } - - override fun showProgress(resId: Int) { - refresh.isRefreshing = true - stateLayout.showProgress() - } - - override fun hideProgress() { - refresh.isRefreshing = false - stateLayout.hideProgress() - stateLayout.showReload(adapter.itemCount) - } - - override fun showMessage(titleRes: Int, msgRes: Int) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showMessage(titleRes: String, msgRes: String) { - hideProgress() - super.showMessage(titleRes, msgRes) - } - - override fun showErrorMessage(msgRes: String) { - hideProgress() - super.showErrorMessage(msgRes) - } - - private fun onCallApi() { - presenter.onCallApi(lang, since) - } - - override fun clearAdapter() { - adapter.clear() - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragmentMvp.kt b/app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragmentMvp.kt deleted file mode 100644 index 68a66dcc9..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragmentMvp.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.fastaccess.ui.modules.trending.fragment - - -import com.fastaccess.data.dao.TrendingModel -import com.fastaccess.ui.base.mvp.BaseMvp -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder - -/** - * Created by Kosh on 30 May 2017, 11:03 PM - */ - -interface TrendingFragmentMvp { - interface View : BaseMvp.FAView { - fun onNotifyAdapter(items: TrendingModel) - fun onSetQuery(lang: String, since: String) - fun clearAdapter() - } - - interface Presenter : BaseViewHolder.OnItemClickListener { - fun onCallApi(lang: String, since: String) - fun getTendingList(): ArrayList - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragmentPresenter.kt b/app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragmentPresenter.kt deleted file mode 100644 index f30468ae1..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/trending/fragment/TrendingFragmentPresenter.kt +++ /dev/null @@ -1,83 +0,0 @@ -package com.fastaccess.ui.modules.trending.fragment - -import android.view.View -import com.fastaccess.data.dao.TrendingModel -import com.fastaccess.helper.InputHelper -import com.fastaccess.helper.RxHelper -import com.fastaccess.provider.rest.jsoup.JsoupProvider -import com.fastaccess.ui.base.mvp.presenter.BasePresenter -import com.fastaccess.ui.modules.repos.RepoPagerActivity -import io.reactivex.Observable -import io.reactivex.disposables.Disposable -import org.jsoup.Jsoup -import org.jsoup.nodes.Document -import org.jsoup.select.Elements - -/** - * Created by Kosh on 30 May 2017, 11:04 PM - */ - -class TrendingFragmentPresenter : BasePresenter(), TrendingFragmentMvp.Presenter { - - private var disposel: Disposable? = null - - private val trendingList: ArrayList = ArrayList() - - override fun getTendingList(): ArrayList { - return trendingList - } - - override fun onItemLongClick(position: Int, v: View?, item: TrendingModel?) {} - - override fun onItemClick(position: Int, v: View?, item: TrendingModel?) { - val split = item?.title?.trim()?.split("/")!! - v?.context!!.startActivity(RepoPagerActivity.createIntent(v.context!!, split[1].trim(), split[0].trim())) - } - - override fun onCallApi(lang: String, since: String) { - disposel?.let { if (!it.isDisposed) it.dispose() } - disposel = RxHelper.getObservable(JsoupProvider.getTrendingService().getTrending( - (if (!InputHelper.isEmpty(lang)) lang.replace(" ".toRegex(), "-") else "").toLowerCase(), since)) - .flatMap { s -> RxHelper.getObservable(getTrendingObservable(s)) } - .doOnSubscribe { - sendToView { - it.showProgress(0) - it.clearAdapter() - } - } - .subscribe({ response -> sendToView { view -> view.onNotifyAdapter(response) } }, - { throwable -> onError(throwable) }, { sendToView({ it.hideProgress() }) }) - manageDisposable(disposel) - } - - - private fun getTrendingObservable(response: String): Observable { - return Observable.fromPublisher { s -> - val document: Document = Jsoup.parse(response, "") - val repoList = document.select(".repo-list") - if (repoList.isNotEmpty()) { - val list: Elements? = repoList.select("li") - list?.let { - if (list.isNotEmpty()) { - it.onEach { - val title = it.select(".d-inline-block > h3 > a").text() - val description = it.select(".py-1 > p").text() - val stars = it.select(".f6 > a[href*=/stargazers]").text() - val forks = it.select(".f6 > a[href*=/network]").text() - var todayStars = it.select(".f6 > span.float-right").text() - if (todayStars.isNullOrBlank()) { - todayStars = it.select(".f6 > span.float-sm-right").text() - } - var language = it.select(".f6 .mr-3 > span[itemprop=programmingLanguage]").text() - if (language.isNullOrBlank()) { - language = it.select(".f6 span[itemprop=programmingLanguage]").text() - } - s.onNext(TrendingModel(title, description, language, stars, forks, todayStars)) - } - } - } - } - s.onComplete() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/modules/user/UserPagerActivity.java b/app/src/main/java/com/fastaccess/ui/modules/user/UserPagerActivity.java deleted file mode 100644 index 70286f28a..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/user/UserPagerActivity.java +++ /dev/null @@ -1,332 +0,0 @@ -package com.fastaccess.ui.modules.user; - -import android.app.Application; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.TabLayout; -import android.support.v4.app.Fragment; -import android.support.v4.view.ViewPager; -import android.view.Menu; -import android.view.MenuItem; -import android.widget.TextView; - -import com.annimon.stream.Stream; -import com.evernote.android.state.State; -import com.fastaccess.R; -import com.fastaccess.data.dao.FragmentPagerAdapterModel; -import com.fastaccess.data.dao.TabsCountStateModel; -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.scheme.LinkParserHelper; -import com.fastaccess.ui.adapter.FragmentsPagerAdapter; -import com.fastaccess.ui.base.BaseActivity; -import com.fastaccess.ui.base.BaseFragment; -import com.fastaccess.ui.modules.main.MainActivity; -import com.fastaccess.ui.modules.profile.org.repos.OrgReposFragment; -import com.fastaccess.ui.modules.profile.repos.ProfileReposFragment; -import com.fastaccess.ui.widgets.SpannableBuilder; -import com.fastaccess.ui.widgets.ViewPagerView; - -import java.util.HashSet; - -import butterknife.BindView; -import butterknife.OnClick; -import shortbread.Shortcut; - -/** - * Created by Kosh on 03 Dec 2016, 8:00 AM - */ - -@Shortcut(id = "profile", icon = R.drawable.ic_app_shortcut_profile, shortLabelRes = R.string.profile, backStack = {MainActivity.class}, rank = 4) -public class UserPagerActivity extends BaseActivity implements UserPagerMvp.View { - - @BindView(R.id.tabs) TabLayout tabs; - @BindView(R.id.tabbedPager) ViewPagerView pager; - @BindView(R.id.fab) FloatingActionButton fab; - @State int index; - @State String login; - @State boolean isOrg; - @State HashSet counts = new HashSet<>(); - - public static void startActivity(@NonNull Context context, @NonNull String login, boolean isOrg, - boolean isEnterprise, int index) { - context.startActivity(createIntent(context, login, isOrg, isEnterprise, index)); - } - - public static Intent createIntent(@NonNull Context context, @NonNull String login) { - return createIntent(context, login, false); - } - - public static Intent createIntent(@NonNull Context context, @NonNull String login, boolean isOrg) { - return createIntent(context, login, isOrg, false, -1); - } - - public static Intent createIntent(@NonNull Context context, @NonNull String login, boolean isOrg, - boolean isEnterprise, int index) { - Intent intent = new Intent(context, UserPagerActivity.class); - intent.putExtras(Bundler.start() - .put(BundleConstant.EXTRA, login) - .put(BundleConstant.IS_ENTERPRISE, isEnterprise) - .put(BundleConstant.EXTRA_TYPE, isOrg) - .put(BundleConstant.EXTRA_TWO, index) - .end()); - if (context instanceof Service || context instanceof Application) { - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } - return intent; - } - - @Override protected int layout() { - return R.layout.tabbed_pager_layout; - } - - @Override protected boolean isTransparent() { - return true; - } - - @Override protected boolean canBack() { - return true; - } - - @Override protected boolean isSecured() { - return false; - } - - @NonNull @Override public UserPagerPresenter providePresenter() { - return new UserPagerPresenter(); - } - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Login currentUser = Login.getUser(); - if (currentUser == null) { - onRequireLogin(); - return; - } - if (savedInstanceState == null) { - if (getIntent() != null && getIntent().getExtras() != null) { - login = getIntent().getExtras().getString(BundleConstant.EXTRA); - isOrg = getIntent().getExtras().getBoolean(BundleConstant.EXTRA_TYPE); - index = getIntent().getExtras().getInt(BundleConstant.EXTRA_TWO, -1); - if (!InputHelper.isEmpty(login)) { - if (isOrg) { - getPresenter().checkOrgMembership(login); - } else { - if (!Login.getUser().getLogin().equalsIgnoreCase(login)) getPresenter().onCheckBlocking(login); - } - } - } else { - Login user = Login.getUser(); - if (user == null) { - onRequireLogin(); - return; - } - login = user.getLogin(); - } - } - if (InputHelper.isEmpty(login)) { - finish(); - return; - } - setTaskName(login); - setTitle(login); - if (login.equalsIgnoreCase(currentUser.getLogin())) { - selectProfile(); - } - if (!isOrg) { - FragmentsPagerAdapter adapter = new FragmentsPagerAdapter(getSupportFragmentManager(), - FragmentPagerAdapterModel.buildForProfile(this, login)); - pager.setAdapter(adapter); - tabs.setTabGravity(TabLayout.GRAVITY_FILL); - tabs.setTabMode(TabLayout.MODE_SCROLLABLE); - tabs.setupWithViewPager(pager); - if (savedInstanceState == null) { - if (index != -1) { - pager.setCurrentItem(index); - } - } - } else { - if (getPresenter().getIsMember() == -1) { - getPresenter().checkOrgMembership(login); - } else { - onInitOrg(getPresenter().isMember == 1); - } - } - tabs.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager) { - @Override public void onTabReselected(TabLayout.Tab tab) { - super.onTabReselected(tab); - onScrollTop(tab.getPosition()); - } - }); - pager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { - @Override public void onPageSelected(int position) { - super.onPageSelected(position); - hideShowFab(position); - } - }); - if (!isOrg) { - if (savedInstanceState != null && !counts.isEmpty()) { - Stream.of(counts).forEach(this::updateCount); - } - } - hideShowFab(pager.getCurrentItem()); - } - - @Override public void onScrollTop(int index) { - if (pager == null || pager.getAdapter() == null) return; - Fragment fragment = (BaseFragment) pager.getAdapter().instantiateItem(pager, index); - if (fragment instanceof BaseFragment) { - ((BaseFragment) fragment).onScrollTop(index); - } - } - - @Override public void hideProgress() { - super.hideProgress(); - } - - @Override public void onNavigateToFollowers() { - pager.setCurrentItem(5); - } - - @Override public void onNavigateToFollowing() { - pager.setCurrentItem(6); - } - - @Override public void onInitOrg(boolean isMember) { - hideProgress(); - FragmentsPagerAdapter adapter = new FragmentsPagerAdapter(getSupportFragmentManager(), - FragmentPagerAdapterModel.buildForOrg(this, login, isMember)); - pager.setAdapter(adapter); - tabs.setTabGravity(TabLayout.GRAVITY_FILL); - tabs.setTabMode(TabLayout.MODE_SCROLLABLE); - tabs.setupWithViewPager(pager); - setTaskName(login); - } - - @Override public void onUserBlocked() { - showMessage(R.string.success, R.string.user_blocked); - onInvalidateMenu(); - } - - @Override public void onInvalidateMenu() { - hideProgress(); - supportInvalidateOptionsMenu(); - } - - @Override public void onUserUnBlocked() { - showMessage(R.string.success, R.string.user_unblocked); - onInvalidateMenu(); - } - - @Override public void onCheckType(boolean isOrg) { - if (!this.isOrg == isOrg) { - startActivity(this, login, isOrg, isEnterprise(), index); - finish(); - } - } - - @Override public void onSetBadge(int tabIndex, int count) { - TabsCountStateModel model = new TabsCountStateModel(); - model.setTabIndex(tabIndex); - model.setCount(count); - counts.add(model); - if (tabs != null) { - updateCount(model); - } - } - - @OnClick(R.id.fab) public void onRepoFilterClicked() { - if (isOrg) { - int position; - if (getPresenter().getIsMember() == 1) { - position = 2; - } else { - position = 1; - } - OrgReposFragment fragment = ((OrgReposFragment) pager.getAdapter().instantiateItem(pager, position)); - fragment.onRepoFilterClicked(); - } else { - ProfileReposFragment fragment = ((ProfileReposFragment) pager.getAdapter().instantiateItem(pager, 2)); - fragment.onRepoFilterClicked(); - } - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.share_menu, menu); - return super.onCreateOptionsMenu(menu); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.share && !InputHelper.isEmpty(login)) { - ActivityHelper.shareUrl(this, new Uri.Builder().scheme("https") - .authority(LinkParserHelper.HOST_DEFAULT) - .appendPath(login) - .toString()); - return true; - } else if (item.getItemId() == R.id.block && !InputHelper.isEmpty(login)) { - getPresenter().onBlockUser(login); - } - return super.onOptionsItemSelected(item); - } - - @Override public boolean onPrepareOptionsMenu(Menu menu) { - Logger.e(getPresenter().isUserBlockedRequested(), getPresenter().isUserBlocked()); - if (getPresenter().isUserBlockedRequested()) { - Login login = Login.getUser(); - if (login != null && !isOrg) { - String username = login.getLogin(); - if (!username.equalsIgnoreCase(this.login)) { - menu.findItem(R.id.block) - .setIcon(getPresenter().isUserBlocked() ? R.drawable.ic_unlock : R.drawable.ic_lock) - .setTitle(getPresenter().isUserBlocked() ? getString(R.string.unblock) : getString(R.string.block)) - .setVisible(true); - } - } - } - return super.onPrepareOptionsMenu(menu); - } - - private void hideShowFab(int position) { - if (isOrg) { - if (getPresenter().getIsMember() == 1) { - if (position == 2) { - fab.show(); - } else { - fab.hide(); - } - } else { - if (position == 1) { - fab.show(); - } else { - fab.hide(); - } - } - } else { - if (position == 2) { - fab.show(); - } else { - fab.hide(); - } - } - } - - private void updateCount(@NonNull TabsCountStateModel model) { - TextView tv = ViewHelper.getTabTextView(tabs, model.getTabIndex()); - tv.setText(SpannableBuilder.builder() - .append(getString(R.string.starred)) - .append(" ") - .append("(") - .bold(String.valueOf(model.getCount())) - .append(")")); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/user/UserPagerMvp.java b/app/src/main/java/com/fastaccess/ui/modules/user/UserPagerMvp.java deleted file mode 100644 index c81c43e62..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/user/UserPagerMvp.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.fastaccess.ui.modules.user; - -import android.support.annotation.NonNull; - -import com.fastaccess.ui.base.mvp.BaseMvp; -import com.fastaccess.ui.modules.profile.ProfilePagerMvp; -import com.fastaccess.ui.modules.repos.RepoPagerMvp; - -/** - * Created by Kosh on 04 Dec 2016, 1:11 PM - */ - -public interface UserPagerMvp { - - interface View extends BaseMvp.FAView, ProfilePagerMvp.View, RepoPagerMvp.TabsBadgeListener { - void onInitOrg(boolean isMember); - - void onUserBlocked(); - - void onInvalidateMenu(); - - void onUserUnBlocked(); - } - - interface Presenter extends BaseMvp.FAPresenter { - - void onCheckBlocking(@NonNull String login); - - void checkOrgMembership(@NonNull String org); - - void onBlockUser(@NonNull String login); - - void onUnblockUser(@NonNull String login); - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/modules/user/UserPagerPresenter.java b/app/src/main/java/com/fastaccess/ui/modules/user/UserPagerPresenter.java deleted file mode 100644 index 81cfdc6bd..000000000 --- a/app/src/main/java/com/fastaccess/ui/modules/user/UserPagerPresenter.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.fastaccess.ui.modules.user; - -import android.support.annotation.NonNull; - -import com.fastaccess.data.dao.model.Login; -import com.fastaccess.provider.rest.RestProvider; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import lombok.Getter; - -/** - * Created by Kosh on 03 Dec 2016, 8:00 AM - */ - -@Getter class UserPagerPresenter extends BasePresenter implements UserPagerMvp.Presenter { - @com.evernote.android.state.State int isMember = -1; - @com.evernote.android.state.State boolean isUserBlocked; - @com.evernote.android.state.State boolean isUserBlockedRequested; - - @Override public void onCheckBlocking(@NonNull String login) { - makeRestCall(RestProvider.getUserService(isEnterprise()).isUserBlocked(login), - booleanResponse -> sendToView(view -> { - isUserBlockedRequested = true; - isUserBlocked = booleanResponse.code() == 204; - view.onInvalidateMenu(); - })); - } - - @Override public void checkOrgMembership(@NonNull String org) { - makeRestCall(RestProvider.getOrgService(isEnterprise()).isMember(org, Login.getUser().getLogin()), - booleanResponse -> sendToView(view -> { - isMember = booleanResponse.code() == 204 ? 1 : 0; - view.onInitOrg(isMember == 1); - })); - } - - @Override public void onBlockUser(@NonNull String login) { - if (isUserBlocked()) { - onUnblockUser(login); - } else { - makeRestCall(RestProvider.getUserService(isEnterprise()).blockUser(login), - booleanResponse -> sendToView(view -> { - isUserBlocked = true; - view.onUserBlocked(); - })); - } - } - - @Override public void onUnblockUser(@NonNull String login) { - makeRestCall(RestProvider.getUserService(isEnterprise()).unBlockUser(login), - booleanResponse -> sendToView(view -> { - isUserBlocked = false; - view.onUserUnBlocked(); - })); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/AppbarRefreshLayout.java b/app/src/main/java/com/fastaccess/ui/widgets/AppbarRefreshLayout.java deleted file mode 100644 index 75426e44a..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/AppbarRefreshLayout.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.v4.widget.SwipeRefreshLayout; -import android.util.AttributeSet; - -import com.fastaccess.R; - - -/** - * Created by kosh on 7/30/2015. CopyRights @ - */ -public class AppbarRefreshLayout extends SwipeRefreshLayout { - - public AppbarRefreshLayout(@NonNull Context context) { - super(context, null); - } - - public AppbarRefreshLayout(@NonNull Context context, AttributeSet attrs) { - super(context, attrs); - setColorSchemeResources(R.color.material_amber_700, R.color.material_blue_700, R.color.material_purple_700, R.color.material_lime_700); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/AutoLinearLayout.java b/app/src/main/java/com/fastaccess/ui/widgets/AutoLinearLayout.java deleted file mode 100644 index 674e07ad4..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/AutoLinearLayout.java +++ /dev/null @@ -1,495 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.content.res.TypedArray; -import android.support.v4.view.GravityCompat; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.View; -import android.widget.FrameLayout; - -import com.fastaccess.R; - -import java.util.ArrayList; - -public class AutoLinearLayout extends FrameLayout { - - private int mOrientation; - private int mGravity = Gravity.TOP | GravityCompat.START; - - private final static int HORIZONTAL = 0; - private final static int VERTICAL = 1; - - private ArrayList mListPositions = new ArrayList<>(); - - public AutoLinearLayout(Context context) { - super(context); - init(context, null, 0, 0); - } - - public AutoLinearLayout(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs, 0, 0); - } - - public AutoLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs, defStyleAttr, 0); - } - - public AutoLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(context, attrs, defStyleAttr, defStyleRes); - } - - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (mOrientation == VERTICAL) { - measureVertical(widthMeasureSpec, heightMeasureSpec); - } else { - measureHorizontal(widthMeasureSpec, heightMeasureSpec); - } - } - - @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - mListPositions.clear(); - if (mOrientation == VERTICAL) - layoutVertical(left, top, right, bottom); - else - layoutHorizontal(left, top, right, bottom); - } - - private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AutoLinearLayout, defStyleAttr, defStyleRes); - try { - mOrientation = a.getInt(R.styleable.AutoLinearLayout_auto_orientation, HORIZONTAL); - int gravity = a.getInt(R.styleable.AutoLinearLayout_auto_gravity, -1); - if (gravity >= 0) { - setGravity(gravity); - } - } finally { - a.recycle(); - } - } - - private void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) { - int wSize = MeasureSpec.getSize(widthMeasureSpec) - (getPaddingLeft() + getPaddingRight()); - - //Scrollview case - if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.UNSPECIFIED) - wSize = Integer.MAX_VALUE; - - int count = getChildCount(); - int rowWidth = 0; - int totalHeight = 0; - int rowMaxHeight = 0; - int childWidth; - int childHeight; - int maxRowWidth = getPaddingLeft() + getPaddingRight(); - - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - if (child.getVisibility() != GONE) { - measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; - childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; - //keep max height value stored - rowMaxHeight = Math.max(rowMaxHeight, childHeight); - - //exceed max width start new row and update total height - if (childWidth + rowWidth > wSize) { - totalHeight += rowMaxHeight; - maxRowWidth = Math.max(maxRowWidth, rowWidth); - rowWidth = childWidth; - rowMaxHeight = childHeight; - } else { - rowWidth += childWidth; - } - } - } - //plus last child height and width - if (rowWidth != 0) { - maxRowWidth = Math.max(maxRowWidth, rowWidth); - totalHeight += rowMaxHeight; - } - - //set width to max value - if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.UNSPECIFIED) - wSize = maxRowWidth + (getPaddingLeft() + getPaddingRight()); - - setMeasuredDimension(resolveSize(wSize, widthMeasureSpec), - resolveSize(totalHeight + getPaddingTop() + getPaddingBottom(), heightMeasureSpec)); - } - - private void measureVertical(int widthMeasureSpec, int heightMeasureSpec) { - int hSize = MeasureSpec.getSize(heightMeasureSpec) - (getPaddingTop() + getPaddingBottom()); - - int count = getChildCount(); - int columnHeight = 0; - int totalWidth = 0, maxColumnHeight = 0; - int columnMaxWidth = 0; - int childWidth; - int childHeight; - - //Scrollview case - if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) - hSize = Integer.MAX_VALUE; - - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - if (child.getVisibility() != GONE) { - measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; - childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; - //keep max width value stored - columnMaxWidth = Math.max(columnMaxWidth, childWidth); - - //exceed max height start new column and update total width - if (childHeight + columnHeight > hSize) { - totalWidth += columnMaxWidth; - maxColumnHeight = Math.max(maxColumnHeight, columnHeight); - columnHeight = childHeight; - columnMaxWidth = childWidth; - } else { - columnHeight += childHeight; - } - } - } - //plus last child width - if (columnHeight != 0) { - maxColumnHeight = Math.max(maxColumnHeight, columnHeight); - totalWidth += columnMaxWidth; - } - - //set height to max value - if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) - hSize = maxColumnHeight + (getPaddingTop() + getPaddingBottom()); - - setMeasuredDimension(resolveSize(totalWidth + getPaddingRight() + getPaddingLeft(), - widthMeasureSpec), resolveSize(hSize, heightMeasureSpec)); - } - - /** - * Arranges the children in columns. Takes care about child margin, padding, gravity and - * child layout gravity. - * - * @param left - * parent left - * @param top - * parent top - * @param right - * parent right - * @param bottom - * parent bottom - */ - private void layoutVertical(int left, int top, int right, int bottom) { - final int count = getChildCount(); - if (count == 0) - return; - - final int width = right - getPaddingLeft() - left - getPaddingRight(); - final int height = bottom - getPaddingTop() - top - getPaddingBottom(); - - int childTop = getPaddingTop(); - int childLeft = getPaddingLeft(); - - int totalHorizontal = getPaddingLeft() + getPaddingRight(); - int totalVertical = 0; - int column = 0; - int maxChildWidth = 0; - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - if (child != null && child.getVisibility() != View.GONE) { - //if child is not updated yet call measure - if (child.getMeasuredHeight() == 0 || child.getMeasuredWidth() == 0) - child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), - MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); - - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - final int childWidth = child.getMeasuredWidth(); - final int childHeight = child.getMeasuredHeight(); - //if there is not enough space jump to another column - if (childTop + childHeight + lp.topMargin + lp.bottomMargin > height + getPaddingTop()) { - //before change column update positions if the gravity is present - updateChildPositionVertical(height, totalVertical, column, maxChildWidth); - childTop = getPaddingTop(); - childLeft += maxChildWidth; - maxChildWidth = 0; - column++; - totalVertical = 0; - } - - childTop += lp.topMargin; - mListPositions.add(new ViewPosition(childLeft, childTop, column)); - //check max child width - int currentWidth = childWidth + lp.leftMargin + lp.rightMargin; - if (maxChildWidth < currentWidth) - maxChildWidth = currentWidth; - //get ready for next child - childTop += childHeight + lp.bottomMargin; - totalVertical += childHeight + lp.topMargin + lp.bottomMargin; - } - } - - //update positions for last column - updateChildPositionVertical(height, totalVertical, column, maxChildWidth); - totalHorizontal += childLeft + maxChildWidth; - //final update for horizontal gravities and layout views - updateChildPositionHorizontal(width, totalHorizontal, column, 0); - //mListPositions.clear(); - } - - /** - * Arranges the children in rows. Takes care about child margin, padding, gravity and - * child layout gravity. Analog to vertical. - * - * @param left - * parent left - * @param top - * parent top - * @param right - * parent right - * @param bottom - * parent bottom - */ - private void layoutHorizontal(int left, int top, int right, int bottom) { - final int count = getChildCount(); - if (count == 0) - return; - - final int width = right - getPaddingLeft() - left - getPaddingRight(); - final int height = bottom - getPaddingTop() - top - getPaddingBottom(); - - int childTop = getPaddingTop(); - int childLeft = getPaddingLeft(); - - int totalHorizontal = 0; - int totalVertical = getPaddingTop() + getPaddingBottom(); - int row = 0; - int maxChildHeight = 0; - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - - if (child != null && child.getVisibility() != View.GONE) { - if (child.getMeasuredHeight() == 0 || child.getMeasuredWidth() == 0) - child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), - MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); - - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - final int childWidth = child.getMeasuredWidth(); - final int childHeight = child.getMeasuredHeight(); - - if (childLeft + childWidth + lp.leftMargin + lp.rightMargin > width + getPaddingLeft()) { - updateChildPositionHorizontal(width, totalHorizontal, row, maxChildHeight); - childLeft = getPaddingLeft(); - childTop += maxChildHeight; - maxChildHeight = 0; - row++; - totalHorizontal = 0; - } - - childLeft += lp.leftMargin; - mListPositions.add(new ViewPosition(childLeft, childTop, row)); - - int currentHeight = childHeight + lp.topMargin + lp.bottomMargin; - if (maxChildHeight < currentHeight) - maxChildHeight = currentHeight; - - childLeft += childWidth + lp.rightMargin; - totalHorizontal += childWidth + lp.rightMargin + lp.leftMargin; - } - } - - updateChildPositionHorizontal(width, totalHorizontal, row, maxChildHeight); - totalVertical += childTop + maxChildHeight; - updateChildPositionVertical(height, totalVertical, row, 0); - //mListPositions.clear(); - } - - /** - * Updates children positions. Takes cares about gravity and layout gravity. - * Finally layout children to parent if needed. - * - * @param parentHeight - * parent parentHeight - * @param totalSize - * total vertical size used by children in a column - * @param column - * column number - * @param maxChildWidth - * the biggest child width - */ - private void updateChildPositionVertical(int parentHeight, int totalSize, int column, int maxChildWidth) { - for (int i = 0; i < mListPositions.size(); i++) { - ViewPosition pos = mListPositions.get(i); - final View child = getChildAt(i); - //(android:gravity) - //update children position inside parent layout - if (mOrientation == HORIZONTAL || pos.position == column) { - updateTopPositionByGravity(pos, parentHeight - totalSize, mGravity); - } - //(android:layout_gravity) - //update children position inside their space - if (mOrientation == VERTICAL && pos.position == column) { - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - int size = maxChildWidth - child.getMeasuredWidth() - lp.leftMargin - lp.rightMargin; - updateLeftPositionByGravity(pos, size, lp.gravity); - } - //update children into layout parent - if (mOrientation == HORIZONTAL) - layout(child, pos); - } - } - - /** - * Updates children positions. Takes cares about gravity and layout gravity. - * Finally layout children to parent if needed. Analog to vertical. - * - * @param parentWidth - * parent parentWidth - * @param totalSize - * total horizontal size used by children in a row - * @param row - * row number - * @param maxChildHeight - * the biggest child height - */ - private void updateChildPositionHorizontal(int parentWidth, int totalSize, int row, int maxChildHeight) { - for (int i = 0; i < mListPositions.size(); i++) { - ViewPosition pos = mListPositions.get(i); - final View child = getChildAt(i); - - if (mOrientation == VERTICAL || pos.position == row) { - updateLeftPositionByGravity(pos, parentWidth - totalSize, mGravity); - } - - if (mOrientation == HORIZONTAL && pos.position == row) { - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - int size = maxChildHeight - child.getMeasuredHeight() - lp.topMargin - lp.bottomMargin; - updateTopPositionByGravity(pos, size, lp.gravity); - } - - if (mOrientation == VERTICAL) - layout(child, pos); - } - } - - private void updateLeftPositionByGravity(ViewPosition pos, int size, int gravity) { - switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) { - case GravityCompat.END: - pos.left += (size > 0) ? size : 0; - break; - - case Gravity.CENTER_HORIZONTAL: - pos.left += ((size > 0) ? size : 0) / 2; - break; - } - } - - private void updateTopPositionByGravity(ViewPosition pos, int size, int gravity) { - switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) { - case Gravity.BOTTOM: - pos.top += (size > 0) ? size : 0; - break; - - case Gravity.CENTER_VERTICAL: - pos.top += ((size > 0) ? size : 0) / 2; - break; - } - } - - private void layout(View child, ViewPosition pos) { - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - - if (mOrientation == HORIZONTAL) - child.layout(pos.left, pos.top + lp.topMargin, pos.left + child.getMeasuredWidth(), pos.top + - child.getMeasuredHeight() + lp.topMargin); - else - child.layout(pos.left + lp.leftMargin, pos.top, pos.left + child.getMeasuredWidth() + - lp.leftMargin, pos.top + child.getMeasuredHeight()); - } - - /** - * Describes how the child views are positioned. Defaults to GRAVITY_TOP. If - * this layout has a VERTICAL orientation, this controls where all the child - * views are placed if there is extra vertical space. If this layout has a - * HORIZONTAL orientation, this controls the alignment of the children. - * - * @param gravity - * See {@link Gravity} - */ - private void setGravity(int gravity) { - if (mGravity != gravity) { - if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { - gravity |= GravityCompat.START; - } - - if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { - gravity |= Gravity.TOP; - } - - mGravity = gravity; - requestLayout(); - } - } - - public void setHorizontalGravity(int horizontalGravity) { - final int gravity = horizontalGravity & GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK; - if ((mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) != gravity) { - mGravity = (mGravity & ~GravityCompat.RELATIVE_HORIZONTAL_GRAVITY_MASK) | gravity; - requestLayout(); - } - } - - public void setVerticalGravity(int verticalGravity) { - final int gravity = verticalGravity & Gravity.VERTICAL_GRAVITY_MASK; - if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != gravity) { - mGravity = (mGravity & ~Gravity.VERTICAL_GRAVITY_MASK) | gravity; - requestLayout(); - } - } - - /** - * Should the layout be a column or a row. - * - * @param orientation - * Pass HORIZONTAL or VERTICAL. Default value is HORIZONTAL. - */ - public void setOrientation(int orientation) { - if (mOrientation != orientation) { - mOrientation = orientation; - requestLayout(); - } - } - - /** - * Returns the current orientation. - * - * @return either {@link #HORIZONTAL} or {@link #VERTICAL} - */ - public int getOrientation() { - return mOrientation; - } - - /** - * Helper inner class that stores child position - */ - private static class ViewPosition { - int left; - int top; - int position; //row or column - - ViewPosition(int l, int t, int p) { - this.left = l; - this.top = t; - this.position = p; - } - - @Override - public String toString() { - return "left-" + left + " top" + top + " pos" + position; - } - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/AvatarLayout.java b/app/src/main/java/com/fastaccess/ui/widgets/AvatarLayout.java deleted file mode 100644 index db84b7e14..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/AvatarLayout.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.support.annotation.AttrRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StyleRes; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.TooltipCompat; -import android.util.AttributeSet; -import android.view.View; -import android.widget.FrameLayout; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; -import com.bumptech.glide.signature.StringSignature; -import com.fastaccess.R; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.ui.modules.user.UserPagerActivity; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import cn.gavinliu.android.lib.shapedimageview.ShapedImageView; - -/** - * Created by Kosh on 14 Nov 2016, 7:59 PM - */ - -public class AvatarLayout extends FrameLayout { - - @BindView(R.id.avatar) ShapedImageView avatar; - @Nullable private String login; - private boolean isOrg; - private boolean isEnterprise; - - @OnClick(R.id.avatar) void onClick(@NonNull View view) { - if (InputHelper.isEmpty(login)) return; - UserPagerActivity.startActivity(view.getContext(), login, isOrg, isEnterprise, -1); - } - - public AvatarLayout(@NonNull Context context) { - super(context); - } - - public AvatarLayout(@NonNull Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - } - - public AvatarLayout(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public AvatarLayout(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - @Override protected void onAttachedToWindow() { - super.onAttachedToWindow(); - } - - @Override protected void onFinishInflate() { - super.onFinishInflate(); - inflate(getContext(), R.layout.avatar_layout, this); - if (isInEditMode()) return; - ButterKnife.bind(this); - setBackground(); - if (PrefGetter.isRectAvatar()) { - avatar.setShape(ShapedImageView.SHAPE_MODE_ROUND_RECT, 15); - } - } - - public void setUrl(@Nullable String url, @Nullable String login, boolean isOrg, boolean isEnterprise) { - setUrl(url, login, isOrg, isEnterprise, false); - } - - public void setUrl(@Nullable String url, @Nullable String login, boolean isOrg, boolean isEnterprise, boolean reload) { - this.login = login; - this.isOrg = isOrg; - this.isEnterprise = isEnterprise; - avatar.setContentDescription(login); - if (login != null) { - TooltipCompat.setTooltipText(avatar, login); - } else { - avatar.setOnClickListener(null); - avatar.setOnLongClickListener(null); - } - Glide.with(getContext()) - .load(url) - .fallback(ContextCompat.getDrawable(getContext(), R.drawable.ic_fasthub_mascot)) - .diskCacheStrategy(DiskCacheStrategy.ALL) - .signature(new StringSignature(reload ? String.valueOf(System.currentTimeMillis()) : "0")) - .dontAnimate() - .into(avatar); - } - - private void setBackground() { - if (PrefGetter.isRectAvatar()) { - setBackgroundResource(R.drawable.rect_shape); - } else { - setBackgroundResource(R.drawable.circle_shape); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/CardsPagerTransformerBasic.kt b/app/src/main/java/com/fastaccess/ui/widgets/CardsPagerTransformerBasic.kt deleted file mode 100644 index e9b17ceff..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/CardsPagerTransformerBasic.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.fastaccess.ui.widgets - -import android.support.v4.view.ViewPager -import android.view.View - -class CardsPagerTransformerBasic(private val baseElevation: Int, private val raisingElevation: Int) : ViewPager.PageTransformer { - override fun transformPage(page: View, position: Float) { - val absPosition = Math.abs(position) - if (absPosition >= 1) { - page.elevation = baseElevation.toFloat() - } else { - page.elevation = (1 - absPosition) * raisingElevation + baseElevation - } - } - - -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/ColorPickerPreference.java b/app/src/main/java/com/fastaccess/ui/widgets/ColorPickerPreference.java deleted file mode 100644 index ff1abdf71..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/ColorPickerPreference.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.PorterDuff; -import android.support.v7.preference.Preference; -import android.support.v7.preference.PreferenceViewHolder; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.widget.Button; -import android.widget.TextView; - -import com.fastaccess.R; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.ViewHelper; - -import java.util.ArrayList; -import java.util.HashMap; - -import petrov.kristiyan.colorpicker.ColorPicker; - -/** - * Created by Hamad on 6/11/17. - */ - -public class ColorPickerPreference extends Preference implements ColorPicker.OnChooseColorListener { - - public ColorPickerPreference(Context context) { - super(context); - init(); - } - - public ColorPickerPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(); - } - - public ColorPickerPreference(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - public ColorPickerPreference(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - private void init() { - setWidgetLayoutResource(R.layout.preference_widget_color); - } - - @Override - protected void onClick() { - super.onClick(); - - int selected_color = getSelectedColor(); - String title = String.format("Accent Color: (Currently: %s)", getSelectedColorName()); - ColorPicker colorPicker = new ColorPicker(getContext()); - colorPicker.setRoundColorButton(true); - colorPicker.setColors(R.array.theme_colors_hex); - colorPicker.setDefaultColorButton(selected_color); - colorPicker.setTitle(title); - TextView title_tv = colorPicker.getDialogViewLayout().findViewById(R.id.title); - title_tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14); - colorPicker.getPositiveButton().setTextColor(ViewHelper.getPrimaryTextColor(getContext())); - colorPicker.getNegativeButton().setTextColor(ViewHelper.getPrimaryTextColor(getContext())); - colorPicker.setOnChooseColorListener(this); - colorPicker.show(); - } - - @Override - public void onBindViewHolder(PreferenceViewHolder holder) { - super.onBindViewHolder(holder); - final Button colorButton = (Button) holder.findViewById(R.id.color); - colorButton.setBackgroundResource(R.drawable.circle_shape); - colorButton.getBackground().setColorFilter(getSelectedColor(), PorterDuff.Mode.SRC_IN); - } - - private int getSelectedColor() { - TypedArray colorTypedArray = getContext().getResources().obtainTypedArray(R.array.theme_colors_hex); - String[] colorNames = getContext().getResources().getStringArray(R.array.theme_colors); - - ArrayList colors = new ArrayList<>(); - for (int i = 0; i < colorTypedArray.length(); i++) { - colors.add(colorTypedArray.getColor(i, 0)); - } - colorTypedArray.recycle(); - HashMap preferenceValueToColor = new HashMap<>(); - - for(int i=0; i 0) { - int lines = split.length; - int index = -1; - for (int i = 0; i < lines; i++) { - if (truncate && (lines - i) > 2) continue; - String token = split[i]; - if (i < (lines - 1)) { - token = token.concat("\n"); - } - char firstChar = token.charAt(0); - int color = Color.TRANSPARENT; - if (token.startsWith("@@")) { - color = patchRefColor; - } else if (firstChar == '+') { - color = patchAdditionColor; - } else if (firstChar == '-') { - color = patchDeletionColor; - } - index = token.indexOf("\\ No newline at end of file"); - if (index != -1) { - token = token.replace("\\ No newline at end of file", ""); - } - SpannableString spannableDiff = new SpannableString(token); - if (color != Color.TRANSPARENT) { - DiffLineSpan span = new DiffLineSpan(color); - spannableDiff.setSpan(span, 0, token.length(), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); - } - builder.append(spannableDiff); - } - if (index != -1) { - builder.insert(builder.length() - 1, - SpannableBuilder.builder().append(ContextCompat.getDrawable(App.getInstance(), R.drawable.ic_newline))); - } - } - } - builder.setSpan(new TypefaceSpan("monospace"), 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - return builder; - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FloatingActionButtonBehavior.java b/app/src/main/java/com/fastaccess/ui/widgets/FloatingActionButtonBehavior.java deleted file mode 100644 index 16f879467..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/FloatingActionButtonBehavior.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.design.widget.CoordinatorLayout; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.Snackbar; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; - -import java.util.List; - -import it.sephiroth.android.library.bottomnavigation.BottomNavigation; - -import static android.util.Log.INFO; -import static it.sephiroth.android.library.bottomnavigation.MiscUtils.log; - -@SuppressWarnings("unused") -public class FloatingActionButtonBehavior extends CoordinatorLayout.Behavior { - private static final String TAG = FloatingActionButtonBehavior.class.getSimpleName(); - private int navigationBarHeight = 0; - - public FloatingActionButtonBehavior() { - super(); - } - - public FloatingActionButtonBehavior(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override public void onAttachedToLayoutParams(@NonNull final CoordinatorLayout.LayoutParams lp) { - // super.onAttachedToLayoutParams(lp); - } - - @Override public boolean layoutDependsOn(final CoordinatorLayout parent, final FloatingActionButton child, final View dependency) { - if (BottomNavigation.class.isInstance(dependency)) { - return true; - } else if (Snackbar.SnackbarLayout.class.isInstance(dependency)) { - return true; - } - return super.layoutDependsOn(parent, child, dependency); - } - - @Override public boolean onDependentViewChanged(@NonNull - final CoordinatorLayout parent, @NonNull - final FloatingActionButton child, final View dependency) { - log(TAG, INFO, "onDependentViewChanged: " + dependency); - final List list = parent.getDependencies(child); - ViewGroup.MarginLayoutParams params = ((ViewGroup.MarginLayoutParams) child.getLayoutParams()); - int bottomMargin = (params.bottomMargin + params.rightMargin) - (params.topMargin + params.leftMargin); - float t = 0; - float t2 = 0; - float t3 = 0; - boolean result = false; - for (View dep : list) { - if (Snackbar.SnackbarLayout.class.isInstance(dep)) { - t += dep.getTranslationY() - dep.getHeight(); - result = true; - } else if (BottomNavigation.class.isInstance(dep)) { - BottomNavigation navigation = (BottomNavigation) dep; - t2 = navigation.getTranslationY() - navigation.getHeight() + bottomMargin; - t += t2; - result = true; - - if (navigationBarHeight > 0) { - if (!navigation.isExpanded()) { - child.hide(); - } else { - child.show(); - } - } - } - } - - if (navigationBarHeight > 0 && t2 < 0) { - t = Math.min(t2, t + navigationBarHeight); - } - - child.setTranslationY(t); - return result; - } - - @Override public void onDependentViewRemoved(final CoordinatorLayout parent, final FloatingActionButton child, final View dependency) { - super.onDependentViewRemoved(parent, child, dependency); - } - - public void setNavigationBarHeight(final int height) { - this.navigationBarHeight = height; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontAutoCompleteEditText.java b/app/src/main/java/com/fastaccess/ui/widgets/FontAutoCompleteEditText.java deleted file mode 100644 index 5d2c4c436..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/FontAutoCompleteEditText.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.v7.widget.AppCompatAutoCompleteTextView; -import android.util.AttributeSet; -import android.view.inputmethod.EditorInfo; - -import com.fastaccess.helper.TypeFaceHelper; - -/** - * Created by Kosh on 8/18/2015. copyrights are reserved - */ -public class FontAutoCompleteEditText extends AppCompatAutoCompleteTextView { - - public FontAutoCompleteEditText(@NonNull Context context) { - super(context); - init(); - } - - public FontAutoCompleteEditText(@NonNull Context context, AttributeSet attrs) { - super(context, attrs); - init(); - - } - - public FontAutoCompleteEditText(@NonNull Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - private void init() { - if (isInEditMode()) return; - if (isInEditMode()) return; - setInputType(getInputType() | EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_FULLSCREEN); - setImeOptions(getImeOptions() | EditorInfo.IME_FLAG_NO_FULLSCREEN); - TypeFaceHelper.applyTypeface(this); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontButton.java b/app/src/main/java/com/fastaccess/ui/widgets/FontButton.java deleted file mode 100644 index 0f984b1b8..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/FontButton.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.v7.widget.AppCompatButton; -import android.util.AttributeSet; - -import com.fastaccess.helper.TypeFaceHelper; - - -/** - * Created by Kosh on 8/18/2015. copyrights are reserved - */ -public class FontButton extends AppCompatButton { - - public FontButton(@NonNull Context context) { - super(context); - init(); - } - - public FontButton(@NonNull Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public FontButton(@NonNull Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - private void init() { - if (isInEditMode()) return; - TypeFaceHelper.applyTypeface(this); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontCheckbox.java b/app/src/main/java/com/fastaccess/ui/widgets/FontCheckbox.java deleted file mode 100644 index 6b9b4edf3..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/FontCheckbox.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.v7.widget.AppCompatCheckBox; -import android.util.AttributeSet; - -import com.fastaccess.helper.TypeFaceHelper; - - -/** - * Created by Kosh on 8/18/2015. copyrights are reserved - */ -public class FontCheckbox extends AppCompatCheckBox { - - public FontCheckbox(@NonNull Context context) { - super(context); - init(); - } - - public FontCheckbox(@NonNull Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public FontCheckbox(@NonNull Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - private void init() { - if (isInEditMode()) return; - TypeFaceHelper.applyTypeface(this); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontEditText.java b/app/src/main/java/com/fastaccess/ui/widgets/FontEditText.java deleted file mode 100644 index 3c886aadf..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/FontEditText.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.v7.widget.AppCompatEditText; -import android.util.AttributeSet; -import android.view.inputmethod.EditorInfo; - -import com.crashlytics.android.Crashlytics; -import com.fastaccess.helper.TypeFaceHelper; - -/** - * Created by Kosh on 8/18/2015. copyrights are reserved - */ -public class FontEditText extends AppCompatEditText { - - public FontEditText(@NonNull Context context) { - super(context); - init(); - } - - public FontEditText(@NonNull Context context, AttributeSet attrs) { - super(context, attrs); - init(); - - } - - public FontEditText(@NonNull Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - private void init() { - if (isInEditMode()) return; - setInputType(getInputType() | EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_FULLSCREEN); - setImeOptions(getImeOptions() | EditorInfo.IME_FLAG_NO_FULLSCREEN); - TypeFaceHelper.applyTypeface(this); - } - - @SuppressLint("SetTextI18n") public void setText(CharSequence text, BufferType type) { - try { - super.setText(text, type); - } catch (Exception e) { - setText("I tried, but your OEM just sucks because they modify the framework components and therefore causing the app to crash!" + ".\nFastHub"); - Crashlytics.logException(e); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontRadioButton.java b/app/src/main/java/com/fastaccess/ui/widgets/FontRadioButton.java deleted file mode 100644 index 6464e5fd8..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/FontRadioButton.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.v7.widget.AppCompatRadioButton; -import android.util.AttributeSet; - -import com.fastaccess.helper.TypeFaceHelper; - - -/** - * Created by Kosh on 8/18/2015. copyrights are reserved - */ -public class FontRadioButton extends AppCompatRadioButton { - - public FontRadioButton(@NonNull Context context) { - super(context); - init(); - } - - public FontRadioButton(@NonNull Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public FontRadioButton(@NonNull Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - private void init() { - if (isInEditMode()) return; - TypeFaceHelper.applyTypeface(this); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontSwitchView.java b/app/src/main/java/com/fastaccess/ui/widgets/FontSwitchView.java deleted file mode 100644 index 3376ed673..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/FontSwitchView.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.v7.widget.SwitchCompat; -import android.util.AttributeSet; - -import com.fastaccess.helper.TypeFaceHelper; - - -/** - * Created by Kosh on 8/18/2015. copyrights are reserved - */ -public class FontSwitchView extends SwitchCompat { - - public FontSwitchView(@NonNull Context context) { - super(context); - init(); - } - - public FontSwitchView(@NonNull Context context, AttributeSet attrs) { - super(context, attrs); - init(); - - } - - public FontSwitchView(@NonNull Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - private void init() { - if (isInEditMode()) return; - TypeFaceHelper.applyTypeface(this); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/FontTextView.java b/app/src/main/java/com/fastaccess/ui/widgets/FontTextView.java deleted file mode 100644 index 451ddd2f3..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/FontTextView.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.ScaleDrawable; -import android.os.Parcelable; -import android.support.annotation.ColorInt; -import android.support.annotation.DrawableRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.AppCompatTextView; -import android.util.AttributeSet; -import android.view.Gravity; - -import com.crashlytics.android.Crashlytics; -import com.evernote.android.state.State; -import com.evernote.android.state.StateSaver; -import com.fastaccess.R; -import com.fastaccess.helper.TypeFaceHelper; -import com.fastaccess.helper.ViewHelper; - - -/** - * Created by Kosh on 8/18/2015. copyrights are reserved - */ -public class FontTextView extends AppCompatTextView { - - @State int tintColor = -1; - @State boolean selected; - - public FontTextView(@NonNull Context context) { - this(context, null); - } - - public FontTextView(@NonNull Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public FontTextView(@NonNull Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs); - } - - @Override public Parcelable onSaveInstanceState() { - return StateSaver.saveInstanceState(this, super.onSaveInstanceState()); - } - - @Override public void onRestoreInstanceState(Parcelable state) { - super.onRestoreInstanceState(StateSaver.restoreInstanceState(this, state)); - tintDrawables(tintColor); - setSelected(selected); - } - - @Override public void setSelected(boolean selected) { - super.setSelected(selected); - this.selected = selected; - } - - @SuppressLint("SetTextI18n") public void setText(CharSequence text, BufferType type) { - try { - super.setText(text, type); - } catch (Exception e) { - setText("I tried, but your OEM just sucks because they modify the framework components and therefore causing the app to crash!" + "" + - ".\nFastHub"); - Crashlytics.logException(e); - } - } - - private void init(@NonNull Context context, @Nullable AttributeSet attributeSet) { - if (attributeSet != null) { - TypedArray tp = context.obtainStyledAttributes(attributeSet, R.styleable.FontTextView); - try { - int color = tp.getColor(R.styleable.FontTextView_drawableColor, -1); - tintDrawables(color); - } finally { - tp.recycle(); - } - } - if (isInEditMode()) return; - setFreezesText(true); - TypeFaceHelper.applyTypeface(this); - } - - public void tintDrawables(@ColorInt int color) { - if (color != -1) { - this.tintColor = color; - Drawable[] drawables = getCompoundDrawablesRelative(); - for (Drawable drawable : drawables) { - if (drawable == null) continue; - ViewHelper.tintDrawable(drawable, color); - } - } - } - - public void setEventsIcon(@DrawableRes int drawableRes) { - Drawable drawable = ContextCompat.getDrawable(getContext(), drawableRes); - int width = drawable.getIntrinsicWidth(); - int height = drawable.getIntrinsicHeight(); - drawable.setBounds(0, 0, width / 2, height / 2); - ScaleDrawable sd = new ScaleDrawable(drawable, Gravity.CENTER, 0.6f, 0.6f); - sd.setLevel(8000); - ViewHelper.tintDrawable(drawable, ViewHelper.getTertiaryTextColor(getContext())); - setCompoundDrawablesWithIntrinsicBounds(sd, null, null, null); - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/ForegroundImageView.java b/app/src/main/java/com/fastaccess/ui/widgets/ForegroundImageView.java deleted file mode 100644 index 0ef9bb770..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/ForegroundImageView.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.v7.widget.AppCompatImageView; -import android.support.v7.widget.TooltipCompat; -import android.util.AttributeSet; - -import com.fastaccess.helper.ViewHelper; - -public class ForegroundImageView extends AppCompatImageView { - - public ForegroundImageView(@NonNull Context context) { - this(context, null); - } - - public ForegroundImageView(@NonNull Context context, AttributeSet attrs) { - this(context, attrs, 0); - if (getContentDescription() != null) { - TooltipCompat.setTooltipText(this, getContentDescription()); - } - } - - public ForegroundImageView(@NonNull Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public void tintDrawableColor(@ColorInt int color) { - ViewHelper.tintDrawable(getDrawable(), color); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/ForegroundRelativeLayout.java b/app/src/main/java/com/fastaccess/ui/widgets/ForegroundRelativeLayout.java deleted file mode 100644 index 7a8c00acc..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/ForegroundRelativeLayout.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.util.AttributeSet; -import android.view.ViewOutlineProvider; -import android.widget.RelativeLayout; - -import com.fastaccess.R; - -/** - * An extension to {@link RelativeLayout} which has a foreground drawable. - */ -public class ForegroundRelativeLayout extends RelativeLayout { - - private Drawable foreground; - - @SuppressLint("CustomViewStyleable") - public ForegroundRelativeLayout(@NonNull Context context, AttributeSet attrs) { - super(context, attrs); - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ForegroundView); - final Drawable d = a.getDrawable(R.styleable.ForegroundView_android_foreground); - if (d != null) { - setForeground(d); - } - a.recycle(); - setOutlineProvider(ViewOutlineProvider.BOUNDS); - } - - @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - if (foreground != null) { - foreground.setBounds(0, 0, w, h); - } - } - - @Override public boolean hasOverlappingRendering() { - return false; - } - - @Override protected boolean verifyDrawable(@NonNull Drawable who) { - return super.verifyDrawable(who) || (who == foreground); - } - - @Override public void jumpDrawablesToCurrentState() { - super.jumpDrawablesToCurrentState(); - if (foreground != null) foreground.jumpToCurrentState(); - } - - @Override protected void drawableStateChanged() { - if (isInEditMode()) return; - super.drawableStateChanged(); - if (foreground != null && foreground.isStateful()) { - foreground.setState(getDrawableState()); - } - } - - public Drawable getForeground() { - return foreground; - } - - public void setForeground(Drawable drawable) { - if (foreground != drawable) { - if (foreground != null) { - foreground.setCallback(null); - unscheduleDrawable(foreground); - } - - foreground = drawable; - - if (foreground != null) { - foreground.setBounds(getLeft(), getTop(), getRight(), getBottom()); - setWillNotDraw(false); - foreground.setCallback(this); - if (foreground.isStateful()) { - foreground.setState(getDrawableState()); - } - } else { - setWillNotDraw(true); - } - invalidate(); - } - } - - @Override public void draw(@NonNull Canvas canvas) { - super.draw(canvas); - if (foreground != null) { - foreground.draw(canvas); - } - } - - @Override public void drawableHotspotChanged(float x, float y) { - super.drawableHotspotChanged(x, y); - if (foreground != null) { - foreground.setHotspot(x, y); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/LabelSpan.java b/app/src/main/java/com/fastaccess/ui/widgets/LabelSpan.java deleted file mode 100644 index 0e055ad94..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/LabelSpan.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Paint.FontMetricsInt; -import android.graphics.RectF; -import android.support.annotation.NonNull; -import android.support.v4.text.TextUtilsCompat; -import android.support.v4.view.ViewCompat; -import android.text.Spanned; -import android.text.TextPaint; -import android.text.TextUtils; -import android.text.style.CharacterStyle; -import android.text.style.ReplacementSpan; - -import com.fastaccess.helper.ViewHelper; - -import java.util.Locale; - - -/** - * adopted class from Android source code & modified to fit FastHub need. - */ - -public class LabelSpan extends ReplacementSpan { - public interface SpanDimensions { - int getPadding(); - - int getPaddingExtraWidth(); - - int getPaddingAfter(); - - int getMaxWidth(); - - float getRoundedCornerRadius(); - - int getMarginTop(); - - boolean isRtl(); - } - - private final TextPaint txtPaint = new TextPaint(); - private final FontMetricsInt fontMetrics = new FontMetricsInt(); - private final int color; - private final SpanDimensions dims; - - private LabelSpan(int color, @NonNull SpanDimensions dims) { - this.color = color; - txtPaint.bgColor = color; - this.dims = dims; - } - - public LabelSpan(int color) { - this(color, new SpanDimensions() { - @Override public int getPadding() { - return 6; - } - - @Override public int getPaddingExtraWidth() { - return 0; - } - - @Override public int getPaddingAfter() { - return 0; - } - - @Override public int getMaxWidth() { - return 1000;//random number - } - - @Override public float getRoundedCornerRadius() { - return 5; - } - - @Override public int getMarginTop() { - return 8; - } - - @Override public boolean isRtl() { - return TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL; - } - }); - } - - @Override public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) { - setupFontMetrics(text, start, end, fm, paint); - if (fm != null) { - final int padding = dims.getPadding(); - final int margin = dims.getMarginTop(); - fm.ascent = Math.min(fm.top, fm.ascent - padding) - margin; - fm.descent = Math.max(fm.bottom, padding); - fm.top = fm.ascent; - fm.bottom = fm.descent; - } - return measureWidth(txtPaint, text, start, end, dims.isRtl()); - } - - private int measureWidth(Paint paint, CharSequence text, int start, int end, - boolean includePaddingAfter) { - final int paddingW = dims.getPadding() + dims.getPaddingExtraWidth(); - final int maxWidth = dims.getMaxWidth(); - int w = (int) paint.measureText(text, start, end) + 2 * paddingW; - if (includePaddingAfter) { - w += dims.getPaddingAfter(); - } - if (w > maxWidth) { - w = maxWidth; - } - return w; - } - - private void setupFontMetrics(CharSequence text, int start, int end, FontMetricsInt fm, Paint p) { - txtPaint.set(p); - final CharacterStyle[] otherSpans = ((Spanned) text).getSpans(start, end, CharacterStyle.class); - for (CharacterStyle otherSpan : otherSpans) { - otherSpan.updateDrawState(txtPaint); - } - txtPaint.setTextSize(p.getTextSize()); - if (fm != null) { - txtPaint.getFontMetricsInt(fm); - } - } - - @Override public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, - float x, int top, int y, int bottom, @NonNull Paint paint) { - final int padding = dims.getPadding(); - final int paddingW = padding + dims.getPaddingExtraWidth(); - final int maxWidth = dims.getMaxWidth(); - setupFontMetrics(text, start, end, fontMetrics, paint); - final int bgWidth = measureWidth(txtPaint, text, start, end, false); - fontMetrics.top = Math.min(fontMetrics.top, fontMetrics.ascent - padding); - fontMetrics.bottom = Math.max(fontMetrics.bottom, padding); - top = y + fontMetrics.top - fontMetrics.bottom; - bottom = y; - y = bottom - fontMetrics.bottom; - final boolean isRtl = dims.isRtl(); - final int paddingAfter = dims.getPaddingAfter(); - if (txtPaint.bgColor != 0) { - final int prevColor = txtPaint.getColor(); - final Paint.Style prevStyle = txtPaint.getStyle(); - txtPaint.setColor(txtPaint.bgColor); - txtPaint.setStyle(Paint.Style.FILL); - final float left; - if (isRtl) { - left = x + paddingAfter; - } else { - left = x; - } - final float right = left + bgWidth; - final RectF rect = new RectF(left, top, right, bottom); - final float radius = dims.getRoundedCornerRadius(); - canvas.drawRoundRect(rect, radius, radius, txtPaint); - txtPaint.setColor(prevColor); - txtPaint.setStyle(prevStyle); - } - if (bgWidth == maxWidth) { - text = TextUtils.ellipsize(text.subSequence(start, end).toString(), txtPaint, bgWidth - 2 * paddingW, TextUtils.TruncateAt.MIDDLE); - start = 0; - end = text.length(); - } - float textX = x + paddingW; - if (isRtl) { - textX += paddingAfter; - } - if (color != Color.TRANSPARENT) txtPaint.setColor(ViewHelper.generateTextColor(color)); - canvas.drawText(text, start, end, textX, y, txtPaint); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/NestedCoordinatorLayout.java b/app/src/main/java/com/fastaccess/ui/widgets/NestedCoordinatorLayout.java deleted file mode 100644 index 922880398..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/NestedCoordinatorLayout.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.design.widget.CoordinatorLayout; -import android.support.v4.view.NestedScrollingChild; -import android.support.v4.view.NestedScrollingChildHelper; -import android.util.AttributeSet; -import android.view.View; - -/** - * Created by Kosh on 13 Aug 2016, 1:11 PM - */ - -public class NestedCoordinatorLayout extends CoordinatorLayout implements NestedScrollingChild { - - private NestedScrollingChildHelper mChildHelper; - - public NestedCoordinatorLayout(@NonNull Context context) { - super(context); - mChildHelper = new NestedScrollingChildHelper(this); - setNestedScrollingEnabled(true); - } - - public NestedCoordinatorLayout(@NonNull Context context, AttributeSet attrs) { - super(context, attrs); - mChildHelper = new NestedScrollingChildHelper(this); - setNestedScrollingEnabled(true); - } - - public NestedCoordinatorLayout(@NonNull Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - mChildHelper = new NestedScrollingChildHelper(this); - setNestedScrollingEnabled(true); - } - - @Override public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) { - /* Enable the scrolling behavior of our own children */ - boolean tHandled = super.onStartNestedScroll(child, target, nestedScrollAxes); - /* Enable the scrolling behavior of the parent's other children */ - return startNestedScroll(nestedScrollAxes) || tHandled; - } - - @Override public void onStopNestedScroll(View target) { - /* Disable the scrolling behavior of our own children */ - super.onStopNestedScroll(target); - /* Disable the scrolling behavior of the parent's other children */ - stopNestedScroll(); - } - - @Override public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { - int[][] tConsumed = new int[2][2]; - super.onNestedPreScroll(target, dx, dy, tConsumed[0]); - dispatchNestedPreScroll(dx, dy, tConsumed[1], null); - consumed[0] = tConsumed[0][0] + tConsumed[1][0]; - consumed[1] = tConsumed[0][1] + tConsumed[1][1]; - } - - @Override public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { - super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); - dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, null); - } - - @Override public boolean onNestedPreFling(View target, float velocityX, float velocityY) { - boolean tHandled = super.onNestedPreFling(target, velocityX, velocityY); - return dispatchNestedPreFling(velocityX, velocityY) || tHandled; - } - - @Override public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { - boolean tHandled = super.onNestedFling(target, velocityX, velocityY, consumed); - return dispatchNestedFling(velocityX, velocityY, consumed) || tHandled; - } - - @Override public void setNestedScrollingEnabled(boolean enabled) { - mChildHelper.setNestedScrollingEnabled(enabled); - } - - @Override public boolean isNestedScrollingEnabled() { - return mChildHelper.isNestedScrollingEnabled(); - } - - @Override public boolean startNestedScroll(int axes) { - return mChildHelper.startNestedScroll(axes); - } - - @Override public void stopNestedScroll() { - mChildHelper.stopNestedScroll(); - } - - @Override public boolean hasNestedScrollingParent() { - return mChildHelper.hasNestedScrollingParent(); - } - - @Override public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { - return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, - dyUnconsumed, offsetInWindow); - } - - @Override public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { - return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); - } - - @Override public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { - return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); - } - - @Override public boolean dispatchNestedPreFling(float velocityX, float velocityY) { - return mChildHelper.dispatchNestedPreFling(velocityX, velocityY); - } -} - diff --git a/app/src/main/java/com/fastaccess/ui/widgets/SpannableBuilder.java b/app/src/main/java/com/fastaccess/ui/widgets/SpannableBuilder.java deleted file mode 100644 index fa9ecb9de..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/SpannableBuilder.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.graphics.drawable.Drawable; -import android.support.annotation.ColorInt; -import android.text.SpannableStringBuilder; -import android.text.TextPaint; -import android.text.style.BackgroundColorSpan; -import android.text.style.ClickableSpan; -import android.text.style.ForegroundColorSpan; -import android.text.style.ImageSpan; -import android.text.style.StyleSpan; -import android.text.style.URLSpan; -import android.view.View; - -import com.fastaccess.helper.InputHelper; - -import static android.graphics.Typeface.BOLD; - -/** - * Created by Kosh on 15 Nov 2016, 9:26 PM - */ - -public class SpannableBuilder extends SpannableStringBuilder { - - private SpannableBuilder() {} - - public static SpannableBuilder builder() { - return new SpannableBuilder(); - } - - public SpannableBuilder append(final CharSequence text, final Object span) { - if (!InputHelper.isEmpty(text)) { - append(text); - if (span != null) { - final int length = length(); - setSpan(span, length - text.length(), length, SPAN_EXCLUSIVE_EXCLUSIVE); - } - } - return this; - } - - @Override public SpannableBuilder append(char text) { - if (text != 0) super.append(text); - return this; - } - - @Override public SpannableBuilder append(CharSequence text) { - if (text != null) super.append(text); - return this; - } - - public SpannableBuilder append(Object span) { - setSpan(span, length() - 1, length(), SPAN_EXCLUSIVE_EXCLUSIVE); - return this; - } - - public SpannableBuilder append(Drawable drawable) { - if (drawable != null) { - drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); - append(' ', new ImageSpan(drawable)); - } - return this; - } - - public SpannableBuilder append(final char text, final Object span) { - append(text); - if (!InputHelper.isEmpty(span)) { - final int length = length(); - setSpan(span, length - 1, length, SPAN_EXCLUSIVE_EXCLUSIVE); - } - return this; - } - - public SpannableBuilder bold(CharSequence text, final Object span) { - if (!InputHelper.isEmpty(text)) { - text = SpannableBuilder.builder().bold(text); - append(text, span); - } - return this; - } - - public SpannableBuilder bold(final CharSequence text) { - if (!InputHelper.isEmpty(text)) return append(text, new StyleSpan(BOLD)); - return this; - } - - public SpannableBuilder background(final CharSequence text, final int color) { - if (!InputHelper.isEmpty(text)) - return append(text, new BackgroundColorSpan(color)); - return this; - } - - public SpannableBuilder foreground(final CharSequence text, @ColorInt int color) { - if (!InputHelper.isEmpty(text)) return append(text, new ForegroundColorSpan(color)); - return this; - } - - public SpannableBuilder foreground(final char text, @ColorInt int color) { - return append(text, new ForegroundColorSpan(color)); - } - - public SpannableBuilder url(final CharSequence text, final View.OnClickListener listener) { - if (!InputHelper.isEmpty(text)) - return append(text, new URLSpan(text.toString()) { - @Override - public void onClick(View widget) { - listener.onClick(widget); - } - }); - return this; - } - - public SpannableBuilder url(final CharSequence text) { - if (!InputHelper.isEmpty(text)) return append(text, new URLSpan(text.toString())); - return this; - } - - public SpannableBuilder clickable(final CharSequence text, final View.OnClickListener listener) { - if (!InputHelper.isEmpty(text)) return append(text, new ClickableSpan() { - @Override public void updateDrawState(TextPaint ds) { - ds.setColor(ds.linkColor); - ds.setUnderlineText(false); - } - - @Override public void onClick(View widget) { - listener.onClick(widget); - } - }); - return this; - } - -} - diff --git a/app/src/main/java/com/fastaccess/ui/widgets/StateLayout.java b/app/src/main/java/com/fastaccess/ui/widgets/StateLayout.java deleted file mode 100644 index 7a126f42b..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/StateLayout.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.StringRes; -import android.support.v4.widget.NestedScrollView; -import android.util.AttributeSet; - -import com.evernote.android.state.State; -import com.evernote.android.state.StateSaver; -import com.fastaccess.R; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; - -/** - * Created by Kosh on 20 Nov 2016, 12:21 AM - */ -public class StateLayout extends NestedScrollView { - - private static final int SHOW_PROGRESS_STATE = 1; - private static final int HIDE_PROGRESS_STATE = 2; - private static final int HIDE_RELOAD_STATE = 3; - private static final int SHOW_RELOAD_STATE = 4; - private static final int SHOW_EMPTY_STATE = 7; - private static final int HIDDEN = 5; - private static final int SHOWN = 6; - private OnClickListener onReloadListener; - - @BindView(R.id.empty_text) FontTextView emptyText; - @BindView(R.id.reload) FontButton reload; - - @State int layoutState = HIDDEN; - @State String emptyTextValue; - @State boolean showReload = true; - - @OnClick(R.id.reload) void onReload() { - if (onReloadListener != null) { - onReloadListener.onClick(reload); - } - } - - public StateLayout(Context context) { - super(context); - } - - public StateLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public StateLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public void showProgress() { - layoutState = SHOW_PROGRESS_STATE; - setVisibility(VISIBLE); - emptyText.setVisibility(GONE); - reload.setVisibility(GONE); - } - - public void hideProgress() { - layoutState = HIDE_PROGRESS_STATE; - emptyText.setVisibility(VISIBLE); - reload.setVisibility(VISIBLE); - setVisibility(GONE); - } - - public void hideReload() { - layoutState = HIDE_RELOAD_STATE; - reload.setVisibility(GONE); - emptyText.setVisibility(GONE); - setVisibility(GONE); - } - - public void showReload(int adapterCount) { - showReload = adapterCount == 0; - showReload(); - } - - protected void showReload() { - hideProgress(); - if (showReload) { - layoutState = SHOW_RELOAD_STATE; - reload.setVisibility(VISIBLE); - emptyText.setVisibility(VISIBLE); - setVisibility(VISIBLE); - } - } - - public void setEmptyText(@StringRes int resId) { - setEmptyText(getResources().getString(resId)); - } - - public void setEmptyText(@NonNull String text) { - this.emptyTextValue = text + "\n\n¯\\_(ツ)_/¯"; - emptyText.setText(emptyTextValue); - } - - public void showEmptyState() { - hideProgress(); - hideReload(); - setVisibility(VISIBLE); - emptyText.setVisibility(VISIBLE); - layoutState = SHOW_EMPTY_STATE;// last so it override visibility state. - } - - public void setOnReloadListener(OnClickListener onReloadListener) { - this.onReloadListener = onReloadListener; - } - - @Override public void setVisibility(int visibility) { - super.setVisibility(visibility); - if (visibility == GONE || visibility == INVISIBLE) { - layoutState = HIDDEN; - } else { - layoutState = SHOWN; - } - } - - @Override protected void onFinishInflate() { - super.onFinishInflate(); - inflate(getContext(), R.layout.empty_layout, this); - if (isInEditMode()) return; - ButterKnife.bind(this); - emptyText.setFreezesText(true); - } - - @Override protected void onDetachedFromWindow() { - onReloadListener = null; - super.onDetachedFromWindow(); - } - - @Override public Parcelable onSaveInstanceState() { - return StateSaver.saveInstanceState(this, super.onSaveInstanceState()); - } - - @Override public void onRestoreInstanceState(Parcelable state) { - super.onRestoreInstanceState(StateSaver.restoreInstanceState(this, state)); - onHandleLayoutState(); - } - - private void onHandleLayoutState() { - setEmptyText(emptyTextValue); - switch (layoutState) { - case SHOW_PROGRESS_STATE: - showProgress(); - break; - case HIDE_PROGRESS_STATE: - hideProgress(); - break; - case HIDE_RELOAD_STATE: - hideReload(); - break; - case SHOW_RELOAD_STATE: - showReload(); - break; - case HIDDEN: - setVisibility(GONE); - break; - case SHOW_EMPTY_STATE: - showEmptyState(); - break; - case SHOWN: - setVisibility(VISIBLE); - showReload(); - break; - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/TabletBehavior.java b/app/src/main/java/com/fastaccess/ui/widgets/TabletBehavior.java deleted file mode 100644 index ed72458b7..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/TabletBehavior.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.content.Context; -import android.support.design.widget.AppBarLayout; -import android.support.design.widget.CoordinatorLayout; -import android.support.v7.widget.Toolbar; -import android.util.AttributeSet; -import android.view.View; - -import it.sephiroth.android.library.bottomnavigation.BottomNavigation; -import it.sephiroth.android.library.bottomnavigation.VerticalScrollingBehavior; - -public class TabletBehavior extends VerticalScrollingBehavior { - - public TabletBehavior(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void setLayoutValues(int bottomNavWidth, int topInset, boolean translucentStatus) {} - - public boolean layoutDependsOn(CoordinatorLayout parent, BottomNavigation child, View dependency) { - return AppBarLayout.class.isInstance(dependency) || Toolbar.class.isInstance(dependency); - } - - public boolean onDependentViewChanged(CoordinatorLayout parent, BottomNavigation child, View dependency) { - return true; - } - - public void onDependentViewRemoved(CoordinatorLayout parent, BottomNavigation child, View dependency) { - super.onDependentViewRemoved(parent, child, dependency); - } - - public boolean onLayoutChild(CoordinatorLayout parent, BottomNavigation child, int layoutDirection) { - return super.onLayoutChild(parent, child, layoutDirection); - } - - public void onNestedVerticalOverScroll(CoordinatorLayout coordinatorLayout, BottomNavigation child, int direction, int currentOverScroll, int - totalOverScroll) { - } - - public void onDirectionNestedPreScroll(CoordinatorLayout coordinatorLayout, BottomNavigation child, View target, int dx, int dy, int[] - consumed, int scrollDirection) { - } - - protected boolean onNestedDirectionFling(CoordinatorLayout coordinatorLayout, BottomNavigation child, View target, float velocityX, float - velocityY, int scrollDirection) { - return false; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/ViewPagerView.java b/app/src/main/java/com/fastaccess/ui/widgets/ViewPagerView.java deleted file mode 100644 index 929c1b728..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/ViewPagerView.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.fastaccess.ui.widgets; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.res.TypedArray; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewPager; -import android.util.AttributeSet; -import android.view.MotionEvent; - -import static android.R.attr.enabled; - - -/** - * Created by kosh20111 on 10/8/2015. - *

    - * Viewpager that has scrolling animation by default - */ -public class ViewPagerView extends ViewPager { - - private boolean isEnabled; - - public ViewPagerView(Context context) { - super(context); - } - - public ViewPagerView(@NonNull Context context, AttributeSet attrs) { - super(context, attrs); - int[] attrsArray = {enabled}; - TypedArray array = context.obtainStyledAttributes(attrs, attrsArray); - isEnabled = array.getBoolean(0, true); - array.recycle(); - } - - @Override public boolean isEnabled() { - return isEnabled; - } - - @Override public void setEnabled(boolean enabled) { - this.isEnabled = enabled; - requestLayout(); - } - - @Override public void setAdapter(@Nullable PagerAdapter adapter) { - super.setAdapter(adapter); - if (isInEditMode()) return; - if (adapter != null) { - setOffscreenPageLimit(adapter.getCount()); - } - } - - @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { - try { - return !isEnabled() || super.onTouchEvent(event); - } catch (IllegalArgumentException ex) { - ex.printStackTrace(); - } - return false; - } - - @Override public boolean onInterceptTouchEvent(MotionEvent event) { - try { - return isEnabled() && super.onInterceptTouchEvent(event); - } catch (IllegalArgumentException ex) { - ex.printStackTrace(); - } - return false; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/color/ColorGenerator.java b/app/src/main/java/com/fastaccess/ui/widgets/color/ColorGenerator.java deleted file mode 100644 index 8219a84e6..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/color/ColorGenerator.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.fastaccess.ui.widgets.color; - -import android.content.Context; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.annimon.stream.Objects; -import com.fastaccess.helper.AppHelper; - -import java.util.Arrays; -import java.util.List; - -public class ColorGenerator { - - private static ColorGenerator MATERIAL; - private static ColorGenerator MATERIAL_DARK; - - static { - MATERIAL = create(Arrays.asList( - 0xff1976d2, - 0xff00838f, - 0xff512da8, - 0xff2e7d32, - 0xff283593, - 0xff01579b, - 0xffc51162, - 0xff6a1b9a, - 0xffd50000, - 0xff00695c - )); - MATERIAL_DARK = create(Arrays.asList( - 0xffffc107, - 0xffffc400, - 0xff2196f3, - 0xff2979ff, - 0xffa1887f, - 0xff4dd0e1, - 0xff00acc1, - 0xffe64a19, - 0xff9575cd, - 0xff66bb6a - )); - } - - private final List colors; - - private static ColorGenerator create(List colorList) { - return new ColorGenerator(colorList); - } - - private ColorGenerator(List colorList) { - colors = colorList; - } - - private int getColor(@Nullable Object key) { - key = Objects.toString(key, "default"); - return colors.get(Math.abs(key.hashCode()) % colors.size()); - } - - @ColorInt public static int getColor(@NonNull Context context, @Nullable Object object) { - if (AppHelper.isNightMode(context.getResources())) { - return MATERIAL_DARK.getColor(object); - } else { - return MATERIAL.getColor(object); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/contributions/ContributionsDay.java b/app/src/main/java/com/fastaccess/ui/widgets/contributions/ContributionsDay.java deleted file mode 100644 index ff6f70524..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/contributions/ContributionsDay.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.fastaccess.ui.widgets.contributions; - -/** - * Copyright 2016 Javier González - * All right reserved. - */ -public class ContributionsDay { - - public int year = Integer.MIN_VALUE; - public int month = Integer.MIN_VALUE; - public int day = Integer.MIN_VALUE; - - // Level is used to record the color of the block - public int level = Integer.MIN_VALUE; - // Data is used to calculated the height of the pillar - private int data = Integer.MIN_VALUE; - - public ContributionsDay(int year, int month, int day, int level, int data) { - this.year = year; - this.month = month; - this.day = day; - this.level = level; - this.data = data; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/contributions/ContributionsProvider.java b/app/src/main/java/com/fastaccess/ui/widgets/contributions/ContributionsProvider.java deleted file mode 100644 index ecf9228a9..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/contributions/ContributionsProvider.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.fastaccess.ui.widgets.contributions; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.helper.InputHelper; - -import java.util.ArrayList; -import java.util.List; - -/** - * Copyright 2016 Javier González - * All right reserved. - */ -public class ContributionsProvider { - - private final static String FILL_STRING = "fill=\""; - private final static String DATA_STRING = "data-count=\""; - private final static String DATE_STRING = "data-date=\""; - - @NonNull public List getContributions(@Nullable String string) { - ArrayList contributions = new ArrayList<>(); - if (InputHelper.isEmpty(string)) return contributions; - int fillPos = -1; - int dataPos = -1; - int datePos = -1; - while (true) { - fillPos = string.indexOf(FILL_STRING, fillPos + 1); - dataPos = string.indexOf(DATA_STRING, dataPos + 1); - datePos = string.indexOf(DATE_STRING, datePos + 1); - if (fillPos == -1) break; - int level = 0; - String levelString = string.substring(fillPos + FILL_STRING.length(), fillPos + FILL_STRING.length() + 7); - switch (levelString) { - case "#eeeeee": - level = 0; - break; - case "#d6e685": - level = 1; - break; - case "#8cc665": - level = 2; - break; - case "#44a340": - level = 3; - break; - case "#1e6823": - level = 4; - break; - case "#ebedf0": - level = 0; - break; - case "#239a3b": - level = 1; - break; - case "#c6e48b": - level = 2; - break; - case "#7bc96f": - level = 3; - break; - case "#196127": - level = 4; - break; - } - - int dataEndPos = string.indexOf("\"", dataPos + DATA_STRING.length()); - String dataString = string.substring(dataPos + DATA_STRING.length(), dataEndPos); - int data = Integer.valueOf(dataString); - String dateString = string.substring(datePos + DATE_STRING.length(), datePos + DATE_STRING.length() + 11); - contributions.add(new ContributionsDay( - Integer.valueOf(dateString.substring(0, 4)), - Integer.valueOf(dateString.substring(5, 7)), - Integer.valueOf(dateString.substring(8, 10)), - level, - data - )); - } - - return contributions; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/contributions/GitHubContributionsView.java b/app/src/main/java/com/fastaccess/ui/widgets/contributions/GitHubContributionsView.java deleted file mode 100644 index b53a707f7..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/contributions/GitHubContributionsView.java +++ /dev/null @@ -1,386 +0,0 @@ -package com.fastaccess.ui.widgets.contributions; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Point; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; - -import com.fastaccess.R; -import com.fastaccess.ui.widgets.contributions.utils.ColorsUtils; -import com.fastaccess.ui.widgets.contributions.utils.DatesUtils; - -import java.util.List; - -/** - * Copyright 2016 Javier González - * All right reserved. - */ - -public class GitHubContributionsView extends View { - private static final String BASE_COLOR = "#D6E685"; // default of Github - - private int baseColor = Color.parseColor(BASE_COLOR); - private int baseEmptyColor = Color.rgb(238, 238, 238); - private int backgroundBaseColor = Color.TRANSPARENT; - private int textColor = Color.BLACK; - private boolean displayMonth = false; - private int lastWeeks = 53; - private String username; - private Rect rect; - private Paint monthTextPaint; - private Matrix matrix = new Matrix(); - private Paint paint = new Paint(); - private Paint blockPaint; - private Bitmap bitmap = null; - private int height; - private Point point = new Point(); - - public GitHubContributionsView(Context context) { - super(context); - init(context, null, 0, 0); - } - - public GitHubContributionsView(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs, 0, 0); - } - - public GitHubContributionsView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context, attrs, defStyleAttr, 0); - } - - public GitHubContributionsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(context, attrs, defStyleAttr, defStyleRes); - } - - private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(point); - final TypedArray attributes = context.getTheme().obtainStyledAttributes( - attrs, R.styleable.GitHubContributionsView, defStyleAttr, defStyleRes); - initAttributes(attributes); - - rect = new Rect(); - monthTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - blockPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - blockPaint.setStyle(Paint.Style.FILL); - } - - private void initAttributes(TypedArray attributes) { - baseColor = attributes.getColor(R.styleable.GitHubContributionsView_baseColor, baseColor); - baseEmptyColor = attributes.getColor(R.styleable.GitHubContributionsView_baseEmptyColor, baseEmptyColor); - backgroundBaseColor = attributes.getColor(R.styleable.GitHubContributionsView_backgroundBaseColor, backgroundBaseColor); - textColor = attributes.getColor(R.styleable.GitHubContributionsView_textColor, textColor); - displayMonth = attributes.getBoolean(R.styleable.GitHubContributionsView_displayMonth, displayMonth); - lastWeeks = attributes.getInt(R.styleable.GitHubContributionsView_lastWeeks, lastWeeks); - if (attributes.getString(R.styleable.GitHubContributionsView_username) != null) { - username = attributes.getString(R.styleable.GitHubContributionsView_username); - if (!isInEditMode()) { - loadUserName(username); - } - } - } - - /** - * Set a base color for blocks. - * The tone depends on the number of contributions for a day. - * Supported formats See {@link Color#parseColor(String)} - * - * @param baseColor - * base color supported formats - */ - public void setBaseColor(String baseColor) { - try { - this.baseColor = Color.parseColor(baseColor); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } - invalidate(); - } - - /** - * Set a base color for blocks. - * The tone depends on the number of contributions for a day. - * - * @param color - * resource color - */ - public void setBaseColor(int color) { - this.baseColor = color; - invalidate(); - } - - /** - * Set a base empty color for blocks without contributions. - * Supported formats See {@link Color#parseColor(String)} - * - * @param baseColor - * base color supported formats - */ - public void setBaseEmptyColor(String baseColor) { - try { - this.baseEmptyColor = Color.parseColor(baseColor); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } - invalidate(); - } - - /** - * Set a base empty color for blocks without contributions. - * - * @param color - * resource color - */ - public void setBaseEmptyColor(int color) { - this.baseEmptyColor = color; - invalidate(); - } - - /** - * Sets the background color for this contributions view. - * - * @param backgroundBaseColor - * the color of the background - */ - public void setBackgroundBaseColor(String backgroundBaseColor) { - try { - this.backgroundBaseColor = Color.parseColor(backgroundBaseColor); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } - invalidate(); - } - - /** - * Sets the background color for this contributions view. - * - * @param backgroundBaseColor - * the color of the background - */ - public void setBackgroundBaseColor(int backgroundBaseColor) { - this.backgroundBaseColor = backgroundBaseColor; - invalidate(); - } - - /** - * Set a text color for month names. - * Supported formats See {@link Color#parseColor(String)} - * - * @param textColor - * text color supported formats - */ - public void setTextColor(String textColor) { - try { - this.textColor = Color.parseColor(textColor); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } - invalidate(); - } - - /** - * Set a text color for month names. - * - * @param textColor - * resource color - */ - public void setTextColor(int textColor) { - this.textColor = textColor; - invalidate(); - } - - /** - * Set the number of weeks that you want to display. - * You can set minimum 2 weeks but is not recommended. 1 week is impossible. - * You can set maximum 53 weeks (1 year = 52.14 weeks). - * By default is 53 (52 weeks and the current week). - * - * @param lastWeeks - * number of week (2..53) - */ - public void setLastWeeks(int lastWeeks) { - if (lastWeeks >= 2 && lastWeeks <= 53) { - this.lastWeeks = lastWeeks; - invalidate(); - } else { - throw new RuntimeException("The last weeks should be a number between 2 and 53"); - } - } - - /** - * Set if you want to see the name of the months - * If you send true, the component height increase - * - * @param displayMonth - * true or false - */ - public void displayMonth(boolean displayMonth) { - this.displayMonth = displayMonth; - invalidate(); - } - - /** - * Load and show contributions information for a user / organization - * - * @param username - * also, can be an organization - */ - private void loadUserName(String username) { - this.username = username; - clearContribution(); - } - - /** - * Clean de component. - */ - private void clearContribution() { - bitmap = null; - invalidate(); - } - - public void onResponse() { - adjustHeight(height); - invalidate(); - } - - @Override protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - if (bitmap != null) { - canvas.drawBitmap(bitmap, matrix, paint); - } else { - drawPlaceholder(canvas); - } - } - - public Bitmap drawOnCanvas(List contributionsFilter, List contributions) { - if ((contributionsFilter == null || contributions == null) || (contributionsFilter.isEmpty() || contributions.isEmpty())) { - return null; - } - if (bitmap == null) { - int padding = getResources().getDimensionPixelSize(R.dimen.spacing_large); - int width = point.x - padding; - int verticalBlockNumber = 7; - int horizontalBlockNumber = getHorizontalBlockNumber(contributionsFilter.size(), verticalBlockNumber); - float marginBlock = (1.0F - 0.1F); - float blockWidth = width / (float) horizontalBlockNumber * marginBlock; - float spaceWidth = width / (float) horizontalBlockNumber - blockWidth; - float topMargin = (displayMonth) ? 7f : 0; - float monthTextHeight = (displayMonth) ? blockWidth * 1.5F : 0; - int height = (int) ((blockWidth + spaceWidth) * 7 + topMargin + monthTextHeight); - bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - Canvas canvas1 = new Canvas(bitmap); - // Background - blockPaint.setColor(backgroundBaseColor); - canvas1.drawRect(0, (topMargin + monthTextHeight), width, height + monthTextHeight, blockPaint); - monthTextPaint.setColor(textColor); - monthTextPaint.setTextSize(monthTextHeight); - // draw the blocks - int currentWeekDay = DatesUtils.getWeekDayFromDate( - contributions.get(0).year, - contributions.get(0).month, - contributions.get(0).day); - float x = 0; - float y = (currentWeekDay - 7) % 7 * (blockWidth + spaceWidth) + (topMargin + monthTextHeight); - for (ContributionsDay day : contributionsFilter) { - blockPaint.setColor(ColorsUtils.calculateLevelColor(baseColor, baseEmptyColor, day.level)); - canvas1.drawRect(x, y, x + blockWidth, y + blockWidth, blockPaint); - if (DatesUtils.isFirstDayOfWeek(day.year, day.month, day.day + 1)) { - // another column - x += blockWidth + spaceWidth; - y = topMargin + monthTextHeight; - if (DatesUtils.isFirstWeekOfMount(day.year, day.month, day.day + 1)) { - canvas1.drawText(DatesUtils.getShortMonthName(day.year, day.month, day.day + 1), x, monthTextHeight, - monthTextPaint); - } - - } else { - y += blockWidth + spaceWidth; - } - } - this.height = height; - } - return bitmap; - } - - private void adjustHeight(int height) { - ViewGroup.LayoutParams ll = getLayoutParams(); - if (height != ll.height) { - ll.height = height; - setLayoutParams(ll); - } - } - - private void drawPlaceholder(Canvas canvas) { - if (!isInEditMode()) return; - canvas.getClipBounds(rect); - int width = rect.width(); - - int verticalBlockNumber = 7; - int horizontalBlockNumber = getHorizontalBlockNumber(lastWeeks * 7, verticalBlockNumber); - - float marginBlock = (1.0F - 0.1F); - float blockWidth = width / (float) horizontalBlockNumber * marginBlock; - float spaceWidth = width / (float) horizontalBlockNumber - blockWidth; - - float monthTextHeight = (displayMonth) ? blockWidth * 1.5F : 0; - float topMargin = (displayMonth) ? 7f : 0; - - monthTextPaint.setTextSize(monthTextHeight); - - int height = (int) ((blockWidth + spaceWidth) * 7 + topMargin + monthTextHeight); - - // Background - blockPaint.setColor(backgroundBaseColor); - canvas.drawRect(0, (topMargin + monthTextHeight), width, height + monthTextHeight, blockPaint); - - - float x = 0; - float y = 0 - * (blockWidth + spaceWidth) - + (topMargin + monthTextHeight); - - for (int i = 1; i < (lastWeeks * 7) + 1; i++) { - - blockPaint.setColor(ColorsUtils.calculateLevelColor(baseColor, baseEmptyColor, 0)); - canvas.drawRect(x, y, x + blockWidth, y + blockWidth, blockPaint); - - if (i % 7 == 0) { - // another column - x += blockWidth + spaceWidth; - y = topMargin + monthTextHeight; - - } else { - y += blockWidth + spaceWidth; - } - } - - // Resize component - ViewGroup.LayoutParams ll = getLayoutParams(); - ll.height = height; - setLayoutParams(ll); - } - - private int getHorizontalBlockNumber(int total, int divider) { - boolean isInteger = total % divider == 0; - int result = total / divider; - return (isInteger) ? result : result + 1; - } - - public List getLastContributions(List contributions) { - int lastWeekDays = contributions.size() % 7; - int lastDays = (lastWeekDays > 0) ? lastWeekDays + (lastWeeks - 1) * 7 : lastWeeks * 7; - return contributions.subList(contributions.size() - lastDays, contributions.size()); - } -} - diff --git a/app/src/main/java/com/fastaccess/ui/widgets/contributions/utils/ColorsUtils.java b/app/src/main/java/com/fastaccess/ui/widgets/contributions/utils/ColorsUtils.java deleted file mode 100644 index 7eb553b4c..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/contributions/utils/ColorsUtils.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.fastaccess.ui.widgets.contributions.utils; - -import android.graphics.Color; - -/** - * Copyright 2016 Javier González - * All right reserved. - */ -public class ColorsUtils { - - /** - * Calculate the value for different color. - * - * @param baseColor - * Value of base color. - * @param emptyColor - * Value of empty color - * @param level - * Level. - * @return The value for the level of the base color. - */ - public static int calculateLevelColor(int baseColor, int emptyColor, int level) { - if (level == 0) { - return emptyColor; - } - return Color.rgb( - calculateR(Color.red(baseColor), level), - calculateG(Color.green(baseColor), level), - calculateB(Color.blue(baseColor), level)); - } - - /** - * Calculate the red value for different level. - * - * @param baseR - * Red value of base color. - * @param level - * Level. - * @return The red value for the level of the base color. - */ - private static int calculateR(int baseR, int level) { - switch (level) { - case 0: - return 238; - case 1: - return baseR; - case 2: - return (int) (baseR * (9 + 46 + 15) / (37f + 9 + 46 + 15)); - case 3: - return (int) (baseR * (46 + 15) / (37f + 9 + 46 + 15)); - case 4: - return (int) (baseR * (15) / (37f + 9 + 46 + 15)); - default: - return 238; - } - } - - /** - * Calculate the green value for different level. - * - * @param baseG - * Green value of base color. - * @param level - * Level. - * @return The green value for the level of the base color. - */ - private static int calculateG(int baseG, int level) { - switch (level) { - case 0: - return 238; - case 1: - return baseG; - case 2: - return (int) (baseG * (35 + 59 + 104) / (32f + 35 + 59 + 104)); - case 3: - return (int) (baseG * (59 + 104) / (32f + 35 + 59 + 104)); - case 4: - return (int) (baseG * (104) / (32f + 35 + 59 + 104)); - default: - return 238; - } - } - - /** - * Calculate the blue value for different level. - * - * @param baseB - * Blue value of base color. - * @param level - * Level. - * @return The blue value for the level of the base color. - */ - private static int calculateB(int baseB, int level) { - switch (level) { - case 0: - return 238; - case 1: - return baseB; - case 2: - return (int) (baseB * (37 + 29 + 35) / (32f + 37 + 29 + 35)); - case 3: - return (int) (baseB * (29 + 35) / (32f + 37 + 29 + 35)); - case 4: - return (int) (baseB * (35) / (32f + 37 + 29 + 35)); - default: - return 238; - } - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/contributions/utils/DatesUtils.java b/app/src/main/java/com/fastaccess/ui/widgets/contributions/utils/DatesUtils.java deleted file mode 100644 index 7243980cf..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/contributions/utils/DatesUtils.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.fastaccess.ui.widgets.contributions.utils; - -import android.annotation.SuppressLint; - -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Locale; - -/** - * Copyright 2016 Javier González - * All right reserved. - */ -public class DatesUtils { - - /** - * Get the day of week from a date. - * 0 for SUN. - * 1 for MON. - * . - * . - * . - * 6 for SAT. - * - * @param year - * The year of the date. - * @param month - * The month of the date. - * @param day - * The day of month of the date. - * @return Integer to determine the day of week. - */ - @SuppressLint("WrongConstant") public static int getWeekDayFromDate(int year, int month, int day) { - Calendar calendar = Calendar.getInstance(); - calendar.set(year, month - 1, day); - calendar.add(Calendar.SECOND, 0); - calendar.setFirstDayOfWeek(Calendar.SUNDAY); - return calendar.get(Calendar.DAY_OF_WEEK) - 1; - } - - /** - * Get the short month name for a certain date. - * - * @param year - * The year of the date. - * @param month - * The month of the date. - * @param day - * The day of the date. - * @return The short name of the month. - */ - @SuppressLint("WrongConstant") public static String getShortMonthName(int year, int month, int day) { - Calendar calendar = Calendar.getInstance(); - calendar.set(year, month - 1, day); - calendar.add(Calendar.SECOND, 0); - SimpleDateFormat month_date = new SimpleDateFormat("MMM", Locale.US); - return month_date.format(calendar.getTime()); - } - - /** - * Return if the date given is a first week of mount - * - * @param year - * The year of the date. - * @param month - * The month of the date. - * @param day - * The day of the date. - * @return true or false - */ - @SuppressLint("WrongConstant") public static boolean isFirstWeekOfMount(int year, int month, int day) { - Calendar calendar = Calendar.getInstance(); - calendar.set(year, month - 1, day); - calendar.add(Calendar.SECOND, 0); - calendar.setFirstDayOfWeek(Calendar.SUNDAY); - - return calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH) == 1; - } - - /** - * Return if the date given is a first day of week - * - * @param year - * The year of the date. - * @param month - * The month of the date. - * @param day - * The day of the date. - * @return true or false - */ - @SuppressLint("WrongConstant") public static boolean isFirstDayOfWeek(int year, int month, int day) { - Calendar calendar = Calendar.getInstance(); - calendar.set(year, month - 1, day); - calendar.add(Calendar.SECOND, 0); - calendar.setFirstDayOfWeek(Calendar.SUNDAY); - - return calendar.get(Calendar.DAY_OF_WEEK) == 1; - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/dialog/ListDialogView.java b/app/src/main/java/com/fastaccess/ui/widgets/dialog/ListDialogView.java deleted file mode 100644 index 45cd3c5b7..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/dialog/ListDialogView.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.fastaccess.ui.widgets.dialog; - -import android.content.Context; -import android.os.Bundle; -import android.os.Parcelable; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.adapter.SimpleListAdapter; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; -import com.fastaccess.ui.widgets.FontTextView; -import com.fastaccess.ui.widgets.recyclerview.BaseViewHolder; -import com.fastaccess.ui.widgets.recyclerview.DynamicRecyclerView; -import com.fastaccess.ui.widgets.recyclerview.scroll.RecyclerViewFastScroller; - -import net.grandcentrix.thirtyinch.TiPresenter; - -import java.util.ArrayList; -import java.util.List; - -import butterknife.BindView; - -/** - * Created by Kosh on 31 Dec 2016, 3:19 PM - */ - -public class ListDialogView extends BaseDialogFragment implements BaseViewHolder.OnItemClickListener { - - public static final String TAG = ListDialogView.class.getSimpleName(); - - @BindView(R.id.title) FontTextView title; - @BindView(R.id.recycler) DynamicRecyclerView recycler; - @BindView(R.id.fastScroller) RecyclerViewFastScroller fastScroller; - - public interface onSimpleItemSelection { - void onItemSelected(O item); - } - - @Nullable private onSimpleItemSelection onSimpleItemSelection; - - @Override protected int fragmentLayout() { - return R.layout.simple_list_dialog; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - ArrayList objects = getArguments().getParcelableArrayList(BundleConstant.ITEM); - String titleText = getArguments().getString(BundleConstant.EXTRA); - title.setText(titleText); - if (objects != null) { - SimpleListAdapter adapter = new SimpleListAdapter<>(objects, this); - recycler.addDivider(); - recycler.setAdapter(adapter); - } else { - dismiss(); - } - fastScroller.attachRecyclerView(recycler); - } - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() != null && getParentFragment() instanceof onSimpleItemSelection) { - onSimpleItemSelection = (onSimpleItemSelection) getParentFragment(); - } else if (context instanceof onSimpleItemSelection) { - onSimpleItemSelection = (onSimpleItemSelection) context; - } - } - - @Override public void onDetach() { - super.onDetach(); - onSimpleItemSelection = null; - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } - - @SuppressWarnings("unchecked") @Override public void onItemClick(int position, View v, O item) { - if (onSimpleItemSelection != null) { - onSimpleItemSelection.onItemSelected(item); - } - dismiss(); - } - - @Override public void onItemLongClick(int position, View v, O item) {} - - public void initArguments(@NonNull String title, @NonNull ArrayList objects) { - setArguments(Bundler.start() - .put(BundleConstant.EXTRA, title) - .putParcelableArrayList(BundleConstant.ITEM, objects) - .end()); - } - - public void initArguments(@NonNull String title, @NonNull List objects) { - setArguments(Bundler.start() - .put(BundleConstant.EXTRA, title) - .putParcelableArrayList(BundleConstant.ITEM, (ArrayList) objects) - .end()); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java b/app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java deleted file mode 100644 index 784512de2..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/dialog/MessageDialogView.java +++ /dev/null @@ -1,174 +0,0 @@ -package com.fastaccess.ui.widgets.dialog; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.helper.BundleConstant; -import com.fastaccess.helper.Bundler; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.ui.base.BaseBottomSheetDialog; -import com.fastaccess.ui.widgets.FontButton; -import com.fastaccess.ui.widgets.FontTextView; -import com.prettifier.pretty.PrettifyWebView; - -import butterknife.BindView; -import butterknife.OnClick; - -/** - * Created by Kosh on 16 Sep 2016, 2:15 PM - */ - -public class MessageDialogView extends BaseBottomSheetDialog { - - public static final String TAG = MessageDialogView.class.getSimpleName(); - - public interface MessageDialogViewActionCallback { - - void onMessageDialogActionClicked(boolean isOk, @Nullable Bundle bundle); - - void onDialogDismissed(); - - } - - @BindView(R.id.prettifyWebView) PrettifyWebView prettifyWebView; - @BindView(R.id.title) FontTextView title; - @BindView(R.id.message) FontTextView message; - @BindView(R.id.cancel) FontButton cancel; - @BindView(R.id.ok) FontButton ok; - - @Nullable private MessageDialogViewActionCallback callback; - - @Override public void onAttach(Context context) { - super.onAttach(context); - if (getParentFragment() != null && getParentFragment() instanceof MessageDialogViewActionCallback) { - callback = (MessageDialogViewActionCallback) getParentFragment(); - } else if (context instanceof MessageDialogViewActionCallback) { - callback = (MessageDialogViewActionCallback) context; - } - } - - @Override public void onDetach() { - super.onDetach(); - callback = null; - } - - @OnClick({R.id.cancel, R.id.ok}) public void onClick(@NonNull View view) { - if (callback != null) { - isAlreadyHidden = true; - callback.onMessageDialogActionClicked(view.getId() == R.id.ok, getArguments().getBundle("bundle")); - } - dismiss(); - } - - @Override protected int layoutRes() { - return R.layout.message_dialog; - } - - @SuppressWarnings("ConstantConditions") @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - Bundle bundle = getArguments(); - title.setText(bundle.getString("bundleTitle")); - String msg = bundle.getString("bundleMsg"); - if (bundle.getBoolean("isMarkDown")) { - if (msg != null) { - message.setVisibility(View.GONE); - prettifyWebView.setVisibility(View.VISIBLE); - prettifyWebView.setGithubContent(msg, null, false, false); - prettifyWebView.setNestedScrollingEnabled(false); - } - } else { - message.setText(msg); - } - if (bundle != null) { - boolean hideCancel = bundle.getBoolean("hideCancel"); - if (hideCancel) cancel.setVisibility(View.GONE); - initButton(bundle); - } - } - - private void initButton(@NonNull Bundle bundle) { - Bundle extra = bundle.getBundle("bundle"); - if (extra != null) { - boolean yesNo = extra.getBoolean(BundleConstant.YES_NO_EXTRA); - if (yesNo) { - ok.setText(R.string.yes); - cancel.setText(R.string.no); - } else { - boolean hideButtons = extra.getBoolean("hide_buttons"); - String primaryExtra = extra.getString("primary_extra"); - String secondaryExtra = extra.getString("secondary_extra"); - if (hideButtons) { - ok.setVisibility(View.GONE); - cancel.setVisibility(View.GONE); - } else if (!InputHelper.isEmpty(primaryExtra)) { - ok.setText(primaryExtra); - if (!InputHelper.isEmpty(secondaryExtra)) cancel.setText(secondaryExtra); - ok.setVisibility(View.VISIBLE); - cancel.setVisibility(View.VISIBLE); - } - } - } - } - - @Override protected void onDismissedByScrolling() { - super.onDismissedByScrolling(); - if (callback != null) callback.onDialogDismissed(); - } - - @Override protected void onHidden() { - if (callback != null) callback.onDialogDismissed(); - super.onHidden(); - } - - @NonNull public static MessageDialogView newInstance(@NonNull String bundleTitle, @NonNull String bundleMsg) { - return newInstance(bundleTitle, bundleMsg, null); - } - - @NonNull public static MessageDialogView newInstance(@NonNull String bundleTitle, @NonNull String bundleMsg, boolean isMarkDown) { - return newInstance(bundleTitle, bundleMsg, isMarkDown, null); - } - - @NonNull public static MessageDialogView newInstance(@NonNull String bundleTitle, @NonNull String bundleMsg, - boolean isMarkDown, boolean hideCancel) { - return newInstance(bundleTitle, bundleMsg, isMarkDown, hideCancel, null); - } - - @NonNull public static MessageDialogView newInstance(@NonNull String bundleTitle, @NonNull String bundleMsg, boolean isMarkDown, - @Nullable Bundle bundle) { - MessageDialogView messageDialogView = new MessageDialogView(); - messageDialogView.setArguments(getBundle(bundleTitle, bundleMsg, isMarkDown, bundle, false)); - return messageDialogView; - } - - @NonNull public static MessageDialogView newInstance(@NonNull String bundleTitle, @NonNull String bundleMsg, boolean isMarkDown, - boolean hideCancel, @Nullable Bundle bundle) { - MessageDialogView messageDialogView = new MessageDialogView(); - messageDialogView.setArguments(getBundle(bundleTitle, bundleMsg, isMarkDown, bundle, hideCancel)); - return messageDialogView; - } - - @NonNull public static MessageDialogView newInstance(@NonNull String bundleTitle, @NonNull String bundleMsg, @Nullable Bundle bundle) { - return newInstance(bundleTitle, bundleMsg, false, bundle); - } - - private static Bundle getBundle(String bundleTitle, String bundleMsg, boolean isMarkDown, Bundle bundle, boolean hideCancel) { - return Bundler.start() - .put("bundleTitle", bundleTitle) - .put("bundleMsg", bundleMsg) - .put("bundle", bundle) - .put("isMarkDown", isMarkDown) - .put("hideCancel", hideCancel) - .end(); - } - - @NonNull public static Bundle getYesNoBundle(@NonNull Context context) { - return Bundler.start() - .put("primary_extra", context.getString(R.string.yes)) - .put("secondary_extra", context.getString(R.string.no)) - .end(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/dialog/ProgressDialogFragment.java b/app/src/main/java/com/fastaccess/ui/widgets/dialog/ProgressDialogFragment.java deleted file mode 100644 index 3869c8dd9..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/dialog/ProgressDialogFragment.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.fastaccess.ui.widgets.dialog; - -import android.app.Dialog; -import android.content.res.Resources; -import android.graphics.Color; -import android.graphics.drawable.ColorDrawable; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.StringRes; -import android.view.View; -import android.view.Window; - -import com.fastaccess.R; -import com.fastaccess.helper.Bundler; -import com.fastaccess.ui.base.BaseDialogFragment; -import com.fastaccess.ui.base.mvp.presenter.BasePresenter; - -import net.grandcentrix.thirtyinch.TiPresenter; - -/** - * Created by Kosh on 09 Dec 2016, 5:18 PM - */ - -public class ProgressDialogFragment extends BaseDialogFragment { - - public ProgressDialogFragment() { - suppressAnimation = true; - } - - public static final String TAG = ProgressDialogFragment.class.getSimpleName(); - - @NonNull public static ProgressDialogFragment newInstance(@NonNull Resources resources, @StringRes int msgId, boolean isCancelable) { - return newInstance(resources.getString(msgId), isCancelable); - } - - @NonNull public static ProgressDialogFragment newInstance(@NonNull String msg, boolean isCancelable) { - ProgressDialogFragment fragment = new ProgressDialogFragment(); - fragment.setArguments(Bundler.start() - .put("msg", msg) - .put("isCancelable", isCancelable) - .end()); - return fragment; - } - - @Override protected int fragmentLayout() { - return R.layout.progress_dialog_layout; - } - - @Override protected void onFragmentCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - - } - - @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - Dialog dialog = super.onCreateDialog(savedInstanceState); - dialog.setCancelable(false); - setCancelable(false); - Window window = dialog.getWindow(); - if (window != null) { - window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - window.setDimAmount(0); - } - return dialog; - } - - @NonNull @Override public TiPresenter providePresenter() { - return new BasePresenter(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/markdown/MarkDownLayout.kt b/app/src/main/java/com/fastaccess/ui/widgets/markdown/MarkDownLayout.kt deleted file mode 100644 index 835e35794..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/markdown/MarkDownLayout.kt +++ /dev/null @@ -1,175 +0,0 @@ -package com.fastaccess.ui.widgets.markdown - -import android.annotation.SuppressLint -import android.content.Context -import android.support.design.widget.Snackbar -import android.support.transition.TransitionManager -import android.support.v4.app.FragmentManager -import android.util.AttributeSet -import android.view.View -import android.widget.EditText -import android.widget.HorizontalScrollView -import android.widget.LinearLayout -import butterknife.BindView -import butterknife.ButterKnife -import butterknife.OnClick -import com.fastaccess.R -import com.fastaccess.helper.AppHelper -import com.fastaccess.helper.InputHelper -import com.fastaccess.helper.ViewHelper -import com.fastaccess.provider.emoji.Emoji -import com.fastaccess.provider.markdown.MarkDownProvider -import com.fastaccess.ui.modules.editor.emoji.EmojiBottomSheet -import com.fastaccess.ui.modules.editor.popup.EditorLinkImageDialogFragment - -/** - * Created by kosh on 11/08/2017. - */ -class MarkDownLayout : LinearLayout { - - private val sentFromFastHub: String by lazy { - "\n\n_" + resources.getString(R.string.sent_from_fasthub, AppHelper.getDeviceName(), "", - "[" + resources.getString(R.string.app_name) + "](https://play.google.com/store/apps/details?id=com.fastaccess.github)") + "_" - } - - var markdownListener: MarkdownListener? = null - var selectionIndex = 0 - @BindView(R.id.editorIconsHolder) lateinit var editorIconsHolder: HorizontalScrollView - @BindView(R.id.addEmoji) lateinit var addEmojiView: View - - constructor(context: Context?) : super(context) - constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) - - override fun onFinishInflate() { - super.onFinishInflate() - orientation = HORIZONTAL - View.inflate(context, R.layout.markdown_buttons_layout, this) - if (isInEditMode) return - ButterKnife.bind(this) - } - - override fun onDetachedFromWindow() { - markdownListener = null - super.onDetachedFromWindow() - } - - @OnClick(R.id.view) fun onViewMarkDown() { - markdownListener?.let { - it.getEditText().let { editText -> - TransitionManager.beginDelayedTransition(this) - if (editText.isEnabled && !InputHelper.isEmpty(editText)) { - editText.isEnabled = false - selectionIndex = editText.selectionEnd - MarkDownProvider.setMdText(editText, InputHelper.toString(editText)) - editorIconsHolder.visibility = View.INVISIBLE - addEmojiView.visibility = View.INVISIBLE - ViewHelper.hideKeyboard(editText) - } else { - editText.setText(it.getSavedText()) - editText.setSelection(selectionIndex) - editText.isEnabled = true - editorIconsHolder.visibility = View.VISIBLE - addEmojiView.visibility = View.VISIBLE - ViewHelper.showKeyboard(editText) - } - } - } - } - - @OnClick(R.id.headerOne, R.id.headerTwo, R.id.headerThree, R.id.bold, R.id.italic, R.id.strikethrough, - R.id.bullet, R.id.header, R.id.code, R.id.numbered, R.id.quote, R.id.link, R.id.image, - R.id.unCheckbox, R.id.checkbox, R.id.inlineCode, R.id.addEmoji, - R.id.signature) - fun onActions(v: View) { - markdownListener?.let { - it.getEditText().let { editText -> - if (!editText.isEnabled) { - Snackbar.make(this, R.string.error_highlighting_editor, Snackbar.LENGTH_SHORT).show() - } else { - when { - v.id == R.id.link -> EditorLinkImageDialogFragment.newInstance(true, getSelectedText()) - .show(it.fragmentManager(), "EditorLinkImageDialogFragment") - v.id == R.id.image -> EditorLinkImageDialogFragment.newInstance(false, getSelectedText()) - .show(it.fragmentManager(), "EditorLinkImageDialogFragment") - v.id == R.id.addEmoji -> { - ViewHelper.hideKeyboard(it.getEditText()) - EmojiBottomSheet().show(it.fragmentManager(), "EmojiBottomSheet") - } - else -> onActionClicked(editText, v.id) - } - } - } - } - } - - @SuppressLint("SetTextI18n") - private fun onActionClicked(editText: EditText, id: Int) { - if (editText.selectionEnd == -1 || editText.selectionStart == -1) { - return - } - when (id) { - R.id.headerOne -> MarkDownProvider.addHeader(editText, 1) - R.id.headerTwo -> MarkDownProvider.addHeader(editText, 2) - R.id.headerThree -> MarkDownProvider.addHeader(editText, 3) - R.id.bold -> MarkDownProvider.addBold(editText) - R.id.italic -> MarkDownProvider.addItalic(editText) - R.id.strikethrough -> MarkDownProvider.addStrikeThrough(editText) - R.id.numbered -> MarkDownProvider.addList(editText, "1.") - R.id.bullet -> MarkDownProvider.addList(editText, "-") - R.id.header -> MarkDownProvider.addDivider(editText) - R.id.code -> MarkDownProvider.addCode(editText) - R.id.quote -> MarkDownProvider.addQuote(editText) - R.id.checkbox -> MarkDownProvider.addList(editText, "- [x]") - R.id.unCheckbox -> MarkDownProvider.addList(editText, "- [ ]") - R.id.inlineCode -> MarkDownProvider.addInlinleCode(editText) - R.id.signature -> { - markdownListener?.getEditText()?.let { - if (!it.text.toString().contains(sentFromFastHub)) { - it.setText("${it.text}$sentFromFastHub") - } else { - it.setText(it.text.toString().replace(sentFromFastHub, "")) - } - editText.setSelection(it.text.length) - editText.requestFocus() - } - } - } - } - - fun onEmojiAdded(emoji: Emoji?) { - markdownListener?.getEditText()?.let { editText -> - ViewHelper.showKeyboard(editText) - emoji?.let { - MarkDownProvider.insertAtCursor(editText, ":${it.aliases[0]}:") - } - } - } - - interface MarkdownListener { - fun getEditText(): EditText - fun fragmentManager(): FragmentManager - fun getSavedText(): CharSequence? - } - - fun onAppendLink(title: String?, link: String?, isLink: Boolean) { - markdownListener?.let { - if (isLink) { - MarkDownProvider.addLink(it.getEditText(), InputHelper.toString(title), InputHelper.toString(link)) - } else { - MarkDownProvider.addPhoto(it.getEditText(), InputHelper.toString(title), InputHelper.toString(link)) - } - } - } - - private fun getSelectedText(): String? { - markdownListener?.getEditText()?.let { - if (!it.text.toString().isBlank()) { - val selectionStart = it.selectionStart - val selectionEnd = it.selectionEnd - return it.text.toString().substring(selectionStart, selectionEnd) - } - } - return null - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/markdown/MarkdownEditText.kt b/app/src/main/java/com/fastaccess/ui/widgets/markdown/MarkdownEditText.kt deleted file mode 100644 index d645b3d48..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/markdown/MarkdownEditText.kt +++ /dev/null @@ -1,115 +0,0 @@ -package com.fastaccess.ui.widgets.markdown - -import android.annotation.SuppressLint -import android.content.Context -import android.util.AttributeSet -import android.view.View -import android.widget.ArrayAdapter -import android.widget.ListView -import android.widget.TextView -import com.crashlytics.android.Crashlytics -import com.fastaccess.ui.widgets.FontEditText -import java.util.* - - -/** - * Created by kosh on 14/08/2017. - */ -class MarkdownEditText : FontEditText { - - var savedText: CharSequence? = "" - private var mention: ListView? = null - private var listDivider: View? = null - private var inMentionMode = -1 - private var participants: ArrayList? = null - - constructor(context: Context) : super(context) - constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) - constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) - - fun initListView(mention: ListView?, listDivider: View?, participants: ArrayList?) { - this.mention = mention - this.listDivider = listDivider - this.participants = participants - this.participants?.let { - mention?.setOnItemClickListener { _, _, position, _ -> - try { - if (inMentionMode != -1) { - val complete = mention.adapter.getItem(position).toString() + " " - val end = selectionEnd - text.replace(inMentionMode, end, complete, 0, complete.length) - inMentionMode = -1 - } - } catch (ignored: Exception) { - } - mention.visibility = GONE - listDivider?.visibility = GONE - } - } - } - - override fun onTextChanged(text: CharSequence?, start: Int, lengthBefore: Int, lengthAfter: Int) { - super.onTextChanged(text, start, lengthBefore, lengthAfter) - if (isEnabled) { - savedText = text - text?.let { - mention(it) - } - } - } - - @SuppressLint("SetTextI18n") override fun setText(text: CharSequence, type: TextView.BufferType) { - try { - super.setText(text, type) - } catch (e: Exception) { - setText("I tried, but your OEM just sucks because they modify the framework components and therefore causing the app to crash!" + "" + - ".\nFastHub") - Crashlytics.logException(e) - } - - } - - fun mention(charSequence: CharSequence) { - try { - var lastChar: Char = 0.toChar() - if (charSequence.isNotEmpty()) lastChar = charSequence[charSequence.length - 1] - if (lastChar.toInt() != 0) { - if (lastChar == '@') { - inMentionMode = selectionEnd - mention?.visibility = GONE - listDivider?.visibility = GONE - return - } else if (lastChar == ' ') - inMentionMode = -1 - else if (inMentionMode > -1) - updateMentionList(charSequence.toString().substring(inMentionMode, selectionEnd)) - else { - val copy = text.toString().substring(0, selectionEnd) - val list = copy.split("\\s+".toRegex()) - val last = list[list.size - 1] - if (last.startsWith("@")) { - inMentionMode = copy.lastIndexOf("@") + 1 - updateMentionList(charSequence.toString().substring(inMentionMode, selectionEnd)) - } - } - } else { - inMentionMode = -1 - } - if (inMentionMode > -1) mention?.let { - it.visibility = if (inMentionMode > 0) View.VISIBLE else GONE - listDivider!!.visibility = it.visibility - } - } catch (ignored: Exception) { - } - } - - private fun updateMentionList(mentioning: String) { - participants?.let { - val mentions = it.filter { it.toLowerCase().startsWith(mentioning.replace("@", "").toLowerCase()) } - val adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, - android.R.id.text1, mentions.subList(0, Math.min(mentions.size, 3))) - mention?.setAdapter(adapter) - } - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java deleted file mode 100644 index a364590e8..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseRecyclerAdapter.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.fastaccess.ui.widgets.recyclerview; - -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.helper.AnimHelper; -import com.fastaccess.helper.PrefGetter; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Kosh on 17 May 2016, 7:10 PM - */ -public abstract class BaseRecyclerAdapter> extends RecyclerView.Adapter { - - private final static int PROGRESS_TYPE = 2017; - - @NonNull private List data; - @Nullable private P listener; - private int lastKnowingPosition = -1; - private boolean enableAnimation = PrefGetter.isRVAnimationEnabled(); - private boolean showedGuide; - private GuideListener guideListener; - private boolean progressAdded; - private int rowWidth; - - protected BaseRecyclerAdapter() { - this(new ArrayList<>()); - } - - protected BaseRecyclerAdapter(@NonNull List data) { - this(data, null); - } - - protected BaseRecyclerAdapter(@NonNull List data, @Nullable P listener) { - this.data = data; - this.listener = listener; - } - - protected BaseRecyclerAdapter(@Nullable P listener) { - this(new ArrayList<>(), listener); - } - - protected abstract VH viewHolder(ViewGroup parent, int viewType); - - protected abstract void onBindView(VH holder, int position); - - @NonNull public List getData() { - return data; - } - - public M getItemByPosition(int position) { - return data.get(position); - } - - public M getItem(int position) { - return data.get(position); - } - - public int getItem(M t) { - return data.indexOf(t); - } - - @SuppressWarnings("unchecked") @Override public VH onCreateViewHolder(ViewGroup parent, int viewType) { - if (viewType == PROGRESS_TYPE) { - addSpanLookup(parent); - return (VH) ProgressBarViewHolder.newInstance(parent); - } else { - return viewHolder(parent, viewType); - } - } - - @Override public void onBindViewHolder(@NonNull VH holder, int position) { - if (holder instanceof ProgressBarViewHolder) { - if (holder.itemView.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams) { - StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams(); - layoutParams.setFullSpan(true); - } - } else if (getItem(position) != null) { - animate(holder, position); - onBindView(holder, position); - onShowGuide(holder, position); - } - } - - @Override public int getItemViewType(int position) { - if (getItem(position) == null) { - return PROGRESS_TYPE; - } - return super.getItemViewType(position); - } - - @Override public int getItemCount() { - return data.size(); - } - - @SuppressWarnings("unchecked") - private void onShowGuide(@NonNull VH holder, int position) {// give the flexibility to other adapters to override this - if (position == 0 && !isShowedGuide() && guideListener != null) { - guideListener.onShowGuide(holder.itemView, getItem(position)); - showedGuide = true; - } - } - - private void animate(@NonNull VH holder, int position) { - if (isEnableAnimation() && position > lastKnowingPosition) { - AnimHelper.startBeatsAnimation(holder.itemView); - lastKnowingPosition = position; - } - } - - public void insertItems(@NonNull List items) { - data.clear(); - data.addAll(items); - notifyDataSetChanged(); - progressAdded = false; - } - - public void addItem(M item, int position) { - data.add(position, item); - notifyItemInserted(position); - } - - public void addItem(M item) { - removeProgress(); - data.add(item); - if (data.size() == 0) { - notifyDataSetChanged(); - } else { - notifyItemInserted(data.size() - 1); - } - } - - @SuppressWarnings("WeakerAccess") public void addItems(@NonNull List items) { - removeProgress(); - data.addAll(items); - notifyItemRangeInserted(getItemCount(), (getItemCount() + items.size()) - 1); - } - - @SuppressWarnings("WeakerAccess") public void removeItem(int position) { - data.remove(position); - notifyItemRemoved(position); - } - - public void removeItem(M item) { - int position = data.indexOf(item); - if (position != -1) removeItem(position); - } - - public void removeItems(@NonNull List items) { - int prevSize = getItemCount(); - data.removeAll(items); - notifyItemRangeRemoved(prevSize, Math.abs(data.size() - prevSize)); - } - - public void swapItem(@NonNull M model) { - int index = getItem(model); - swapItem(model, index); - } - - public void swapItem(@NonNull M model, int position) { - if (position != -1) { - data.set(position, model); - notifyItemChanged(position); - } - } - - public void subList(int fromPosition, int toPosition) { - if (data.isEmpty()) return; - data.subList(fromPosition, toPosition).clear(); - notifyItemRangeRemoved(fromPosition, toPosition); - } - - public void clear() { - progressAdded = false; - data.clear(); - notifyDataSetChanged(); - } - - public boolean isEmpty() { - return data.isEmpty(); - } - - public void setEnableAnimation(boolean enableAnimation) { - this.enableAnimation = enableAnimation; - notifyDataSetChanged(); - } - - @SuppressWarnings("WeakerAccess") public boolean isEnableAnimation() { - return enableAnimation; - } - - @SuppressWarnings("WeakerAccess") @Nullable public P getListener() { - return listener; - } - - public void setListener(@Nullable P listener) { - this.listener = listener; - notifyDataSetChanged(); - } - - public void setGuideListener(GuideListener guideListener) { - this.guideListener = guideListener; - } - - public int getRowWidth() { - return rowWidth; - } - - public void setRowWidth(int rowWidth) { - if (this.rowWidth == 0) { - this.rowWidth = rowWidth; - notifyDataSetChanged(); - } - } - - private boolean isShowedGuide() { - return showedGuide; - } - - @Override public void onViewDetachedFromWindow(VH holder) { - holder.onViewIsDetaching(); - super.onViewDetachedFromWindow(holder); - } - - public void addProgress() { - if (!progressAdded && !isEmpty()) { - addItem(null); - progressAdded = true; - } - } - - public boolean isProgressAdded() { - return progressAdded; - } - - private void removeProgress() { - if (!isEmpty()) { - M m = getItem(getItemCount() - 1); - if (m == null) { - removeItem(getItemCount() - 1); - } - progressAdded = false; - } - } - - private void addSpanLookup(ViewGroup parent) { - if (parent instanceof RecyclerView) { - if (((RecyclerView) parent).getLayoutManager() instanceof GridLayoutManager) { - GridLayoutManager layoutManager = ((GridLayoutManager) ((RecyclerView) parent).getLayoutManager()); - layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { - @Override public int getSpanSize(int position) { - return getItemViewType(position) == PROGRESS_TYPE ? layoutManager.getSpanCount() : 1; - } - }); - } - } - } - - public interface GuideListener { - void onShowGuide(@NonNull View itemView, @NonNull M model); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseViewHolder.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseViewHolder.java deleted file mode 100644 index 6f4b3d9a8..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BaseViewHolder.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.fastaccess.ui.widgets.recyclerview; - -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import butterknife.ButterKnife; - -/** - * Created by Kosh on 17 May 2016, 7:13 PM - */ -public abstract class BaseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { - - public interface OnItemClickListener { - void onItemClick(int position, View v, T item); - - void onItemLongClick(int position, View v, T item); - } - - @Nullable protected final BaseRecyclerAdapter adapter; - - public static View getView(@NonNull ViewGroup parent, @LayoutRes int layoutRes) { - return LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false); - } - - protected BaseViewHolder(@NonNull View itemView) { - this(itemView, null); - } - - public BaseViewHolder(@NonNull View itemView, @Nullable BaseRecyclerAdapter adapter) { - super(itemView); - ButterKnife.bind(this, itemView); - this.adapter = adapter; - itemView.setOnClickListener(this); - itemView.setOnLongClickListener(this); - } - - @SuppressWarnings("unchecked") @Override public void onClick(View v) { - if (adapter != null && adapter.getListener() != null) { - int position = getAdapterPosition(); - if (position != RecyclerView.NO_POSITION && position < adapter.getItemCount()) - adapter.getListener().onItemClick(position, v, adapter.getItem(position)); - } - } - - @SuppressWarnings("unchecked") @Override public boolean onLongClick(View v) { - if (adapter != null && adapter.getListener() != null) { - int position = getAdapterPosition(); - if (position != RecyclerView.NO_POSITION && position < adapter.getItemCount()) - adapter.getListener().onItemLongClick(position, v, adapter.getItem(position)); - } - return true; - } - - public abstract void bind(@NonNull T t); - - protected void onViewIsDetaching() {} - -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BottomPaddingDecoration.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BottomPaddingDecoration.java deleted file mode 100644 index 8a1ab7d20..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/BottomPaddingDecoration.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.fastaccess.ui.widgets.recyclerview; - -import android.content.Context; -import android.graphics.Rect; -import android.support.annotation.NonNull; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.helper.ViewHelper; - -class BottomPaddingDecoration extends RecyclerView.ItemDecoration { - private final int bottomPadding; - - private BottomPaddingDecoration(int bottomOffset) { - bottomPadding = bottomOffset; - } - - private BottomPaddingDecoration(@NonNull Context context) { - this(ViewHelper.toPx(context, context.getResources().getDimensionPixelSize(R.dimen.fab_spacing))); - } - - public static BottomPaddingDecoration with(int bottomPadding) { - return new BottomPaddingDecoration(bottomPadding); - } - - public static BottomPaddingDecoration with(@NonNull Context context) { - return new BottomPaddingDecoration(context); - } - - @Override public void getItemOffsets(@NonNull Rect outRect, View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { - super.getItemOffsets(outRect, view, parent, state); - int dataSize = state.getItemCount(); - int position = parent.getChildAdapterPosition(view); - if (parent.getLayoutManager() instanceof GridLayoutManager) { - GridLayoutManager grid = (GridLayoutManager) parent.getLayoutManager(); - if ((dataSize - position) <= grid.getSpanCount()) { - outRect.set(0, 0, 0, bottomPadding); - } else { - outRect.set(0, 0, 0, 0); - } - } else if (parent.getLayoutManager() instanceof LinearLayoutManager) { - if (dataSize > 0 && position == dataSize - 1) { - outRect.set(0, 0, 0, bottomPadding); - } else { - outRect.set(0, 0, 0, 0); - } - } else if (parent.getLayoutManager() instanceof StaggeredGridLayoutManager) { - StaggeredGridLayoutManager grid = (StaggeredGridLayoutManager) parent.getLayoutManager(); - if ((dataSize - position) <= grid.getSpanCount()) { - outRect.set(0, 0, 0, bottomPadding); - } else { - outRect.set(0, 0, 0, 0); - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java deleted file mode 100644 index b7df17baa..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/DynamicRecyclerView.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.fastaccess.ui.widgets.recyclerview; - -import android.content.Context; -import android.content.res.Resources; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; -import android.util.AttributeSet; -import android.view.View; - -import com.fastaccess.R; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.ui.widgets.StateLayout; - - -/** - * Created by Kosh on 9/24/2015. copyrights are reserved - *

    - * recyclerview which will showParentOrSelf/showParentOrSelf itself base on adapter - */ -public class DynamicRecyclerView extends RecyclerView { - - private StateLayout emptyView; - @Nullable private View parentView; - private BottomPaddingDecoration bottomPaddingDecoration; - - @NonNull private AdapterDataObserver observer = new AdapterDataObserver() { - @Override public void onChanged() { - showEmptyView(); - } - - @Override public void onItemRangeInserted(int positionStart, int itemCount) { - super.onItemRangeInserted(positionStart, itemCount); - showEmptyView(); - } - - @Override public void onItemRangeRemoved(int positionStart, int itemCount) { - super.onItemRangeRemoved(positionStart, itemCount); - showEmptyView(); - } - }; - - public DynamicRecyclerView(@NonNull Context context) { - this(context, null); - } - - public DynamicRecyclerView(@NonNull Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public DynamicRecyclerView(@NonNull Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override public void setAdapter(@Nullable Adapter adapter) { - super.setAdapter(adapter); - if (isInEditMode()) return; - if (adapter != null) { - adapter.registerAdapterDataObserver(observer); - observer.onChanged(); - } - } - - - public void removeBottomDecoration() { - if (bottomPaddingDecoration != null) { - removeItemDecoration(bottomPaddingDecoration); - bottomPaddingDecoration = null; - } - } - - public void addDecoration() { - bottomPaddingDecoration = BottomPaddingDecoration.with(getContext()); - addItemDecoration(bottomPaddingDecoration); - } - - private void showEmptyView() { - Adapter adapter = getAdapter(); - if (adapter != null) { - if (emptyView != null) { - if (adapter.getItemCount() == 0) { - showParentOrSelf(false); - } else { - showParentOrSelf(true); - } - } - } else { - if (emptyView != null) { - showParentOrSelf(false); - } - } - } - - private void showParentOrSelf(boolean showRecyclerView) { - if (parentView != null) - parentView.setVisibility(VISIBLE); - setVisibility(VISIBLE); - emptyView.setVisibility(!showRecyclerView ? VISIBLE : GONE); - } - - public void setEmptyView(@NonNull StateLayout emptyView, @Nullable View parentView) { - this.emptyView = emptyView; - this.parentView = parentView; - showEmptyView(); - } - - public void setEmptyView(@NonNull StateLayout emptyView) { - setEmptyView(emptyView, null); - } - - public void hideProgress(@NonNull StateLayout view) { - view.hideProgress(); - } - - public void showProgress(@NonNull StateLayout view) { - view.showProgress(); - } - - public void addKeyLineDivider() { - if (canAddDivider()) { - Resources resources = getResources(); - addItemDecoration(new InsetDividerDecoration(resources.getDimensionPixelSize(R.dimen.divider_height), - resources.getDimensionPixelSize(R.dimen.keyline_2), ViewHelper.getListDivider(getContext()))); - } - } - - public void addDivider() { - if (canAddDivider()) { - Resources resources = getResources(); - addItemDecoration(new InsetDividerDecoration(resources.getDimensionPixelSize(R.dimen.divider_height), 0, - ViewHelper.getListDivider(getContext()))); - } - } - - public void addNormalSpacingDivider() { - addDivider(); - } - - public void addDivider(@NonNull Class toDivide) { - if (canAddDivider()) { - Resources resources = getResources(); - addItemDecoration(new InsetDividerDecoration(resources.getDimensionPixelSize(R.dimen.divider_height), 0, - ViewHelper.getListDivider(getContext()), toDivide)); - } - } - - private boolean canAddDivider() { - if (getLayoutManager() != null) { - if (getLayoutManager() instanceof GridLayoutManager) { - return ((GridLayoutManager) getLayoutManager()).getSpanCount() == 1; - } else if (getLayoutManager() instanceof LinearLayoutManager) { - return true; - } else if (getLayoutManager() instanceof StaggeredGridLayoutManager) { - return ((StaggeredGridLayoutManager) getLayoutManager()).getSpanCount() == 1; - } - } - return false; - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/InsetDividerDecoration.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/InsetDividerDecoration.java deleted file mode 100644 index 991ecfc6e..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/InsetDividerDecoration.java +++ /dev/null @@ -1,69 +0,0 @@ - -package com.fastaccess.ui.widgets.recyclerview; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.support.annotation.ColorInt; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; -import android.view.View; - -/** - * A decoration which draws a horizontal divider between {@link RecyclerView.ViewHolder}s of a given - * type; with a left inset. - * this class adopted from Plaid - */ -class InsetDividerDecoration extends RecyclerView.ItemDecoration { - - @NonNull private final Paint paint; - private final int inset; - private final int height; - private final Class toDivide; - - InsetDividerDecoration(int divider, int leftInset, @ColorInt int dividerColor) { - this(divider, leftInset, dividerColor, null); - } - - InsetDividerDecoration(int divider, int leftInset, @ColorInt int dividerColor, @Nullable Class toDivide) { - this.inset = leftInset; - this.height = divider; - this.paint = new Paint(); - this.paint.setColor(dividerColor); - this.paint.setStyle(Paint.Style.STROKE); - this.paint.setStrokeWidth(divider); - this.toDivide = toDivide; - } - - @Override public void onDrawOver(@NonNull Canvas canvas, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { - int childCount = parent.getChildCount(); - if (childCount < 2) return; - RecyclerView.LayoutManager lm = parent.getLayoutManager(); - float[] lines = new float[childCount * 4]; - boolean hasDividers = false; - for (int i = 0; i < childCount; i++) { - View child = parent.getChildAt(i); - RecyclerView.ViewHolder viewHolder = parent.getChildViewHolder(child); - if (!(viewHolder instanceof ProgressBarViewHolder)) { - boolean canDivide = toDivide == null || viewHolder.getClass() == toDivide; - if (canDivide) { - int position = parent.getChildAdapterPosition(child); - if (child.isActivated() || (i + 1 < childCount && parent.getChildAt(i + 1).isActivated())) { - continue; - } - if (position != (state.getItemCount() - 1)) { - lines[i * 4] = inset == 0 ? inset : inset + lm.getDecoratedLeft(child); - lines[(i * 4) + 2] = lm.getDecoratedRight(child); - int y = lm.getDecoratedBottom(child) + (int) child.getTranslationY() - height; - lines[(i * 4) + 1] = y; - lines[(i * 4) + 3] = y; - hasDividers = true; - } - } - } - } - if (hasDividers) { - canvas.drawLines(lines, paint); - } - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/ProgressBarViewHolder.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/ProgressBarViewHolder.java deleted file mode 100644 index a34127c08..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/ProgressBarViewHolder.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.fastaccess.ui.widgets.recyclerview; - -import android.support.annotation.NonNull; -import android.view.View; -import android.view.ViewGroup; - -import com.fastaccess.R; - -/** - * Created by kosh on 03/08/2017. - */ - -public class ProgressBarViewHolder extends BaseViewHolder { - - private ProgressBarViewHolder(@NonNull View itemView) { - super(itemView); - } - - public static ProgressBarViewHolder newInstance(ViewGroup viewGroup) { - return new ProgressBarViewHolder(getView(viewGroup, R.layout.progress_layout)); - } - - @Override public void bind(@NonNull Object o) { - - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/GridManager.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/GridManager.java deleted file mode 100644 index 9f3cc68f7..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/GridManager.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.fastaccess.ui.widgets.recyclerview.layout_manager; - -import android.content.Context; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.util.AttributeSet; - -/** - * Created by Kosh on 17 May 2016, 10:02 PM - */ -public class GridManager extends GridLayoutManager { - - private int iconSize; - - public GridManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public GridManager(Context context, int spanCount) { - super(context, spanCount); - } - - public GridManager(Context context, int spanCount, int orientation, boolean reverseLayout) { - super(context, spanCount, orientation, reverseLayout); - } - - @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { - try { - super.onLayoutChildren(recycler, state); - updateCount(); - } catch (Exception ignored) {} - } - - @Override public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { - try { - super.onMeasure(recycler, state, widthSpec, heightSpec); - } catch (Exception ignored) {} - } - - private void updateCount() { - if (iconSize > 1) { - int spanCount = Math.max(1, getWidth() / iconSize); - if (spanCount < 1) { - spanCount = 1; - } - this.setSpanCount(spanCount); - } - } - - public int getIconSize() { - return iconSize; - } - - public void setIconSize(int iconSize) { - this.iconSize = iconSize; - updateCount(); - } -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/LinearManager.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/LinearManager.java deleted file mode 100644 index 2d830d361..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/LinearManager.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.fastaccess.ui.widgets.recyclerview.layout_manager; - -import android.content.Context; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.util.AttributeSet; - -/** - * Created by Kosh on 17 May 2016, 10:02 PM - */ -public class LinearManager extends LinearLayoutManager { - - public LinearManager(Context context) { - super(context); - } - - public LinearManager(Context context, int orientation, boolean reverseLayout) { - super(context, orientation, reverseLayout); - } - - public LinearManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { - try { - super.onLayoutChildren(recycler, state); - } catch (Exception ignored) {} - } - - @Override public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { - try { - super.onMeasure(recycler, state, widthSpec, heightSpec); - } catch (Exception ignored) {} - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/StaggeredManager.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/StaggeredManager.java deleted file mode 100644 index 46a754303..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/layout_manager/StaggeredManager.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.fastaccess.ui.widgets.recyclerview.layout_manager; - -import android.content.Context; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; -import android.util.AttributeSet; - -/** - * Created by Kosh on 17 May 2016, 10:02 PM - */ -public class StaggeredManager extends StaggeredGridLayoutManager { - - public StaggeredManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - public StaggeredManager(int spanCount, int orientation) { - super(spanCount, orientation); - } - - @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { - try { - super.onLayoutChildren(recycler, state); - } catch (Exception ignored) {} - } - - @Override public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { - try { - super.onMeasure(recycler, state, widthSpec, heightSpec); - } catch (Exception ignored) {} - } - -} diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/scroll/InfiniteScroll.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/scroll/InfiniteScroll.java deleted file mode 100644 index 7a55a4966..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/scroll/InfiniteScroll.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.fastaccess.ui.widgets.recyclerview.scroll; - -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; - -import com.fastaccess.ui.widgets.recyclerview.BaseRecyclerAdapter; - -/** - * Created by Kosh on 8/2/2015. copyrights are reserved @ - */ -public abstract class InfiniteScroll extends RecyclerView.OnScrollListener { - private int visibleThreshold = 3; - private int currentPage = 0; - private int previousTotalItemCount = 0; - private boolean loading = true; - private int startingPageIndex = 0; - private RecyclerView.LayoutManager layoutManager; - private BaseRecyclerAdapter adapter; - private boolean newlyAdded = true; - - public InfiniteScroll() {} - - private void initLayoutManager(RecyclerView.LayoutManager layoutManager) { - this.layoutManager = layoutManager; - if (layoutManager instanceof GridLayoutManager) { - visibleThreshold = visibleThreshold * ((GridLayoutManager) layoutManager).getSpanCount(); - } else if (layoutManager instanceof StaggeredGridLayoutManager) { - visibleThreshold = visibleThreshold * ((StaggeredGridLayoutManager) layoutManager).getSpanCount(); - } - } - - private int getLastVisibleItem(int[] lastVisibleItemPositions) { - int maxSize = 0; - for (int i = 0; i < lastVisibleItemPositions.length; i++) { - if (i == 0) { - maxSize = lastVisibleItemPositions[i]; - } else if (lastVisibleItemPositions[i] > maxSize) { - maxSize = lastVisibleItemPositions[i]; - } - } - return maxSize; - } - - @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - if (newlyAdded) { - newlyAdded = false; - return; - } - onScrolled(dy > 0); - if (layoutManager == null) { - initLayoutManager(recyclerView.getLayoutManager()); - } - if (adapter == null) { - if (recyclerView.getAdapter() instanceof BaseRecyclerAdapter) { - adapter = (BaseRecyclerAdapter) recyclerView.getAdapter(); - } - } - if (adapter != null && adapter.isProgressAdded()) return; - - int lastVisibleItemPosition = 0; - int totalItemCount = layoutManager.getItemCount(); - if (layoutManager instanceof StaggeredGridLayoutManager) { - int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(null); - lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions); - } else if (layoutManager instanceof GridLayoutManager) { - lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition(); - } else if (layoutManager instanceof LinearLayoutManager) { - lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition(); - } - if (totalItemCount < previousTotalItemCount) { - this.currentPage = this.startingPageIndex; - this.previousTotalItemCount = totalItemCount; - if (totalItemCount == 0) { - this.loading = true; - } - } - if (loading && (totalItemCount > previousTotalItemCount)) { - loading = false; - previousTotalItemCount = totalItemCount; - } - if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) { - currentPage++; - boolean isCallingApi = onLoadMore(currentPage, totalItemCount); - loading = true; - if (adapter != null && isCallingApi) { - adapter.addProgress(); - } - } - } - - public void reset() { - this.currentPage = this.startingPageIndex; - this.previousTotalItemCount = 0; - this.loading = true; - } - - public void initialize(int page, int previousTotal) { - this.currentPage = page; - this.previousTotalItemCount = previousTotal; - this.loading = true; - } - - public abstract boolean onLoadMore(int page, int totalItemsCount); - - public void onScrolled(boolean isUp) {} - -} - diff --git a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/scroll/RecyclerViewFastScroller.java b/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/scroll/RecyclerViewFastScroller.java deleted file mode 100755 index f16a7e69f..000000000 --- a/app/src/main/java/com/fastaccess/ui/widgets/recyclerview/scroll/RecyclerViewFastScroller.java +++ /dev/null @@ -1,240 +0,0 @@ -package com.fastaccess.ui.widgets.recyclerview.scroll; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.design.widget.AppBarLayout; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.ViewTreeObserver; -import android.widget.FrameLayout; -import android.widget.ImageButton; -import android.widget.ImageView; - -import com.fastaccess.R; -import com.fastaccess.helper.ActivityHelper; -import com.fastaccess.helper.Logger; - -import it.sephiroth.android.library.bottomnavigation.BottomNavigation; - -public class RecyclerViewFastScroller extends FrameLayout { - - private static final int TRACK_SNAP_RANGE = 5; - private ImageView scrollerView; - private ImageButton scrollTop; - private int height; - private RecyclerView recyclerView; - private RecyclerView.LayoutManager layoutManager; - private AppBarLayout appBarLayout; - private BottomNavigation bottomNavigation; - private boolean toggled; - private boolean registeredObserver = false; - - public RecyclerViewFastScroller(Context context) { - super(context); - init(); - } - - public RecyclerViewFastScroller(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public RecyclerViewFastScroller(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(); - } - - @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - height = h; - } - - @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(@NonNull MotionEvent event) { - int action = event.getAction(); - switch (action) { - case MotionEvent.ACTION_DOWN: - if (event.getX() < (scrollerView.getX() - scrollerView.getPaddingStart())) return false; - scrollerView.setSelected(true); - hideAppbar(); - case MotionEvent.ACTION_MOVE: - float y = event.getY(); - setScrollerHeight(y); - setRecyclerViewPosition(y); - return true; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - scrollerView.setSelected(false); - showAppbar(); - return true; - } - return super.onTouchEvent(event); - } - - @Override protected void onDetachedFromWindow() { - if (recyclerView != null) { - recyclerView.removeOnScrollListener(onScrollListener); - safelyUnregisterObserver(); - } - appBarLayout = null; - bottomNavigation = null; - super.onDetachedFromWindow(); - } - - private void safelyUnregisterObserver() { - try {// rare case - if (registeredObserver && recyclerView.getAdapter() != null) { - recyclerView.getAdapter().unregisterAdapterDataObserver(observer); - } - } catch (Exception ignored) {} - } - - protected void init() { - setVisibility(GONE); - setClipChildren(false); - LayoutInflater inflater = LayoutInflater.from(getContext()); - inflater.inflate(R.layout.fastscroller_layout, this); - scrollerView = findViewById(R.id.fast_scroller_handle); - setVisibility(VISIBLE); - Activity activity = ActivityHelper.getActivity(getContext()); - if (activity != null) { - appBarLayout = activity.findViewById(R.id.appbar); - bottomNavigation = activity.findViewById(R.id.bottomNavigation); - } - } - - protected void hideAppbar() { - if (!toggled) { - if (appBarLayout != null) { - appBarLayout.setExpanded(false, true); - } - if (bottomNavigation != null) { - bottomNavigation.setExpanded(false, true); - } - toggled = true; - } - } - - protected void showAppbar() { - if (toggled) { - if (scrollerView.getY() == 0) { - if (appBarLayout != null) { - appBarLayout.setExpanded(true, true); - } - if (bottomNavigation != null) { - bottomNavigation.setExpanded(true, true); - } - toggled = false; - } - } - } - - public void attachRecyclerView(final RecyclerView recyclerView) { - if (this.recyclerView == null) { - this.recyclerView = recyclerView; - this.layoutManager = recyclerView.getLayoutManager(); - this.recyclerView.addOnScrollListener(onScrollListener); - if (recyclerView.getAdapter() != null && !registeredObserver) { - recyclerView.getAdapter().registerAdapterDataObserver(observer); - registeredObserver = true; - } - hideShow(); - initScrollHeight(); - } - } - - private void initScrollHeight() { - if (recyclerView.computeVerticalScrollOffset() == 0) { - this.recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override public boolean onPreDraw() { - RecyclerViewFastScroller.this.recyclerView.getViewTreeObserver().removeOnPreDrawListener(this); - iniHeight(); - return true; - } - }); - } else { - iniHeight(); - } - } - - protected void iniHeight() { - if (scrollerView.isSelected()) return; - int verticalScrollOffset = RecyclerViewFastScroller.this.recyclerView.computeVerticalScrollOffset(); - int verticalScrollRange = RecyclerViewFastScroller.this.computeVerticalScrollRange(); - float proportion = (float) verticalScrollOffset / ((float) verticalScrollRange - height); - setScrollerHeight(height * proportion); - } - - private void setRecyclerViewPosition(float y) { - Logger.e(y); - if (recyclerView != null) { - int itemCount = recyclerView.getAdapter().getItemCount(); - float proportion; - if (scrollerView.getY() == 0) { - proportion = 0f; - } else if (scrollerView.getY() + scrollerView.getHeight() >= height - TRACK_SNAP_RANGE) { - proportion = 1f; - } else { - proportion = y / (float) height; - } - int targetPos = getValueInRange(itemCount - 1, (int) (proportion * (float) itemCount)); - if (layoutManager instanceof StaggeredGridLayoutManager) { - ((StaggeredGridLayoutManager) layoutManager).scrollToPositionWithOffset(targetPos, 0); - } else if (layoutManager instanceof GridLayoutManager) { - ((GridLayoutManager) layoutManager).scrollToPositionWithOffset(targetPos, 0); - } else { - ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(targetPos, 0); - } - } - } - - private static int getValueInRange(int max, int value) { - return Math.min(Math.max(0, value), max); - } - - private void setScrollerHeight(float y) { - int handleHeight = scrollerView.getHeight(); - scrollerView.setY(getValueInRange(height - handleHeight, (int) (y - handleHeight / 2))); - } - - private final RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() { - @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - if (scrollerView.isSelected()) return; - int verticalScrollOffset = recyclerView.computeVerticalScrollOffset(); - int verticalScrollRange = recyclerView.computeVerticalScrollRange(); - float proportion = (float) verticalScrollOffset / ((float) verticalScrollRange - height); - setScrollerHeight(height * proportion); - } - }; - - private final RecyclerView.AdapterDataObserver observer = new RecyclerView.AdapterDataObserver() { - @Override public void onItemRangeInserted(int positionStart, int itemCount) { - super.onItemRangeInserted(positionStart, itemCount); - hideShow(); - } - - @Override public void onItemRangeRemoved(int positionStart, int itemCount) { - super.onItemRangeRemoved(positionStart, itemCount); - hideShow(); - } - - @Override public void onChanged() { - super.onChanged(); - hideShow(); - - } - }; - - protected void hideShow() { - if (recyclerView != null && recyclerView.getAdapter() != null) { - setVisibility(recyclerView.getAdapter().getItemCount() > 10 ? VISIBLE : GONE); - } else { - setVisibility(GONE); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/prettifier/pretty/NestedWebView.java b/app/src/main/java/com/prettifier/pretty/NestedWebView.java deleted file mode 100644 index 500f30235..000000000 --- a/app/src/main/java/com/prettifier/pretty/NestedWebView.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.prettifier.pretty; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.os.Build; -import android.support.annotation.RequiresApi; -import android.support.v4.view.MotionEventCompat; -import android.support.v4.view.NestedScrollingChild; -import android.support.v4.view.NestedScrollingChildHelper; -import android.support.v4.view.ViewCompat; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.webkit.WebView; - -public class NestedWebView extends WebView implements NestedScrollingChild { - private int mLastY; - private final int[] mScrollOffset = new int[2]; - private final int[] mScrollConsumed = new int[2]; - private int mNestedOffsetY; - private NestedScrollingChildHelper mChildHelper; - private boolean firstScroll = true; - - - public NestedWebView(Context context) { - this(context, null); - } - - public NestedWebView(Context context, AttributeSet attrs) { - this(context, attrs, android.R.attr.webViewStyle); - } - - public NestedWebView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - mChildHelper = new NestedScrollingChildHelper(this); - setNestedScrollingEnabled(true); - } - - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - public NestedWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent ev) { - boolean returnValue; - MotionEvent event = MotionEvent.obtain(ev); - final int action = MotionEventCompat.getActionMasked(event); - if (action == MotionEvent.ACTION_DOWN) { - mNestedOffsetY = 0; - } - int eventY = (int) event.getY(); - event.offsetLocation(0, mNestedOffsetY); - switch (action) { - case MotionEvent.ACTION_MOVE: - int deltaY = mLastY - eventY; - // NestedPreScroll - if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) { - deltaY -= mScrollConsumed[1]; - mLastY = eventY - mScrollOffset[1]; - event.offsetLocation(0, -mScrollOffset[1]); - mNestedOffsetY += mScrollOffset[1]; - } - returnValue = super.onTouchEvent(event); - - // NestedScroll - if (dispatchNestedScroll(0, mScrollOffset[1], 0, deltaY, mScrollOffset)) { - event.offsetLocation(0, mScrollOffset[1]); - mNestedOffsetY += mScrollOffset[1]; - mLastY -= mScrollOffset[1]; - } - break; - case MotionEvent.ACTION_DOWN: - returnValue = super.onTouchEvent(event); - if (firstScroll) { - mLastY = eventY - 5; - firstScroll = false; - } else { - mLastY = eventY; - } - startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL); - break; - default: - returnValue = super.onTouchEvent(event); - // end NestedScroll - stopNestedScroll(); - break; - } - return returnValue; - } - - @Override public void setNestedScrollingEnabled(boolean enabled) { - mChildHelper.setNestedScrollingEnabled(enabled); - } - - @Override public boolean isNestedScrollingEnabled() { - return mChildHelper.isNestedScrollingEnabled(); - } - - @Override public boolean startNestedScroll(int axes) { - return mChildHelper.startNestedScroll(axes); - } - - @Override public void stopNestedScroll() { - mChildHelper.stopNestedScroll(); - } - - @Override public boolean hasNestedScrollingParent() { - return mChildHelper.hasNestedScrollingParent(); - } - - @Override public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, - int[] offsetInWindow) { - return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); - } - - @Override public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { - return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); - } - - @Override public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { - return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); - } - - @Override public boolean dispatchNestedPreFling(float velocityX, float velocityY) { - return mChildHelper.dispatchNestedPreFling(velocityX, velocityY); - } - - - -} - diff --git a/app/src/main/java/com/prettifier/pretty/PrettifyWebView.java b/app/src/main/java/com/prettifier/pretty/PrettifyWebView.java deleted file mode 100644 index bcfe5c554..000000000 --- a/app/src/main/java/com/prettifier/pretty/PrettifyWebView.java +++ /dev/null @@ -1,269 +0,0 @@ -package com.prettifier.pretty; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.res.TypedArray; -import android.net.Uri; -import android.os.Build; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.webkit.WebChromeClient; -import android.webkit.WebResourceRequest; -import android.webkit.WebSettings; -import android.webkit.WebView; -import android.webkit.WebViewClient; - -import com.fastaccess.R; -import com.fastaccess.helper.AppHelper; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.Logger; -import com.fastaccess.helper.ViewHelper; -import com.fastaccess.provider.markdown.MarkDownProvider; -import com.fastaccess.provider.scheme.SchemeParser; -import com.fastaccess.ui.modules.code.CodeViewerActivity; -import com.prettifier.pretty.callback.MarkDownInterceptorInterface; -import com.prettifier.pretty.helper.GithubHelper; -import com.prettifier.pretty.helper.PrettifyHelper; - - -public class PrettifyWebView extends NestedWebView { - private OnContentChangedListener onContentChangedListener; - private boolean interceptTouch; - private boolean enableNestedScrolling; - - public interface OnContentChangedListener { - void onContentChanged(int progress); - - void onScrollChanged(boolean reachedTop, int scroll); - } - - public PrettifyWebView(Context context) { - super(context); - if (isInEditMode()) return; - initView(null); - } - - public PrettifyWebView(Context context, AttributeSet attrs) { - super(context, attrs); - initView(attrs); - } - - public PrettifyWebView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initView(attrs); - } - - @Override public boolean onInterceptTouchEvent(MotionEvent p) { - return true; - } - - @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { - if (getParent() != null) { - getParent().requestDisallowInterceptTouchEvent(interceptTouch); - } - return super.onTouchEvent(event); - } - - @SuppressLint("SetJavaScriptEnabled") private void initView(@Nullable AttributeSet attrs) { - if (isInEditMode()) return; - if (attrs != null) { - TypedArray tp = getContext().obtainStyledAttributes(attrs, R.styleable.PrettifyWebView); - try { - int color = tp.getColor(R.styleable.PrettifyWebView_webview_background, ViewHelper.getWindowBackground(getContext())); - setBackgroundColor(color); - } finally { - tp.recycle(); - } - } - setWebChromeClient(new ChromeClient()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - setWebViewClient(new WebClient()); - } else { - setWebViewClient(new WebClientCompat()); - } - WebSettings settings = getSettings(); - settings.setJavaScriptEnabled(true); - settings.setAppCachePath(getContext().getCacheDir().getPath()); - settings.setAppCacheEnabled(true); - settings.setCacheMode(WebSettings.LOAD_NO_CACHE); - settings.setDefaultTextEncodingName("utf-8"); - settings.setLoadsImagesAutomatically(true); - settings.setBlockNetworkImage(false); - setOnLongClickListener((view) -> { - WebView.HitTestResult result = getHitTestResult(); - if (hitLinkResult(result) && !InputHelper.isEmpty(result.getExtra())) { - AppHelper.copyToClipboard(getContext(), result.getExtra()); - return true; - } - return false; - }); - } - - @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { - super.onScrollChanged(l, t, oldl, oldt); - if (onContentChangedListener != null) { - onContentChangedListener.onScrollChanged(t == 0, t); - } - } - - @Override protected void onDetachedFromWindow() { - onContentChangedListener = null; - super.onDetachedFromWindow(); - } - - private boolean hitLinkResult(WebView.HitTestResult result) { - return result.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE || result.getType() == HitTestResult.IMAGE_TYPE || - result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE; - } - - public void setOnContentChangedListener(@NonNull OnContentChangedListener onContentChangedListener) { - this.onContentChangedListener = onContentChangedListener; - } - - public void setThemeSource(@NonNull String source, @Nullable String theme) { - if (!InputHelper.isEmpty(source)) { - WebSettings settings = getSettings(); - settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING); - setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); - settings.setSupportZoom(true); - settings.setBuiltInZoomControls(true); - settings.setDisplayZoomControls(false); - String page = PrettifyHelper.generateContent(source, theme); - loadCode(page); - } - } - - public void setSource(@NonNull String source, boolean wrap) { - if (!InputHelper.isEmpty(source)) { - WebSettings settings = getSettings(); - settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING); - setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); - settings.setSupportZoom(!wrap); - settings.setBuiltInZoomControls(!wrap); - if (!wrap) settings.setDisplayZoomControls(false); - String page = PrettifyHelper.generateContent(source, AppHelper.isNightMode(getResources()), wrap); - loadCode(page); - } - } - - private void loadCode(String page) { - post(() -> loadDataWithBaseURL("file:///android_asset/highlight/", page, "text/html", "utf-8", null)); - } - - public void scrollToLine(@NonNull String url) { - String[] lineNo = getLineNo(url); - if (lineNo != null && lineNo.length > 1) { - loadUrl("javascript:scrollToLineNumber('" + lineNo[0] + "', '" + lineNo[1] + "')"); - } else if (lineNo != null) { - loadUrl("javascript:scrollToLineNumber('" + lineNo[0] + "', '0')"); - } - } - - public static String[] getLineNo(@Nullable String url) { - String lineNo[] = null; - if (url != null) { - try { - Uri uri = Uri.parse(url); - String lineNumber = uri.getEncodedFragment(); - if (lineNumber != null) { - lineNo = lineNumber.replaceAll("L", "").split("-"); - } - } catch (Exception ignored) {} - } - return lineNo; - } - - public void setGithubContentWithReplace(@NonNull String source, @Nullable String baseUrl, boolean replace) { - setGithubContent(source, baseUrl, false); - addJavascriptInterface(new MarkDownInterceptorInterface(this, false), "Android"); - String page = GithubHelper.generateContent(getContext(), source, baseUrl, AppHelper.isNightMode(getResources()), false, replace); - post(() -> loadDataWithBaseURL("file:///android_asset/md/", page, "text/html", "utf-8", null)); - } - - public void setGithubContent(@NonNull String source, @Nullable String baseUrl, boolean toggleNestScrolling) { - setGithubContent(source, baseUrl, toggleNestScrolling, true); - } - - public void setWikiContent(@NonNull String source, @Nullable String baseUrl) { - addJavascriptInterface(new MarkDownInterceptorInterface(this, true), "Android"); - String page = GithubHelper.generateContent(getContext(), source, baseUrl, AppHelper.isNightMode(getResources()), AppHelper.isNightMode - (getResources()), true); - post(() -> loadDataWithBaseURL("file:///android_asset/md/", page, "text/html", "utf-8", null)); - } - - public void setGithubContent(@NonNull String source, @Nullable String baseUrl, boolean toggleNestScrolling, boolean enableBridge) { - if (enableBridge) addJavascriptInterface(new MarkDownInterceptorInterface(this, toggleNestScrolling), "Android"); - String page = GithubHelper.generateContent(getContext(), source, baseUrl, AppHelper.isNightMode(getResources()), - AppHelper.isNightMode(getResources()), false); - post(() -> loadDataWithBaseURL("file:///android_asset/md/", page, "text/html", "utf-8", null)); - } - - public void loadImage(@NonNull String url, boolean isSvg) { - WebSettings settings = getSettings(); - settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); - setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); - settings.setSupportZoom(true); - settings.setBuiltInZoomControls(true); - settings.setDisplayZoomControls(false); - String html; - if (isSvg) { - html = url; - } else { - html = "" + - ""; - } - Logger.e(html); - loadData(html, "text/html", null); - } - - public void setInterceptTouch(boolean interceptTouch) { - this.interceptTouch = interceptTouch; - } - - public void setEnableNestedScrolling(boolean enableNestedScrolling) { - if (this.enableNestedScrolling != enableNestedScrolling) { - setNestedScrollingEnabled(enableNestedScrolling); - this.enableNestedScrolling = enableNestedScrolling; - } - } - - private void startActivity(@Nullable Uri url) { - if (url == null) return; - if (MarkDownProvider.isImage(url.toString())) { - CodeViewerActivity.startActivity(getContext(), url.toString(), url.toString()); - } else { - String lastSegment = url.getEncodedFragment(); - if (lastSegment != null || url.toString().startsWith("#") || url.toString().indexOf('#') != -1) { - return; - } - SchemeParser.launchUri(getContext(), url, true); - } - } - - private class ChromeClient extends WebChromeClient { - @Override public void onProgressChanged(WebView view, int progress) { - super.onProgressChanged(view, progress); - if (onContentChangedListener != null) { - onContentChangedListener.onContentChanged(progress); - } - } - } - - private class WebClient extends WebViewClient { - @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { - startActivity(request.getUrl()); - return true; - } - } - - private class WebClientCompat extends WebViewClient { - @SuppressWarnings("deprecation") @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { - startActivity(Uri.parse(url)); - return true; - } - - } -} \ No newline at end of file diff --git a/app/src/main/java/com/prettifier/pretty/callback/MarkDownInterceptorInterface.java b/app/src/main/java/com/prettifier/pretty/callback/MarkDownInterceptorInterface.java deleted file mode 100644 index 3a4f00f65..000000000 --- a/app/src/main/java/com/prettifier/pretty/callback/MarkDownInterceptorInterface.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.prettifier.pretty.callback; - -import android.webkit.JavascriptInterface; - -import com.prettifier.pretty.PrettifyWebView; - -/** - * Created by Kosh on 13 Dec 2016, 3:01 PM - */ - -public class MarkDownInterceptorInterface { - private PrettifyWebView prettifyWebView; - private boolean toggleNestScrolling; - - public MarkDownInterceptorInterface(PrettifyWebView prettifyWebView) { - this(prettifyWebView, false); - } - - public MarkDownInterceptorInterface(PrettifyWebView prettifyWebView, boolean toggleNestScrolling) { - this.prettifyWebView = prettifyWebView; - this.toggleNestScrolling = toggleNestScrolling; - } - - @JavascriptInterface public void startIntercept() { - if (prettifyWebView != null) { - prettifyWebView.setInterceptTouch(true); - if (toggleNestScrolling) prettifyWebView.setEnableNestedScrolling(false); - } - } - - @JavascriptInterface public void stopIntercept() { - if (prettifyWebView != null) { - prettifyWebView.setInterceptTouch(false); - if (toggleNestScrolling) prettifyWebView.setEnableNestedScrolling(true); - } - } -} diff --git a/app/src/main/java/com/prettifier/pretty/helper/CodeThemesHelper.java b/app/src/main/java/com/prettifier/pretty/helper/CodeThemesHelper.java deleted file mode 100644 index f00c3cc6c..000000000 --- a/app/src/main/java/com/prettifier/pretty/helper/CodeThemesHelper.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.prettifier.pretty.helper; - -import android.support.annotation.NonNull; - -import com.annimon.stream.Stream; -import com.fastaccess.App; -import com.fastaccess.helper.InputHelper; -import com.fastaccess.helper.PrefGetter; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; - -/** - * Created by Kosh on 21 Jun 2017, 1:44 PM - */ - -public class CodeThemesHelper { - - @NonNull public static List listThemes() { - try { - List list = Stream.of(App.getInstance().getAssets().list("highlight/styles/themes")) - .map(s -> "themes/" + s) - .toList(); - list.add(0, "prettify.css"); - list.add(1, "prettify_dark.css"); - return list; - } catch (IOException e) { - e.printStackTrace(); - } - return Collections.emptyList(); - } - - @NonNull public static String getTheme(boolean isDark) { - String theme = PrefGetter.getCodeTheme(); - if (InputHelper.isEmpty(theme) || !exists(theme)) { - return !isDark ? "prettify.css" : "prettify_dark.css"; - } - return theme; - } - - private static boolean exists(@NonNull String theme) { - return listThemes().contains(theme); - } - - - public static final String CODE_EXAMPLE = - "class ThemeCodeActivity : BaseActivity(), ThemeCodeMvp.View {\n" + - "\n" + - " val spinner: AppCompatSpinner by bindView(R.id.themesList)\n" + - " val webView: PrettifyWebView by bindView(R.id.webView)\n" + - " val progress: ProgressBar? by bindView(R.id.readmeLoader)\n" + - "\n" + - " override fun layout(): Int = R.layout.theme_code_layout\n" + - "\n" + - " override fun isTransparent(): Boolean = false\n" + - "\n" + - " override fun canBack(): Boolean = true\n" + - "\n" + - " override fun isSecured(): Boolean = false\n" + - "\n" + - " override fun providePresenter(): ThemeCodePresenter = ThemeCodePresenter()\n" + - "\n" + - " @OnClick(R.id.done) fun onSaveTheme() {\n" + - " val theme = spinner.selectedItem as String\n" + - " PrefGetter.setCodeTheme(theme)\n" + - " setResult(Activity.RESULT_OK)\n" + - " finish()\n" + - " }\n" + - "\n" + - " override fun onInitAdapter(list: List) {\n" + - " spinner.adapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, list)\n" + - " }\n" + - "\n" + - " @OnItemSelected(R.id.themesList) fun onItemSelect() {\n" + - " val theme = spinner.selectedItem as String\n" + - " webView.setThemeSource(CodeThemesHelper.CODE_EXAMPLE, theme)\n" + - " }\n" + - "\n" + - "\n" + - " override fun onCreate(savedInstanceState: Bundle?) {\n" + - " super.onCreate(savedInstanceState)\n" + - " progress?.visibility = View.VISIBLE\n" + - " webView.setOnContentChangedListener(this)\n" + - " title = \"\"\n" + - " presenter.onLoadThemes()\n" + - " }\n" + - "\n" + - " override fun onContentChanged(p: Int) {\n" + - " progress?.let {\n" + - " it.progress = p\n" + - " if (p == 100) it.visibility = View.GONE\n" + - " }\n" + - " }\n" + - "\n" + - " override fun onScrollChanged(reachedTop: Boolean, scroll: Int) {}\n" + - "}"; -} diff --git a/app/src/main/java/com/prettifier/pretty/helper/GithubHelper.java b/app/src/main/java/com/prettifier/pretty/helper/GithubHelper.java deleted file mode 100644 index 03cc2cb47..000000000 --- a/app/src/main/java/com/prettifier/pretty/helper/GithubHelper.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.prettifier.pretty.helper; - -import android.content.Context; -import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.fastaccess.data.dao.NameParser; -import com.fastaccess.helper.PrefGetter; -import com.fastaccess.helper.ViewHelper; - -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; - -import java.util.ArrayList; - -/** - * Created by Kosh on 25 Dec 2016, 9:12 PM - */ - -public class GithubHelper { - - @NonNull public static String generateContent(@NonNull Context context, @NonNull String source, - @Nullable String baseUrl, boolean dark, - boolean isWiki, boolean replace) { - if (baseUrl == null) { - return mergeContent(context, Jsoup.parse(source).html(), dark); - } else { - return mergeContent(context, parseReadme(source, baseUrl, isWiki), dark); - } - } - - @NonNull private static String parseReadme(@NonNull String source, @NonNull String baseUrl, boolean isWiki) { - NameParser nameParser = new NameParser(baseUrl); - String owner = nameParser.getUsername(); - String repoName = nameParser.getName(); - Uri uri = Uri.parse(baseUrl); - ArrayList paths = new ArrayList<>(uri.getPathSegments()); - StringBuilder builder = new StringBuilder(); - builder.append(owner).append("/").append(repoName).append("/"); - boolean containsMaster = paths.size() > 3; - if (!containsMaster) { - builder.append("master/"); - } else { - paths.remove("blob"); - } - paths.remove(owner); - paths.remove(repoName); - for (String path : paths) { - if (!path.equalsIgnoreCase(uri.getLastPathSegment())) { - builder.append(path).append("/"); - } - } - String baseLinkUrl = !isWiki ? getLinkBaseUrl(baseUrl) : baseUrl; - return getParsedHtml(source, owner, repoName, !isWiki ? builder.toString() : baseUrl, baseLinkUrl, isWiki); - } - - @NonNull private static String getParsedHtml(@NonNull String source, String owner, String repoName, - String builder, String baseLinkUrl, boolean isWiki) { - Document document = Jsoup.parse(source, ""); - Elements imageElements = document.getElementsByTag("img"); - if (imageElements != null && !imageElements.isEmpty()) { - for (Element element : imageElements) { - String src = element.attr("src"); - if (src != null && !(src.startsWith("http://") || src.startsWith("https://"))) { - String finalSrc; - if (src.startsWith("/" + owner + "/" + repoName)) { - finalSrc = "https://raw.githubusercontent.com/" + src; - } else { - finalSrc = "https://raw.githubusercontent.com/" + builder + src; - } - element.attr("src", finalSrc); - } - } - } - Elements linkElements = document.getElementsByTag("a"); - if (linkElements != null && !linkElements.isEmpty()) { - for (Element element : linkElements) { - String href = element.attr("href"); - if (href.startsWith("#") || href.startsWith("http://") || href.startsWith("https://") || href.startsWith("mailto:")) { - continue; - } - element.attr("href", baseLinkUrl + (isWiki && href.startsWith("wiki") - ? href.replaceFirst("wiki", "") : href)); - } - } - return document.html(); - } - - @NonNull private static String getLinkBaseUrl(@NonNull String baseUrl) { - NameParser nameParser = new NameParser(baseUrl); - String owner = nameParser.getUsername(); - String repoName = nameParser.getName(); - Uri uri = Uri.parse(baseUrl); - ArrayList paths = new ArrayList<>(uri.getPathSegments()); - StringBuilder builder = new StringBuilder(); - builder.append("https://").append(uri.getAuthority()).append("/").append(owner).append("/").append(repoName).append("/"); - boolean containsMaster = paths.size() > 3 && paths.get(2).equalsIgnoreCase("blob"); - if (!containsMaster) { - builder.append("blob/master/"); - } - paths.remove(owner); - paths.remove(repoName); - for (String path : paths) { - if (!path.equalsIgnoreCase(uri.getLastPathSegment())) { - builder.append(path).append("/"); - } - } - return builder.toString(); - } - - @NonNull private static String mergeContent(@NonNull Context context, @NonNull String source, boolean dark) { - return "\n" + - "\n" + - "\n" + - " \n" + - " " + - " \n" + - "\n" + getCodeStyle(context, dark) + "\n" + - " \n" + - "\n" + - "\n" + - "\n" + source + - "\n\n" + - "\n" + - "\n" + - "\n"; - } - - @NonNull private static String getStyle(boolean dark) { - return dark ? "./github_dark.css" : "./github.css"; - } - - @NonNull private static String getCodeStyle(@NonNull Context context, boolean isDark) { - if (!isDark) return ""; - String primaryColor = getCodeBackgroundColor(context); - String accentColor = "#" + Integer.toHexString(ViewHelper.getAccentColor(context)).substring(2).toUpperCase(); - return ""; - } - - @NonNull private static String getCodeBackgroundColor(@NonNull Context context) { - @PrefGetter.ThemeType int themeType = PrefGetter.getThemeType(); - if (themeType == PrefGetter.BLUISH) { - return "#" + Integer.toHexString(ViewHelper.getPrimaryDarkColor(context)).substring(2).toUpperCase(); - } - return "#" + Integer.toHexString(ViewHelper.getPrimaryColor(context)).substring(2).toUpperCase(); - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/prettifier/pretty/helper/PrettifyHelper.java b/app/src/main/java/com/prettifier/pretty/helper/PrettifyHelper.java deleted file mode 100644 index 7f3087f31..000000000 --- a/app/src/main/java/com/prettifier/pretty/helper/PrettifyHelper.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.prettifier.pretty.helper; - -import android.support.annotation.NonNull; - -/** - * Created by Kosh on 25 Dec 2016, 9:12 PM - */ - -public class PrettifyHelper { - - @NonNull private static String getHtmlContent(@NonNull String css, @NonNull String text, boolean wrap, boolean isDark) { - return "\n" + - "\n" + - "\n" + - " \n" + - " \n" + - "" + (!wrap ? "\n" : "") + "" + - LINE_NO_CSS + "\n" + - " " + (wrap ? WRAPPED_STYLE : "") + "\n" + - "\n" + - "\n" + - "\n" + - "\n" + - "

    " + text + "
    \n" + - "\n" + - "\n" + - "\n" + - ""; - } - - @NonNull private static final String WRAPPED_STYLE = - ""; - - private static final String LINE_NO_CSS = ""; - - @NonNull public static String generateContent(@NonNull String source, String theme) { - return getHtmlContent(theme, getFormattedSource(source), false, false); - } - - @NonNull public static String generateContent(@NonNull String source, boolean isDark, boolean wrap) { - return getHtmlContent(getStyle(isDark), getFormattedSource(source), wrap, isDark); - } - - @NonNull private static String getFormattedSource(@NonNull String source) { - return source.replaceAll("<", "<") - .replaceAll(">", ">"); - } - - @NonNull private static String getStyle(boolean isDark) { - return CodeThemesHelper.getTheme(isDark); - } - - private static boolean textTooLarge(@NonNull String text) { - return text.length() > 304800;//>roughly 300kb ? disable highlighting to avoid crash. - } - -} diff --git a/app/src/main/java/com/zzhoujay/markdown/style/CodeSpan.java b/app/src/main/java/com/zzhoujay/markdown/style/CodeSpan.java deleted file mode 100644 index e12b9f34f..000000000 --- a/app/src/main/java/com/zzhoujay/markdown/style/CodeSpan.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.zzhoujay.markdown.style; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.GradientDrawable; -import android.text.style.ReplacementSpan; - -/** - * Created by zhou on 16-7-2. - * 代码Span - */ -public class CodeSpan extends ReplacementSpan { - - private float radius = 10; - - private Drawable drawable; - private float padding; - private int width; - private int textColor; - - public CodeSpan(int color) { - GradientDrawable d = new GradientDrawable(); - d.setColor(color); - d.setCornerRadius(radius); - drawable = d; - } - - public CodeSpan(int color, int textColor, float radius) { - this.radius = radius; - this.textColor = textColor; - GradientDrawable d = new GradientDrawable(); - d.setColor(color); - d.setCornerRadius(radius); - drawable = d; - } - - @Override public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { - padding = paint.measureText("t"); - width = (int) (paint.measureText(text, start, end) + padding * 2); - return width; - } - - @Override public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { - drawable.setBounds((int) x, top, (int) x + width, bottom); - drawable.draw(canvas); - if (textColor != 0) { - paint.setColor(textColor); - } - canvas.drawText(text, start, end, x + padding, y, paint); - } - -} diff --git a/app/src/main/java/com/zzhoujay/markdown/style/FontSpan.java b/app/src/main/java/com/zzhoujay/markdown/style/FontSpan.java deleted file mode 100644 index aeff93a8d..000000000 --- a/app/src/main/java/com/zzhoujay/markdown/style/FontSpan.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.zzhoujay.markdown.style; - -import android.annotation.SuppressLint; -import android.text.ParcelableSpan; -import android.text.TextPaint; -import android.text.style.StyleSpan; - -/** - * Created by zhou on 2016/11/10. - * FontSpan - */ -@SuppressLint("ParcelCreator") -public class FontSpan extends StyleSpan implements ParcelableSpan { - - private final float size; - private final int color; - - public FontSpan(float size, int style) { - super(style); - this.size = size; - this.color = -1; - } - - public FontSpan(float size, int style, int color) { - super(style); - this.size = size; - this.color = color; - } - - @Override - public void updateMeasureState(TextPaint p) { - super.updateMeasureState(p); - p.setTextSize(p.getTextSize() * size); - } - - @Override - public void updateDrawState(TextPaint tp) { - super.updateDrawState(tp); - updateMeasureState(tp); - if (color != -1) tp.setColor(color); - } -} diff --git a/app/src/main/java/com/zzhoujay/markdown/style/LinkSpan.java b/app/src/main/java/com/zzhoujay/markdown/style/LinkSpan.java deleted file mode 100644 index 056090c94..000000000 --- a/app/src/main/java/com/zzhoujay/markdown/style/LinkSpan.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.zzhoujay.markdown.style; - -import android.text.TextPaint; -import android.text.style.URLSpan; - -/** - * Created by zhou on 16-7-2. - * 链接Span - */ -public class LinkSpan extends URLSpan { - - private int color; - - public LinkSpan(String url, int color) { - super(url); - this.color = color; - } - - @Override - public void updateDrawState(TextPaint ds) { - super.updateDrawState(ds); - ds.setColor(color); - ds.setUnderlineText(false); - } - -} diff --git a/app/src/main/java/com/zzhoujay/markdown/style/MarkDownQuoteSpan.java b/app/src/main/java/com/zzhoujay/markdown/style/MarkDownQuoteSpan.java deleted file mode 100644 index bf2275247..000000000 --- a/app/src/main/java/com/zzhoujay/markdown/style/MarkDownQuoteSpan.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.zzhoujay.markdown.style; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.text.Layout; -import android.text.style.QuoteSpan; - -/** - * Created by zhou on 16-6-25. - * 引用Span - */ -public class MarkDownQuoteSpan extends QuoteSpan { - - private static final int STRIPE_WIDTH = 15; - private static final int GAP_WIDTH = 40; - - public MarkDownQuoteSpan() { - super(); - } - - public MarkDownQuoteSpan(int color) { - super(color); - } - - @Override - public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, - boolean first, Layout layout) { - Paint.Style style = p.getStyle(); - int color = p.getColor(); - p.setStyle(Paint.Style.FILL); - p.setColor(getColor()); - c.drawRect(x, top, x + dir * STRIPE_WIDTH, bottom, p); - p.setStyle(style); - p.setColor(color); - } - - @Override public int getLeadingMargin(boolean first) { - return STRIPE_WIDTH + GAP_WIDTH; - } - -} diff --git a/app/src/main/res/color/search_tab_highlighter.xml b/app/src/main/res/color/search_tab_highlighter.xml deleted file mode 100644 index 9bd12757b..000000000 --- a/app/src/main/res/color/search_tab_highlighter.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-nodpi/web_hi_res_512.png b/app/src/main/res/drawable-nodpi/web_hi_res_512.png deleted file mode 100755 index fcb3043a6bd4d4e7812b186caf47c56562308a71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 121788 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

    _}Y~!z* z?-cyB-foB<>LpXOz$yYRrr~o?*Cl!1#?KXFe&x$W%{gLLWdSItA7e_JFFMdgIBS_c z=ZQ_1Nk-l`UzBVAd#LX|xt(7ndhK(C*SGGH5(QSuz|W4jg&_J0ezHN^{RrPAK6cF`0_;rhfrz8Kxx{6QU+xwDW9iF;R(3wcLA9~j5f;7sDAUtz)>$Jr> zv=G`_dN|+FR(O+k#L zriJb&hR>%q`)u++t7|5%25-h(b4`n(c-r74beF?doWOBmAE+kf)qx07-g_T#^c(m? zrU!D%o4eoxQ6TFAv-2L#*2HC16NxHxlznHx?u}skXZ9#KA3{X&ID>;bl-H-Jgs2FF z+MA{ELuMyxjGifM{b0Yn~R|P z4ENu3*8K5H+VxH6ptAUTSN&|@=v?@)Jz+=suXuCDo27rxIR;N_C?ml=o<@xQ4IVh% z*#TX-(yS{0Mip|NKDuDJa+BYkyz6LT*!SD>tvR=_Tkm%W0;lRQi*eW$ z?=lduB+rD9r-tb6m9x3df2Q7c-zDihG0u?bCSE*B zoRX}$@Xl9(=XFw?6l08#PdfbROc!0~xS%h)mOEr{a(pubHyP!msTIgZW{7f;b5nUM>wC#T+<<_={5pS9B z^Z_vdPN0jAOD(W}#<1Dt?2Ob6Yn-IIltXe0F@p=c=~qpm^fH`_*0L43J%yc+6Sb_P zmmyEor0Ft<541wT92_TCEOj=P&av=79aD(joAI4>#=nYIJ9)}l3GY}ri*5cG7gH?w z=FiAiGz||(CfK=4O}4I9@1NHo@}?U5V&=qogBJ&cJS}1=X`)Zu6i(Pnkzpmq81O&qYxI zqFu7o7jM8zrM#^xT$K^>R0BWsYQOa-IUvP5Crwn?piWuL9|-^}`sW-C4#-v17w1Os z&+RM^I~q7zqXyBunU2lEm<;j;aN^6vlT-3f;TIO*0O=JGse;J^;FP&UXYpvq*qqZH zb0tHDvHcoZMh0RT=br8jkGq@zN{}GYEAuDr=W^J*XLBR<_YuCWR>Cw(OL~#zd9+)K z)>`KneH)e-SmUXO@6%2-a|PJqe}2B6ro7+D(e#?^a#Kb&9f6`rd8x0yGDt}7;&$?) zcA1>vjV}?Ku6f?x0qAlu?VuF)`H#oVu_WnpSXxO^0-EMHYI4LBJofAEBv*8b-mJ$t ze2oEMQ@6RjQ{@Q}%@q8d-=D;|`AUMS_&7ACm$s?p;k7yRcR z<3W=%gcvp&s0UWiZg$aWuOOc~6c$Mu>0=Ku?s*aLIT| zX_c0@8KiZU81ecps+*LfLg&1ZU8dURTmY1V(q1NixJ&`~z%p-7hlkIJ&O*baLANZ5 z=-PGy^N$uJQ{UNCb3--7{@|*{$+qyzN{9v1G#>yRC(dq}g-ate!+lS%SI90{a(rea zG*(rtOTSw^8`XcGBOCMOE-~U%-|TJK_Lu3&zxaQ&T|vObNW{PFkdili95N(A%Sx6v zgSrRIGQe}fbmbRvPqSl(($bJp(LSomvxCO;!K=;|Jni7XY`MZv@>!Xil zJIYc${nK=NxDCx|;4~0A4r#Cz@dTsp0R#0_|CXvp%N!=*>Te3q(;4g!-i-#k7IEbG zt$BJ1ipo-GTu>Ffj3;e*k(%+u3g( zb+o0Ebxy|0#WI)G=gg6Q7fbA6-~AcGr!=yUgd$*5t`s$#R|ZavVWh*?>fHZkDBxgyTKMK zkf1_62E9^-+$ki~80^ERKs>=Jp1FQH4hP{eSaF|;%mIF(_pqLacn;NLH_?(-BZZ%< z&SEWQdWs^C_Tb&LhamrGK6XY_j$6EPA#^*?ytCA<&w4vZ6Kuv(wZO6DQ&v7Gz5xrK zavyA20vndUZSI~Qef0$F$diy;wM0E%Se>Uzfo4V*KGz>+wFaR3%^vu|6?ZQ|R(?M> zL0vxyk}DQy>DY4_hB>@W)<*Ujd6PNgI(`O;%fdUqRv+HXC~hHn)+lb3GO)>^&{s3= zQDIdxj(4==c2=KwEosind&ni62>FQJO-NEJn={CW$y)y~tx2;#X%TZqktw{s+L-C^O zHt1p8*?D&oRbLIXfLBzadlRkkjSqOGkDraM8~ympl#{G$>)dNByoyf@--%6c%ym8y zuNq1iNW_C_ANjEe^Uh0^bO>G7e1e@-^Q+T#zK;U->%3#ODdicm;AJ?>qAIfr?0U>w z8C=0Oh$f>9FJa6Uk*q#t%IQ7GX{d_i6lI(&i+g%MQyH;4imZgg`ebN;mx@0Vor6`D zKrneLX^Z&zv+&l_?eVUl;0X5#=(;TtTy|@WCDc6tivo~?P{m&M^ACoQt-5r}0V77q zd*VMU~{4%l9jjX0D`l4PI;-Bo8FRNw*&=u^tN_*DYM=^`ACBvL-9WQozDmvz^~imVDKDfq)so9N})80gHc z71h_%e2}8JshCAjkZCPwTaD&afL~|f=ub6&InQLO-xL1)$zz=!!%SxLY186^=G2_8 zo1CxQ?-phTjk~GS=0uh}yKeX~HepMk{xQdXYXMDlsQSc4+Yx|hpkr<;ib-vXGg2V} zMHiWR9q=tQ#skgPkm8n2mS5fsU}Xu zvGG4u`!bcP71B?C`{e{`tFLj4UL{J;?OVO@vPKxQ6)al|?DLeQkyDph&74+WL+G{Y zpJ)=&4W0_5U?mcXvBmx>wgqN92ihu=PgXwU40*{qLqw1GK&7s!duTaJGfK%Ty z_H%ukoI+X$w*TZ;n%(+vz?D5aiZh<9m8xF?ey?_3WAkLUE{ijvubNJ%-ZvQU(}X|% zP|owod&9&WQzTeQ@O_GDwF=JxK9Td!c2)YJVpA?GL&%j<{*kyA_YcIKQ2Q&=_7 zF7x8r=2!eo7|Xt>lqJ2w`wx{otig_*8@%a#-gp0xbMr=j&J)5I3N!{m&JIFoExUKg zPM>R_;lr`0@eCPyzRwl-&r&d=_c{O++2tlb03~pO3v??XB|5ZhHikM zxn>zq!W)6>nf`wdx7pRfD+IqsEJ!FMN;=Hk>jcpYKwF=$v{>f_j-WEzCPm-rvX#%Y zal_8ufVldEHprX*inQWTerRi9?G%Mm)Pyxk<`^Wx1h~mJVIP^-~{aXV_7QF zP^5|yMQw)=D%n=Kg`@Tv^Gsb7RDQ`5mCKR^D^O`;I!moeFu7nOORo;HXbt9Q>MY#Ce3fH8wg71Lbi?j!La-?i2E!Tlw z+__`M_tt73Y~5&Q$-t?6_*L03?Z8kPUeK8v@^ad%CR|ciAgU2zYp!Fye^jVLp!%d% zAKbDI>{93(q;=guY%GyeL>nWJmd4ef$CsUYDlQtuGhJQte~P$b93I2DF%t8w9D>{> z_bwfWJ&WwEUE$c}@rh>-kZ#vlj(}lFFl-e9RFNBV)2=o)CDQbUH6c5{fk;_T)eVed zAL3Ipu#<3=q?P0DfiA3VHqBvfjAE}pjr6h--cu=m_?zxb)rcBI*J*F0a?S5g5cJcP zUePmgAO6`(poR7(iJKO+b3PR`QY5cck3A)E{lTal{l#6-)gyWP%8*_^#(6gCmXW;u zAD@Da3<5ipjUTAf|1vpmXsZT89k$+x!FJ{{>p$)kn+$(1OL~+{w~?h6lgvQ%b!%vk z4%i$oh2CWCr1peP!J-GxF}}ZGZlnee#evfb$lU$=u7YP%(Zbw2*838j9o(lBeaK{Z zDyh6x8%-^5V{$vfw<%Rz@=V=|SUONzq>-xafoOw)!vbdmbz+^FLv>ji^G9UCVjCCb z{IgI%dY^~=l9#Oana zE!qT8sQr8JQ*$)y&hKA9Yt18fD3EmJu_qe+-=casYA5oe?;<9%>CW-;&B91FUpFoxfJk~%Z! z8y?t+9oI@ejEr3}12N-@&frB5T(i~6XldtR2MWa?`BsbJCJ>|m9F7;2j(pj=1oadQ zCOLeWUUOI(G8O-BPE>#qcO=Mg<;zc|s7uNY<(z`^NC2t8%pXxr@i=_TG>7FK4%c#= zcRJ)2P6WOe-|YQt%W+VjyMe7TE!6YfdI8WeA27h4`Suh zdIf_cn7wqeg6J`WTU)9xwM`4Cg#foFI^aWpv5|a#_k+S9-7P9enTw%NI4c<}7K~}2 zJ$ez?r=pCcrT|o!w*Tncg&MQD2C*TDuvAI-P#zd0n;+slrczse`|dWh=>nM`;@vvu z!~(+14}bO+Vr63(C`jcZkVAw<34JSd&9KAxPpb^{{BIn=!h9u0gEl zwm{XH!lp{>{h0GwAjOS(l9e1;V8mSt&E`<@GZrH)$XltQmwwPS^|rTY*3AH!p~6K) z2~m@4HyT$C{tb@aUO%WtN{YLDBw3EK9`(SVlN^138%?wOe=pSsymNN$>O-7K13CQW z*nQ;_Ip{$T*!$HA+?Pd%=VM8rsnf2Xi60nt@vd&d(}g``o+l(%I<@asX!j3zNNeV5 z06mR>i!U^fL<6OMOxF=oas}3d2FS$8iVs6zQK{-myo=(jKa@vc4D8Kz zmO|<_KAEp@b%dKysz%cLM6#hXOo@hu|_`X?oAyGl{>+!lw zK-p6P%wdxn6&q}gEMZqM4490VQ1BNp04sZGA#nwyI4-v4p zRKe!;RR0vqgU;}}MHOD#=}mWXJ!EHZ6m3n7^NiA5wM^gUUhRk3_Bmzn00iAfIt4*slVoD~7i`gJq9M}}(-R67{we=95=8<# zGik=qem3pot^(1|k@mG`C8g6|d?|U+a&x9B7VhDvf*6{By&D1V=D?OypzUM8QEan| zfmrxJB6fFHT8NU!FCEGKaCuY*%#obY+R$Bwb?b?cY%<7C`nK_H=jzPK z#JptBU0qZ(mvv$2MCGglEeo$8rFI~`W@b&!`00z@WV$uQ5NV?++_{>*%lGm`d2eD7E68F6OAE879iIpWYTE%K3Q%Slaf z^-0O^D-|qg+*E!l_c^<^6lMm@UJ9|o3gbb=;&Sjuf_1Y(TeN`o5KoT=xAnaZC4)eR zlga7=F&NY#xAoKP9Wu#1jvcl$vg3_ivbWVHiRuWIUe@Xl^Hltg2Y(~O8h_Tmlc>^kHFDWqXKwvr%Dd*`g z4nbLl)FaQJldhofGez_dnHu>GetsHP8M{>6Z=OcSC(|C(`>=Juj1&_evA^K5R*9He zAWMuzfHt$oaE`_j`_N6cu#IbPx5MeEOG8&PMn-zrNA()wXF!;E8I^hf`PB5STk014x4J`3RKs)rC@EtJ1d7 zS@$8h)PHd0#|<8ES0WV-f4%npI$|8P0+adQH=LUsnfu>rrqgMKEE@*r@2{q>l2&>K z8Mh6GCQ#BH711RNwhh>d8&g%?l3yNdrMz!*h0@5b(W~x!KhcVBQ4a(i&JE(+a=y+xfXrm|7DBp#*2)MU>ZfEv3;Jr(U z_-heJrBB|W zK4j}bcl41yrTfnI-%Q{?hOc2O>KvN^^Yfld6v{P*z5ytF2Io=Gf5J6^=+iOBa~wu; zLIzcheAGjDTL>u{p*@-!TZ`b8U<560SB$93u+o4ZSQ)H_!+AO4Um1 zpsl7jmmP>Q-W$#S9^~nD=FQjj2I5QAceh|Xjd%v8nm{Lxs^^_mMOJ(xFLQ-Th8w?* zh?i`jpAoHWDd|nB>kBP{=Dsu2U?fE3^N7wk8+TpU9?bbxNh6E1*d#`P5HDRLgS&jZ zLk}g>$FWdIjB!rbYXbRf8Kt?1lXuff<124{Ke3hs2JrQ26>TIUo_nn^37V((g)=>w zP6`zCXY7-(qm@lp35;owBa=Q0BJyA*HQu|8`r2u$xFekops|c2aC%ZSRYfx{se~7% z``3M0B%Pkux54;}!3Ffy#?{g`Pe7@N=)LZGuG0zv!yG*N z=`?yj(K#Vf;UU3^k=QBt`dn=YSGWSgM zX>NYJa5bF?)!;M6!0DP|rf?O1;b$zR#(9*KQ}O7UXKi*juu%kO`vKIozZ*O`x(|rZ zK5M!2P%oTBT7WJho7dW0aOTB4H$!X*U&=abRN79PF_VmC)EU3_~Rh$d*(#0d61G?GSU5AtYHKKW7 z66~~rC_G>E*o^8bF4hKcoHntatJ6L_xMl^R!m0!>P+n2igB9bYF6#9dv%5AX0_|ZO z!R6+L5x&F>H!sxh4Sbhy->OqKfFLyh&St7r)1A&QLS!obgzwC+FUaTymM_TF=o|Rm zLqvB8_3~4eY<|@&7W1A5El^dskTA08n&j9B{ZvGu?Sg{x( z!&<&rO1~tm+kTUS$(@IxD}yb-_IQOO1i8}1lT4iFp-B?HTglOhQl9*De{jVeE} zv|#xuruhU`$PCxe9kuz45lF%^x9=T^-m`t7>wyH*N$8%tT)U%O{ajBJ4(r4t}>!bTr7G>1?sYKWa>`}^g_>*#gpmVPu|D3xdp$B}(XZsL*3LL4!&bkDK#`b|fnKOF$$}Xy$@3}o3+pGLmv(J*&r@?=hR2@`YSkfR?fVp;J&V4c!1`}y~BJ|HK zy+;eboids2RH^YAj0_>e?6dE%dU5%U9nYR7Z!qU%5~Ad{2>a-UlDsFAe2ZX#d*^^1 zXlcBzcSJZX#?cxjy^*M*J|Rh+tyeL4(psXco3x}G>bW5g#*nMyk%MDM#j3R9gcchH zebodNzDsus>S1^O!JQE(|=p6Y^xUn8Nl0GBBCr2wM8 zXm>l3Oa_+<cyMBk56G8CaC7?Nxzun;&u(^{0tvk%uroioYEIKq zs?r~<>TmXe95$dgrtDa$66RKN#1gvdne!3YeRlcsLn7-atZrYp`L|iKGEv$bZ8V(F zATLPW0_R{Dci$TPJK|c$7>QE+JtjF`sanckP~%j1O6Mr(VY*;aYGa6MXO-;|hM5w$ zzXUng@8BU8@baQs_&xP#1fkwqtHpoJ9&s4jTR2$#+6**uJn)gh`v7!Owua<=cQxT= z4B+X#m$YCT@mq8~t#=#hKmZb&BD71%O%eWVNLK}EW{7j2$yl0~!{0CCgVON+(pSuG zZIN%G5c_?+_X6_KlxbQ%9~BF2@RdAAw8iE<7+qrBG{ruEg&k&mUL<6iGLeyGKT4l3eM> zC*b(bW?cKAwyoaPqv1(8dPcZ^O|ESiR<>&i-5k=qti&a*R#!3y;ftVUv0-48c6(#A zb?&>Li}0qDo^(>47+bSlN?VhNri&f5fPMd93&^k6pufnS3V$FP8=OV->bg7U|LF;R zQ3>5MWoI!p%7oAGUe;kel;R`N{DNiv?=v7p)aSm(U%sDLXXqykWg1~kk0kLJlQS@e zy^}o({L^AH?^w?dWMM)Viq*zBMg2ve$;dbwy>I#*R4t0@On6am_r7^x9fJ^&@Yv0h6tO%4IT+IKiInD)>sd@n{ZK6Zt#hh9h2~0+`;A!$>ozw)Xp8U4?anADafy_7O{hrz$ckybvQ}-zkTSM*Zs`N9ar2` zKrgAyRliggF$c@{LAdpLk80k|u>=bJv%26u*mX%7NX@M%`N5gP9DlOI$j`|4uCucu z<+-}p(*V-&_Z75T6ME?+?`f>_MlVw>0oxzyE!uQRQ$d(^|cPDQ#ZGWh~7ihd6vzC_8d8tt^T6!*8- zOobNMqokySEH=c1p1==bRgRm?a`o<4g+7x$*^p$-3*qMC!`=Fyw7uUH10Wk^_kE`d zg&Q-rC~d&2w@KV7+7gKi)2l)he$3zg8Wxfz!dj@U*rEmT5$l17|D7MjXBY4+_0ghz zho&?&TL|TIYaxfrVR{dsdQCaUDoT4-^+9qQOZRx(46)m$idioK>+P|H$Y(J>*_m4r^5v{Y*gQI|X| zJAyH9ZWA9SF^2cAaSZc`Jhzy%W2psF$v1J-piioC2I3a1@I6V{DYc3&5~_v_Tipdi ztI=vbh&QwFJD*v8ZKkRgRLCOzLcaFwZ~`0&7;k`(>jED&sIQP*kA`O8*ARg zXFj-&P1Ky8VV4N1F3=whvuPWW%dyCVTC-c~uInCRD)sivJY`D79sYC(Clivo~-< zO`;kkY{y@A)x-1M&{?=b!3$I6a@3GgeejzuDP%wSR3a59QG_Gdol^G{-1*q`otAEH ziC-S6rycX_l^R3J=j7KSp=QD9KmOzErXT$(4|e0kL3qc?7s!{9jf<4Z-plWt6e6M- zrF^Pf1&88HfeDE|Bzjup9-ByWW8!)o&L%}dBv%$eU0p85Uu+*2+%W|M(_Yg`+}rxl zvfOvrDWn$YyHYA%QgM8t4H=3@*`42iWv^^trc(1izlxnH#|OE#>%ak!*bOH-642hM z!EMlO1Q$;qE~O18X~bjo7%LESv=G^ST`aLx;`d$W?_@ZIO<@K*mB4Ms;aewax*^$X z0NuUh!LIhzC=t)k)s|l>!SO~d#1xEz+%v%{@0g;>#+audx?x7}nD@g;5== z>5twzdd^M+mT`*a%f|~9jTfS3RUo7Js8!}k<%iO7%GXVugAnfF?Av(KDt+>BNEYmE z2wun3=s8i`l>ok4sUU~&&k(SJxTtCX+rEKFtj>P05de^c#QwT7a_m5 z0xzF+v}r#Fm^anI3^PI*PbT`{6r;RzX5hzV;8|OB^>S!T?kmD|NZo64hgEYVblxBB z*bedbgB=an!R6X5S=eJ8rC9CoF6$f5!z3%Ehi9ug!0+YPMd~<|rnuLTR77Ch*(~AQ z(?C}yvT$~-*q4uWZ+a}qev4g83uT<&aQO*6J*$&nT6s4IT6A_=QYhcgl?}~!D@8M!9-$fAm1F0B z&=y`SpX+uP1anW#&aOR*Bu$hIacrt2sz(jP@n3ZWw;g7?FQka#oxD?#?Uu3#2ReUY zElzi1m|)6iXTb%$XX~7JQAuJd1yPpUP{~|jX_oYlMJwKDIF+RK5RL=hE3f^-0q!^6 zCEj!8ar|K3aNpw&&6WdZSZH1G#t#xHJ|=NqB(YUPqFBPDA8vofCa88}5f=DT*Qnw6 zy}R=F5U&T+N%58^gbtdgMBQ!Nvi6pA+o3bims+DXAGqt=AJQRBbP&c+8Rp^W*$HBj z-U=>$@+$6&8GZ&M|0!=c zO5!+&cjR(pE>iIGXb^PXOqTu>s`NmdZNbSimW)g!?sJHENhEXVAB%_kl4`~{O9V0J zu!?fM*yOsj&hl`Hff0&#A#8n>j_sa_${rFIPGOnksjHD?{od|;eB^PCAbKETju0%H zT@$~QzgDao)56Ja^G5XwtI?*aI+z%E zv+vOip{aL1OovE~JO<%iD5}Vbf+DrWP~1FiYevY|M7n;gZ(IFeul`M^j)+tf$6Tf^ zbzaeIpO4U^nvLl3cR-lB+Dv&p?h2GS*Tsp}yl)iP+`xiE^>nLPm5$19>E=nWsIv z`3~#!U%#N(&vX*R4uWDPjjOkbmpz4*)ost!p54OMIQ>5?Ix_u@<8_V5 zxMU2j+Rc78prDDk6}(TUXxW(!Aa4(m%bqI0_A{93q^qJP-l$#CzVBiyPjv~N_>v}3hHHJ zivP;dOK=RqxY}y)5zL%-rZ>F#the@0r#)y1`MdcH+5&ZHK($-e)H9!rYxaN?u%ICF zxKSkuL!#iz>(s$kpdT?~ErUI7W!BGQhla$VKe{G*F^Ri4bqjesA@?mNwXP-7KBO`D z3nqHBQR-YLxl4!leO#N9EW=y#3@T=wwqdBs61G+sruske{;^fvGWm<2MxIv@)CBa% z-@_ODW^9#s_Rc+SZ|6&Rsb<)Y6R2N4?pxVo22@0MWf@b6EpT;Vv;_cDrkf?k2xi@X zNJhKUJ5MWSusLjWC#xdnhmKzQVc=;>*-7G_{K9Gt6D-F(_WeD@#1@cdMJ`iaEOFyV zvM%38Xjf8xSCg7Oq}Tm^rL{Sf;1g}BlpL~FIfp%VHH9CaH-%ZHtI7=Hm(r9VSw17w zZQvbVvHw$N*rGUy-7)PdCbMAs@gOtzFZ0)0FVuRV^H=sZB+3j5Hl8gh z4t*}^ke*=8NngqQ`mjk+Kc`90Orj!l+DI1SdF6!P<>zETuEfT?L#XgFQQHFWMH4gg>y9WqGd+SK zmkUrut^z_ku^eC?Ng4zmE6lA=NDheZtyHtq>!eM~n&2ji{%X=@Q?A zJH@_d!jAb%l}obk80@`nmoBxd^>nW&JaD#VJ>p`3g#)Lw923~ZpZSYljLpXzAO@S{|=MqsqM?Ny%`qjQo7S2RFEmBt!c=` zFC}ljJ_J(wllqpql5|u-q%!mK_SD)e&=%rBq{}aiN9uW-b4%*Q+E%!)kw`VOKo(Vk z+o_25XSSQXjRST$23MO8z7s#+#CXo%-PX*}V&uM!yDnN70MVE9a>aVDeKDW?vx>K{ zN4`JVu2WaXEGHEaBgcpZ!|Dsq*wETYVQR%W#tu9|!X8$HneS#g>jIG=sfE90;X-1d=ad-&K;{+#_&lC#0F2oQ*SWENQ3a(*t^c#s=FW zkt=fG7O~4{1@3o-sm09Ww_H<`KOb7ma9Ad`#*He&nrW)n2lb}&C1X5R{H1e}qWcj@ zX#hN2-+*oF7-6jn!9$z8}vA(jY(YlA!5st*mMKgGtq^f*l zJ2?p3q4;ffQ|N)}!EVB_X9Gwh-nT z%nKp@jFL*@WG)mSwu145mwiYzjCToXz)vlaS$#r!M5{SeeI{U>I$+LYnWIVLfiUl< zb|FV+aDMQTOP}vs_onR2#2qf???XBV14-4hyeG z_4nSFEaGh+PR#n~i<$Tt#0Jri))C+NezLDHUKroY|9#L*%yf5k*$Sbo6u}xn!-}?0 znL)V*=GhLmSCo>#mp+9MWj+-(PjbdYXX%{!qHYGc4a`w}aIs1t}<*iSTN>o>}pq4+L7LU}ckb7in}p-Qk>Tw^An9;6L5_$Ka}_M4sE zmCiXX2jg;w+!H)l2rLk3yqAMT;`Lw-TU>qrvOFXdymN`WcbZ)=&%a=a^jsAuw#>i0TU?saq6#SagM0-QWEH3zPFIz@3s)m7<(rMgv zd7|!o2{73@Fv#Xu_d2}JXG%+qW`yBfYqU}ANVZ+(=Yhdjkp_vmxdZ3r+*Rm`r(q^P zAgLC@{oDstfCI(-IrOGq8_6Fcy8r!2`)41Nzr~+AFfOht6hC|fK231OJMRuYAbDq> zc#Fx1e4CP;O5q|Bt>|+aj>;?z|Lb)+$=YZSPmv|;`&f*XT+j6_W7-RFR8JbHK99Dw zU|L6~#UJqdb7FgR#XgrYYpe7-E%>fUWi(dkH?zB!ZQqE+u#c(Gf>2?4XVymMbr zx-Ol4jO6%kH+sb>Lw$MCQX3{(JXBs*%r3tCi2hL*w=0YM-a-+&(YjOQzx0|l`< zYJ$yOhY&ew!Gd`1EUkPriZ42m5c>83+@i}|jvtRd$^+A7{(G4TK~td$l4M@rwatrL z%yNX70R1XaFyZw~VILHqMlABL|E~EAlI;G}6p#`QpC<8et+EM%+5h0FAg^MenmM?@ z$XoXaMk|-B)kN_0-fa-^;Usjb#9k_0wg^vRNkQVLz$VrotGNcsfTwf|z|GqW4ys6D z-=#M)U~yYo2IavWXm3{>_g zfO5gU0hY#TbXe%cZ;|Ngr{g5Qsky5s4J&>K^)|*qB~hFh7Hg6uNpiKm*;LmO~2~r zDE`;r8M`<~6lxa61lW1NBro`BTq%v%U-ijhnY31@&z#Uyv4AaBWClmeIAj?J; z(fveT6ntMA8HX#bLwBFD?+CJqD2o^rnUqItzmc~0N*l`;a*t1C?tjMmKaS2j5bFPr zhuW~#d;6;T@YeNIc0LNvZPmFy8pW!z~|DiTHH6e1&M zJ2yVRcfWu9;U9c_?meEb=kxiPRL9nYy`bzC&T~1iwt%%(>{P`{#LrE$o@7h&?mcTP z`btaXj_4EDo8s$7a0`{P%9Xj{B*yr3xu^HVTOfn?oitW-n|d@c&PRlZi*`)M*lT%W zwXt`M=H!rhr671Gi9?meR=!Ch)ya5^9N65QDV0c1Y;|?_J~8&=*$?$cvwb7`U|XvT z@Q`5=7^JmZO~I~cU5|Sj0I&mc<|~eIiTKPqW$Ea-`Qka3KQ*yXJ34^xfvB zMFK+Mc^8hMl(*t87H0o@`7X}+Y&R5u4zxwEI=iRIlXv?JUz(w08y<5QFur-_rO&4FU@GSQnAM;Vt7mb z&}o$(Uq_z18joR~NL+P~pxO0q8s_&5yny{eot~qRxka*ap{KoHsM03y2E=rlvzkC< z!Y@U7b0;q$2zY=MQJR>`JyoWyX}tjwe$9LE`t#Zi&)nm1U6K^c%9GDu0gJCs&(kqw zIs#{~4duzeZd2w@*q?xi&po7QccpXaX}&HF>8JtCLPLBLg|@YNk*bDCJzrdG|4T^>^-k!fm`K<_g2Fxn(XdB^}E>I zxu7$aTyq4D`GA;mB3fL%Qa)m0S1$VS_Ujwe3^b_G3=Cd|JSe{$k(a0tmacTrY%uCf z6>Z|(2IA8+U9b}A-=;<1Ee}gA!4|ncj9GDj=Nn6e_W11kzRUC43LJ=r^1dHjV3Suv zRT2$VMU3LqK+p8$T$%&h>hb+^2<>i3%53cXd#UdM>AQ*KnTZLa`ocfW9pyPxob|#{ zv0rb4L;8XpMjOqA7rkosjaGV)=<-benf?Y+FgwBsn8OaEF_^qD14h6m88lDaUe9u* zS}j~5PTh1TN$Sy3+6tG5Gyi3Sl4X z4~v_}<`w>I!9V%Dtd}};+0TCu6z~O0rliw@aks$bJ;uDx`Lt}=>xhWR=B78}hvRGe zyXhpXhHkEWT3?g%AA7z6@o1A7&yytm3Gd{(X}d>mO3w61bMzMWZA0(!xNnY`F9S>h z73J|Len1APTQ5V0%c9^ApHU~(=%_bDI2^{)iMxQ6M0}mPT;~*hzeB7%-BcAqN)-6% z($St2nk-(DQt&WHv*YRKzMdLKj$bdDrU@>JHe`*tft&X>w9x8iEfhPDp?zM%pI*7J zJ&_$}HAAoULgxAO&dz1P=&cDekf6~*+YTc073n)jU_G1l{s=+mGAr4d87bMCI+8x- zExuP<9n8|L`mG%$x%ZUj037)=H)+xN0=R#KDE3PBp^4`6SIu{tlJY(HzSg=*6iEp#;8J&CWPYFp{RgIOXe(71are=+Y7(B!1ol4iDtt);mBDtCyz zj31FP6+riMhaPX80jTUv5J{l|^up5ryUC~3C)M5h+3lIPL_J3uvOyrj)BEQ+f?oPQ4`V@wjhp3)x>rn zR%Zj|OR9QOKz=hU^F+dpk*@RG^HP+B|0ra0%sg@KM~Jy|nxYJp3RlJ$PM)~k zQCTW%cyP%FFBFQ}&CCm|ICFTr9C;(LX_xFj3>Fr-hfH4@<&_wKNA1Wnr19NmHaNe7 zBqbIgBA?CL@!BEEZ9n3z1uI^)z;@t$`2gL7kmym5 zMJly1WKigCsK-}+6CeDr6VnrBT@0(Ic$01%O`J9Zezh+cVXs4)mx-M`aUgYBB3U+) zZiM$XrORwH&BcQ)&k0|0=6g! z)60c#j!km6onh&c8jqheT*~|RjP6fNdz7qdATn=Jf&OICLlzL3WsBeBsLSRc+elrz z5E320PE5xq$o&KKve~NznO*KGn+W^svBOmuC2w=odGTwHMf6RJXSdG57YoW0h|+8i z+57fhT)h#I8hcHc7X8Drzu!D%^iO_$OZy}F!n)v7!~NNE_1*wqrDIpuNMvk(9?M2p zq$8czZxh0(Uzmwj&IP}Vrp^#&yr%4V+`RN2@Myba$j)wo>TG-MgT=faSSkeFbZ_pE zisjjs*&#|JKc@4b&^l4D?Bk@g;3$bXcCb__v`Ge@dOgVWC}cmVKKPDxb2f{qOs4Cm z%+{wKE4Iw)VpLb&>TD|AnZ$nG1hIs#4=jXx;S=?-JaAWw3{vrvlL-%5*i|B3gbtc1*{=RIb#&%L; z_bnvR`FWLe)lJcxeB8I```^^&;n<7wrCfc)#iuuY!*MQzdDm0BYEOYrNLLQaF7P*N zQJ%C&>mBZTUCcjK#;V~)N8)b;eCp2fk)XwX;hdBp+Z*yeRTol5W!0xj2xrSZxoJUyG34uu9E-}!fA<``7+rHGhl>X_EKL#1iz$XQs<+e1AjGqN<^RbV* z`^Z#PP`uu_(;QmWHzsyXPwd%kfhDbz_R*K*;m75rL(2#EC4vmpqnEl-o}R3ZF?z29 z9<0L{O?U#=YgY6Ia|My9Ad6GC<$!Dj$p%Y0bLx=>4ED#rZ2a#{z}O}*R~JeANdpt% zDHD>P5Ek~zeN!SRR1WO z!Uu}rhIsX}tg0ITeawQ?P~Uq5lOW-{i`l|_pCLTa}Kq-r~cqlbO12% zbs{0obpnbB$e*q4;=l9)5wDM2JYcO_rwJVq!ZN^=!RC%ubm-we`ho!1qbA2A|4>rh z6}e=D47=#U@~>e?`9C0O4y$#NT z97TGOpX9+|+RYLfsoXqZDLEE_FLhAeYa$ouEYT4U#_d3=EZDz`(-p_0y)PJ#M~l1@ z#0NTQl93ZnT4!o2@zWoAxRicb_E@MH{Bhi4PGQH!_?f#ajXbi!^W5Xwb<;`Ip^`lD z{E^8hMKcI+3u*njPThusmfeuo=r_Jd@7mv{6_^NCHmY3efIg8ud9mN*;YtNIJ$(U; zgNx;Oc63;_lt?3S98AC}NyB;;5NM);`c{jSrqnQfsF!4}Bl+%C!z#_e-X2Q@@YIUL zqXLZ?^IXoXwjt-z93R9>o2kGeNT1oM ziFsKBYJ_GDpz$RGlr0JU#C}aOW(>~bMb7lMKV;I9w@Xh1&_4wHOvtOUynWnAQffG$ zGuu5WvUo>JIUs8(HqGf(U_o*I@bFIa6;et4Z><&M{G!>0l-bj4X{ajlWa_ljmxPU) zMQ+^RcFo6wB&C5?9&+@lyvEb#qV0zI_`Tz+^;BnCN8sr^<{C0zQT7*`P6eK1en-98 zewmy14XF9#E@X0NQShJoV5BE`QnX(2gbcIf0|@FNGVd1y<9sLB8yR5;Mqu>+A{DfX zwBf?EE)N{2UnS36jT!Yhsur_@f7Tz7f&I=((O+q9 z$;BW3CvYF!jVHrehchv2VJAehOxp2maI*6$Z9cL24*2NJjo&$uw9bMxq2-2K&#b)d zgM9+Vo}IeE&vP$fVk6^N@ZCGEQZx zjL#O%e+U-R48Nn=3wsRW>fgjO0qys>kfA5}SmGFdQ`M2_7T<26mriNCK1TBffs>X{ zR-1Muam?|5_15=Ep^q2NzG|186ASwu^&6!n1KjK4{ZZzt#Y^;T*C|Wn3A3-ZN$@ppe_Ma-2$IbE zps)k&8#!{QO?+qhfpd4kj91t5ToKi(!Dx7d3}Um)sGh)AW4WG-!@4J=Q`^k30EDj9 zXNGyAv+?!Hq3Ud^Jk951`k<7~?mi5<+YyLoRxN zo310=bAAv8uAN|n_?n%;qRptPSipE8i0`GDTOol?e;~rw$3-yWu^JQt4*_)Mj4vko zmOQl50ACTR95w_RTUgpJhE>hz7v|2%UyQAzf)uTPc&16xPkh{g{;yx~@PY;4S~Z^5 zq7`3@zlEQw1u|Fs2H>yksla&8RZ`8ut77oog4B_gu7vZ_;-}nG$N$?g9d!-9Og@>? zz|dzZ{03+y&X->JdEbn8-blqjlS=HD_4?!BsQ0Z_HfD)vyoR>dSEKB=OX5`E2Kiui z^Y}gIngl}OYpec)RLXvUVJF)?RJ#XD6oqslo{V-2kG6QZgMa)5~f{Rwz_L=cdbGzVk=!-pu( znHO;oNnWx#sZW(@;NL%IPd#hD0<+>3+P{~Vp4eq6M}J)hdeTAiuamsIrAXHTurvce ze*-0~4$e+eS7W~93*ZT!P%eG`R{X1gwb7XKDQnFA*2UON8J$C{BjTb7Y0{dRm4!R5 zh%@nEX3t2<1fF4(aN>qj>|mjE7biWW%cq4lPyEF-wq&^D-qtrqLM@?2z2^)&eh=yF zb-}B;nF@4EYc79$_pIH*@XLve_@{I^;?4E`)Pm?+@O*+TpLg3}9Dw^@isu$*T0Xna zS4WG>XF)84Q4U3|+()9HK!TbpfUz9v;a~wbu#1&*u?c?Si3u+KS6AGtL%;D~nd=AC1cOC8 zKEJ~6uw=WC+LWK0gZ_TY842jl^gQPo|q+QEapGT;PaMdHX@08yJSQcQvGn9p?5 zi;pTrV9I~$OeX7ezvaHk$@anM0(n+W{@keteUj-CIH!|(wKL`vNaxi(H8|AwlA_Ji zcI|D*g;|{eZuP2}fVx8e@^s->cre;uACgUmUBE-{xBh_~wN|)PTbZ#3yXefyjho~i zrdSexhWh|Aaj&|nVT;HV^(XM626@;ImHwD?CoLcg;mO9Xa09|d2T#sp)|djfH#7Xq zkMB{F?XGllE_YKaa62I9p-4a#s13o`6<{S~%)!nk;`QDcx#{X)x8!vEK)UzWIPltA zP63l1TXJOu9nvrC0F2wrJqhaOW2?5Vmdnl!{SIp94r1-M{#i_)(7_Tp1&)(HtV(Xp z;2O$A9?`;z{zYy z;@5b2b`zPt3)!^BY1w4f`Rfyw4lh)Q;{^xd>(t#MQbUS0;f8gX#Iafo>Co{@N%Yeo zG@a|mX5G4ht0C|su?Q^91j~C`pbM4basl`Vo^ZGQmL+jsCgLOnLu}34&*HEVt{y~R zcSl3FoC5}M^l=n=RB>%0-5VF&%Wjp04*)F&q1wO~tR*xW{r;EDD|i9+de38ixFOx; zhdqM@EtA4URX@N?gl(H;miX2eY029jZs4WzsXdK-DO^*@`bmcV8P?%nj0iKtS6_%v03K&sDBuUN>ple->Z7lYLkN#E!Ac*O#gQH#FOa{wt;Z-^bcV9 zMJ+mcOnt(qe=Yr%9BO=XOpzXKY7B%QK-~(uoh)_9I!yknJkuK&SAPOlC^!_QQ{m6t z1-2$5jYRqlY{{v;N5WOD%+_IQZ6puXFz^hug3x1i9rr65pdWPU(IXGrAkKyhbV2W+ z|7BL95@s&VmXrHl!1|orj-NI~wziME?`ixN%Uw#K3#IeLA1|`XX0z~W&T!EU>E`Iy zpQrj{Uz}?q@hYLkq7yIP9X7RsyT}WZdW$O7n-SL^J9RmjUA(BvsU50Mjk(@3^-F6! zETWw0ON^+s_oU#q~ZM z7YxRyi!{Mwjd*wT0|mias&W;uVOSLc_8?t~SRG=Rti-dx`pM9@6!8hH-S-4BLpj#K z+no7CnYi%{mD)i{Oi-k6-=5?En&)G=ryeL^SJCr+;3XRW6&kVA3}&)kvAh>yKSg0e z${B7zHOp*H>zMYd6fRkkkxbjBqF<-g*c}@cF_1nf{xZN-k7Gr*^FKs2EIX;;gU80; z&ju{dDq^lu?L7Qv#oy?zj%MLDQn*cdKA)1uw91um45o?mqs{kykipoiTFGgZx=%!;?`V-?lU(m*X_nV-4%D*G5sv-5#VsML47od%8N0{B%W)k&R8bNhDXSRDI&wZ2B z?Yk*nw)EG^YqR2Arf@2euKK#siqi2dWD)+LZu-Le^m2*A0FI_g|1>By(I&(VKfcv0 zl2#4T22N93q=FA(%Sb$;0!qM(dB3%rde}ZPG+0AVxljO@m91nGf;s&JY14i}Tx1(Y z?Q{xxB6IZPd6{ujJqJ5Q-C|n0p2(jJO2LW@MV|2wl2r{ALM0H7;%jj2YW*yeEh9}U z1)g#qu74?NW20GE0Wq+Ko3KiISJB}9DRCd1g0-A-vx;XpgHrX z9V}#wRHnNul;?@k2bX|Hpm+s+DLH(Y^bo`^!S)xm$}*?%2k+CpBww-ghyGLL%fLcS zh;`AFt~X^RG$$MfpV%}PJ;}FtHZA3TAIo$=SRTiEPOnnc!1hiuz_(pdpJ>l#ey(_G z8v4yBZY(st>Lq!VK+zI~p)E~;`c!oe7Pb@eBz9XMW=RFCx2jY%^z|;FVKNS5xVu1K zz9QTm78A2IK#am`>ee^%^bdy#R~DONs?>bL-Rxx`cyCksX)@K;T9&#DOh__Qgn9r- zZvb&0zhS8Y6Ds<}Fz=&iHG^->Q&L5-qncnEzvGQ91U*#5G<7RnPE$?u$yS(+j6lyiF&?=Vj*bdU;sMaJ5D;cIa2jm77TvRE({3)8#JaawYM?5O2J2K^-dR!pN*dCFS=qKg zMf|fnc9KU~{dd}I#ozMFlj4!^HpZ9=DvACCOuTW@iI0!Wc=yj3Y=`k~o^A9dD_@9B zDBG&eDZpH^&7tOaT8rsQqsaP^o*uAjyE(J+PI;1=sQ}~FqWycwJfb-PiuA9F{(Gmu zYo0%Idk%bQm(L|bcc9ly$cDV90E5>yI)C1UR~pcuIu?x3=P^&{UKtJk9R_-CP#nO+ z3CnimXPqi_9ua1>H9~#j73rN70J=I>*vkS)*27pfJ}_Y9yARHb%p>HAXB%_$@DYQ& z*a*s}8iTC1`JhuK@F39t2bq96K_fzy2l~h{b79Dqako1)^b1226QOM#{k4qP^KHNA z^cn8_nJ*U6EPH|MLzeHCd4Dl}&#Wfvmb`5|%Cg{=QX<9^OqZ@??!%LVVfw9u?gtW4swU!yzTWqBEH&AJWw$>+NVxruG`q#` zhvUKz*Jn>Z5o^K|wIG_}=h|{P{U{CIZ54W7M7h_WKPT%CtMY}RoS%ls9$x3jcYnK5%OxDj4x?p{n`HQEMV+IYH`9xr~uY*Gqq!3f-jxSnNV_5^Lmhgt6VkFz0$UhV=mZJK+x zqJeKrIOieZug}B%DS>(`gY39_JV(v0D0pJ4Rp8-6A|%bKp3f0V%>Gu@Hb)8Q)kSgw{J{zhTi!AtimX?dzH@{j>u9K zc+l=XwB-LT!?W1eL$Fx=FsvtS6SVp~Jkj~>3V_+epaoVGG}-r&Ex0m32>_n+m~-Y4 zHFn*=R|6|K=WFP-$5&$u%s{*atTVf;3{F8Y(+q?UH=Zij$92I2rQ&Tc*t=DmzR3^# zsx}05Xjd38k>}99oSZma)_to;wm0gv9xa-0Z&`i%{7xJE$YEspWnB<_SU2%K@Mybh z4t`Y5x_=MGbWb$pO5Bx2*Uw;~-XKbHYA~Jg28s&0C0sQ6`LN2>*@9u4N0O_LXx~om z{Yu*;su-?0Wh^-};FrFB%5u4&JQv^hW`N5pw4J`oFYW>q<>kI~nA{YJcFz-!#>}Mu zlFvogPF2`j2ir{^J@TpaD;?C1PNzkHji_T$)gf7;NE*AFt00i%ir(E>kg&2nq4ZaE zF)%^W>g4Dr(w0Il#ASbNb4XU4B?0DWiQ;dFS?xiF(2^Srjw3MemXeCj__YkGL~D_>wZ@H^*A42(<7?Qo?r=v z?Y;YX&lrk=b21Z9Qd;9D2|04xE;n4W^W^ls-}~}fLped*nl*}tiu0nm@A)c%FjMrn z5B8qWynGom-}k~8m>22CIa;DfI=W&RQt8jT-c(*0)s7a|@QsnAl~E1JAOEUyh^$+P z)v15PGiPiA;Elx>Wu~WQJ>Rm8A(smZrB0efFDsd=8Y`hD@n!sv zL#ik^R0SQUmZ&qAba|oHP>YmGkBX1X+BNj&{~R0%J0>7 z(N4Oh+xC~g5$#MQGZ$un_yPVWuu1hl*sZp+3trr9>+P@XIu*AmPk47eZFLzFX2Y)b zy!WS3AB;%jNMPUIIn14#k)Ww9$j&8Z&^OF;LWzGf3AjMZ|_ zFS;8$R=rtHAd*fUBIt6*wj0BSjnA(&uw$^2gp7hN%GL$oC0=yW515DpHshD?|D>It zNVujT{&Ly&3UcJ&-EBS9I`;bgpkb{{dGs2Uqi)92`h55>;jT zO0=aXzuo&i&0OUnxqhW|cA*I-vP*S46zU>fqCoFt2~NJ027HbHI_k~u$G{qm)>pFw z86`Jeu|GfB6Bd+Io7Ygl%yS36G00Y+tAQ=32J$R*4p^ZWFO6UP>9{`2weX86i%J-U%s!6vDt8p7M= z2=3e51+VvOV~V28CX+wuQ=epu>HOBQ)DynoX-|67Y9z##xiLiOc5x5Q)7jHk`EqbsLwlZN*Br2 z;S$-Hky}JqY@)jvte~RUBjo1ROo9x0)&JOyouysdOMd?>l3CzUJv%#Jm})~w$~!8; zl0Vpex(Pc#0Xg)z0`sK+_uo258N+w!Vn%VGu_2YO$kWXPj;WUw!QgO+&u*GBVjL>N zx#16%s-Z*@N8<$`J0JiB!C2m^e`5ZoV5E5*>^-tX#}?6lyPQr1A3cNDIN|^OXUKtn6c`a65WYv>GOEP#;} zA+|H3UgSB8-*x<*zPuNIqlH-A1V057?&ihIZ>9@tf%x*WF6{sdAJT*)Z$-1RoMTcR@cAIU5j{Ai@^0n; zW$BS@E|GT<*D<>Yj5f1b^*5T9{J?4cil@&Y>Mv+hTO&`6K&YM#qR3rpV3^(p7ll;A1>-=W=JB zp(DCHG~msjFqKJN`bmnkyT_2Xn1Ejl)M-4c)FGq8N;d@Bo~o*`_G$8}yME9McTKE* zez>!C|KXO}p8k<7yVVotNB=Zeza?3D{LM!ebP?T%Sfn#ED8)-};zfN@pLhY|T(0;! zT6_h*gbv{TWraQJ)O><{mND`cibAEpaHi<*@<*`PkzopgVI%YhO)UB}vUp`5aBMZ{ zQhxgP+a{dBT=XcOp1M^1nP)4=Co>R3&c!RckDrfDb)Def&-EY~AvD(TAib+WQye8q z$Z}aNS&PecvHAjfcI4Jw*@cXc3(sF_QTEXf^6XWLKV+XH7QTV@_SrFTpx z#NdJNlkrhiN|X%dB4eFB&7VI-xJOHsTIytQkK8=QrwQwi9z5_j;*3c8{Jf;K%U|v+ zbKm3Pke=PAhmPjoE_atjUuAKPSuh5`i7KP~m%Ee$k;l+aiQ7mTW|+ z8giO8+tC&KjHrVjz=YFxmB@yNcN-2UX)^Dp$*nqe#uJGQH}9&t0ZwfFCm}LV^8%SJ zXyGHnu3TIGBCiUX(TKG6Pb^YbF_AF(anN4hr(?orhmbJCa(??!aw!;3BGRYu+SD`& zo;&9Ale@wKKZ6!`SQ0$I1MHYKxHDKJk8Kh!dMLJx!=N$^S7$}DzrA-s^5Sk ztwFQZVHw>*EG=8w-QtY+hB=%?Dkj!qEiV>$nf|2|tRd4yk2+*n>+IR1iCVBCk4Eh!{Qb#^5 zI~mKL`*zs|6J(W%&fAI+m92sq=>SKS`X1SoxEfQ6HZ1l=)`aUM=755HCF_^a8btUV zv#zjmoG?~34_{|&DV>)SDcFAeY%aS-O})B?&b2{?$C>y7Kq)GKG)BCr$f~>zvDGa`HiR64KRfGj}A1u1%dGBO%HzBA6oyn zRw6YMFNzc`HI0AqFj_&pR4-AJhR>9RD_<2B40~T>t$?u+Y2hQ{%p%+Gb=}-<+byRm zduVXi+?kPxt{5FzttmE#D}J*A$}XK=F(*y+S$C#Azj2qZzUp~JMH!@6r3bk;W0#G@ z^oZs~m^2zA)SP8d`9}Os-lbL>t>uWkBuVH<{Yl>JCJh4HILLW$KDLLzSqx1?JI<;% zI^)ji%o<+a-&qWuWz=b|l-|0*rY&2?Nf4$X_(zt3&u7~EeSf8K@8Af){m@AIy|ZJ| zJC2h@Nm7}aqM&7P3{j>4AX@6jb+lEcPL5}N6v3`oY63W%I0w2@e#v=JpXSmnfRi@% z9(W!>RkKn~L|b6e4ab(iHhkDUqFHG)5tb}xj^%(*jJSBUn|z1#!2@T7^jS)2oEzSqFQ8!DWZb~UTKp~VG~jIIZp}ai z2Crf}8!0!%$12jxzn=~UA9T874OW4`v(ndTjGHss8MN8bw|W!P-V_2ZVoZ&USe_tp zbi@@`3M)>f^OrF`%Jf(CkZFv7A`f(md&_A1o^8}b@Kv|*9WSi1Uy<2;YUM#yd8-3L zsprJ@r$is2biZDn7f_T2>Qg@-^s=!l@h%wXqQh?hx7c4M#6UB^L{5xtpr@=ud}|gVzio-xi!sfY zXd;>JB}+I7G0E>)!yDjih=lk?)f|>zewvV6_{$sgAUtL4lpPS{Y2SO8BCfq6huQEl zVosWjs0om}1DLF3;_*9U1}_X;sfIVVqf@C9^9_u`t|i@g?lH;Q%uYW;TLdbH zRaB%dt)=+&35IbVo^nuzvq=>rDkDqYSt2vQ4=i0S@9`8lKEhoulv*qBE+R!zU3uS3 zCq$c!nE2IH0Prl6q^hZf-9y7a!&HLOGtPNpjVLoxmAzZ+swTHH#|02V4zJ$1D4zGk z^YiobH`wOcc7m!lMsYs4YyLa>U9RMa)_=b=@ut$D?yhdX{*ZG-mZ>Ccg!}riWZxLg zRodP{t68dGUg=t%a-t)cl5zCDn?c1>?86Rasw|{AOFTv!Y~STdn}lFCD{X}GIGW`rsjs2Q zZSeX1UnG5)eAhX$v*1(AdYbUv&@!rku+@x zAz@nx&yT*-{XNK#^^&Sbx(&w-n)D}lkFcj#9%^GelKvd`IV|YwM75*a z5SxQ2jfn-W-0K&_m`U-Mo*c36jKZIEHSk+>xrgf|aoRswqyc(_?d!3{BYb1@`u?}B zqJRZh`e-7uuSSJ{?|v}Ww=dS;;}`eL1?lVJ^mXWj)Ejr5wVV<&V!su@ZlcQ{Wx~sn zN}7k_5%GUZ)T!&(xptvSAu5|VQ@qiIMs#2FPKj1pfE{(DZ)BP=JF=_;s{W z181NwO)?E0vJqg{>+OS|(OC7?Jx**al-^kr<* zbkXpWNQrITlL`LoC#bk@c*HOPzjuZW8s1;&vqUMb9s}h_I5qMINK|D`S(rIC>J4rZE45$i7 z;mcsGZ#*5ruAbei>TxLZ9swFU4(9;pk#qtp+QR-jIo?{GnvB`(-I}P6RN6A{g3-ru za!hL;dm%+{x~PYYhD^^%S5OiA?PGJ7PNiDnTVwDi%5c^J+HSC#lEr7}j3UtnUF6vQ zBJPCvWDz%L+P3Jsg!7FOGE+|~JLjsH23rnHBrJnMTS`!D2r@{nn~6J;!LH)B8N4MC z`w zhJUO5W-ln}8u2_qxLji~AhUrpiS7$NYeHjq7k|%U)cQNno$=S=jfq1D$$IoCWh?`j zjKIkn>sW4ut~?Wt2$5aUnwCaLrq_Z>yP``WN<_iJ3m1902ai2lV|6rTt$t7W4Ii=5 zuYGPQLwwV(lG_F>uK^15zE+GSns z3y3nl-uMyE?Ufk<<3!)g&2WaK!Z+SgHa+EOOK6s`~`( zxCzn~Zq;11>i{^ppnr$Ay7FMHcu)3j($}9F?7IQm)0L5M)s)F%r5=xNo9&*JS z{6MY}l=aqQ-L3P%GJ<(rFQp+i+s*W z?>{Mwz;6?~ELe8|=MsNFm|$qc3%F`V@xf;$JI4}=%V?<*x5G=qBPAI>LiUcW^%soS zRdnj&D`vE3YnpIw@ZmsHSDc@ykdIYNFHbtWl$zaGvydNoEl5SfkU3yCkzlWnP&4)! z@u*0goO4d>@j&b}ZRJ)Bck~(^>@yN{F9rt4Hu+YQVUR&|wgLWVyqt-3sC#OO{LC=P z72Of>q~W17Ea*+hI-w-+OZu9j`a#Ir#nTA1W%~ zS0`)7=HAjQv2IIc_{VH%(z9Ooa>>t+v1;zU?lG)H$sg{SBRA`J!xD({!0GnMxq6dM zVMP-bGi=(1Klq)9AJ6lIRT0hP)|u!?UoY%G`{}SMZ6E1WOrT2i%mRCZe+0QL=+}Er zw=jiE#7(NFz+kP@_F3cSx%g&6wshsKpR|*Vs+%^S&R*4rBxPPqyj+L*O&N%7)zZ?? zLJWvvt=;DS?Vrq~tI$}1NO)+^1vlx7G0Rs?w5kHomhO$Kix1dROW_N}JhbdKp)qYb z7~=pPE%0HIaZZlzbpeq=5-nifu_4byLzn*JYz2;|@4v>027tY%)zG;YlE5*VaUBf3 zIWA!qaOd(0kPOBAn=LUFkp&N3xt4J<;%qf;3+%-4O5sk4Zw;lx`D)d@0@jOO%a1$8 z?>}pDKe#qYTG<^_x&@~!k{H|{^C^fe{*e$n67*!m%uo0QzwmYWQo#jf!@%jJE{fq~ zLK>U)rWs#3ve%n;^e8Dvx*0FPGCrvcodEbJpbsAd;(+cwa$Ox>FMoLM{bmS6<4K7N zRDCBaqFL#pIdIjukc^ZX@C*@MbDj8jUe(^+SONK&vXR1pBeqwQVG=lFz{f52X1QKy zh?A5{lqyfoWij$vNK`nRUG7L`>Z+Omqltu5f2n#4hTi40ES!R^OFZL z|JFWJBD`qN>zw%yjb_G zcPFcVq^O#Su^#S-lB%_hBt)}dh#bmo+CUyZ^L6*VH^2q2u<>W*A-HIb~V! zd0bNKDcmF!72t7{Z!h@kWLRqlxo}5VZ>ght;@g>z`$=Uo3*VhDYz=!qh7^r_82$cf zKAGOQ&jpRWmJG*szJXiJkVN@s4F$wa9nF2Zzm^?JvKa5?rCW^G*P=r!-TZk+WV7ki zzlyDCkJk_*H|uli=n2MzZ3~z;+4h3YvD-^t4Su`G(wOnT7{@~UGiHktrCd3Jv9|!0 za&|cU3z2YDyJTIFKy@;GSzgbrheeA4OhG6j?-e0~$)v8(M3K~W2%0HHX5iRz)K`Sx zh0B1)tMm(3qppDF&~>W2qP8X>H$Ta~+wCc6TIk_b^=#LJklu@Pchd@H^D0g@F(Rcl zC48F2I#!jOVCw)ab0uCAc6>C!^iPxpaL=@S8FxK7XTH@tTHECvlI1gl@6&e#wA>#n ze=3@k?NT`2<-T>+a(C#D$0G5)=TZK3FS1^h%bYKe?n~v(FDXWen!9MaBBeB=lR1Wo7Ii$(ad8wJW3&Yy=Ot@hZSC^L#~~dK)Q`0fW{0h0soi%>k$8 zYtbv;XF)4%bY?SdkwNCQ#ubCxw@{D60l;w{GpN9TXyS#TCHa)qe-L2`+fKR)9p?@)^^Ix1i!q!n<=0 zwz8|tRw??5a^!7Aqoc7SwGB|TUXf?Zx#QJ3fB&13dz&Lqj6B@D`yJnCx=%)Euess` zo9l_BsTVIDEF*5(z}qZm_BUnvz%^>YUmruufywH6o5VX^37Pnojlfrio`}6BZzc|@ zQcs|vC=bfV0l>AN5}Mudpx*zrFJl>j6NI^jsl#)aH(3FT-Dx_Hc%mAnm2Dn-S8Su9 z9x+?r;m3v~+Z%hcWPeN*dpn#ml=t`wRMd_efdw0hGd0r&zfPw74allhlG+^n#W*KD z{3URVa&+1)YF0G**cK5q|2r%WJ*6-0$|~DPl;$4jUXJ z07K5*h~6KH%Y{Kw#XR2CoxFoeT`QioAExWTL{vj$1wm0iadhDZ8S4S>IdNs(lVx-5 zc3vO&ZC{-%O?{Bd%G@I99^kIKfoa}QEW4EiV}S7Lsj3zR7RCsJ9DKoI0?^~7M5{CN zUCn^?q-8LsJhkJBv~sIX*_p-A*zY=)4c3miJ|H7E!(V_G%MoZBVaMFpx)#2(eP74h z#N{fByxR+$*@LeeCC)aHA8!bcy$SJ=&Toyf;PRu=^b;cdzVkShmoaciio-c5v*!keY7eX|jH!>B4SB`n+*`U$XP-uCMQ* z6ux%-DcWgcRy*jWax|@pt#8dDD-{l&lnY?NLfQ@K zvG(+=_bY?gW#wa8+^l2GPj%c_tmAbJHp*=*+~0UcJMx)jzs}{@r}y}<@Icd2^kSdS zcog(soxDc=Wb~!)ekjwn&y<#c0>ZCg< z_Y(TvM(8O2)kWM%XB#NKZgS0|Ui@lTWh9dLJ2in_w@V$#{o>#GOyRjiN3DtsjCmvNTSaJRPc=j+|#d; zLSWQ--Dyw>s&6k!WHR|NboVXn9XckX8n}j$1MK1Fj#;Dkg1I;FyJXistdW}#A5T(r znMGNv<-+l|1mkO`FS`>;UEvH@C4yM5yK(zP1m?ww?@5oA=^I>(DS@^naQsds4*qDH zeptMJT7UHJ5B}YPzEA7GoZl|=H?c0S^to3Xh>KrT z{|{%KJ(bS7_z{qnQ>puE&9L1s+HvDABs|Nqs#%BU%T8rH zAnclY3yrZeK{uNAD!-QV!n&z>@lIncM0p{Z1l0R+*#y4OffK^|lKEd^#P7pD3yd}v zc326u2e$DDuWizmnKQhH2XmcYu1{0XBt7lMmAh}7Q3Zw3Z)Zq1ZvP*|`?L$#cUSNa z$s@Ax(|=^`8xSjX9535l*rGh(kqRr~%*9YAXS7rU>}NxiE;OqhA?d8=lN|xQiz00sn3qiPsSGf{h3m>{X$>BL2Y z2PnOwjqC#gEIF>%{|+)-XB)4ua`&(Ni2@$0;$0b8Z=%0~=D$y3h6qZa`t)%8{#VkB zhxa<~@a7I<{~c{U&lh(A9emvPj?+dkOp#)*KQz_S^`BIocrm>hBcr_Zu_H z*e4d8$NjMs6ZnVePt9@zT zT=&zWZk232U4g2_{ps7Ln0s67qx8r zF&WE8i8u3X{2fk=7_}%l0k1EeD!z27L`uv>7f)ggMS=BX7QgJBd|GoN40`mR(9G6f zQ^;|k{p$lYK7poDg+T8~-em?|5sHrk39qxPUcmm7%OtD_68SLmX!qjh z>j#=+pLqfyF!*^O?MuRWWk3%&GOeuq;63#6wy)PFjAhse zMuGl0T|wC~4pD~p>Ey%$E+^j-f#-0vztv#$)fw6!1ee$mn-!y@zs?~J{-MXjP4+ba z$C4$02ZA*8WYByueQ7GNUg_?A6x~}yo_XFf6Mwi-okUG>R8mBOCHT^-w?ummA8sJHs z;6cQV)6imfr4R3-_GMvsee0N{J8q@#oKi7@FuB zsombU<3Q1SM38!?frCQT1OO&;9o*mhTY^+9Fdtdn82-pMa|_s3RdxH)c}VyHU%=}K zRK@RBC(z?3@Nbz5rj_a797JExig=Q5l{cl<6DknwZ& zwLm{tiE=JBpQ_~luxk|80iCZAQ z{yoWkP5;t3l)7)u@@bXx;wyv*dvKbpqxSa}6;*1BD+J7u|K;G{z2ZI}!#uWcydNa^ z?k~x`oI*2d+&Onvh1sI?Yz=dRz3 zu?z~zjhrCFwmd%E*>y-)uqf1M92u282&}U${f1;ys{r8*C<@YkwIf>r=mG^;3Jz^= zg(GB|Yfm`h!h~3(Q>KskN2k1nZ8CrW9|ti{JFg!)>cIIEBZ!Knpk8 zsuj>c+&>XEhB#cgG{-O14)^J>(DcRF@D=z9-g9#8V{yo0h9AUUH~YS#e6T`t@j>w$ zxAO2O*#HLeaAj{{W;TF1%}kkO^kvgO3_s>*-Xvm|pRo!Xcwnc`j_=rl zyP3}}iRKA}>aLc6R#o5{MJPToNGh9=%>l+pBs?npJ@(@q-Mn)P+%@bw8F8Dd)9;ws zsrnRDIrAEq6Y|@ID-86DeJo7Ha8@d(BpeIyeT=5CsCU~oStu?J3nQRJ*{>ast<)d@ z!De4**I3f>|Ej8Il)vU($|+#_#Av&oh;10v3B)vZ0rWuc-DPxue@G3MB90E(vm21E z)`(b2&NGl?6c-7s=XEBta8|B*2E4RH`c_ug1$N90mIq7FV-I-l29AqVUK%dL`Dimz zrSM3R6X(TzCGh?dgB_>w1Nj#cQ~AfI7KZs*6q%LC5_Sbyi`KFU`N#Y54}rz?6!`)* z`NG7;T2w;20KqX4n-1os7I&2SgX|5?@FQpb?pIs&Cy}psYNw=w>7>*<2w9w;G)=~=OXDn74#|>n*M51ds*Oq75*q2&I4M1mpH^QjArf+|k3!2FPHfM> z2m0zkn-NX8+#l*8T~K<9VZFC+y~Ha+(AX`y1|zSBBb&Q=D<8DAium>kjSPD;T zzX9-2vfl>%97v0$c9~ks)hO=0CJ{Vk?>hNFv7F-SOnoJWs(29fQ5P~pP_DGFo`b9f z`tQM5aa3pk>?h=SuL1}?27(6;X?_OE0OU@Il2!9aVk4v$S#laUEdz`KZU&N(JL=U- zTo7h+cC~`r3I*Kt|5+;3CiW@s;77^ zNj@kA%z^y0TMgpe{NKgUe~AzWqp~Iwh>J=Ofh&qv93JB5<%2JwN!_B1X3m(>qslw$ z8zRZLUlORw$FgAlsA(I4Z2$0@dP&M{&>nH$ z8+S6F=}aal8rz6Js+oqY4PJ&ozQ*xyJRZBz*Ev0ELFr2rRK5IUEXtl%7Gia!f!sC0 ztApnJVHJKI8|(})?9?@CK}ZCAM;)N`OEg;nw9t3(A+~rRKQh1}y|ZzF$=J_s>wPJB z@>>p~ebD1O&0+f_`{vb~M1r6`!~N|Hs+wJ~hGGhYOk$ehcR_KtU~Vy?b>I%l8Hhhl z!Ay|q!!||(fr}5g1rq4fa?pLO0wI<|I5sN#K1!;$!(J4be_I~+omdEQN~ppP(ojF= z>79AJdHU5*ZD(HXnQdPG?3~5#xN=v4@dCXeaQ`P~+^5U)M!$C6=zOyt@_~QQ1}tGG zPOT;HUv1qrO8S$PgwMsNPV_h9lMIymJFbIrE_I1Kx&$oB`_exC7P)st2&fe84|C4; zL45uwt0k&no7}cf%y?ow;GxF2MoAPP4jX)ZVeTV-8jXxE1<0;@U`7x23WwDdU*?-1 zLlZeKC?~ZT)`uBfpX1$qUK)ZY$#-I5>V%F2n4tUOuNod%=0fE45JGP?LQizgAWV6@CDaA-nCZz*P<;Yf9?la^Tgo8 zdV)?#c4hb8gU>!S_}k)Vc8&U1cbB#qJ=zw#yBgiO@yqOEQ+T7uY46%WavOQ>&D_L$ z=1fnicQiRo!DxM^M;?|=x1{+QzM{uHh~=*ji@6N5&w)you@*8Vj|Bw3EQMgi($rnx zkJckYfxkPqv5qi+KHiP40Y$C)m}i+(5^k8 zA!O61WyyIPu~pv=E9IgOMqw;doHlGWTOsm{W7`u^IGFlG>XEl0a7na!L^1(%MUF92 zoXLpgJ{BinqD(wDyGUgmqM)F1dn2NBwgA^N^>#v_5q@))$eQCeYoPgp4hn_8DnNL- zuFcisSYhTeWlI8446kY#HwHX%kOAaD4}tzrz&olS6t4(3Q3ieVhn}`6n>t0wvhH!& znf>7woV5WFn6b^a7I}+Hg1fsGIBtU-SfjnWLg^Mq_gV|;G$^yv0#&{9)*MEJ?lxxT zCn_6P|Be3%ggz%y^H_iwmd5{en%L9Ir!Os$Iu(F4uGzN-c~*wv(Nn9a3J^R46gFn$ z^&NhpMPNo);kV>2VRCT=|JI1_TDVmqKV`MC%vuzu&*W|M+{W^JQT2piOZUgp-2Lrw z=|DmJ7+q0YurnL?EJlM+6YwjlrT=3wpdy=yJJ`_hG{4Jk`pHIEM^55=6fN$W5FIf4 zOtMy|KmO{`--G4`uHb%Tms3r-jwJ0Xn`xaI>! zX8uTZ%hl$W|Si#?TI4?ZO-rEe-G80N2o; zhZv!Y4Izr3{3nj-fS>XX{ib$tqIz@iayCIq!IU8PHCbe>W4Yj>@W*1!1Vt3k6?1-W3EtJO3?F${F}lK@W6I`#<5#rSC>WQy zf-hoT&;ngH_8j_^mo5i^o^}7vVE!(byl~AGstM%b;L^EoP4;OU-o1(b~v?m>GpZ{Gvd@fkj}m9 zw7Db@$|4Cw65KFk*Dgs4p;<%7%5l82x6-5BHjvp#=%k*F-J2V_^x|&}{T(3ZE?Pd| zxu+z|`gdaFV@bdj$}oP8KM*q6q{zrL5IL&N22sT;Z~n_V4&xFIgDDv+H|HBO#{_<9 zpnd#8nqb{ZApaV-BydnKjKq(F`x!pV*|=qLvNcz~Uhv`yziv@b*kIBFnluFZ_zoep z|M>&up+-VbBQp35H0>lF4(fe_Q?jRedCRjb453sx*198KRvAJBnNYE^aDh#r<`iz; zVxY}~M;PLa#Qma+H1NFM(u8asPR0_Y;gcV~Y#EostFSz=j!_nBDSCgUedWg7P~#sO zi937`_hvb3C-8o=FPhV5uPerlmOPu?&din!CZj$wSsza#=GREq)OZIQ+U3Zf*HYzB zF`1;GMfG0`h`ZM%@!n@XZ}#% zp=l#o{y?$d>(g1(*fy~^SQnTE-bsp~vqa82-jnRtas{1)4kp7csJ(p*zO4}XpcQ0H zZoEcE_<8ri_zNi53C0E@gvvwR%|tvE`2*0r3Q^qN+3(GQmWI*z4Wm!k;)U1;+a4}* z!T$so_khRZacaxp{#H(FW|?4 zVCr>HhdZ!qf8#p^WcwkIIcMfV$#ux1dl+e3pf+Aref)-!Db|Mj{!d>m&tVn=v4!yc zE^PEYtSskQ=_ul)e+j9sZk!&=Y*5e_J(8eX?0`4b}b+$P`;S z?ANq5U#Na!i`z7z^e82JUz_rEAhERc38V%o7denAvDad96Y=#JE}{B@8njS7+wdC1 zJ_2tjxid$oZ=Mg3Rl1h!n7M=OeXlvKr6nCZ(6)dj$XivIvLnGAcZ2tXsnR!o!U$>x zQ2hLW*ZYU%Ms^0A=FiJ<)@z*>{KIB~uPYO{i-NFl4kaiLr3AWu!1DpfH*!$}3Otnn zlD*vs{nZuf5K@#a>2E0E^3jiT-|#w#P2Si3Qm&>E<2aTYg2W}dQaAt8Z;Tm}^jP32 z4&>m}_Cs7+-SKM6QCq-n&Fox1+~;eMcd+^ErdWsB@o)1O=9Mo|7kgHSvxT_ug2QdH zX%wY{>`;f-xLe(9X3wp}Uz8uDUAs&I`IH0N*lU|uA87UdwX6f%JwJFC#_Hpf$6eu1jwTwWV47L;;Ox6&w@RkgU?A}XK~7tok^ z*L`OY(gCf09sD>#O|D^7n&|>pfqdwtQ5ENF7L#|Dq=O4}jU6Gn%xjGZ#f?ywbFIMWbI4|F66!dAmbX(L`qvx=+-Tc|2?J;^J_FbTubQZ}N#hLJX_pSr<*WZ4Ji}vyy#?cM|61IQpT3Jh z3c?Q`8PBTeer8XdB8kgot3PI*Uz)kZ)jUV}(ZWBO1__XFLXP9Zd|#aW(e32AC5l(i zK8#Gk@0El(20s=D{Sm#AbDyd-E!q*f?fhC$K0@x>QXUsX-C-qU?xO|*3(y0>a`+GE@^Bd<#jJ1}sX7<&>i!-)o&~_=gRkFH+#a zp&&zW^hLBd$YCSuL$&n@D@vy$gZu`!QRojX7oi5E!zSH3rTv8&Af!&hB)*^&|R8`2xGax^5yuv;;O}y$5gKOT<|8emASGGmv zZ(M8I9hr6iFun_v>U9LPa8T86N;J~3MA{9u+k`5vk&&!L`B}-_|JT1FUGPu`Yr{Vp zGE3@0l`(lmpHLUyv4Tnj963fL-lS9 zcj=+9@t7XB=x8H@&1NN@?yJrJE!*16BIok>md`Y0QHMrHgj>bNEDA5!*XS#fJ74-j ztDmdDnm`yw>16mgomvj`aBGeCdmhlfjf! zN@Nl53c+}e*Lw)^T|9dRAjcP^1K99dN9eWPnk6pK?C}b(K#Ux@d&}#<_+SUIeVo5m zgBWJdHQIm}^RoKQV4ImrXPeqn*P1b6Sq_8IE; zNv%uVZeCf7Fz+Ddc5?5AqW%-o=2K!OJ=BJHKLYo@aMcR+d-Irk)zNE-DJ#aJUZ7cVLS9oA9)DpQeHq~+M(cPF4A=Zz z)%l0EiJj9Z?)?8&=j^cfTT_(`{Otq(_B&VzPKx8R)fs!EAhE^d9YgN|m2FGPF3@Fe zTpd#ar#^tgpA+_X$r*p6?yMEewQpfP4)rh(gLDa4^61X_hv3Oq-JoQyL;34ms@t+m z`E*ywRh8(nFTT9T8)uddjZaV^S0G3f=?De?YB^81AvOd zo=xD!n^7g#p!Ry09u3ft@r@pNk-ej&(7xgNiDUIxJMK%F(Y4M+?6oc8u_(b4hNbR6 z-0x(-1KbpYdoS_pA1lsjJO=pZVy&EP_jRoT+=0=y*nVkFR##d5co0>?K{YZjZ6G-~ z`>&gnnd)^nTgGLf?sp+72leMFNC_mSa0rwk=c=nH`s8x++&lG>Ezz1ohYu(uEi{7_ zz|{>x9ljWi%&`zZXk^|_7-lk{4_ z#R+ajZIZ@)px+hW5@=(5s&=ihV~uWF$LE_;-(lTjwkooR`o0i()|aMDiLbmbGA&eF z5yv=_0P$&D#gdEwk$<0g`v`Apg7mUi02VHY;VpSk*8Vb>FYK++h9$(r2d>RfR^{Hl z(*u4Tk>!Xv`2$>SkexgZ(zQh&0vCmpP0oIN;Ydxx-?Vzl6zTjeJH%F2dUhUNp$QjJ z2KB4_O11}x^6-1f7l-sq(%PJVt_>u-A50D7zfR^h&(O5uxQ*S%tjrg)%y7H$<@H*u7Q@L9Jo#Ip*MH!3znDMtoJNM_jP-mtRA z3v(T^ZrFzLK1(j{(h;u7%hVQLI#)c!OJ*7Rey=@nMJh$`rNHz*Qa(dWKDU*#jZO}W z@k8I23Yv6FjvBbSTk>5{m}>5B$?|FWXYUljFAf-orr@tbz|TSZW$u4_5W?3K3wBi{ z)Qr5|KEs^b3<8M4!aO8AuwENk<`6&_TRd~sx!q@YlpTU9VhvN2e^N%)r{O0Xl?3;0QMlJZ#{1?_br*YG5+m&uPIHUi?hDaKITwhXdNqkZr zLXp)9j%flxl=CuD-~*lGKFr{hg+)~TIPgfRi6l6Gdi)X_ax(B3EKLKf@cuwQ@-|g( z0e0n>ZE%Jz&^t@MeF!)Qre<@`_pA|r&@Hs(kU>2Ox>~`feK+r`T%abGh;;7%F_sEL z{V;ts%sHPuL$vvcyJfu`VVlJr>bZk*;QC5c%H!W`#~pWR#T*9Zc^9I^li%%?4GG;c zEEXbg^UvThuHPGLdE%`D9-%yq7e7$#+iJn-0$~mAV21`u za?o`o#4syV*gr}N|J(oc-cn!0e|2u$8Vcgz_O(_)?pw|f$eQd$e(+0h`5t%Z4oYRS ztd|%$Y?p@5fqj#?V2S!XEV@rW_<0xkI|o8wBvsf;NqvcFuXXk;HiivseuL6wE3aw@ z`#pD*z^cnIq$VSIUe41t*i0ULw$<8ZXN(z68?5-HsBg}NXlaW12c^EP`&t$NgMpAx z5Io*W9{S>$hdAiagNQ*GV86wRMqS;!EJh7l`hl#A8~;PU2pj+he-E&X#Nn@tWvifd z!FivudY*#Tt!Li*kWRh&oK=mr8l}f_T+g8X3+11>uqxZlj@d%}w+Z6M& z+XZe(M;Gaj4|?M&Dw;jyDJl!Cy05X<0!TF+(%KQhKwQPOs8 zLtkvzKKq&)_FRPurW%QoBM0BECUjFQ-0}M)I_8S*tM~wt1h+){NPl_3BSo;*znJq8 zVzfV5P6$V#VP(QJLotq~Y&)|A7v=u8|^C749XvyI~G6@2M71cEquY zswp1=*UJ7o8bCMt!W#EXL50?0eRevD0W{@rAIjgZJvcNE|BD{)+x^`!kXI-Z)`*g2 z;t{9lS+aG5`r+ZcBEz@bQ}?xzP(tPM@RtW|O=QgYRhh*-_3Y4F2yN`6Io#i&6M=K6 zGiT#avCu^N@THG5N!kua_EowOLmD@F{S&EL8*Y6OU;m+3e7E(+^_-V~2Il8Ebs1V< zQ6<*#W`FE+(v*ux03cPEAS|=^z^`jEIKQWqE62oICkpe+Zi#rSshq{h(SmWBG{rZ7 zJa|%KaLO7qe&A49AZSG@zX`Hx8yrR50e8c_S|P=PV1MH@lHDBbsf(hKV0_mZhu!BI zyU1Vl5}wXjx+ZO0N7!@s{;+7E$bo-%M=;IVZvMo5TEp4|jk_BTlS~#_<5YtR`d$)u z-F>6Fb;Ki=(y$#Ghf;#<(O+y_!WNGFw}`qO0BFnC@aR9c?tR5n`E0$)L^uf^4vmSa z3at8E{^GtKU^Vw7vcV&5oZrKn^n|vDU4p|%!SGcFCi7zsS;U|2$_jzF%Zd))V}FXC3(~e}|`OEBb;=J?@_H^^9-) zJ)^U6rZ}&uzDhS-@!v><@Ghe!YE=At}$L5{<&T<@SN$rg4F@%9UanRwPFLJi9)C?2L_6gY88{=)k{|HZ|- zppj+z5@(oH_Y3sszz9|;r%7Go^IwY))LAIH!UJ$hrW@PSgUp;@<@G~Zmb|Z;sLvvi z2f3P{?C-_Au35*gLfY(7{+BJwKS#dsM+?8#alFGZq(!eyUeN$s&!khfV&ml-ERx?D z_*ZcI@LQt-4{sXfj4}`XRWONDn5Ibo<3*Pn5rXXwgZg*Ev?gH+Al?oGDK#fFgWT7h z!&!YqziGCeAr9l0YC{v-slrH=W9^8A+GnA6EXm>5&< zMx4N-I~~aSN*8zE@XHeVB>_i5aA@bB5nA`aahsP-`qN22zBLg8ITm&N7wfd&{4jH# z+u||GI|B{h@;!J5im3X<>8?;XsK$7niaPGlhWM7?3MNZgecLiB zSkR9F8_2;OH)iZ@q!u_&PgsF5K2~5S*iH^VdIN)L`M_^Kf6zby{CkJz4B={)O15rt zytmc`&o@*}KP_}}aNg4NaC!IxDfkz}s>1tyqLGyeW8$#$f=ApFQJ61Q`7>p5=&R$L z30DqH3+qvbP!i!rAr|8P##1!64>a&rlLF`kG1#_gNAg?(?;1;u*YXw;ypj=)zr$K& z_1%J>VgCy;Bf=gmXI=W6>ebdht6WZb+Q+ENB#v;2w0&uaS(cX%<<)AHG?rWzpL8!F zu52ix3uC|{EMr?ec9ew+lfs{#GYM}JFKH0auv_AIvvbE8#|C4uPvph|JfZnL6FqH) zu4|#S!t>>`HP2FT$!f=D2wFz6yM2&DUsI?A zlRct($EQl7Mb(~QL4RaQPFV9=-YM3In}b?X=q;c(Drq}FeigDv%M-b)VZSqBp6VRa zk?+4z`n)Bm+Oni2sBmk~pj73XQwO)JIK_Foez=x$sBw4)didP~p733!CJvegqDMNp z58=3q5oniPF1dTdYxj3jXgTI1jJE4f>&rPN{lR~Uzh;FjtHvSJp^xc;oegZh1;u#S$X&qX2D6BLxVT_zNA`|TJgSW`8&*kGe37roKdBV3M8vgbuKg92{s zBr(WYjJM{9MC|TofYWZMO9!wb$2cHKW|xgrE}p4A8tIuY_UeqJHwhhBFu%h|!}DD5 zlMF)Ul5(Zvxe`J;;f}nGag_+65NhmhvwMmuf_2ZpUnzki(&o@K1F@j7UP{PPgi8UW!-Re`%Ox zxBtY>z0*rN(U&@`(EeLE`F_0Z`_A-lK{;k9vzB)(bTtDKj~o?TXGXrGOPh69bZ%q! zG%$7R*(R%q^+TY`g~E9tF6iF2v?6qysTBWH4wlkgGj-#cv_17!g<~`Z(4&=q#lH=q zXJ5*urgo<#EeSq>CARiV@!bgj?&6}qvjq_8P~9q&O^{5mlX8%v;B;KmkQK6&cQ3ZvP@b%cXgIxptjzl zRfMqwnOFf=XR}(_qx!D@xbgQl_&Lfp#)mZaRn$OvLsQZ&sUD*Ah ze6eMBoIk@3IVK+LgC`x1)GWj{8=&6a#=QlXZiy2z9^e{j+VX6T)l&CeDU`}hLy#(| zb`7l`CBk20q`@IAKIprkC8=ojFr@T3bStEq&wH;3G3vb#S7LJnB3&EMUt&)^>%g6D zIecvA4F~+_Eh)k@>J#Q=iEUPp$rM)U-&^ z(}mP!RrEK&aL3@~xZuy?nlLq)TS&Oiutv=%LQ+-+-r&fu&L0~Et1x_~`rRdyfvF|b zWeb4afp2*+8ZL&srzWW0#$ueQb{nd5)<=s@ei(*&T+8(d$tq(0`|Wkds4j8W-X6zt zTBb9`V6j;_2fL$Z>ujuGclTD`U%PnhPThuW<&zwWdY7OpA&PqdHL&DUVuAvneG5_m zw|Znwud0F_Z(^v4rbQ^jJXtwxz-O#UA_cd5Htc5Fm~IpiHZOa05i5oYYX%o&?!y-o z3MQ0w!P=q{Ct?mFMO%(FBb}UWf|)YMFWPu!^@#XN`IZK|r-5hWcixW!n}#doB=l#E zGE&WOmK^0mVYBVpPokk6dy~DHZ~iYV4SVwZM&66h5jlc)dqgTt!TO21JEaCjO+G9q zR!&7(66LIS>IaM(nsP6NEbhBZY1!0k?S5;8h0A6n8T`Qg)Jv*iF>6p!J%1fX_!d~b zZkM>+<y2Upu-)4CunByj0)GjaxO!{h!kn|7sElIiJr^mwS@w=|B}yIm zDH*(qaWeG~G(hpF#q%D~&8s7ma3$zT#mQ_ifh4`v1Q?E-8KID-P?uc*U#Sc2eQXEd zD)fLM(9LZdb}szt@$h|P*DiNxehlZx&0x>sH?*vU%8Pk1i6ifQ#^W;_z3P_6e12lJ zs}{^I<9Os`9p2>utAx-Ov>OlNR{#6nS)Wv2h6&}w*>bOy;~EbE@pZJ9>epWznRDb| zJ;{OkZ>$xc%Dny+#7GsUz^E$D*;;&| z6-*CwSSj?*_xKco5-jQjkFdvjM|O@n$Sgc|{w2tLZK@U&8DIf^QJ3exvvL3cu zv*!4Aw?}(PD??#SG*NCL&$0$#kR-4#M zTiWo4vQ0*l13n#Oyz&egFe0Rm;h{QDH?X>aT%NdfMja{=1u1G;ep2c*Gqjsn;f;Sl~8Gf0{_@ZJ;mn!BH=ZTPF{?+@i6aM zqp)o?e>1-h%+DZt@1h*@7jCs>&24St#CGIb>s?Na!3gb2`&4~h?*rDKl?`zIi>}CO zBx{zca9h&y>}ke~R@JBR^Z#}(OQvb_J;!mopL`J$-^r`yH_aJ6?3)(@r#w9{>Y*j| z{v28YyduT5zYFryqb5Ocg7xirhe)v?)qDK)Kc%r^X!vOp8_%y$oBCK-`R@7C$>{Xt z6Z<8;zc~|`ons`~lx#eydE2HXBlPRn#e2?nF!KP$nc8&w7 zaJSRTuDkn`#rHnxI~}PNp+eh5G zGI2&WMOKwuJ%hU+x{X;e^&|hAKxG}=XxntP{E>>f-1v+{modW@{7Pc>e7d9zV(Xx8 zW*RkeqfXQH;oduiG#ss9=1aL#@+wb^G{@!t%C;d|>U!H!enFn&`Oj{LavwDe#V z^ts7;V%OVt*XQ4Wj(w;n_kvj8%Hhz|yJMQax^^btbAdaZ01R#J#fqn#nv{Tyny3sv zPZ=bL?}vXc&b(0ci}|?tg50pbp2WX$bmf2TK#;Hl{&4ujE*BkNI^lg`Fw9EZiF>eR zVpd@Aq-`-F_t)iLq>5vC@4My?kC-L%64fKZTXq*%&-s@=#C{I0^J#N5~8Amaa5r+cD)s zwjdzWpbN36nzRmV#W|q*KRD#oox~NN1{F^k(1z^M&3gm$5kUsE2Jw$96wjR~d6KNA zBX#L_jK9aqhSMV!DhEg+ z&WnAMF+KZL8$U&@1r_T=ZQgV!HrZoF|Y9Ie0&E%0xoWT969*TG&vON-DiTnou6cL9`y8r6 zdY8EyQswH}<(Rz0zFRp5Ww%=V5?@&RkO=+TeaZe@tj&^FWN0Dh^DzbWE!AWi)pT3> z-p41?!zc(e!Zd#V8zohaXZ3gqb)Ua75983c&JS*F-H87D@=t3Z=k5lEmtH)>++W&8 zuUk(V;n^AphMsPIJV%6>E?NZgqaVo^5lNRiBGulmwr6w^Rl>DOc^KIiB3wPk6Zo@IEXYE`G84ykQ zv3KbHfnMwX>|1i=s&@3rtXC!n+xM2q1q!v1CrOSWX`JNVkr<*BKmL)Je#}*K$Y7(uyBX;oUk;^?8n3Cz30cL(V={pBt7nYgJFZS?;p9x>yL?i=S)zBpU= zn6mk@70tJ0DVp5BVdd03KM$^OT26C%0AF)Zi-L-=ix)cy=?zc%9^DW4z}&YdXZU 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 diff --git a/app/src/main/res/drawable-small/splash_screen_drawable.xml b/app/src/main/res/drawable-small/splash_screen_drawable.xml deleted file mode 100644 index d40947f90..000000000 --- a/app/src/main/res/drawable-small/splash_screen_drawable.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - diff --git a/app/src/main/res/drawable-v26/ic_app_shortcut_github.xml b/app/src/main/res/drawable-v26/ic_app_shortcut_github.xml deleted file mode 100644 index 747f232ee..000000000 --- a/app/src/main/res/drawable-v26/ic_app_shortcut_github.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-v26/ic_app_shortcut_issues.xml b/app/src/main/res/drawable-v26/ic_app_shortcut_issues.xml deleted file mode 100644 index a6a3cb6f2..000000000 --- a/app/src/main/res/drawable-v26/ic_app_shortcut_issues.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-v26/ic_app_shortcut_pinned.xml b/app/src/main/res/drawable-v26/ic_app_shortcut_pinned.xml deleted file mode 100644 index 596399ba8..000000000 --- a/app/src/main/res/drawable-v26/ic_app_shortcut_pinned.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-v26/ic_app_shortcut_profile.xml b/app/src/main/res/drawable-v26/ic_app_shortcut_profile.xml deleted file mode 100644 index 1bae31866..000000000 --- a/app/src/main/res/drawable-v26/ic_app_shortcut_profile.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-v26/ic_app_shortcut_pull_requests.xml b/app/src/main/res/drawable-v26/ic_app_shortcut_pull_requests.xml deleted file mode 100644 index 01856928c..000000000 --- a/app/src/main/res/drawable-v26/ic_app_shortcut_pull_requests.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/fastscroller_bubble.xml b/app/src/main/res/drawable/fastscroller_bubble.xml deleted file mode 100755 index 30d3322f7..000000000 --- a/app/src/main/res/drawable/fastscroller_bubble.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_person.xml b/app/src/main/res/drawable/ic_person.xml deleted file mode 100644 index cd59a3e61..000000000 --- a/app/src/main/res/drawable/ic_person.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layouts/main_layouts/layout-land/bottom_fab.xml b/app/src/main/res/layouts/main_layouts/layout-land/bottom_fab.xml deleted file mode 100644 index 2a5fb4b08..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-land/bottom_fab.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-land/fragment_container.xml b/app/src/main/res/layouts/main_layouts/layout-land/fragment_container.xml deleted file mode 100644 index 73de28ee4..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-land/fragment_container.xml +++ /dev/null @@ -1,11 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-land/header_title_with_toolbar.xml b/app/src/main/res/layouts/main_layouts/layout-land/header_title_with_toolbar.xml deleted file mode 100644 index bb6ef69f0..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-land/header_title_with_toolbar.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-land/issues_bottom_navigation.xml b/app/src/main/res/layouts/main_layouts/layout-land/issues_bottom_navigation.xml deleted file mode 100644 index 39b4d36bf..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-land/issues_bottom_navigation.xml +++ /dev/null @@ -1,10 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-land/main_bottom_navigation.xml b/app/src/main/res/layouts/main_layouts/layout-land/main_bottom_navigation.xml deleted file mode 100644 index ac4ad8a5d..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-land/main_bottom_navigation.xml +++ /dev/null @@ -1,10 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-land/profile_follow_action_layout.xml b/app/src/main/res/layouts/main_layouts/layout-land/profile_follow_action_layout.xml deleted file mode 100644 index 9f0f152d1..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-land/profile_follow_action_layout.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml b/app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml deleted file mode 100644 index 64e4787b2..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-land/repo_file_header_layout.xml +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-sw600dp/bottom_fab.xml b/app/src/main/res/layouts/main_layouts/layout-sw600dp/bottom_fab.xml deleted file mode 100644 index 635135e9f..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-sw600dp/bottom_fab.xml +++ /dev/null @@ -1,13 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-sw600dp/fragment_container.xml b/app/src/main/res/layouts/main_layouts/layout-sw600dp/fragment_container.xml deleted file mode 100644 index 73de28ee4..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-sw600dp/fragment_container.xml +++ /dev/null @@ -1,11 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-sw600dp/header_title_with_toolbar.xml b/app/src/main/res/layouts/main_layouts/layout-sw600dp/header_title_with_toolbar.xml deleted file mode 100644 index 95a03ca43..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-sw600dp/header_title_with_toolbar.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-sw600dp/issues_bottom_navigation.xml b/app/src/main/res/layouts/main_layouts/layout-sw600dp/issues_bottom_navigation.xml deleted file mode 100644 index 39b4d36bf..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-sw600dp/issues_bottom_navigation.xml +++ /dev/null @@ -1,10 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-sw600dp/main_bottom_navigation.xml b/app/src/main/res/layouts/main_layouts/layout-sw600dp/main_bottom_navigation.xml deleted file mode 100644 index ac4ad8a5d..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-sw600dp/main_bottom_navigation.xml +++ /dev/null @@ -1,10 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout-sw600dp/repo_file_header_layout.xml b/app/src/main/res/layouts/main_layouts/layout-sw600dp/repo_file_header_layout.xml deleted file mode 100644 index 645aabea3..000000000 --- a/app/src/main/res/layouts/main_layouts/layout-sw600dp/repo_file_header_layout.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/accounts_menu_layout.xml b/app/src/main/res/layouts/main_layouts/layout/accounts_menu_layout.xml deleted file mode 100644 index 46ac29240..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/accounts_menu_layout.xml +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/activity_fragment_layout.xml b/app/src/main/res/layouts/main_layouts/layout/activity_fragment_layout.xml deleted file mode 100644 index 6af3b366b..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/activity_fragment_layout.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/fragment_container.xml b/app/src/main/res/layouts/main_layouts/layout/activity_main.xml similarity index 79% rename from app/src/main/res/layouts/main_layouts/layout/fragment_container.xml rename to app/src/main/res/layouts/main_layouts/layout/activity_main.xml index 62d87ed8c..f3b5c51ab 100644 --- a/app/src/main/res/layouts/main_layouts/layout/fragment_container.xml +++ b/app/src/main/res/layouts/main_layouts/layout/activity_main.xml @@ -1,10 +1,9 @@ \ No newline at end of file + tools:context=".ui.modules.main.MainActivity"/> \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/activity_main_view.xml b/app/src/main/res/layouts/main_layouts/layout/activity_main_view.xml deleted file mode 100644 index c8d097843..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/activity_main_view.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/activity_search_file.xml b/app/src/main/res/layouts/main_layouts/layout/activity_search_file.xml deleted file mode 100644 index 5baebfb02..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/activity_search_file.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/activity_search_user.xml b/app/src/main/res/layouts/main_layouts/layout/activity_search_user.xml deleted file mode 100644 index 3550d2ad4..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/activity_search_user.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layouts/main_layouts/layout/activity_settings.xml b/app/src/main/res/layouts/main_layouts/layout/activity_settings.xml deleted file mode 100644 index 92bf4d943..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/activity_settings.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - diff --git a/app/src/main/res/layouts/main_layouts/layout/activity_settings_category.xml b/app/src/main/res/layouts/main_layouts/layout/activity_settings_category.xml deleted file mode 100644 index 8da74ff58..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/activity_settings_category.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/add_banner_layout.xml b/app/src/main/res/layouts/main_layouts/layout/add_banner_layout.xml deleted file mode 100644 index 6022f74f1..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/add_banner_layout.xml +++ /dev/null @@ -1,9 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/add_gist_file_layout.xml b/app/src/main/res/layouts/main_layouts/layout/add_gist_file_layout.xml deleted file mode 100644 index e79093a14..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/add_gist_file_layout.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/add_label_layout.xml b/app/src/main/res/layouts/main_layouts/layout/add_label_layout.xml new file mode 100644 index 000000000..39a96d4e0 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/add_label_layout.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/add_milestone_layout.xml b/app/src/main/res/layouts/main_layouts/layout/add_milestone_layout.xml new file mode 100644 index 000000000..d690df522 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/add_milestone_layout.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/add_review_dialog_layout.xml b/app/src/main/res/layouts/main_layouts/layout/add_review_dialog_layout.xml deleted file mode 100644 index 62cabc425..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/add_review_dialog_layout.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/bottom_fab.xml b/app/src/main/res/layouts/main_layouts/layout/bottom_fab.xml deleted file mode 100644 index e017f7ad2..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/bottom_fab.xml +++ /dev/null @@ -1,16 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/branches_tabbed_viewpager.xml b/app/src/main/res/layouts/main_layouts/layout/branches_tabbed_viewpager.xml deleted file mode 100644 index 20950f765..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/branches_tabbed_viewpager.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - diff --git a/app/src/main/res/layouts/main_layouts/layout/centered_tabbed_viewpager.xml b/app/src/main/res/layouts/main_layouts/layout/centered_tabbed_viewpager.xml deleted file mode 100644 index 1ed3e4205..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/centered_tabbed_viewpager.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/code_editor_activity_layout.xml b/app/src/main/res/layouts/main_layouts/layout/code_editor_activity_layout.xml new file mode 100644 index 000000000..ecc9ce1d2 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/code_editor_activity_layout.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/comment_box_layout.xml b/app/src/main/res/layouts/main_layouts/layout/comment_box_layout.xml deleted file mode 100644 index 81ae2130a..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/comment_box_layout.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layouts/main_layouts/layout/commit_file_full_layout.xml b/app/src/main/res/layouts/main_layouts/layout/commit_file_full_layout.xml deleted file mode 100644 index dc8949a7e..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/commit_file_full_layout.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/commit_pager_activity.xml b/app/src/main/res/layouts/main_layouts/layout/commit_pager_activity.xml deleted file mode 100644 index a6db0cd7c..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/commit_pager_activity.xml +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/commit_with_branch_layout.xml b/app/src/main/res/layouts/main_layouts/layout/commit_with_branch_layout.xml deleted file mode 100644 index f57c518f4..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/commit_with_branch_layout.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/create_gist_layout.xml b/app/src/main/res/layouts/main_layouts/layout/create_gist_layout.xml deleted file mode 100644 index 0b94c410f..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/create_gist_layout.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/create_issue_layout.xml b/app/src/main/res/layouts/main_layouts/layout/create_issue_layout.xml deleted file mode 100644 index 0946dfa0e..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/create_issue_layout.xml +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/create_label_layout.xml b/app/src/main/res/layouts/main_layouts/layout/create_label_layout.xml deleted file mode 100644 index 9bfe7c399..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/create_label_layout.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/create_milestone_layout.xml b/app/src/main/res/layouts/main_layouts/layout/create_milestone_layout.xml deleted file mode 100644 index 51a0e865e..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/create_milestone_layout.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/delete_repo_file_layout.xml b/app/src/main/res/layouts/main_layouts/layout/delete_repo_file_layout.xml deleted file mode 100644 index fd278f409..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/delete_repo_file_layout.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/dialog_picker.xml b/app/src/main/res/layouts/main_layouts/layout/dialog_picker.xml deleted file mode 100644 index d5e44c25e..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/dialog_picker.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/edit_project_column_note_layout.xml b/app/src/main/res/layouts/main_layouts/layout/edit_project_column_note_layout.xml deleted file mode 100644 index ae97220d5..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/edit_project_column_note_layout.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/edit_repo_file_layout.xml b/app/src/main/res/layouts/main_layouts/layout/edit_repo_file_layout.xml deleted file mode 100644 index 64bb5eb2b..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/edit_repo_file_layout.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/editor_layout.xml b/app/src/main/res/layouts/main_layouts/layout/editor_layout.xml deleted file mode 100644 index 711b8f6bb..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/editor_layout.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/emoji_popup_layout.xml b/app/src/main/res/layouts/main_layouts/layout/emoji_popup_layout.xml deleted file mode 100644 index 417978f3a..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/emoji_popup_layout.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/fab_micro_grid_refresh_list.xml b/app/src/main/res/layouts/main_layouts/layout/fab_micro_grid_refresh_list.xml deleted file mode 100644 index f65a66b4e..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/fab_micro_grid_refresh_list.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/fab_simple_refresh_list_layout.xml b/app/src/main/res/layouts/main_layouts/layout/fab_simple_refresh_list_layout.xml new file mode 100644 index 000000000..91b113d94 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/fab_simple_refresh_list_layout.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/filter_bottom_sheet.xml b/app/src/main/res/layouts/main_layouts/layout/filter_bottom_sheet.xml deleted file mode 100644 index 6f245ba37..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/filter_bottom_sheet.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/filter_issues_popup.xml b/app/src/main/res/layouts/main_layouts/layout/filter_issues_popup.xml deleted file mode 100644 index 6b77bb955..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/filter_issues_popup.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/filter_issues_prs_layout.xml b/app/src/main/res/layouts/main_layouts/layout/filter_issues_prs_layout.xml deleted file mode 100644 index ae8c934cc..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/filter_issues_prs_layout.xml +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/single_container_layout.xml b/app/src/main/res/layouts/main_layouts/layout/fragment_activity_layout.xml similarity index 65% rename from app/src/main/res/layouts/other_layouts/layout/single_container_layout.xml rename to app/src/main/res/layouts/main_layouts/layout/fragment_activity_layout.xml index 95359fde4..ea6633aeb 100644 --- a/app/src/main/res/layouts/other_layouts/layout/single_container_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout/fragment_activity_layout.xml @@ -1,8 +1,7 @@ \ No newline at end of file + android:background="@color/transparent"/> \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/full_screen_file_changes_layout.xml b/app/src/main/res/layouts/main_layouts/layout/full_screen_file_changes_layout.xml deleted file mode 100644 index db01da078..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/full_screen_file_changes_layout.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/general_viewer_layout.xml b/app/src/main/res/layouts/main_layouts/layout/general_viewer_layout.xml deleted file mode 100644 index 459b2411f..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/general_viewer_layout.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layouts/main_layouts/layout/gists_activity_layout.xml b/app/src/main/res/layouts/main_layouts/layout/gists_activity_layout.xml deleted file mode 100644 index 26ef18051..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/gists_activity_layout.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/gists_pager_layout.xml b/app/src/main/res/layouts/main_layouts/layout/gists_pager_layout.xml deleted file mode 100644 index fb96b9ae2..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/gists_pager_layout.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/header_title_with_toolbar.xml b/app/src/main/res/layouts/main_layouts/layout/header_title_with_toolbar.xml deleted file mode 100644 index 497906b18..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/header_title_with_toolbar.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/icon_row_item.xml b/app/src/main/res/layouts/main_layouts/layout/icon_row_item.xml deleted file mode 100644 index dce0bad5a..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/icon_row_item.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/issue_pager_activity.xml b/app/src/main/res/layouts/main_layouts/layout/issue_pager_activity.xml deleted file mode 100644 index dc553a765..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/issue_pager_activity.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/issue_popup_layout.xml b/app/src/main/res/layouts/main_layouts/layout/issue_popup_layout.xml deleted file mode 100644 index 94eba3c58..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/issue_popup_layout.xml +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/issue_pr_bottomsheet_layout.xml b/app/src/main/res/layouts/main_layouts/layout/issue_pr_bottomsheet_layout.xml new file mode 100644 index 000000000..578b8c379 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/issue_pr_bottomsheet_layout.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/issue_pr_fragment_layout.xml b/app/src/main/res/layouts/main_layouts/layout/issue_pr_fragment_layout.xml new file mode 100644 index 000000000..e1503e129 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/issue_pr_fragment_layout.xml @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/issues_bottom_navigation.xml b/app/src/main/res/layouts/main_layouts/layout/issues_bottom_navigation.xml deleted file mode 100644 index ea6e188c4..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/issues_bottom_navigation.xml +++ /dev/null @@ -1,10 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/issues_prs_fragment_layout.xml b/app/src/main/res/layouts/main_layouts/layout/issues_prs_fragment_layout.xml new file mode 100644 index 000000000..fd5354a3b --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/issues_prs_fragment_layout.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/license_viewer_layout.xml b/app/src/main/res/layouts/main_layouts/layout/license_viewer_layout.xml deleted file mode 100644 index 995d5e7ec..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/license_viewer_layout.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - diff --git a/app/src/main/res/layouts/main_layouts/layout/login_chooser_activity_layout.xml b/app/src/main/res/layouts/main_layouts/layout/login_chooser_activity_layout.xml new file mode 100644 index 000000000..07310e066 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/login_chooser_activity_layout.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/login_chooser_fragment_layout.xml b/app/src/main/res/layouts/main_layouts/layout/login_chooser_fragment_layout.xml new file mode 100644 index 000000000..26f27b340 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/login_chooser_fragment_layout.xml @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/login_chooser_layout.xml b/app/src/main/res/layouts/main_layouts/layout/login_chooser_layout.xml deleted file mode 100644 index d5cf21ab2..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/login_chooser_layout.xml +++ /dev/null @@ -1,268 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml b/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml index 1eb921c59..27f106f5e 100644 --- a/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout/login_form_layout.xml @@ -1,196 +1,189 @@ - - - + android:background="?android:windowBackground" + android:orientation="vertical"> + - + + - - + android:layout_height="match_parent"> - - - - - - - - - - - - - - - - - - - - + android:layout_height="wrap_content"> - + android:orientation="vertical"> - - - - - - - - + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + android:layout_gravity="center" + android:padding="@dimen/spacing_s_large" + android:visibility="gone"/> + + - + + - \ No newline at end of file + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/main_bottom_navigation.xml b/app/src/main/res/layouts/main_layouts/layout/main_bottom_navigation.xml deleted file mode 100644 index 5d9d934e5..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/main_bottom_navigation.xml +++ /dev/null @@ -1,10 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/main_fragment_layout.xml b/app/src/main/res/layouts/main_layouts/layout/main_fragment_layout.xml new file mode 100644 index 000000000..59a8b0cbc --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/main_fragment_layout.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/main_nav_fragment_layout.xml b/app/src/main/res/layouts/main_layouts/layout/main_nav_fragment_layout.xml deleted file mode 100644 index f837f1f53..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/main_nav_fragment_layout.xml +++ /dev/null @@ -1,14 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/markdown_buttons_layout.xml b/app/src/main/res/layouts/main_layouts/layout/markdown_buttons_layout.xml deleted file mode 100644 index 871ef449d..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/markdown_buttons_layout.xml +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/markdown_link_image_dialog_layout.xml b/app/src/main/res/layouts/main_layouts/layout/markdown_link_image_dialog_layout.xml deleted file mode 100644 index a673c395d..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/markdown_link_image_dialog_layout.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/merge_dialog_layout.xml b/app/src/main/res/layouts/main_layouts/layout/merge_dialog_layout.xml deleted file mode 100644 index 50d3c6de9..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/merge_dialog_layout.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/micro_grid_refresh_list.xml b/app/src/main/res/layouts/main_layouts/layout/micro_grid_refresh_list.xml deleted file mode 100644 index 1f9efe2db..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/micro_grid_refresh_list.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/milestone_dialog_layout.xml b/app/src/main/res/layouts/main_layouts/layout/milestone_dialog_layout.xml deleted file mode 100644 index 1426e6def..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/milestone_dialog_layout.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/notification_activity_layout.xml b/app/src/main/res/layouts/main_layouts/layout/notification_activity_layout.xml deleted file mode 100644 index 4c2a8d4a5..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/notification_activity_layout.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/picker_dialog.xml b/app/src/main/res/layouts/main_layouts/layout/picker_dialog.xml deleted file mode 100644 index 3db32c5a3..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/picker_dialog.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/playstore_review_layout_warning.xml b/app/src/main/res/layouts/main_layouts/layout/playstore_review_layout_warning.xml deleted file mode 100644 index 9b1049010..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/playstore_review_layout_warning.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/pro_features_layout.xml b/app/src/main/res/layouts/main_layouts/layout/pro_features_layout.xml deleted file mode 100644 index 8b12e31fe..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/pro_features_layout.xml +++ /dev/null @@ -1,302 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/profile_bottom_sheet.xml b/app/src/main/res/layouts/main_layouts/layout/profile_bottom_sheet.xml new file mode 100644 index 000000000..09df7a36b --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/profile_bottom_sheet.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/profile_follow_action_layout.xml b/app/src/main/res/layouts/main_layouts/layout/profile_follow_action_layout.xml deleted file mode 100644 index 05ba94bb9..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/profile_follow_action_layout.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/profile_fragment_layout.xml b/app/src/main/res/layouts/main_layouts/layout/profile_fragment_layout.xml new file mode 100644 index 000000000..3bf88d786 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/profile_fragment_layout.xml @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/project_columns_layout.xml b/app/src/main/res/layouts/main_layouts/layout/project_columns_layout.xml deleted file mode 100644 index 24bb34727..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/project_columns_layout.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/projects_activity_layout.xml b/app/src/main/res/layouts/main_layouts/layout/projects_activity_layout.xml deleted file mode 100644 index 5b32d310d..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/projects_activity_layout.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/pull_request_files_layout.xml b/app/src/main/res/layouts/main_layouts/layout/pull_request_files_layout.xml deleted file mode 100644 index de055b8e0..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/pull_request_files_layout.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/repo_file_header_layout.xml b/app/src/main/res/layouts/main_layouts/layout/repo_file_header_layout.xml deleted file mode 100644 index b3cb4ae92..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/repo_file_header_layout.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/repo_file_layout.xml b/app/src/main/res/layouts/main_layouts/layout/repo_file_layout.xml deleted file mode 100644 index ea41890b3..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/repo_file_layout.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/repo_header_icons_layout.xml b/app/src/main/res/layouts/main_layouts/layout/repo_header_icons_layout.xml deleted file mode 100644 index 09b9b6453..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/repo_header_icons_layout.xml +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/repo_pager_activity.xml b/app/src/main/res/layouts/main_layouts/layout/repo_pager_activity.xml deleted file mode 100644 index 2773147e0..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/repo_pager_activity.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/review_changes_bottom_layout.xml b/app/src/main/res/layouts/main_layouts/layout/review_changes_bottom_layout.xml deleted file mode 100644 index 2441b414d..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/review_changes_bottom_layout.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/review_comment_dialog_layout.xml b/app/src/main/res/layouts/main_layouts/layout/review_comment_dialog_layout.xml deleted file mode 100644 index 1805f9316..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/review_comment_dialog_layout.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/rounded_toolbar_fragment_list_layout.xml b/app/src/main/res/layouts/main_layouts/layout/rounded_toolbar_fragment_list_layout.xml new file mode 100644 index 000000000..08517895c --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/rounded_toolbar_fragment_list_layout.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/search_fragment_layout.xml b/app/src/main/res/layouts/main_layouts/layout/search_fragment_layout.xml new file mode 100644 index 000000000..7b094131e --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/search_fragment_layout.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/search_layout.xml b/app/src/main/res/layouts/main_layouts/layout/search_layout.xml deleted file mode 100644 index 041aef209..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/search_layout.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/settings_layout.xml b/app/src/main/res/layouts/main_layouts/layout/settings_layout.xml deleted file mode 100644 index 8da74ff58..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/settings_layout.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/simple_refresh_list_layout.xml b/app/src/main/res/layouts/main_layouts/layout/simple_refresh_list_layout.xml new file mode 100644 index 000000000..db825f017 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/simple_refresh_list_layout.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/small_grid_refresh_list.xml b/app/src/main/res/layouts/main_layouts/layout/small_grid_refresh_list.xml deleted file mode 100644 index 043b423c7..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/small_grid_refresh_list.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/submit_review_layout.xml b/app/src/main/res/layouts/main_layouts/layout/submit_review_layout.xml deleted file mode 100644 index e7caa0d4c..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/submit_review_layout.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/support_development_layout.xml b/app/src/main/res/layouts/main_layouts/layout/support_development_layout.xml deleted file mode 100644 index 9cb4207b7..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/support_development_layout.xml +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/tabbed_pager_layout.xml b/app/src/main/res/layouts/main_layouts/layout/tabbed_pager_layout.xml deleted file mode 100644 index 24b893f05..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/tabbed_pager_layout.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/tabbed_viewpager.xml b/app/src/main/res/layouts/main_layouts/layout/tabbed_viewpager.xml deleted file mode 100644 index cdd42087e..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/tabbed_viewpager.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/tending_buttons_layout.xml b/app/src/main/res/layouts/main_layouts/layout/tending_buttons_layout.xml deleted file mode 100644 index 584c7eb8a..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/tending_buttons_layout.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/theme_code_layout.xml b/app/src/main/res/layouts/main_layouts/layout/theme_code_layout.xml deleted file mode 100644 index db17e0450..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/theme_code_layout.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layouts/main_layouts/layout/theme_layout.xml b/app/src/main/res/layouts/main_layouts/layout/theme_layout.xml deleted file mode 100644 index 43ffbbf07..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/theme_layout.xml +++ /dev/null @@ -1,1000 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/theme_viewpager.xml b/app/src/main/res/layouts/main_layouts/layout/theme_viewpager.xml deleted file mode 100644 index 1d5cefac5..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/theme_viewpager.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/title_header_layout.xml b/app/src/main/res/layouts/main_layouts/layout/title_header_layout.xml deleted file mode 100644 index 393c004b5..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/title_header_layout.xml +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/toolbar_activity_layout.xml b/app/src/main/res/layouts/main_layouts/layout/toolbar_activity_layout.xml index e324ce5c6..4ab55aae9 100644 --- a/app/src/main/res/layouts/main_layouts/layout/toolbar_activity_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout/toolbar_activity_layout.xml @@ -1,48 +1,16 @@ - + android:layout_height="match_parent"> - + + - - - - - - - - - - - - - - - - + app:layout_behavior="@string/scroll_behaviour"/> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/toolbar_fragment_list_layout.xml b/app/src/main/res/layouts/main_layouts/layout/toolbar_fragment_list_layout.xml new file mode 100644 index 000000000..94a21ba3a --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/toolbar_fragment_list_layout.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/toolbar_fragment_pager_layout.xml b/app/src/main/res/layouts/main_layouts/layout/toolbar_fragment_pager_layout.xml new file mode 100644 index 000000000..b8614e5d9 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/toolbar_fragment_pager_layout.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/notifications_bottom_sheet_layout.xml b/app/src/main/res/layouts/main_layouts/layout/toolbar_tabs_activity_layout.xml similarity index 57% rename from app/src/main/res/layouts/main_layouts/layout/notifications_bottom_sheet_layout.xml rename to app/src/main/res/layouts/main_layouts/layout/toolbar_tabs_activity_layout.xml index 2b0ff5a0b..4ab55aae9 100644 --- a/app/src/main/res/layouts/main_layouts/layout/notifications_bottom_sheet_layout.xml +++ b/app/src/main/res/layouts/main_layouts/layout/toolbar_tabs_activity_layout.xml @@ -1,16 +1,16 @@ - - + + app:layout_behavior="@string/scroll_behaviour"/> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/trending_activity_layout.xml b/app/src/main/res/layouts/main_layouts/layout/trending_activity_layout.xml deleted file mode 100644 index cc88799ca..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/trending_activity_layout.xml +++ /dev/null @@ -1,168 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/trending_fragment_layout.xml b/app/src/main/res/layouts/main_layouts/layout/trending_fragment_layout.xml new file mode 100644 index 000000000..dbc55fb58 --- /dev/null +++ b/app/src/main/res/layouts/main_layouts/layout/trending_fragment_layout.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/vertical_refresh_list.xml b/app/src/main/res/layouts/main_layouts/layout/vertical_refresh_list.xml deleted file mode 100644 index da12bb032..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/vertical_refresh_list.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/view_pager_activity_layout.xml b/app/src/main/res/layouts/main_layouts/layout/view_pager_activity_layout.xml deleted file mode 100644 index b20450d36..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/view_pager_activity_layout.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/main_layouts/layout/wiki_activity_layout.xml b/app/src/main/res/layouts/main_layouts/layout/wiki_activity_layout.xml deleted file mode 100644 index ea30ccb2c..000000000 --- a/app/src/main/res/layouts/main_layouts/layout/wiki_activity_layout.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout-land/appbar_start_margin.xml b/app/src/main/res/layouts/other_layouts/layout-land/appbar_start_margin.xml deleted file mode 100644 index cd2f7e307..000000000 --- a/app/src/main/res/layouts/other_layouts/layout-land/appbar_start_margin.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout-sw600dp/appbar_start_margin.xml b/app/src/main/res/layouts/other_layouts/layout-sw600dp/appbar_start_margin.xml deleted file mode 100644 index 6f1f12da3..000000000 --- a/app/src/main/res/layouts/other_layouts/layout-sw600dp/appbar_start_margin.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout.xml new file mode 100644 index 000000000..78836c04c --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout.xml @@ -0,0 +1,37 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout_bottomsheet.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout_bottomsheet.xml new file mode 100644 index 000000000..77f5c11c0 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout_bottomsheet.xml @@ -0,0 +1,38 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout_primary_dark.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout_primary_dark.xml new file mode 100644 index 000000000..10fb4a949 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_layout_primary_dark.xml @@ -0,0 +1,38 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_round_background_layout.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_round_background_layout.xml new file mode 100644 index 000000000..671f0f300 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_center_title_round_background_layout.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_start_margin.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_default_layout.xml similarity index 60% rename from app/src/main/res/layouts/other_layouts/layout/appbar_start_margin.xml rename to app/src/main/res/layouts/other_layouts/layout/appbar_default_layout.xml index cb6c61110..77062defa 100644 --- a/app/src/main/res/layouts/other_layouts/layout/appbar_start_margin.xml +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_default_layout.xml @@ -1,18 +1,20 @@ - - - \ No newline at end of file + tools:title="@string/app_name_full"/> + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_elevation_dark.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_elevation_dark.xml deleted file mode 100644 index 7275e7366..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/appbar_elevation_dark.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_logo_center_title_layout.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_logo_center_title_layout.xml new file mode 100644 index 000000000..6653859ea --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_logo_center_title_layout.xml @@ -0,0 +1,40 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_profile_title_layout.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_profile_title_layout.xml new file mode 100644 index 000000000..2dabdc4dd --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_profile_title_layout.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_tabbed_elevation.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_tabbed_elevation.xml deleted file mode 100644 index 412be0046..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/appbar_tabbed_elevation.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/appbar_tabs_center_title_layout.xml b/app/src/main/res/layouts/other_layouts/layout/appbar_tabs_center_title_layout.xml new file mode 100644 index 000000000..cdf124381 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/appbar_tabs_center_title_layout.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/avatar_layout.xml b/app/src/main/res/layouts/other_layouts/layout/avatar_layout.xml deleted file mode 100644 index 92d2dc0e9..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/avatar_layout.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/bottm_bar_menu_layout.xml b/app/src/main/res/layouts/other_layouts/layout/bottm_bar_menu_layout.xml new file mode 100644 index 000000000..333725407 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/bottm_bar_menu_layout.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/dialog_guide_layout.xml b/app/src/main/res/layouts/other_layouts/layout/dialog_guide_layout.xml deleted file mode 100644 index 26fe04f7b..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/dialog_guide_layout.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/drawer_header.xml b/app/src/main/res/layouts/other_layouts/layout/drawer_header.xml deleted file mode 100644 index 922f14863..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/drawer_header.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/empty_layout.xml b/app/src/main/res/layouts/other_layouts/layout/empty_layout.xml deleted file mode 100644 index 34cdd4564..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/empty_layout.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/empty_state_layout.xml b/app/src/main/res/layouts/other_layouts/layout/empty_state_layout.xml new file mode 100644 index 000000000..6b51b5c57 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/empty_state_layout.xml @@ -0,0 +1,33 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/fastscroller_layout.xml b/app/src/main/res/layouts/other_layouts/layout/fastscroller_layout.xml old mode 100755 new mode 100644 index 1aad0c51d..992c6fe40 --- a/app/src/main/res/layouts/other_layouts/layout/fastscroller_layout.xml +++ b/app/src/main/res/layouts/other_layouts/layout/fastscroller_layout.xml @@ -1,6 +1,5 @@ - @@ -9,9 +8,9 @@ android:id="@+id/fast_scroller_bar" android:layout_width="7dp" android:layout_height="wrap_content" - android:layout_gravity="end"/> + android:layout_gravity="end" /> - + android:visibility="gone" /> - + tools:ignore="RtlSymmetry" /> \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/filter_issue_pr_layout.xml b/app/src/main/res/layouts/other_layouts/layout/filter_issue_pr_layout.xml new file mode 100644 index 000000000..e574029ff --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/filter_issue_pr_layout.xml @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/filter_search_layout.xml b/app/src/main/res/layouts/other_layouts/layout/filter_search_layout.xml new file mode 100644 index 000000000..d089b4eb5 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/filter_search_layout.xml @@ -0,0 +1,484 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/filter_trending_layout.xml b/app/src/main/res/layouts/other_layouts/layout/filter_trending_layout.xml new file mode 100644 index 000000000..b4f37ba88 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/filter_trending_layout.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/home_button.xml b/app/src/main/res/layouts/other_layouts/layout/home_button.xml deleted file mode 100644 index c028c2113..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/home_button.xml +++ /dev/null @@ -1,9 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/icon_dialog_layout.xml b/app/src/main/res/layouts/other_layouts/layout/icon_dialog_layout.xml new file mode 100644 index 000000000..3ab564539 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/icon_dialog_layout.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/lock_issue_pr_dialog.xml b/app/src/main/res/layouts/other_layouts/layout/lock_issue_pr_dialog.xml deleted file mode 100644 index 1e206cab2..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/lock_issue_pr_dialog.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/lock_unlock_issue_pr_layout.xml b/app/src/main/res/layouts/other_layouts/layout/lock_unlock_issue_pr_layout.xml new file mode 100644 index 000000000..89f8f564d --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/lock_unlock_issue_pr_layout.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/message_dialog.xml b/app/src/main/res/layouts/other_layouts/layout/message_dialog.xml deleted file mode 100644 index 99846afa1..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/message_dialog.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/nav_menu_layout.xml b/app/src/main/res/layouts/other_layouts/layout/nav_menu_layout.xml deleted file mode 100644 index f7578edb4..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/nav_menu_layout.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/progress_dialog_layout.xml b/app/src/main/res/layouts/other_layouts/layout/progress_layout.xml similarity index 67% rename from app/src/main/res/layouts/other_layouts/layout/progress_dialog_layout.xml rename to app/src/main/res/layouts/other_layouts/layout/progress_layout.xml index 25708be1f..6f81686a7 100644 --- a/app/src/main/res/layouts/other_layouts/layout/progress_dialog_layout.xml +++ b/app/src/main/res/layouts/other_layouts/layout/progress_layout.xml @@ -1,14 +1,15 @@ diff --git a/app/src/main/res/layouts/other_layouts/layout/reaction_group_chip_widget.xml b/app/src/main/res/layouts/other_layouts/layout/reaction_group_chip_widget.xml new file mode 100644 index 000000000..80d7f6fd3 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/reaction_group_chip_widget.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/reactions_chips_layout.xml b/app/src/main/res/layouts/other_layouts/layout/reactions_chips_layout.xml new file mode 100644 index 000000000..b20bfebd0 --- /dev/null +++ b/app/src/main/res/layouts/other_layouts/layout/reactions_chips_layout.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/simple_footer_list_dialog.xml b/app/src/main/res/layouts/other_layouts/layout/simple_footer_list_dialog.xml deleted file mode 100644 index bba7212d9..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/simple_footer_list_dialog.xml +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/simple_list_dialog.xml b/app/src/main/res/layouts/other_layouts/layout/simple_list_dialog.xml deleted file mode 100644 index fd1f2aba0..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/simple_list_dialog.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/other_layouts/layout/state_layout.xml b/app/src/main/res/layouts/other_layouts/layout/state_layout.xml deleted file mode 100644 index 670b1d378..000000000 --- a/app/src/main/res/layouts/other_layouts/layout/state_layout.xml +++ /dev/null @@ -1,7 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout-sw600dp/login_row_item_menu.xml b/app/src/main/res/layouts/row_layouts/layout-sw600dp/login_row_item_menu.xml deleted file mode 100644 index 2b34fdf51..000000000 --- a/app/src/main/res/layouts/row_layouts/layout-sw600dp/login_row_item_menu.xml +++ /dev/null @@ -1,17 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout-sw600dp/repos_row_item_menu.xml b/app/src/main/res/layouts/row_layouts/layout-sw600dp/repos_row_item_menu.xml deleted file mode 100644 index 30b5fec9c..000000000 --- a/app/src/main/res/layouts/row_layouts/layout-sw600dp/repos_row_item_menu.xml +++ /dev/null @@ -1,18 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/add_filter_row_layout.xml b/app/src/main/res/layouts/row_layouts/layout/add_filter_row_layout.xml deleted file mode 100644 index b9f2ec609..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/add_filter_row_layout.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/assignees_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/assignees_row_item.xml new file mode 100644 index 000000000..0b49ef26e --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/assignees_row_item.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/branches_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/branches_row_item.xml deleted file mode 100644 index 76c98a50b..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/branches_row_item.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/column_card_row_layout.xml b/app/src/main/res/layouts/row_layouts/layout/column_card_row_layout.xml deleted file mode 100644 index f1cb6e86e..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/column_card_row_layout.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/comment_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/comment_row_item.xml new file mode 100644 index 000000000..bd2ad2eb9 --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/comment_row_item.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/comments_dropdown_layout.xml b/app/src/main/res/layouts/row_layouts/layout/comments_dropdown_layout.xml deleted file mode 100644 index f34974ef4..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/comments_dropdown_layout.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/comments_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/comments_row_item.xml deleted file mode 100644 index 04708ca33..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/comments_row_item.xml +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/commit_file_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/commit_file_row_item.xml deleted file mode 100644 index ad1ff13d0..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/commit_file_row_item.xml +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/commit_line_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/commit_line_row_item.xml deleted file mode 100644 index 6e1507915..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/commit_line_row_item.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/emoji_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/emoji_row_item.xml deleted file mode 100644 index 775724a96..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/emoji_row_item.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/fasthub_notification_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/fasthub_notification_row_item.xml deleted file mode 100644 index b6030d6ed..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/fasthub_notification_row_item.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/feeds_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/feeds_row_item.xml index b87a0f839..f50c24af0 100644 --- a/app/src/main/res/layouts/row_layouts/layout/feeds_row_item.xml +++ b/app/src/main/res/layouts/row_layouts/layout/feeds_row_item.xml @@ -1,70 +1,86 @@ - + android:paddingEnd="@dimen/spacing_xs_large" + android:paddingBottom="@dimen/spacing_normal"> - - - + android:layout_gravity="center" + android:orientation="vertical"> + android:orientation="horizontal"> - + - + + + + + + tools:text="To some, a believer is a sex for loving." /> - + android:layout_gravity="center" + android:layout_marginStart="@dimen/spacing_normal" + android:gravity="start|center" + android:maxLines="1" + tools:text="An two hour ago" /> + + + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/feeds_row_no_image_item.xml b/app/src/main/res/layouts/row_layouts/layout/feeds_row_no_image_item.xml deleted file mode 100644 index 1d7194e4f..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/feeds_row_no_image_item.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/file_path_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/file_path_row_item.xml deleted file mode 100644 index e25e17472..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/file_path_row_item.xml +++ /dev/null @@ -1,15 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/gist_files_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/gist_files_row_item.xml deleted file mode 100644 index 63c3accc4..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/gist_files_row_item.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/grouped_commit_comment_row.xml b/app/src/main/res/layouts/row_layouts/layout/grouped_commit_comment_row.xml deleted file mode 100644 index 1ab1ba860..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/grouped_commit_comment_row.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/grouped_review_timeline_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/grouped_review_timeline_row_item.xml deleted file mode 100644 index 65166bc1b..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/grouped_review_timeline_row_item.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/icon_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/icon_row_item.xml new file mode 100644 index 000000000..b4dfacfc0 --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/icon_row_item.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/issue_content_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/issue_content_row_item.xml new file mode 100644 index 000000000..63a53ac85 --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/issue_content_row_item.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/issue_detail_header_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/issue_detail_header_row_item.xml deleted file mode 100644 index de2ba390a..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/issue_detail_header_row_item.xml +++ /dev/null @@ -1,235 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/issue_header_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/issue_header_row_item.xml new file mode 100644 index 000000000..ec01e3c5a --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/issue_header_row_item.xml @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/issue_no_image_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/issue_no_image_row_item.xml deleted file mode 100644 index d2b3b62ae..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/issue_no_image_row_item.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/issue_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/issue_row_item.xml deleted file mode 100644 index fd63f721f..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/issue_row_item.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/issue_timeline_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/issue_timeline_row_item.xml deleted file mode 100644 index 75cb6b0d0..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/issue_timeline_row_item.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/issues_prs_main_screen_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/issues_prs_main_screen_row_item.xml new file mode 100644 index 000000000..439cf9e9a --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/issues_prs_main_screen_row_item.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/label_color_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/label_color_row_item.xml new file mode 100644 index 000000000..47851a2fc --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/label_color_row_item.xml @@ -0,0 +1,11 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/label_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/label_row_item.xml index 0ba7da092..ad89070b1 100644 --- a/app/src/main/res/layouts/row_layouts/layout/label_row_item.xml +++ b/app/src/main/res/layouts/row_layouts/layout/label_row_item.xml @@ -4,36 +4,39 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_margin="@dimen/grid_spacing" - android:foreground="?android:selectableItemBackground" - android:paddingBottom="@dimen/spacing_normal" - android:paddingEnd="@dimen/spacing_xs_large" - android:paddingStart="@dimen/spacing_xs_large" - android:paddingTop="@dimen/spacing_normal"> + android:layout_marginBottom="@dimen/spacing_micro" + android:layout_marginTop="@dimen/spacing_micro" + android:foreground="?selectableItemBackground"> + android:layout_gravity="center" + android:background="?card_background" + android:padding="@dimen/spacing_xs_large"> - - + android:maxLines="2" + tools:text="Label 1"/> + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/language_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/language_row_item.xml new file mode 100644 index 000000000..a89acf906 --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/language_row_item.xml @@ -0,0 +1,17 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/login_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/login_row_item.xml deleted file mode 100644 index fe4a34c41..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/login_row_item.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/login_row_item_menu.xml b/app/src/main/res/layouts/row_layouts/layout/login_row_item_menu.xml deleted file mode 100644 index 2fc886631..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/login_row_item_menu.xml +++ /dev/null @@ -1,17 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/milestone_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/milestone_row_item.xml index 1f07e71a8..0d03cee20 100644 --- a/app/src/main/res/layouts/row_layouts/layout/milestone_row_item.xml +++ b/app/src/main/res/layouts/row_layouts/layout/milestone_row_item.xml @@ -1,60 +1,31 @@ - - + android:layout_gravity="center" + android:layout_weight="1" + tools:text="V5.4"/> - - - - - - - - - + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/no_emojies_comments_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/no_emojies_comments_row_item.xml deleted file mode 100644 index fda143005..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/no_emojies_comments_row_item.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/notification_header_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/notification_header_row_item.xml deleted file mode 100644 index 0f3c56d03..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/notification_header_row_item.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/notification_main_screen_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/notification_main_screen_row_item.xml new file mode 100644 index 000000000..3c72854a2 --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/notification_main_screen_row_item.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/notifications_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/notifications_row_item.xml deleted file mode 100644 index fa3c53c13..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/notifications_row_item.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/org_profile_overview_layout.xml b/app/src/main/res/layouts/row_layouts/layout/org_profile_overview_layout.xml deleted file mode 100644 index ffc615d47..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/org_profile_overview_layout.xml +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/organization_row_item.xml b/app/src/main/res/layouts/row_layouts/layout/organization_row_item.xml new file mode 100644 index 000000000..7cf3b58d1 --- /dev/null +++ b/app/src/main/res/layouts/row_layouts/layout/organization_row_item.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layouts/row_layouts/layout/preference_widget_color.xml b/app/src/main/res/layouts/row_layouts/layout/preference_widget_color.xml deleted file mode 100644 index bb8fb8ca4..000000000 --- a/app/src/main/res/layouts/row_layouts/layout/preference_widget_color.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - -

    - Thanks for those who contributed to FastHub by adding their language - -

    - Chinese (Simplified) @Devifish

    -

    - Chinese (Traditional) @maple3142

    -

    - German @failex234

    -

    - Indonesian @dikiaap

    -

    - Italian @Raffaele74

    -

    - Japanese @Rintan

    -

    - Lithuanian @mistermantas

    -

    - Russian @dedepete

    -

    - Turkish @kutsan

    -

    - Portuguese @caiorrs

    -

    - Czech @hejsekvojtech

    -

    - Spanish @alete89

    -

    - French @ptt-homme

    -

    - Korean @Astro36 @cozyplanes

    -
  • kOT^gACrLw5ShyGC_c>y8FtJ)ddcUlx56*mPGKZlC+XZNaMy3U3&1Vm#$zv=E|^N+D> zC3wQiYtmKb9~y|GUBpya@+FR3N2XLoKwMnW)AL9{eMq5k_4vRZI^cF7VMf^j4ch@e zSO<6~L;BSvAIk#>Wo!gc6e;>r?K&RJcFOFU6xsnKe`b&96_Q;GDRfVl+*#O_Q>#BF z=lAE^&)lEaK(5mH$h^&wHu;FeyTCA~Gqk;Qx9A8qQJnOwtl&Ja*=sPul0eVliRiCV zfvmy|^gk&0tln=>WzE6gO=Nqx68t$#NSHV|+=m4>w&?-HE+m2M_7~xoOkgh~tdBH} zx-x-+HS)jx4t#&X{yXwlF2q5p^w^lcH}Sh|9oTxB7Rwxr+!W&9UnF&Sql(}9JrIyd)Q-#wmd~3hnbpua-VQw$bfVu=gP1V`@5+`g%GA&&>}ZJVV5c;TUOQC#ppK`a#C!OX=@|bY(e|SV%5AJ}x;Y zABcnhCx1z)Q_4y3RbvR;o# zOuN1)!?8fY80(yGUA$f&@+^h#XX!!j;zty{!#Xn`k-<4*$8&-H3pJeaLxr(*FoeGF;WU)SaEL${P^lxQka}V0Je*N?rHw(7#iXZ_cqY zE6YqyNbbK2?BRbGSObWFm=D)P>jSt_@8Y%P*fcjJbw#3LEpIBCn-j96%t)Ck^%N>b zk+Xeui6r-Vt;wdGOeQa^@xd>*ne(aBT_QahdbwzxKV{dblMH#u(aVw8+yh2yUv|A> z>zBJI8;inFF}H|+GU#mW(4l4?7%U2BS&)0IX}2vmMDQ7|c2K@zN*9_)@$DS4&D4ns z4YoQGCzOyi_Fexv$fE9Ma&fAb#xIp>UX}1=5RPm%CpY2e%OCDaA6(b1tq-MgGHf0u zCU?pvs!!htP|fJ|+1ekg{p@lqBy?M60T)|Oj5#=MtM~CZw-YUYE^D-yf_c4#sn?c& z{a#X_AOp#9X~+0SE1T*(mCn@**2DvBnJTGwIrw{3jLDy2A}Hm5QBihR@2W8l>sfePN8t>@XWP(dbl?%9YPuyC+zZ2`FxUwyUR5K5 zX>!mYA>7&2{A$I(4F^P-asU2(_Hp0EuUR(lzD&oWk(ke(o}Tif>;Y~hgy<#=W6CV) z$bkEef|+PqMAaGKcQ5375?({pETCS&Mk5C>=AtKr&PmQ~%_34e=|{A(yP#@%4|%HXD5IuD@PZg4 zwyy;KnXA^#?V&o1+TGV?5BFi*^=tDM6=fQTP;O_4{r8}KRL`J&=idK*&f@-#4ZW$3 zoX59QJl8avwpg3Uo<^~mQ^rKhwOqokkBnv-3W*Py85W~YXIc}+W-5+2Y4N(|r1n}i zC~9rhud9M7Y`Q0jZ=TAe(US0GkF2Y47f~bnm ztu^(Loc0++0ZmjZnpQ*@7Ht7J${c1w9C<+nmlSU!&tB>QRYL5GQ$BR4=grP)+!yI0 zuW~&ZdiIq>ecV!V=w{iiC!eBkM6b1s9p2Zp^PEdsw=R7+r}O4lr?VVF6(H)foOTkT`C0#nbQF&uhZ97{0 zS60Hg(x3r9K5DWfcN6#TsvQqPXaBBIU|4^Gh+qRFFMJe(ScwB9bV7S_^CBu01O)ue z;bxt+HD3l^Bu}JCjPMBE1Y-Tfk*83%j=z2|J2yXp~HA>zUKr`zD`B~Ls2m8CUJTRiCXhm{cv15Gj!=xIPf?+mi*2z$1D z=wWQ#O(x@8o!^6Ti-_l=i;aATMMa=-hr6*w@}eY6Tc101TzIC_Tet?x97!CWG+E`C zVIGphskjq9(+`8+@xm2STQ{71_bieB6nX}Ga)B3+0+4Jr@po3@an^jRvS2TDWv=$c z$p#($Y5GOd-+`Od6e6R{JE0})RO*~bhSDh25H%%C#@%HXPlD|YX6t)0xL4eZZGPV4 z?3O$5w|vJCNi@ooKmX0@cEl_1fhRtts42yTA7hd4aS{@uQ*%dF_g_#K>~pkhcx8od zE+joR-rY8gEBG-s$w%;sdg9X~lt*MTseHjc!TkrlQ&VyoA5;bFU%sf3uTcL`=KIx> z(Yfuj?9B4T3rq;O;BGCz||UBnD3 zWRc=kKBmi7@wNB+7fC^kvpBWNBKEQJuco&(d8{iA1{?VdAH6oDB2`N=2&BDi9muB6 z`5`7lK*Jt8k;!aMU6@F4+*c?={1@Bj$ z$ylZHQu&GqYYc_u#QS6r+8B+mAnmWfc}1al6b$;4I}SJ_A!ZfHL@8W>m=)X(xA*RI zi8soZwQVX)bPSM)#=V#AUScCx?noj|zL672-~b?0-_puz5NxA)j3X{_@mrkBsDoK> zwZF+0%XAzK>l6CMg;!NP8!$XxlhvMCTSgL9yg(nEVs{3bX`Dwlf8+XDSMs9Xvi$}( z$vlwZu`!5{1RQ0H2{VNuQ9!-*9PbXcD%gb_1pGDkZqL%nQ~0TDJ2L)6Hf^z=9xOov z*BHuCFF=D^kDP*3g~BfiR_rmzN#-~E3A5t_VyMGm|%Seq`MA97nqPl zJtu)yeg%ctVB%JgLtW%Xip-4TF7%5pJJulWo-v)tu0S0|(m#i2?=o}K>TZ?)tkd7I z!Gzb~1`>FsEon;fC#V2b#EPOB=lF855{>S4xrSj-!?NpAw9Hc9jb`3P{~o!z|JgC= z6NNE^vl>)?SmiQkC~9!o?Tvu^p}zyDxGQ zpL0_*-Vaep(K6>!Huy>3SUsYfq#O7|aO@V}lPMwc>ify8S3at7&gIC+JeSEP3J9`$ zDU@+@;Fn}DWetu=vB-`Y8IuNc;3KDYnneoh#iC|2GVbfj-JMKQg0z8 z0LT|z{yB?7a~B`=ISKB{+@L}NLOdnKVMfPulv{V|F}WF6X4S7&(4%382+f+8+vm4< zX#d_8tZJBVhV5-;l6+q+x& zRm))hr&nkguSJyAtXL;|8@j{z7YT4cjRVjbfy$3A9=ghc$;oa05C3HUA_89DA8x*b zkA`at6qRF!iHQjY&{Y1eQ_*LQh(9_&v5my_;$p^a5z`t9i8{8wL@5aJneGBeee3D( zFB&-%+~^0_-EaHnPh3pz9JDImVwQKAYKNFYT1bGs0tT#8^;qXNuB>&vvmHI2>C6Z^ z(aOCuuxr*TSyzD_w>f+su5xAjV*GE^S^<3S4tV>Ua|uSJU$4;4gcjbiU*Gr3Fb%)8n(`bn@?##Sg2d5HvopJh?S6$jn-(tyuF= z!hZJeZyNC#Ka3}{`zIahmO!hO(_g2z9W&RdKXqy5&UPL6+v|uGo_uv6yErnnynsu} zdE8;oEbQsLb>LTcaq<(H?3&6ejpXIwpK5`r^#chn)}N|51=%~bWJqMA392)fmAIbCNrLxJk-Zgt#>PhSB1!W2 z{frMG`3(egdKs)Mh6YK*OdD255_Q6tuPP1G$m(B_4(xP#P6xe$=XK8!92aS z)D-Z<%_N*?dw7T?JL-?SchAueFS^4tbM@d|0>MW$^l($yd4PRu(d^f8yXsr)-ej{Asg)?_UvTmjp4*$*uaq$3zkr< zrih9M{V|Am7gRX=kD?#| z#A(tFI?PaRpe6|!92H|h#KbA^e^?zxQZwisJ4LoYda@qrS{+aZgc1}|MMp-GL41Hc z3bB|W;?d4qc0z&z0)?{yE?8aAlt&>xGy9Lv3cDw+<(9uhB+=C?*0wkuZfh{^v^iGK z)9r*I;_UU4G&q^!91t%Wm`yL1d2j2~!1p){U9Ho=H@pwu=G*)KfZXrn){1Lb(i z`@mHI`2lC(W`H+5JI;;1S&k@G{AirQG5UPwCfu4)Y#rh#v;tR_;|&C31YQ~yp{ClrH7E>qRk zbDa4mP9^!aQ+nZ5PY~4$^K0R)KEruWxTWrX?GItDNB?|z^LLQ;v)095IeBAJ5qvHr zqaA6};TaTbB*|NEJ&X-C3pvl{fD1pjj)_of4ge;1OfF{DdzW@*oW-_)9_fLvucUqk zSJDAoWjd=ScX;6%BaV6`d9rPP$-9X0Hq44$Y#?kR4sQkwS{*!!2HLK;q-A zxi#NLm4k-ItzCOk;CBIR)R&N=xA{2=-zdxrq`X!INc8Y|zH>uVonmOHbVYyv=TP~; zOx?mFcxU?qx%EJb*|{}M5sxNVYmHyCQY%Ny-^B+&b}Y&dv1x&5uXx!Lw$pL9=kT;8 zpL{sukUStlf<=H!-C2G_F0rk0y1{t1arMPcd&BDb!5hs+7&y<)@MfC5p$BcP0R+o} zc%FzaBUwnPS;9;_Ms>BORt&iz>U$aBp?%Nxe9MkI-JnPsXZh|nv83C)q`P+u5%DQ& z3_(xj`S{N{LypoQAtgPP;@+*xjz*L;QuTI0l4K}Vi9eg=&7 zQ{_jdT`8?clY4iNP-DmXtu%Oe;&`<2F{i6Gh}47cF*_t3;X!*pWvtAipB)hrV6WGK zaZS5=7t8~g$u&)}k-b*L=Y|;RQs5Cp@AE$uo$?Yy)X!L~Ru-n4e_A15NI&cZ2{=L( zaUMem86?0O5|UOP*~>&a9F*^o07jnEg4VNt;+Xq`Bff zG&orLbWiPnYApZ%)>!pz1WK!02vlZGv~kw0IrM(XHTnK96!k6QKq=~E4!vou@UF%# zX6BApJg$PXT*X;*)5O>4TP|)IT}dw4V>bxeq@EqXK~ZNVc?cTFeNvZMA{1vOA*BA} z$eeTT;NvT@^4*9Jt?v!TXYQ{tUU6ULDkku*%fZfHP-DCr`AuoX|E^pM-h3is|D;R3 zPS3-z^CpUkN}M^5Z+$)^F#TaPIdYC^;K@+(p;vb>MG8(3BMrsNB-19PrNA!?A9GZ& z$T#~pbG=JS0-~pNfAU`{Odxe` zn$paqB%l6IN})i;0p|Xx@{41eN=U~pE6Ga^lRae7@i8iKCcuudjF3HC8JvMgGzn@e zb9I5E9`XI(*$7oeffC=#9|A`L`GnT$K&D0^`$n5{GT)#fVH3ta<5UYQ*)(ZTY>=aL zoO)%ciSfvQ$Admzf1Wp#lWt*15L_y<6;ye=*}mcJJ8qQpcVPjAfy~(PKu5CmP-U8rB<2f?mLU9sI+E~$WQ!{%i;(guXCV_!I3AAAq17cM4pkin zo<7?E1^=Fnmq6jt84lw<3erwcjTr~W*0#1V3>)s8TG$dG#$$cbJ{ep^iIi~gKoZk1 zw}Abox^YI3xv}(?&~bz0F%IJVxER&`Qw(52XpvY+21KQd93fcjPIuh65Zh)m(1%>| z=4UZL#=u36Fc_!psizh3WW0u<);oyQd{Ih#4P-ErOPT0UrZe`Wi>G%Tb7(5;V_N z&c28d6pW!w<9mf`IEd~Y`B@QZGZt(8NWKA%vcwKG3JD}No$6=YM-!AT9-&uX>M&N# z?`*)agcVLf$N)KX+D>Qx?bGOrEf;*G`(H~lq)A=G68WDy^zYE-@SR<|=O2SvW4tqp zm+~nazv2};Cw%#p-9+)@zB29=X-ny^V!Q>Bc%h|OHk2*j01+fO$iXqzULnN_{HpBe&qbp0ds>5VU>%#6-hP=>eRPH3a5Osa}+LTzrJ^Ops&m)Ef=PzyIIni(Y^l+45 z6#1LaBXl37gTDg`bz$C`?LPjvQ(DLp-4>C6Ytk%YAWjgqomA-Snuq{rGHlWApz50_ zeNiG`qBXH7Al_}%%d+K@c-wVVWWX1>j*0~rJSJPOpGOKjU%0lCq7i8d(#DDNW@Tkv zCF%?}{k9hW4s^27i0OY0k$I)-@J5Nv6*My>_aqvMe^yRg{oYW-q3kN`65kz#ct#-9 zx=}OBHtYy}Pcc<|M6=!Ojezzv(%9C|5QFmRBx6w$E&=-xfEz;YeCHdnUkI4tLsgY$QL{(te1_D&Q|-c<7BW`etEh6AZHt4m z#`Pbyr5s{!MYWp{?f@z%IJh}NnfCJK7Y9{WCn4Mr+w@M^D-a=re6(h;WDk0;w2mF6 zlge;wBR~Dkc#4IVytgxu1q8+NpP3)(+OyNw z9uvn>nf(z?S0s{OMqv2HC@GJOywb6u)~B54{XdL-by(D07wu32gCN}?-L16L(A_xF zp>(GrB`|a<-3%bz9Rd!eNJ~jbNlSO%A8&r&_s6~Wc^sS(o>9-7v-jHj?6p=KZuUm7 zez~0Z7nH?W>o|@}6rFGLYK4|d;=ikqBVv$6Cb(?#TN;!MW525NuaY4J*oME~7t1h3 zNnrn8Hw;D_``8og{)Cq{Z?D@X@YDzY?T~zjGvlWl-es7bXQxuTpy?jKQ7Duar}tSP&;?ImJ8*1j$Mt2ZT~R*7h?jbv?Q> z>`L7eE9A|xPAj16cOqXI4|cO=&H%ya)GQi1gz7io{P>x5GC=`&&(HO~0bFnM@zNty^5l^adj=Au zMD!rL%qK~}S=|ZeD5t0^;};|(K8l<906u~k_biHv_Dfq3(D&i15W8Cg=nd~{Mca?Z zlpFgmZxj20%DC@d*W&&P1IZb<)NuNamIO9dC2uo8NzNoXpM3vq6-58+!vAjXZU^6U z&fp#@xm>I!{~aE->fM@12wkJbnV+pJ=2@WA}`gdx!#>rQW%>hSOq8yl4wV1ZpW&4|(?X?svFvmIR=PGCQ6GH2NpnfX3Io-o>oD@e^QJ zeGwqhqYYf$0J0XQfTu5aQQ5s4CvZQO(%81j$=xK@D&p#^GEm{|dv8_c@Fr9C$16PJ z|K0qRY0FQJM(B}NK)4eG$7#ACpvP&EK>!Mrj31|`PXV!)D14cm@g0Epddh33j(mpK z3pk>vdOcfZedpivAzG&n+ie;R(jxbE>0FZbKBwy-&W@6Qr@tMvQA&BZG)1LoO@19)UIM&$q~tS=>p@BoC^% z)-tB0-;5kv0XLOFK}0`qc#pbYKO>AEH-OPvUhhCXP-V7DINDFrKi+=u)-d}V##+Nm z9YYaA@MHR+U@%Sz)zm@}wdNeRbr=;qqzQ?}8Y}F>baakwkkBYgogKsnITk1~}l_pNS070CAw|%XjMf9yRa}pN#R_jlAH3y$9 zRR)3CG0(GSzloL4fXH+T3^*7c zrA>h>X%B!w>7VwNZ6p0ai{uwE+tt<8=FX1Ci!t?Q2dF3B^PKh%q$I1M?pVn8p3VmD zZ+Txz==cMIS?+E)_mWtG>!AC#I{=u{rrLT3h4H^2hRt5@I0g!fCXXjFP!de zz@Yd?D97Rb*5xkAB2j+(RuuI3awPOM0O7v@b77c&$bPaVf`R1o6r}imWOA|>7;;CE zw6bCb3ZgOt+-d*28!yT2Ms5Hs$**1WdF>irUS7^Yj)7@x(UOT015@Si0EGT1lsf<% zV<7;iXT&W5)z(dpk2b};U>H^q1^6$In7JL=}A+J-j%i~Q@hWnUe zI%g#?Pyi4gjsUF>)PQ^1aKg7&Knvqh%30(3n|ta|z#IR^fa!GG3e_HH@xG`A`ntA z=NE3MKmc=v`R3;4Ar20*C9Rku{+ZwFlTwqxd%3b;EkFS4(DK`Ye$89JfAZFa3(zaN z=c9r40e8>$N(IY5wSoVG{kN-H4HiIm=;6=fkAg^RmxRAAr!y;J0n76!7w2#7ca{rS zXn)o@NT&bSS(ik`zK)wKZt*5c2sgMEC1h&vIuYQ%8H9@-S21A_ ziMZ7%l;^}Uv(@8p23Z#VDPgzfG@E0y88v{u8;+QZ3_g!59DzsB$O&8DHGOsrH@x0>+ zRv^u9j1AXJ!^KFY?;KeNO1GInALV1(pDZ2 zz9MD+RG~JmOS@eDwMISGh2YQjl=gQ-18k|*kwZT5%ERJ)7%~BeTS$RE@A_?PtNeG$ z7Z?h0Fev@@{QbWvDD`XFlfTG~A2ieqI7gB(M zT-(71U7GW6i8>Uqh$f#x-?$1_Kf@IJxNZibeuZ2k2!OL+qld`8x_y8J|;AS4c>y@ftq(?IDKF=B^WG|Ea(c{(XNM+;DjrD^{>7sWY z!Ii;Iqevu<9g4MWgalp3>=9ZQ(tcE6x)_0=WaV7)Lck&<-FrLe<9yhhaMTN~_>!L|WPzU8Iq#Pvq#%ap0qIKW|S zMC5~YK)lK`6qM5EBVumE*Vi@~fSJW0!14YskF18Cn|*dQ+GYo_#cb zTV!)-TTkAvE!X*u=w%)MsU7xaKK7r``j5us^jAQ|&w%{SWZ`fM&}{m5ByVVlTC@e} z?=$kh*8-yK%TQY258KM@U)!Pp#Ecr=YBgkIg=d5x#2DZS(J@sqIPbtCHouMSR45hX z-rFh=y^h`p8(8hUG1yKL!hP0?9cHVGpppDh)(K}LKf*FFd>5yb5fJ@;kF?5{wF+E~FC=3TUO zqns-yR3&N6%HUs09Up;TLkvNBt;Ity^&`M%8r8 z1arQVW@2)>M`-A8D6OcT_v#GVFo`&7>U{EZBRO(=d z_<=X}FT-MX#I=nJ^m6w;BQ1M>fPN05;fdUHTX$c1TS99}N+o6%$>!;qcFL$>TpMBg z3?yl08UKCFonWRZYD+`K!#8p4_hPaMWn6g)5Tb~+b3B-m)LY<6TSwWXb|ac*3YU4K z&LbwVQp1l4wYr)$waUDkG8@yvM?KzJwFn{iMpdt(-HKj}{E4JatbQaX-zyE4>Ciz!%fUL&LgGSN?QhQE6!j6G; zi2<_)czUr=$pgc7t@DnN=GL{`ax@a0dz4tqLUM)Jq3`UGObX*Ux#iH1{Fr`8Y8xBL zq3MDmE|A$UFoNtmURZOh@gtBvRUiNY9?G}q{ah!H)Z2IBB`10$VJg#_)DZ{umP;>= zYA4h6Yek)L*n;k-_OM8E`^xgHzE8w^-4s_;LJEsbSY=)0;y#J7bkU(GhZFIg z5p1)>M-jQE*dpX+$MnoXPU~7@t~`VkqLz2_kN+`V)1~B6|Dz; zxRiRA;E}^ZMT{IFB;Z1?I4>mpQj?wq28OJpA+b2bOia3%FMj5`fCLOtgofGLw&8%O zKDM``(|ad#d~`BJGo=z}lk0{Z66)Kr@vlIgkIExyD_qxDk5ohh0~jWBCR1-B_l$rY z1&i3S#?ZM}Z<5BcE-G$mw$ zu-9LNRF3azVw(%-=AX3cGh4%*P>Wp_gbtbI{ZhpYjTpiPs&Z2Sp6|MLd z4w5fYNm*v*dOFI6^0i&T4;08_7)!(?-*8=^Xsrb1uH@Ua(U0V&$I37}-Uh{RxB?sB zdS|VqU~h0XZRW!Us?ikT$C*P9<=LFA=L-)U`l&xPTPrqN&k z@_(Mv0djdd4V^LJtu&%Wni={}vDPFD^nky1)PvrBq$@2au5j^(b?n5e%l=YwP3lhJ z!efmL+hD9Wt9gp#J10Kgdu`F|mB8JdlVp8G@x&nFE&}~|?z>%Kxuy|ccR@|c_=oAI z2}+C#W~QBBRxqu;-R~kiR3s_+MYv)h4GnpW;oVVlz>J29As^?~_8xtVTsS!sF40r% zs^#Pt+F18PSY@Tt2S=N1i7aY@kc6MBuh>MSV3utt>OjsO3wbRUyYbN)7pAr%_f$R| zXtw2P&*P(f$js9jW2sckj}K={TX}|`sXr8EUtGvvEnp3bZcas<68IOl%lljy91=as!p;!N2=s3rx?BByD&xJ9{f`Y*V$ZbwN z!~prDqDN;3;XxXVDm(!-Y{dEz)8fg62NF>Y3$^8hU}xGcdk<#9pOME90b`!vsG)a0 zxEclqPa^LmaUZZ0kV1c=OEy0Xh#j_Z%Eamnm-o`fAO!FfxHCfkp;YH@`e-0EJz}92 zPVZ6nR=wL+jAZFL##~Ryt(UV?HItzK6}Cd|QdT@36-PVAoqz3|TG174AyfSwgPadN z_VZ^cTRXdl*JBu*Eda_~JJKod3bcJbGO5!@fI3}`l=hOu(ZHspc)eTL?fiPm>7&TY z2W2Be%VRgjSfb+$_gV4%lOq3q@|*hqtMUB}vHzqCbS^C0p0`NJ=;H(TmT~wZ#K$06 zuIGmHP)VwmEFcn89rHkBV#7PIpDYwP@p6NZZhK!N(gL{vL*%eQyv!n)mAT@%l$5v= zC0&WMF7OW3)|BKCnX)C)@ud>>k602T%Ant^_kLIWAdD5zq-Kj?spJwI3a4k=E;-H^ zLy=q0-LQcp4SHXYHA@FZQ^+tSh*1KM``Vc77Q2ia_*(a0V1TVql5RE}de}HTAmg*^iUF zXKt$O6ht2;(ix(Q@c%sne?f0g2bn*hpS@RBL>4@*arCh;!S^^>&NApHM7QZvS@vH? zZy*#z@cQsT>voIOriX5RgndkE`9GmwVzy?=zpxh+m6dB%ZAJOW|Kv#QlOx3gYJiw9 zTkKrP&3$~o2IohFqFCdT*vJ~iIv6700kO|A?|>lEi9rMMSzxZ{BeWuPxZo9g;!UoJ zR}62-@3p5`a+#@i+st~g9CB?A^4{CFV8xw*T?-pALJErXm%1bP*^4H~tCd2Mp%i}|s>uewRSww$|ppAu$GZv46#nn85H+-rm+y;dQ=7H>+;h7JJSYM8PFo`^MP6GQJLSQFmksv{{vgy z#;WM#@@9ij@FRu#7pCYws{}pqtriynTJ3IH8d8!)K8^bo+8E!%y21Pr+DF#qn+EO3 z0T6kGTqpyX0M-i31}#Ec8CB{#!ly(vQ?g#q%+xf%b`S&oc4dYlETm+7GJPsBlzowG z3LHR$!k+SW&M@g`>-hM>i{QE?)3}W=2rkcEl$*-cN?0JeTWbqw!$eq8i2qkNLA10i z@0UF7onWGND;a_UF8ch98!7H1wN&}NN8U)^aS9SB9=k?tnMS`-c0^em5In96!|jbr z6CT|>Z%qt=$OmL&qSwiJpmHv-5Ng!jiLa{~8P?{LKx$=UNtdKYsGs(V+ISR?oM0?G zfnbOL|w#~ zzVHX*Pvn+tJBgbxl*p@DFQF3sIN7}5tQ6c-{f}ztuOkp_lp*Hnj`APTZ|&R3f=+Fgf(-hALmxLU+Zer(@JPQA>R?t>0sUZTp7x3> zs8@F0gx9$#_b``v<>VOqC6MQmg7MUkgI2P|1o~{PTe;kOYmgG zBgG{F+G5Z8TH}RPKQnAMujR!-j!SnD_C#0+o$Yp1Erix2#~q6KYMbTGHK59f_wC0M z_b_?|mr)uwtE8qigUI4C0UR(8wG`fX{1Db66piF)F~?gscIE;VY%&6=qn8XN#sAa? zxIM~Pk-Pf@%*}omeBs>NiX^nYBi5Tp=im|U9CbF>X%`hIM}dw*;$VI&bLz1+7)NCS zn091{$0AYGkBMr?6{ZQ*th2)o-HPg1qWZ$>(j^lzRd`~ z`2x3eFBvQln0ZJ4HZw(>=y1)usH`|(y-~=MFffo69Tu&6V|Q!k0lLVUG&;9vR8;yj5<98mhuI(KC20z@03QgP1rC(!pkOK_C75G%d)y<{y56|(L%=di z&kP2yX+WTJU4lUK@?N!z*Jue-q`6&^cOWHJ@1Nr1*bTSH^&UiZM(1AjGopuxvti~j%t-&XhXIFaV3COdQQxdLH>RltXI!stUjPL2 zi;wA;ft{ScP26_)btZM8o~?N11O8VwWm`9_{ih}c-iVY(-*HxDQ1fQjF4F@WMwx=P z*%;`fedR!T8hS!`BdA%B_20KP5x4a@<<4@sw7H5tIr?ysW9QNUX;#=IInm5UG7D2i z67zH=t#MIBr54#!L^6PcnKV?Z>GidvOPJ`o^$MTCYy}}<%kJ6zTe_*gLum>%geRKl zv=z4S+WGqIDkIeRFL1O0jteIuPDT*>-!{(Qv8$Eg&%@LpO0h*j>gXy|grhsZTnk1< zNY)F1SR1ZtG=>jw0_Ec<$k;1Dc#{?r4^`{IiGq?oMz95J^ z5-8L9{Zqu5&vW%xs?C~CwuWGLqt=`Jx;ZJ2lKI>IG%#DC;e`~g^X{8s zf1;CyhVACHUUX@(|1Of}#JaJNAW7urBxDGGn@B;{*RHzB z5dDN&qV$HPVMlWVZ-k>4VW{%rE22W&6 z$Gs<97H~-bhH_CU`kycU@aDMKl(ntb&%4tXby0j}gr=3^kxyh!sI0?AWIGv8zk#9A z+-daa#4784cmLO~V59W^zX^?5bv+7B@i0YhAW6iicngvz~U@Ro*t#3L?uO+c9sKXIXg zrp{}zY|gT7($M=B8Dx8s@-w|%vGPo{QGL`ou4(DXE6c~m%c7qo_;(beyHFbZSH^tK z9KojSUctp4V^`Ig=$4iQb(QEf!gFEr608vl7u;2=x+ZWSw+}6jI7yPM3mB~SLv2~d&Psu;cHWJcSj zE1#_rkNFNWD-sY0BQ0Jmvi3hBUy^Qz=4e$ouf4EB9(ilUZAvHBi6MP>(e|PZy?+&O z1|kBq4NZwxb>HT-3l|RL-X-58;MDpm4f@9$y>{YQ5^QXwZ8~2+B3WdYeQ6RZ{A#8> zo9MkxX~Uc*a`akQJV$$e>S(3G5QWiXci*;-;1;rZd3lj!b9_{++(wpx`?XQ>+ z-OqDNl?&6X%ZWl*va47xrB?^8Emv9>;b`3x5s_P@R37g)g8NNj{W*BzK)hykCoY;C zXhM^cEdDg^8l(19Tuw+!qzo9sfc0;wu9zVIJqu7H`dD2vQdK7mF>vy`%Mzt(dEFP_ zim8}Z_W919QTQ+Z&sGQW?5n@nbn{<#5~Z0vbLYUQe0_nx)pUSr6*^fsA^FCb&0u@Em${=B!%m*{3I;t`Y$T+#k(pBkH#dapo4G}4 z1y7<+Hwp2Fg@8mO1vG-~f~a{t&e_;aasd=sMEi2Y1~Henp0cu1A}nF|C}3f{kkE24 zLv~>}Iv}sDMa9N4eEI2$Ms6s-w@fQvf>x1E^R{&Ez8H%qd9Ey+-W~kTwh4Y;>-Jfl zR?n}cjjVY;*6$!&$NlfP0j#YjW_Py!e+83&7u*c_Z)EfAFjRi}d_WsiM8o5Vo#g`3 zSX_P#VzXmUc%H2K3xz2{s&Hl}c59{^7$g315!0El45x`&fyCJXVZL&y26u{0MkH77 z2@ZxgRGNZNRCExDm7$m^)@3AR=VH$JJ9dJlK6-Q-+#MQTFi`*seh0T33g=3rvwu`v zR#CP5nJB-%KizdWEw6%C&HWzCyLXfYdq)5`mvQw^Itf+;k@ zibR!-@er)#16zk|5F=scdoSEMO2Jp!>e;t5t z%nmktr&YZ;GqyZsMkOP6mUjhR5vnm?1+Or@cba)DcvAbRez+fH#@F34b(z&&%yGaA zmmD2O6i0VNp7~)}732rZxiv+s z)lOh_0Y`%?9d-sVN6P7IJEQR!&Qla{g96uJ7j@NSfMRHFO1}ufJYHqx`;FeQw<%bx zo}TZg`Fx1d8iZ)&Wz0GP?Mw(|k5A5;mxFj-IuGW|N&p!Ukc-gHu!S>SCIi1~LZ(#T z_}<(cXYeFqH_RcdGPmATHN2IXeHu}Qdd+^E zD-M392$^lv)eAN2ocfPvKVK25XQMx*Q>UBFP@>dETE;ulXC3(}KU`O+Yj4*3KKji5M89vA%oaELqu*ku{{5JD$ z06rlJfk{-TG_jDZenWk?+sieN{UOC~i`$4hthM9oS1cYsAG0nZ$6)aTI8|RtPaeak ziiO9`38<^5>DWdyJ2ggv7)~9`DMgs3rp3sl=6M}ORJ1ZOU?;}n`@O*e7*U`5X@|$T%8Rt1>f0qGmQUH zWjRC;PA#UvgxA38~Zm@vj!QlqHHp7e$^Ixbshvo*A*#%#*D)OnMrC8L@w1Y9ii>PI?`WAlt5qET`_RRv9^@t>)lZ+pBrJ$$8m z72(KDtNNitS8;6T{qcJ?5A%y}N%0h2Z*PB5-Cn*))YHTqmqhM~Y9Jk`@vRd3VqXp^ zVP^fYv=bz86Z)QW-$BvmEpf+!`Q}A%NV;QdBEypnIUSQ9A165Bau`T+m(i7=kr(4; ztG^iLY05(I(Qp&r(e^hU?hh9_?-=(7hcoU7?7(;@o33UNVs01iySGX8k19^5z6T?* z-1$~xE6d3Ik|>l_GKMZ&V)?Tva+|3-VS_BJq9%510@}XhI)5cee9$fXdk>v0K%sTG zdC-R6%{)8D%xb6-7xFs@5cdqLx0}Lo5C!ZZK)`%^yE9D)!@q0a?Zm)Z2CV-<-8RSX zIQ!FbA)nHi8eAz^&3QmSU12n9fhpA!YxBd04|TH+`dCKFXjC##`pe~jl95F!6658Wm(w*V2>uyTwueGFk$bvN-oI!TV2r46YSy~7 z@pXv=OKLVEXf&n~=2&-avT9ES;f)g{Y}1q!O*^2E`wQW4u3y$vh2iOb;w0I>XZ#b; z7^K9QK)TQo@{jYoB}MRz#T>2}(DU8w0YJ$-&vur=cy~ZpODSE8e>?w zU!%qaVb8sGFf%$(|KTkItCOFdxQV(mzTcPs?&IYVMi>$BGRyNIkYI_~aaDAXqg=04 zKTMBJhM$n>2x}Y3U2Ui8vb7YnapLW+wylG;8L#y#&30)g2EN6z8ySC z88<9FZPJCeWC_d)>=@geDwI_vDj##0uA~Ixpdqb-PH<7kN4FA#jo7O+mWYt7VMkRm zu^|TvlWAIV7Rt{bcMBbO4BL2)i*s(n+X_)5#F(^yf2GFf0*k(-?aPV~MONVJ+QK}e z`0hx}DNu?3thGCFH^ zZq@F1?#oBYvm^}(Fws>%J6}ARlXhu@Wc(#E-r2K=gW5hMg}0b*k{(f3&XI=TOZ#Yn zC3CO6n$_wsbQK)u&ek_9j;WbW1*cYGC5Fz=&!2b?15{MB0ATKChwM}3>#Z|iKo;}f zoMi9p?N5M@2Qmaq<63vF#tX%J0Qt_-D={GQ{u7Od9YY^)ApP_5-)}%D%NVMGm)+kT zKYxL&Jv+ky)m2X;@GnsVpMJy4wMBQ!^= z_)ING=<*~m#O_l(L118=edhauih6XEv!Kf>jrMFl-k^8m;7;NPc3Mw&Z}h1G!BWi! zX#-7X&zbD&%qPW~Dr}MPIUjDnMJC>!O)1){Ro*LFH^Ls+;qB}G?{!=rVft%JyTxQk z=g%X%<(s+Qpw5qTX2@#>+ZL7Vf3{UN{xt!)_$B>8Lvpt9lqMiQyJ@HMS1(r%)UP7a z^EtNc_z3Pf>;|O6<9vhQbGbvEfV@U(nJ}NotT_1+@tiZ%)D%hL8!xs-`v}b@b6K+! z+!nj~dT!OaAk2p<(AHWfw?qqFbcEQVa!{z9jhK{hK*-aQJ-);P=48RUe^ER=08gMh zfU)1bJ}M_o&%3#*h4sv2w2|7Q!M83Pp*4 zrX1*eje;htwo&O+?ow{pkA>6DEGQFLB*n>ZI7y58)QC23aP0~IuRlhj&$b>@sXP#0hI!TRs8u*m$^8g_hXn8aF= zv@#3rZVC?l`H^~avQA$}uou8oZfVLw)|+w#Rc}rwD;X;+^LUjcHjXuTA_u zyXqNMwM9iZhm%S{IR^?~#4@UiX)FdP>rQv68;a74L6#zUuTQ4LpMC9?CP*pcdP?eG zvwY#`vok6XA2^qU`7mjmVd4OoMch6kb!c7b8-{N68V+RH=O!#?1369iQR_t(U$OH3 zJ`AG)w7QT;@rZ?JG7)d`rsw6Z@2^R?hr%xcmZXlC8Hrxyh|8M~6s;SU>Bb%FyC%Qt z_xCwERHF2`-aH>N2UwLMgO^k?hX2npz+TEKxbF{GYP(R6bdaj$Oh32 zYAx%jv@X#x!sTR)f9WD5=b}dSpJzY!^JQe;YfDsU?hXz|pMrom7sy|JO_kS5@Ne7E1L@80jj@$^U_MfkFNy{m z%&k_Ihv=(oK<(r6u6>&I$dl@|xil?Sy`H<(OqRXg*`D*U!$#7jlP-cdHtpz*xr)bX zbVp-cUuoQOm#}0@FwbY;4|<$wW9t^^f`V7uF1jO0Bayv(qpe(#mt~ViHIp^W%W3Q5 z?A?#Z1o^9DM%{evVrdZeYKoU!W^nrhEzD~U;uD`1i!Id1wlCppEeGqVcB)!RM+sk} zKUm-SLf>4Gi)5<#-q?f@%bh3>UVrMp$g`JP!Lfdt6*>L(-f#-=B0YIW9r7Q+9fH9t z17-)Z?6V!eQ)u>{-?|z|ugw#Ukofx<3^_V32~g`QkwzmNIVtCdTLyF5Pk?0_&66^p zs1+K9G0UUT_LC@0BLd4swSNg%*?NP^=ON9GEC@NBdL|d;-4o2xU42~q&`FFmBV2ei`}Jo_;G z$$D^gdwmG!;h`e>EjX8(LGvA&tNmI-Y-UUFYNfu~oNKv;p)xMawk0q?(8Ps^EhhXX zrF<|{-vLT9d|2WU35Mtxk{C0j<0G1RN{p5w9c88wL<%4P<@fgWLN7+h{e7jqT;Xgg zq+%YJEVB9L9SiUCw)ALN#^=JO7bH^Ed_>>Bn`962*E>po{wSxcd_g^@WbZ-e`)Wo2 zj;A}eAq5;HbIJv5 zYP}{RI02gm8Xk~92ye<}oYf?e{Oe5Fyo_3RR%H{u2TiD`^HHVduw8dGM{Rf~w|n08 zT_OyPb_p@M#)iAQ9k2-Sns|K>IaYZ8B-W(4?-h1{0&E)jeY-mUz5^Lu zHmRmSUs(NJS%PxTJ`zeU>{(7sLT91wz&WOH3aJ!m+I_K>TwEYvoLN@}N!o#xqn6!3 z_j<)j{IlwU;S1R7U#W~>okWf5U*o)7w_QXs?I*Ik+@zN((QRMm7m~}l!Gb2QN+0Sr zR1{@RM%(b@0=JP_h0eujUFp#P#iD9|jaxEO z)n%?C%NB3BL2XE#lXZ5>c&uQsrA~B5`im+X-wp^KmDGv2y0K4<`uD1db4)_zVG;Cz zp<;_^b5n81&iVqC(-Gg1do0dqPnS_r79r|igGThRNt6ay zqCg!O63`6X=@wHs2&}wJvX%F-cjlcX^V`d>22BSBhGudvK8}#txJ{&UeH2>;E0@(5 zLE_b#FH$qMT9(oM(Ict!r(@G*G7TDTi*`+7zO?x2E}==Umr7zwIPqLteQ{ob4Z7Or zIU_7Z!6szh@{ z=L;t6n};d1SWMmH*}D}~xA2j#m*1#?*&tVFP6h$Iy^O3N!lWi5f(zIorO7kXZ5fp9 zVfH>j3egmP&2dch5>V+Dnuo?TM>+8_J&j(Ah{14E`^l6+s~;!G?s1lL-^I;d^M?7d zo}rQd{3X{UbRUN1A=OjG=Kks!#L%B+lvg)5cO!a^<=vxMur2HP(x zC-1kqEK*2{mCp-J6V@#&0%-Lj#sd##9n3IMWSu@J(`+)bW+q4FkylhPY!(33o6eCF zRwS>m(F#~FiNo=`tsKgpAeHx8+ZP*ddxA@ITs!Tt_MY>=i2OZ#_I?BytXyd|;&)WE1jJx8pYl*%n) zghNO^ZOGm`7=!LLqB>$M06)chUr&ISApu&Hm$=01P1(vu2gq5uqt-kkBH&IyQgjIL ziQ9YPe|!C@<@QywQSZIk(kJR+{wc#Q;88n!`iDRY8W!>IlX@JzSczMqm6es+-K$P? z@y^FLqmOrv_$vXu70|sp368^~t~kKB)p-G3xC@XpM((^PO5Q8s-P;Fu`uYdb6oEVB z}1qlJZsXU zph=JUQ+sYXJ(sYTFsR&8#mhIjO-Uigc6Mp^xlsXiwN|&PpowPfKs%|UnP#SL0|x8d zEn{I!^`U6#7HULik0w+!<8^M4L1h!_qqFLH+gx4faN)@&nXY-TELy}DX2&QGk+Rf` z{Glri@ta)xVx;--iH!>fi6M;ddlTg{gi$fw(@AfCcI)$;v=wz)c~380uznC9qw6{T zuyr*`?a+G4+@O|Im0FPAv}Zy1!d?3LQ4&-cr&~3-Xf$&dpa1Ew4JGfkPh`+6ASX8n zkYY?2LBGEOG5{qKt@B)7b1vwM_?Q(<%V0o`W6s2m@?QQ6bbh@qVKQ$gFx%*4b#=OP zFSP@j18B}Z2azVfbSu4yK!A}7quct>O?@vNj`3`R!ykT{fJ*_&BB099%$$Jr6WM_cr2T-fp)>0{|{sYH_^85)ZqF&#I52Mrk$jCuXG28=V>Z=Z> zFSujsw@yALBsPE^*5H2D7qL)IX&SEY*ASu9Cw){8L5nb6s1F2)^qWPtvbhO#g~`YRwP+v(OYUMZ>nzO%qP{Yd5+5h0&(Q41(Fyy?L7-jX{PG8x zasXw7_p@yQ&s2bZF5fz_yo{AZaB-ksk?jtn@e2Tl>{|KeLOdjBsKdhzJlL@woKC@T zJ=h5w=Y6RuwyU~=4jU;&1)FNEN5jH)ti9xCI4*lnzH)qAUu!Mk z*F@2|xWzJPWc=K*O~Y`wZeXVwad{O4iDrx9{9SNl;>GI;eV;VBhC=uKT=xn$BQ$Ol#2=;u|MVkTsGUy!e_ge84kr;LZ%z#|) zsZ7`X7Jy>}^Sw5uG6Rv=$YR;GHeLx{ZV16)B?zRB*Lx%_c_DIWI#@dmRnok8Y#P!qw1z4cBNDCvkM*P;45W%L7CE?q z0k$rFRRMYA>Sk54%~bZFyWxX+K$N!m3&UJK?U0t1Jv z3)3W8`75#B?H_Fq3--p%WK0HXHcCaX;dtNsXAc5W%`mZDr+WQ+G9E}qvwJ90bn|3R zB73sjps&GUHY8@D*^T+$v>K~(V}qsgbr1WgHwWNaJ)upk3kY-s08!ofSG+tjSG767 zL7jMQ35b38bV2lTDn#ZPKIAHAl;dc-M_VSQN)-6@$dpOh+AVBWScN)tFp$xrAvhaSLTt z;g%&jIkDG_tx#GfeVtX6Yt5f$OKtcz?ofD+bn6+;S+<8b?=OPJh5qwYIny7)$a^9(An(G$Ei|$RuF_J-f9=kZgtiv;b`Ln-*O1W-8o#~LpuK0 zXHSk2zhwnhrac4M(v`I*)WWF@r3StlP<`(l)liQ+#fFyQoeN&5@|Hnt@H=(XgJB9{ zT0-$=#Be1fH%)w$eq&^Qy5~F?uRPHXOKT`uD_G;Ew@IjJ9uT>?_ug!ExOXW6H32dn zZvY{gj=rO-8}TXQx19H6=+Fid*cGw~;QI465$Xa^`cd|s?oORrcPOZ+RsqviiB9TD zT_&x2<+J0fn_ORj%UXoba_>W%>kH6k7k2c4s6T6A-gA#D0297Tomjdoq##8i0CE(! z=Or7uVsiT|VR?z(0zNG0f9P)jZ$UcK=(esVep(%iw11e~(WV64I{dpm9)3XF?S2ZkGJJApD3L%SG*4!7t0*|?YH$R!t}uMUtZs$TXI@-#FB z>6yI|(7P~4@%J(QRRKctVaM;c#nb?&7c63tiD1ocSVo3pYlGacFj4(}BCRS*v=G>p zZ0DJueFBa7@s0P>^Ao41mP~*PJ;T-~7a~W7_f73^DWK0ykt)#oH7JN-0>YpCDlaJ? z@HG43J4Y_=#0xOTWC(pz#zjx(_B)8Y*X)*_1!O&MkFwG4O;6O{_|^XS1sFFLw`bq$ zB!-?=8Z^cLqAFqc?RM76qe?&-w{y3g3cziB_aYB~B+!1sx(T2J1j+#DyoTPJ1-eV> zHh>Ca=PrzBdE{gL+P#Y7`Z=OOtQk=H1_=R5pl<+OCIq18C|Y-SZ^Cx3B0~wN4)uJ0 za$n8<{o&)dX#G*#lJU#Kj#VPK2pALCWmu9=zH`73lbD!j44)DdlKVm(M}IPlL=h)d z(wQp9XDVawE+SwujF)^P!Ivzj$;4blBZKAvfvsq%y-O-Yl&R>926- zRi&1%2|hG*!3@GAl@)SUl`W%9-9BYbMLy%R6k2a=D_l)NYIvAX#o|oO&5AUn(IT8(6rS$L#m!JogpJIIRq}^) zWlJ2d;$1C%Om|!c9+&l%z*wo@3ymsf;P$Q60f6#Hel}7)D)&~HIGt2pbG$l~)pk={ zfT3@ei9YlI;Bmj4+_A8*=%_0)A7L%bK-`4<8@o zSh1PB#)(ExA>?Eh-Z;}Zd$q7ww{k8WX|qy748veaQ;q)mG@uUkEs>nJH7`n(4Nx}N zr-1nA!_+OS#HsRBBteGAa%6J>hdWGj>tSDfxlriH+fPF8GJ+zPvf~-zuk=XfqqW_M zJ)o_<^)+ACDfHTG(c(+w7sm)oRIq8vj@Yj~!sZSH21{M|gdU+xiU}zSdW3`L{Q_Bi zwn93x*x=rX1lMp{-AICvTZhk|n04#LNe$-KevNvb+?Jhe5(e#IVSFRQp|O>;-FDg1 zE1k)c>*WNL}YsTg}NUNgElfe z`F2KenpKfDRL?LpE9TL0A4E7;dC13G)V5f_9E)tLA9q3x>QRsukQs7psotXlm#`xm zO4v6~%ZPt{8-_mT(4bzy;xCz`gE8)4*TJiHUtfD1BI-K;wCOxNyE{TH*38BMb(>;a zwv0UJq4M|No{2y2GAZW$3yD_A(WiBa}hX)OJgDdJ}hy z%`@Unj}eNc*}snQ01LYaOQ7s3a&q^EL%3YpE*~v*;juM@NDs!a8maW;%r7s5j(cm8 zgIH9jO|w0@W< zlC!)3XpOuNNF!i7+)I>P^a{3r-n;p^w{t=Y=-s&kGPLhLi5pXTTV7@DMAp!()Mnps z09cB0<_z#(P`V!~`TK0)*2evrDvJo#v%icz8Kzl(2!hiv@Uni~^DCWQ6E44Sso&2& zemh-eyrrjO(95WFy_;&$zMrQ8 zcebc&ucFlr7}r#fvRa#^*KiFM=A7@wC{Yyxf}^RsXfQq zI(aH78XF-MShQs@L`^qIU{t1v97aCMk@Ei`>@A?G{I>4lL$`o(2x$bQyE_F0r9(QU zQ|V4gky1js>k!f%(juXRgfs|9cYphM@9$pUZ;bc-KVu+AK@QKe*IsMwwdR^rbwQj3 zi}ANgqtuNf6^RaZ9mm8?M~<(_aCQDlS!#0Ltl~8W8>1K*6A6WJY{4m7reFpWr{K7=4@fX$0sSL108B1s0!8gu&!ctnch0+xSKGcL zi3Piv^79Vv?M7EWfEX|eyu$=2Xhz%M)JU;Eto^!}d~ z#tLC{-NjNjj90dvWBQ9myNMmwimp2LlXTp=t!W#D@k9of2xQiIDc-FR486Rf0HyaCk*^spM?A(s}t9yto&r$m`U%@tU8G zMNeq=t>e8|+v_st<${+xsk{)GZRpTfGPDKVF0C_`y$wD#?+Y$>AN58)GR-BP(~v53TIEnco07!tVr@zeXtYeaYdZ~U;ENPk!n ze%wsW(}w5#$7f`8*~mdH4(rhfLX@%^jlGt|Du?UcR&3 zy{=u*lfC+G@!3zr6ScTXb6KuQFu%3P0LAC^m0b~%S}czH#h;O-UA)uj zVehLA5n0{H^L!xsX$PkxLJ|rC8?DM^?I{E_|2)CF=ImqA9B7u6v^9$E=MUv9HujLSp!izXtu*#2P6shW)*xotlB__%5)j zhnx-6No!n=OkCe$7U@MHa|r0Bk)Yd&nylR#d%y-Sn9u0ic%vsDlFPpS)HEuIQc^;y zI@p@qvd4GagrUleVl;i9Z*F?#8ORQBVuo2v7JD806$)@3fJU%d=$dPVE+5C^x~4rU z-YN0B$;8jJ6K8hE(>>wRBLL`euLC3<7(fTSBF^Fm0!bfSQ3j-`K%xaP?5`OtqIuUuPUkU)tJvaENqz;MW{@=-^-@ikd zdoM|QPwL${8${2U5pk7`ItSYKs{lqcGbDTKLQUaA9egFySR6HAcS5@6%w53Sj?y57 zSe~2Rg)lK1f}klCR2$Y=tC;^Ne$&B#VbrSeIHDQ?!9pqG>XB&t{ARA{Ds+&}_;sN^ zja+I0aNI8pY*aXozfIBUfv&c`X;4p6qrH&fVuaZvUP=k~_N3WW^&#$L+c@`B^ zlX<^{3;*-5@^_8f+umVc?$ZsV7m=H3HexHG_Tz2MhL(9av{ahIf?-|V(}^@MT0!Tbic6BmeaIUi`qKn z?V^9D&kw<&@P|nD5*@Y03>B)Yt4I;JL+mc*6+1%4vuCithLKE zl(Zb!_1qZvQN=SVNhI+TwDC!)t;MNrK(TRh)YpSNU48z@^(%3qaC(5tSuA0!8ENIq z@y8@OQCg!ECs#MVZ+&*3*ZWVg3H;{xoV^66Yx0<#{n-lqOoZGYbppqU1AYl0{N zKnLoZ9iJdjm_R@eTJlfw1FV5xzkmN;AqqS6gNwfZsJ6gj)`lU27Q{IMID`NNJB)yI zVfU|Ie(eiri!-(rYk-S+4M?@3Ue(s!%K5Y&{&{su93dOgujTvSCQcpSvWjbH6k9)u*>-`yuxH{RS z1#O!)v9rVA8+vgy8Y0|2pDj8A>lJMLX&>uLjR3%L^oQk~hhMm={Nl|&>3L`elBzfF z=ozWhlQU+<=CDoommAF;?mSJLl!=;QSa|yRn6>Dg6D*UG+~k?zq-R4{RF_t{q8+DB z-QxNalz`KzdgCy!OpfmvGNtHgFVq%hLdYvu>C9R-3}Bj483kF}XW58rk<2As*xFxm zZhTz%-6G_cOE`K^8*a&NZ)U#aJdCVyI{P$fddWCBk}`=Yd!w`yS4V2}UTdUpamF~S zQqO*#nZAFlJiKKOlQ~*JC6H#P@#yicUiY+OZ?ca^^~1aA6f+nK4y?bxvM5qj~g{DG?v)iU8#BZ{Sp_f5IbN51~2T9~6m>?rsb$*%v^{zDk^Tf#yRI1EQ^K4v=%?78K6R{9yU+_e_nNbM>9WvC-! z{j|ZYjJj+HCd=gd2}avAf=><-rtRF#I8CSoXWQ!(;r8s3*Vtf#+*4quK3R#<{B=s? zw=}Q&T761fwOrQv+3yE9iE7=U_aulV0NU)rEvvGV@O{1|E8YC>2O^Wo<7vB6xqgNZ zzcZ3f#?Q7eeII>lf{Ar|sWYdacqIL+H+S&cQTByBt6d=K8q(vL+}xHG`#q|KEeES; zXIZp0A5*k(CVj*ZZ``%(#@867Tjp4{+aYh80z++czLSNeL&ef|s*{*b!70MrPv z1e-*IId5MfbmEV!d1MAq-^1CSEJs=dx(N&R3qXJ6w4`#`c*2ek;SUuVkd553xq{1; zi2+UVPrg^D*(>dE+Crzz{14SuV>y-%S<6{`qN1&{b%&OJ*Vjy^{~v%RXNlVN%zmU& ze=tt!Xyu(kjK^;ltq>7ZG_yOSEHL@d?!9*TLv*)267l4IJYF6~!ZZ^9Hd%f>s|BWR z;^3%P3=aqhRJm!+Fo@aGB{eZfd-GIuUXv7O5vVf5;)&;Yx7uAd30#?@J6~g8r*~7W z#$y?wb%^`jQf>k`1)91r<_7` z6fXvH$@4mfZ=!?X*h!vhtG7B`9yTfeyTX=}KKt9|d6g|ag?`K_#)DQrsrnD2J8tvm zX`Bi3Y-a2)5G8C};{9}ejb4MY-${oD3p=GSiZ#T=>H^e4&^myagkX&UV-LIl8vPco zbVIKYpKWhJ)3bN|b?^7LS~v%s^YNJ6(d}8gztt7I5VvI*uXFGnUQ{z_%O8PP(ofes z#bz1bd<3!?kWck*1vm2&GB%g~a*WRM|2poWegAQ{akt;$e;okW9o%Qgm*a>N8bjS| zS)PV=hhjS5E@EPoak~0=O5;G)RwV?S-m6io;^ka-2}4kb7b2x>cW&FtkkIw3B!=qW zQ$ft^=bO4Rjc#RPQmdHTh_5k(D~&G1hpt|1V&K-n-7~Gvs>0HE&^KHf6+2 z1_l}e9o@5imm+GVcSJQ_I0YHuVf#?aGIl_p6P%p9&u9!O{dtB^Z&Dga(}!KNiw?Dr z##b|w_bTubn;(U-^oSe9(-n2pt}txSXrz9x$1cw3Txh>iAwn#XLQhD!Gzt7((0vra ze8?~xC&MH)T#hAf2Pt~T1st@wOl)d@asfLQv+d?J8Vw( z_hdCxUa5>``K4$myA^o^$V))m@{@xj&%-Y%+#A|$yP#!qcJUDaibEZJxAmlFK|K@l z+Z(X2!>QI`jq48~bwJyzW)EI5JH7B~w+^CO1aeCLh4uEcd^L`BQX#FX1U>BHR+QIG zC=~D_df+^k9GpkBdY136tR;j%3#^?$$6L|5fl&WzG=kX-C(>)>g7*&EeZ=2N@3Sbq z)Ta&T#AZoarph5M|Jo4 zh4o~d#r0@s!N`HNDJ#`zeso&G*`?1n^S;^UGk1j;$_4o}`Ot}rZThKk!|&8~4cqQd zX3ORUHcOQEBN%ZEd>2wjh6P^k8gIT8ARzNQ|2@Ay&SL?DSAhPceULh*>*J5VGyu7<> z`v1XO{mN1F(?GVHsN_@-WyYzR5Y(G_&^VORA8N@MfO30CPiq7&c4&N|9l&!iGP zi`RtiDyuCQIZ%KcB_F3H5fZBpIE)|;CI7O}L5Rmk;Q8Yz3TQDkp-4=lD-<+oN`CkVUk5;356YnWw7pN_8uvB)}OLzL?X!sWLY&OM6 zrbsN!v>#uKc5!qa<4jJjMAg84zNvk``#RQeWO!_X=*FK6uz`k45B>V}t8CVNcWwZn zQdD6;XtA|z@(&I{>&weJH>}|I>_%Tfd*R2{ZSaQAFKJ59A#;GMht6*w!1;Y&OL4WzCZh>6wXwH0Hw)vns8~HLo=Uj-B-SIh}t z)HB=rD}-~=oWH{8ZF>DOnX!up8GNXvUi5cJq+v2(AyL&kP=D8rsv6yCzA5F;Q&J-B zfQF6gBGS|0Ui+9cPE%w%qU1RB5NIx;gQk?p#GupzeqP;X#85>x9RwYX7yVVmig`3H zTaz?(l|?yhg(}zt1y;|>X7envWfmj(XpA6nrwQ|s@@0;h%lugZH6P={p5WA=R&}Hf z40s&|yWE@as~*i^so8q^f6O&xx0zTK`++>n5EA;iW!X?J1lkyFBwfZbi@$( znDr`j?B2P|Tzf)3I(^aqoV^i*#Ri${IzHW*eRB#|QnH)h@;Yb%jH>hH&^~Z_2xJ zl9;s-_u-NR*T3Y%XYB7H9%rC;0C?1CO^oJW)*+q#FSpJR&E`c7!Bs8`&0@pu&{Zk9 z)z?wMWNtpjLpUPi zmDMNoW3cMu1T8)YYx(Ahw~Sv#6KS&ymZs+Q(tQy-&192H#`$8#<;kMi zg;Cm+@{B%0!hC{alJl600HLa`rmCb+cG!NNpIAcUO>dJ-xI=|pYRaWA!8;;B>b9(| zB+u`m{DB1@bWM#KOsYSAKJFlTUi2h{w}9ys9SPK|&&ZiH>Eghs6M!PC8J*wXCQf*9 zyXQ#`Q79FVNeV@UGa8mzKUe_TBPHUw45mLtwB-{lNUT$}2JU;CDQ`l8VNF|15MUei zdYs*W#op}p_sA`Fz=r6aXUifAd)Am0ge~xoByX*bA(Ul!zYxg2LPAUgwr^A5m2%^= zu1L7b%QYa9r#{*ksel3U=GcQJTz}$#53Ro~yj^dC=MUG05YE3?igm9Vn-Ia0m)P$P z*%9Ckl<<{?r|*CUl3)7>JRd7`^#L-Uv=BJhsqZa097PA2^V%+ltJaYLX7WF3$H!i+ zqV&lSWXTS=pi01&H``yOzv=n^S7NOa{#KMQ;8B;Lbj1D1b+)Cf>xg`fiPLP;ZF9`> z6O~dNOe&R-HO4^UwkAIS75XCZQwxJ|Fq1nuIZo*@@f~T0P$ashPQDt$OUFmcNTiik z8pf(^6A>u%h1jK!4Wy*mgLe~2Y&3H!7atJ5mTp{litA(ht{^90PX++(bCU9*MO*w+ z_AjkQ96$YLA(~&XVTdl4v%-p+Jn^w1k0XMu$?_Vh)at5+u$^>^=Raw@VAhL4#w_c( zM8;5jtEDO`juSd;mt-7xGV*ILmp~^W;p#w{9;0_%=jC;QFNaU-q3=3zC4K_wypK*= z^NX_xa%bs;m+uD#Fd#EgGw*QxEPd`jNg0iM(L~zx*}1vN_39iIOSg~ao-bfZ_XZ%Q zKMDjZoYtvgYmV1Q(Xp{eY?90H&^_8ltKhdO@K*R4mv`AeSb$xDKM=&jukLNHCf#r# zAb5<8ldz&ix~?a_*VxeH6~e+3g2&#~nM&&4*38pWmxtcS^}N~(kuI#Ca; zl9pzKikSQsrfY2KmtdAvlQ{rmCNl1}!}i;_3c-~bn^(mcftJ3Nex3cX9GhjUR?UqL9{W>RmiNP*(Gq2sz zuKJ(oQd5|DszwzVX@|GiW5eO!+hch?<;m(8u#e-LBkjpD5*I}QB<%C&O+SW}o9F56 z0I`&&l5}oOzBZvBf$>%A)-@=GFQx%SDJcxH8F*GfJV((;*?&E6+T>gi1MOe4syPw z-98B7&zYA!E=XeFci0TBplwMb*l{t1l4hEF{;(;7T?jNa|$_*_J?wIIk$bQCI%NrmAW!xUE z@b}sZ|9fo(*Qew!LrH7Av3?2KT@J2T zI~E9%_s>JZ+a&o34#E|AKru@SQJI&3VDxAuC3QD@{YlMWNc2mYUqm|yhcswgrhy#j zoGHbahiuRorGLM5XG-6;#^ps!{8kopP z6WBGK_}=Z+c=~fI{u$SxCnl;4AnRLa#+DLygpGC)ax`|*Jtt1%PEadJ&8!Y6@G{Jo z=TfH&k{L$djpujH4uS;xX#X0dxme3&6BimJGF1qw)<8AsE#+?W5 zqzMAAQ6xLO7p@E;w~M&90cj3R5fK<4thji2W#3z9QV#==$Z!w}mH>SI7|5{wlpyPy zsD=A{hvuES?Crg|#so*76;cRLPH?=)Ul9Z~|Ax!0QUnipH4=1nx`60Cu0;Lp8c=nw zP^0~Ggo`cftpxfdaKSl4Alq|mlfc;x$3I6I9@99q96W(XB2cnN4!mNY1MmN=d43(h z+7{T)go#-}BM6=#IDLD@4@XITGU>h>`8hAApt*3-=I^fF?)+Ko! zcAkenl$H2}E}x6TXOm!)x5JcYe3#|keX~-31}oV`eQ5O?Rji`6dgkVMw*97*FVxom z+)ocOU298ZU|^8~s=KYFsy?|;M( zz*t5QeLPD5*8$+%M=1+H4JzJPM_L*Qi-=9>DwEhsL!E)(?Uk4>5H;$?AUV^h^}qAW@cx;kMEP?* z1}EVwu@32CA@`aV!K4&1o<_}weKlygIGE<_37Wl^vxVY}f~bc{^*ZTsho(sXn#(G^ z<~qwDmPr=YPEXTG2AluD4vOk8g?S97MOGCWs61dl;Z9vlM*qju{QkK)j0{j zVZm3;=E=YhN z9PF2|f$SU8@u$ewH41h1Z+gyrxyHPpc6c$Wez%i#S`Vvn#=O=z{R-x0XiNB(Qreic z@HD4&>P+b%&xXs98L3M2mo5w|v}lr`Pvl90Ucbd+Z=4jpS|xkt$djb^=3FeVC66Zb z1DE-ywMZn`T6q5Sl2}DpN=(^Rx6m&N)Q-Ee_JuF~_)OugEm+-H#4Fb(_^^=dHABImB(^OU@j_xSW$&Y347A&-*v|;e87pFIVX~M3<*&BY zDnqSAq7*JPM?M~KuPweg;OM25Oge6 zDAPZ73_d>>_Y$U}p^+X3;ujE|b`w$I*{JEFR!+v( zUsxeUhSKnrAS`*4RR1U|eT^`k(^J60=hSCEWBKFIf=9_&6B`uo-f+@(Vy<{5*JOKs z!r~xac&z<_5e=W?UG*B4TCb+QeB)xT``rb?j3UXyb%SKG`kqKUv_)-He5oiL*4|X} zbDt{Fly(Ku=)lwTUC+`-_u|w7BH|Gn4+QOuOH0J2t@QaRiMqm>U6AvsnzS$cG@~PK zd6rJ=>v*LHmSrWe%|xPEW2a``7n-;rg{o0E8rkaEs#WDI&7r2w9x6C}CZ-JT{M`92 zzFCtDyK1s&@yYQ8X@_`eU^FG&raHxs0m0PzMoehq0FL>#Pl34sO0305s|3A$Kicl4 zot1U+Tt~I#2icYGwO5u-Cm$Jo%ge(5dwoQ;LGwoZ$6o*WESw9#HL=$OC1VryWhEfLMMbbr4KI_OEOk&Ex==_E4f5nfBFgkND1AO%{X1;p~TBKuc)UZ+fL}u^LeKDK_ zvpJJAy~hndn@*l;8mSK`dJY_bO*x%I*WROf-2d`bP5p-TjuVv0iXqmxlhaxdjwM$^7~1t(zFLoOLRolFzW{~F-H)qo2(>eht}xShku#tDo?&~Xm~ib zbprjwtJ{l>PY1Y;5E!(lrT59q5zO~Vok^tdSYj|XUkyR-BsIN7|Ff^AYKESpk&{q1 zfyJe%#>J4@_q{1NJWtq{MOUhR56F4iuh~NM{RTn_BHt^0zyB!V6q3;Li+u*MEweK( z_eUPK(ante0FeQ6w35Lj%7YwZ$=;Er!Yr$yPINP+#tB&~#zai>aR20Mjb^Z0F?McG2+I*7@IU&vzNv-|o3c{q~t_cQjd&)Y)HMWgaf4_n&y z9)uudY)nq=)(|6odf8+w)mENvXK;@_)vPU-7{zEA5=lACYtv(Tq@afj(W{2t$RD>% z>M9Ky=TZ$6;H2%3XQaLA;SD{tYV!+AvejDlAN@#n^exPSy$vD(LKw~umd4YtUl%@H zjbs-sSh{l_n`8x(Q`G+$C-_{*j>0S>W8U9zE1hzKAXDe@Ehoj!2YuzQup{808@qrtWH#tczE)6L9)=%gv-+C(fU;Ox+a!VlMHBO%agFM2^{FEbMxz`(cJ~k zI@sIyR19%ml|?|Ve`Fd){&&-dfBgA>?0SWzf;7-mjLW>$^1 z)U=9te&ntra3(YF=%)f@Br4Mh)A6?}Fyr@ccP3 z$jTKlR?piaQ<>s`%&*4kP$xq6rx5;S+Au)Dj&$- zB+{OjitO-{5X3mBm~L7sr!~9vgsIxD*Mss*1qAEvrWlx}T(;H0wu=G^b^_P*C_Pk6 zX+}enHe%}0!mikz4}SE5gkRJwn_JBa5tez57K{2r(t-0Z{a(#VV@w`EurF;EC*Ui;f5)ZNp`Z z^%Zn4JoH}CcfxBNL%K!jCvgwddsU`_id7NN;L9c zB`pY0{~UC5OhRt4RLA1Q48gJt^)^w=CLKjvxr`*+Nm>5=lHO0*<@aETEPm-m4*8}? zh@^}8DZ8;E}EVo9?s;Y`>Z!+P#{T26@ z8HNW0L1}1Q;!}in^k-fUukX13MAWy4v@;+aac7^zqSMCdieje86ZH`f-fJehaSos^ zo_XiOzHLuH@3E6KWyQX3{ZS0dsWV950H&Wr4Sj<(_p&Wl-d0W+SNsAIvR&60iKnSa zCKc~ECp8dXI&=(+SM4!%>cq6QKdE;`&oF{Dm?+9d$|~|7oS7B$I=q%&y5 zk?|MU`1PpaOX=Oyg&3CPl*pl{(3&H9I21^d5n!+q2hZ>HIttvu)%i%oF}Vn$V5v`P z!~$9ObzgCR?hNNhHL}Q$8Qh2sqNFeGS8a7cc>g=`Nq99iJ<4>>Rci-|dRc9t$pLz5HN(bu$)zn+eKnOo&!knH@Ai%X-}6hxGduVHO&_}*@NsK#HCBY61v zS+-Jfh?LLKAJ`oM*po!?qJZ+{hr>QBh$1SOtnMs!hk z(OgJ=?;;yoP=^@H=9p95qbbADU8?8o(c9oHGnW4bTmWx;W(3-vW zn+`vnwJZJtvzfl^Jw2OHHT& znlJM!FOo=Cy+iAW)fMufci@%$eoN!UN$GpkvlMn}Donp)CgR?vkW!Qcm_EsJZpK`R z4`mgP2;JNBD|p6c?)47QPBjb25d21;CpIJ_2-kJizz7uZiVKR)EX5Q%&+gQnnx)yc zq+T=e!d4A`OKN+NHOKT>lx0|t4`For9m=4+SQ(0v3IzkQ8a)OJ@>ol}$5XN_d0qbo zWBIvAx(Gq+SU)#OJXBaZI$oYg8IF~``}PNRf_d}Yk?yd%%O6U6yoxg)RI0=uw(C@T z^yaEWdk1Pn@)}}2~=brG_sNx0( zCE`3hjzdTLpPoThqa-3-@Mw5cq3A?B=a~Pxt_|tuMpEdOv>UWE-H}UI{BA94GcK!J@Rh>H%OX;Q)OWWRY3c52C zv*4%CnE52|EQIT&6Dvg;YEmpaPuB7zln=d&VtRdUouF|SE?1NNj7iO-H+TuPDQA-2 zAOL5uT&jyoXiAYHzp_~*m1u`u21=L8S3f>Cr!PibB8IP>#laYyFLKt9Dr*snsaN7r z=OMa0!femcTj<vV{}B8K=ouh3|g{#65r>sG6j0tYIum94FY zUG6D_{omXp|wAPGYrZyA6UzwlAh5Bfyx_R6Rj9a zC<<@atx{vYBwm)6CcqBgB@K~uY5nk(wvV|F#jAFva&kGpCDM%ol{Cm`jI}#YsYhJy zRkV8^_M}#x7(_~uI#oFvCzX$H#Xtl%pe)nbUN}t7%hz0n-R#6*qMjU!`6p9C`M&O*wT~2F^_tspAxvH<@=UrPj#V1{E^;hpQ|XJ& zuM3q%Opwm5FZhU)#DXgpoDd+~U%#G`J^#x(@*@BEi>Jimej<<$Moj^{74EP07dy8e z3gdR~8+CMM6(>?zwq*AoCSry71K3aqS@z zmF_%&vF;l53p7wtVR zz!Ar#W1AomT8u73yP_Q#L@RoSoKU7cD039it4P|Cn62Z|nXJ#(=ictZ3Q9Fz;t7Ap z6UzT1>0`7Qtg(LW{-))684J>Kv@2}xli9l&vz8zgrEmoyM(Ras7KU{Ml#b&;pZ2@2 zcIxW7H<54GL93uprsby?YrW))`K^(TI_@wc?P&B;JtL1XPiIwhc3D|LZ1)UK4b6|0 z)C7?*L}WTe`n3GfC8j4l52MhMhLz&CsbC!@FPeN9At_DbkNAbu9qhTtFq^TG4@lzC zu&AkQ?1SEX;2LOAh^x^=m~unOYW;P}>g`6tXAvJsoN_>7r_oB2qK&DfGk=fHVb4Sj zm2~FtNUktxN)&dyR7XnBuR;~9t?K*;owZr04rza(y)lG&o9$?V|3Qgy2;gs z4>{V~c%)LcX;}O$zAlW44*Eeqc9QnU-xsFUAQYp!A%oBf(5bf!PXgn>abBJi-O9lh zjmn5+R3JalG*M$98cj;i;lM=6RXCw&_{}rjd>PhfIg?BZSu~AeLi{ssnXfvUVz%dQ zss*_oeY-xo^TdU47nY#>We?$GY}yA^zT5ar>8OeDpS7->EZ zlae;E43x^2@P30ufm|ognUveuN*2uleWcTYXPiTH$A^tBwOftTt zec{KrQlg>ZV|dUqD)JF-uuG8AbY1?BWJ2&6IequO1 zNoL?4P8tdoe-?WKh0=7mmUC<#)+waqorKnoI?N_q5u5FQ^HW3U2C*GuP?K9qvC14H z2b0i`$>y7?3zU>=vuH=2SbGlgApV#NL#n^N-Yoaxru)plBlFJDee~nVhYhW20=uzt zW$%pBbWcp@9&B4{`w{i%3{cZl8l){3E@OS?IFgVy_wGx5wbvUQR=*i`aeu2)-E`!9 z2>aTJ1Hyg(d(;7RMl28&B@zy?jpzZy{r1}}!rnZ&zwO?ojGzn;KTbX4Kt$}SkRM^c zxiHgwfkN-z!_ONs3*n87FEHtba<&N(-m!Pp-+3~Iuz5%l5X%SQ7DM(2SBP;da$d+^ zusJ(X4f4n!ASliOw)s#65+$LTw|>ZD7m`*6{WQ^M!TAt6BKyi>M6pG>a-p1;bfQg` zv}$7-Iaf7ASl5f%xR1f@m~yOb$T!~A)-^85R%v|Z7yHp<_qr`#hY6&R9kr|q88Ept z+=R%P^u)n(cPB;;pos#)+JCOMX@A_jE=LBI z_?*u+(Ti3a-aUIi(tuzz+$RfRyA#(I9~vY=W7?=^rP22}H$To&o+>eTyhCL7tEEK2 zUH*hk%YK(lwkRJD$rhf{LVhft6pW(NQ7Ghr7mtk7Qq!qOQtiriZc<;nyp$A7WD-y- zDI1Cgd>l0c%I?tq&Hs5G10}m=IZK;kWp-%`!ae{{VVuo*ko>)ZNcsQA zDZy=>J$WP~;sM0tdhE{luJ3AKU0*hGoppG%V0HO9`RZ&ZZ*@4+lg|?jOzo1==u9>m z4Ku`JZgZD34&E)9EwIUvh7ur4`H zm5^GC9PU?x50uf5tY@vn46QN2J3VUcv< zn*G{j*v8Gj1`DEx*dCGb{Jx@H85vP9o2Rc&KAoXR<$iasVz>{I@rXNx@MYRD8B zoXC=gSmYs<5M)Y_S4p?MPPoC;^>atKtX4rKgu`i8bsLW#cdG4CTZV?9juewk{e3i5 zAN96EQV~qUhGG31ncHPsBa7EU^GAWQ|1nA#8Pt$}nI(6x)262OCzBggh?~zo#l@sO zK|i9gdP>Qt1X*e&v=d!TMw97d7LCqQ50t*EZO?JVShB_dd&mTnzpWHKPQ&ik!SIgd zCpOUI*h~BMk+u(CVldYwEYvhRCn&5KGYFXvVoOb~9gn^r?YxAOrNd$xMJR3n%Q9h- zBF-q*#~_NY%nmi}G;p+^(2wTa{m6hGA5AdA-c-S=DdLX_YrVV=acJ_ypn3chC{$-` zEP4KnQzraRN*$-JwPUO-@z;I9Uz!)G^suo83 z0)K|WUV;UR!yX^-#O2MXX?bVf;2CWhIt8AraLzVYF?Qli_NuOZLzYy}j#rofjUhn| zdRIp%xn0j~Bu9AdB+4VHG^Gwub7d@|sB{r!+TASlow4`!Y>Ceg4{fMLL&!i#a4DCy z8ypsQ@HHI|!+#{V-`JChv^Y3a@%x5@=5aXOuKu|Y|NQF5o7Gq^A(cx@cfohtMj7jJ z%4N=I%Qlz?{8rO_J;hs2!8puJ`Wl9$2kC^`A^Qi+GcgVL&x{tmk*C6qbbUjl}dz6mr301=V*{uzD5L7 z>s0Do({h?xv#&L-moOv1(R@m5!uWBW)xKA5y1Ke0r#-U(Emhdo=EqU+pT;E(O|X0? z*u-(UuXkUpTr9aepe_m<-G<*?E%=XA_}%g0^$;<2qZMyag~kM7JC9P`qn}>&d7zp0 zOLeSE1C2N+{%VsX#|C!{y`b-$n5ZqBJy!Yw<6s~29gi^;*rI{Bq`E}O;U0`5n%PvC zDmo>-K+X#vPo=VsY)!t=dxnA7W%IhU;c8bnIdO=Zi=gFvIqHq5+mwO3Z_uazZqB&u ztp7dw^*dW7^Snj7ogKcmZ+j4sDSm_I*J{e`|9hGweM!=)s+a=G;N^#;U58j~jF3<= z=ZMb4Y#PG%khwSlzm`0r?i+oRSn4yT5(fNC3N?eJE@DJdW5uzXoGn5HTU@GyuNuSR z@+cGK(rON5P7~}RNTKn~exMt#?|cFE*_u&CcsKkKpM)uh%J^h!;*Cg~*NF{)J@AQ) z2(JqMvq3@eb4wL|3^#`;4aA@p_h2liPWYINoq&|+CN=H$~Smr`P6?AsAx@MN27`^-8JqWTnr5qz>af)GWvYu zR#W}Sr<2uBf(= zCocq`|HMCIMqrCFYnA<)68z)6{+$DSH2mKWui-w34vp*AC7JB}_9(_{y=OWnZlsQD zLr_X|1zrDl)tXRh?A}_82)*FE4nlj28_Z|~_8F!`7J7Rs=ne)_2eWo^ID2%7iU%WZ z8r#`nWp+7CWz5V7?CFiK0v|Rvng+=L5su(iEk23e_EZI0)~8QL;TvvlZuA=?U<@JT zzeo!inJ`rNnMww=bKB*wbxXfJ0uif0n$H!eXrao`DySZ_>{hofn$@N93;qZ=d-Y z@>)LaiDO2y5ThxKv>19%K2-~tiKZZ5pZwR`htd3bjxwt?1jq=0Y)D{zo8N9)0uR|E zgFoO?e8Mn52y#P!c05wY56euP4kM8JM{?WR+H9_z`jlOVhlg2=+FF=YIQ_0Y{?Li7e@)kO_0!fS z8WFoSTNB?CLTD%G&#ud}zALEMW%>^PlB8@E`vEG%`LvpKf>6Hd5bq zQeJXOnG}Xg`4xwMPQt!?D2QFJ4m-f0*$tu6W`YUUdOGt!#P&bShW{^9GDlAl^A-A& zlcAB9D#^f*{n_Iip$b59DsM4DGbZ2BJkDzf?8u;zOKfMzSkv?}>G zd}#8oeHW+vCy570p1e8NDFa9}DgRrr^tgw1s8fJtO?gH__BR+}Kv?VuM1p|XS_r&B z?PnlvH_ZW|f0n8NEdv&TBseVAdUHAp0tZsS&D9w<9RBqs8KDE9zC643{JA!_ww8D5 z7YcH7AN}C#RWUNc?f71-j`qsyKa1S=f1Cip<5mF3_?O_viyV(i2a6_2I)llIYQS>Q znbGSE0zV~W^YtHK8RWPWM?PPpC@CfLr^amy=vSn zNPBzb2cHZ!29W>jgIIs_kql7?FbA_}lk4*X$d_c!;L?h=)UjMSN|&;H#Shh{J(1?k z1qES_{#UaQr3{ga@K-;o%+LT})E}**GZ^g;up6l(^L8`yRLK8qcOK4e1!=ihPeYb; z>aXgHCh5MuIBHx9BMmqd%8&=|Z4TZVGBD%j?v6xjOR7yJI6gxG2aqBF`cxFXdWSW@ zM1VTC!Ef`u$b5cdBy%K`$gm$+5?aRtWf6o9fGkDpfLoE@{2pMlLRy^AHnITYBtS1N zOP|^t+yR7#hsUW0s_iuS!jk-iJL2D_E&r#*3kSy38h0WB8^!8?4_Q;3_UsgQ9Er4D zPE;Ur_+B1MW(;@05vrwr6s5o@HSPNXg9DE#?+z#xMwe8UiH;mwPYCzg@5CNFelAkr z4JP-J+0&HGd@|4WYAhwfhjdZ{~K2@5yg(c;eGnsaKi{tbhQBbw*cE#m;FUa zxa&J+*Qs*bnW0rdV7qoIavA{?t{q6YBBPe)dF;(@JIlZ`T7ba`h!0?l6Q|zMsB@Ud z9Nnu0BUhvn)pfq*+u88EO626bdVnqT+qXVS|1Sm4(jZn24h6-DIUV1))IT4d@c?Rvm=3vyuN+*Q6LUDxoW^H2LajX zbgMUiv-_S{$rbPzC;?~`9#k05K69lg-KQ-nE?(-!6<1=S3cz}NeOxGxq8}QZF@X-Y z)@OJ~c!!J%;5`TpCzE=y0`&sNcxhY~Pb;V-^aEEr(J0F<-K*;A-ji^@q3yZ3_3~=;PLf~{GH4B;#FKq!AFPswr@#Ww~M2!#Q0!6&CxVku)y*PY>h8rIHV<~6O)r%CSAxK~)bemT|dr*!t8BeekM$*aHX1b;#T!k-EyXzPVuUV6cqJ@)~pA7#MKY(4H_ zH0l%m?B%wr-R`3nV0NQNV8|O`jgYKS{~mEeBvjb#H)Ii5f6+|lfO*44hBy3xk~y_@ zLNP=0Qe{S}m|B6=Lli7RW^_MHw6DAsP8Rp~ zt2kP@5ChJq%&1-L$K6-qy-L5EOR+s?mgU;=G7V?&HZE{VSuz*_+!S zH)fGv5UqT(LXUk4xY|}W2Ci5MxXE5JX!~^<0C_M zQe{4n=`Df5Hbj-899&X<2XhcAG_T;3ZV0V%b4=6@&YW=ny$hbWbQn_yiU^$Rch54b;`UKeS(4bhI+;Sx;A*uo$)wJC!p}!VJ>LY^|-cOG}xpMe(DM zkd?)6c&^U&lnrky44O|XJ0pQ$6a5l2fcvXJ?nsu5t*z~Z+niTk#jEUV@0&Gt|CGA} z@mskGAzprdT%F2g72DaVCMi$*6)o>*%Cyb1WS-}Fszk^LrS01LI?uI^b*$r9=TCZH)Vc|6dq`m+U$oodPO3}Z zvnG5X(zYMQ^wh9RSMD@fuELzp zw;}%0k3)axWL?6czKHvZOnf|w<|rO{mHOmIrOTd?rDYZ+=hgEgCNDM&QH`2^JBQbm)!GIz5|pIhl(Dmo!m z>FV?O^Y3UmE7r+SI{Ran_IQ2%LYrIv?~XFkQw9{^aMNYi7IoEW=JVa?M@NJ3%kGpI zyjJ|E!L~oaB&rMZsOnvDTPOA{`z{d?2nq?MZ8kwvxU>A&7+K)z`7@!JFs{lh%Oyd6 z*6+`JMx`!t`=vpQl$6x!vXmK;Y|RD=Gfa+P#KSI?1EkzLCEtF)Ejdw5bGYIezx)03 zAj}B%6n4GsV`sjnt}^3nj&nOY&}P>mDUk7OS8?_i^BTa`AR6=hi?hB~ufw zk^eruRXllLFp6*_?jy&X%^+)LF}^!M_8d!GdsR$8H{iOKFz!=%yTa76?J@njQR&b~!0yZKm)fW?nox1+-e+`rX{0M~zN ziok40-;A=+zqYE5T-<5TXRkmH8gQTQ?(QxUL^ok^M>a+9GYu3J6#TIr?hWi7W6$iC zbF9+j;2+r%2z)8h63%OiGBP($$jb|;aNdF?y*2vk{J~AMY?@6JtD-`<=O7nae~Mca>5<5eq}3Q)Y_{JUGl z9^l-B#s90A`sZ(oIsa4`)EgTcFf|&7H&Q2hcoTtu>pMttMty>nCpXR2$qwgaA#rGc zmzVeDl1?u&0r2pmG-O0|;F%)){` zn7vWI!g)Ueo?QbRpsZz+eDRtve4xI0&4M41Xq{~}{xH3u{x{^p_O`aW;^HSzmgT<* z?di`?8IeA0f=!#G}%TiSKkYtTzmzJ2mBQ{6-a5Z3jD(*U>lT~sc5-1{wa0wJcaf9 z1MrICj{sCp>8B}by3B7ug`yYtNq4fULa`ozKW3wAFl?83YS#> zSh&R>@u$w&XnE+Hi~CTW3KTnMB@}v?Zrv&QFdrei2Zr12iBqSeLb(k|LIZaK9ouD4&Rz`Ru=5+-!#waCgdaOWg5EovkUe}O1QU|aM|=-tR!B}s!D}Gr9#g&uloHL# zUWQH;l()#$K7H_Z+^)|c1aD=3t)&C*j-q$6*#MrLf&%wQOJu$N_JX14>Ef167}%1e z$bx54p^~L7{DhoU#H%0*pi|eT$FUPwqHCA5Y}?$2O(%Z(f1(ksOdYE!Tdr)J4AF5_ z9RCxYg)F?s9EYu19{*<(PT0mF0t1j3U|Do1W14L)n+&^bX(5S%wzRYqdjLh*RR^5Q z7L#BIcgt;VW3RJS)x+7k$6Ak`JTORmN1tN$7H=|S@Bj&mt}z2W!T{8jyI97-1g%A8 zjSA&4CWAgkvu>SwnLRti*cZ848XAqrzoL*m+iPl5LIt!&Qc4PQp9y`yX5&(lqv zdFBOO_qX*2i`nb?3rsx@Pq6w-xx$^zAW}9PEcS;Ny8OJVOkDo@g;ez_lyr6_|;G|;31QP@wUPJzeZmfDSED1^yno@ z`^6|hbwxR0Z>b$CL<^yX0zj%G5H9DoD&$ksE6JsHWVyE?z+vTOa7;F2N% zYkz-#s!!eg^IH%oD)7(1I>oy+CrR{t;zn)Tt?mNhemn4Ua-a}!cxQD7fmH8DKj2`r zz1dJ{0d7mZ__=OwC9oF@LuDa4hpQo|mm6t1!ebj%`;(jjM@M)?!!TuCscQM(NNVsu zugdl{%Q4cz;NXj~`}{+)DoD-capG!n>I>k0OSXocJ-(*RoI4^u?9p+Hf*b)12645l z+pYpKr!`R~s(;#!=H&_=GG$U*>D-6}Vp9b|&EKpFCREDk$v5vw(pXwknX)7OAS^JK8S| z1H8N*Mer#teoPBG^F}OV5ym!<`lXxi?_J6=*O@2s)E;>7@gm+z?G?*x=dGo9@?UTe z$T!F}B~#(1?yJi-pXE@R4+7z=h{_7RxZIHy3{#we2Stgjg|(~z-Ndwa`Yry^y6jO63_dMswyC7Xxx3}w5dwnx8vc64^(0aop^JiwAKZ0-A^ zwFeqv8%yoxjZ94NCA#eqh*sZUyC|_+R;X9|3GdHTXMgdl7}pb!0P5gq%NKC}v1?Fc z1zZzZr4GNq~F$nC)Uf18OAoB7}H~YddPjz-sdF z@!@AXZOqXR(}y%#0mp_~fyk_)Bz5b>%C!Xflpfy7VU7c>H|6IPk96byZ9iO zJhgTKgaXR~5E%aR3<1h3S9ai(QUdpBN2KgXZK#9r@2uF;)7u;Rsmc;30#NNM)J47~ zpL*eov60b8N>cP6h%uYTa{t%bZRAbnlg(Pr`+vD<+RavZuxN=;S#Ixs_t$QD_jIq_ zcGpuMV9hGWBItJuYDNr;0oASNNcsC1;Q*2O-ajts{33PR{+@ahc!uuf>AkT_RX?FU zK!hY}NvIv$P4sbIWVUG? zSr6*j+AiE06L@=Xw0OBA1oCX8pVfo=@#<1ir;)W~<$bQoNGn(W6iOYV~RjHRAe$kA5=ShI!C)bC-fJVmMoB; z6_r}-%kuy2}+Ck_5;0e~?xr31cSLgR;j(5^Mh zt$sdVae9*HG|le^anad(AK#xL{|{l3^a;j?Q1xuUM%9PD{vClQHyxHVQOJ-QgsC^R zAX1LhOq7jrm2`Oq@bh8UCKOeKW(%;sZUPU0cV$`stjfVm)=-&4K+AO6<_~iDzky8O z=zm^rpMryfzf?{E8$&PxN9iE^de85M?rWznvW+0K^L;7>A3{kdPb@YOPzYccsJU>n z7zi_nZT|JGF98D|IV*p{)IMi~V8FWpr4POK8mz})7!t=Y@ckXJ(C0~~zhOXs) z6l4;x`x2U(FhLS_I_=IB{o)nepTplYN9Wujh*&}5VZ58J3RwVI%TEFME7d`{BE=E1 zcl;Uq-^!y->OaH^!#aO)_VdwusEeH1gYyhCZK~N%@ZgZ4Khs3vn5(hu=@WMmK)jd! zftE|o74k6N3UFt+hAmeiFsAwV(uiJlpNAu=&c_U-JZT7IMnTT;A{E(o7k1u6At&Ih z{^D*y&zpYIh0e`Oh%qozM3uL>#_RkJ46#3|f28^MUinD<4=R;&0u1^2`BaluClIBK0@`}bbS{JmFZxXKC> zXPB3a@Kh~pB5jT}cs{`L<-XjpR!&#-rTq z|Av$QeElhx@ZpaT#ae!TVL{rpyQjwn$Pv6u-nu6r2K*p@oOqsbx6l$7{Y!looL}y&_xsc5ydO?}VC491 z_zOd)V&lW8a+6YSeb`3p+|92HPv28!4e%5G;Ju4SE_Y5}sqenB0mVZ?!*^kyO+&Bl z96UZqna#|cn_cRwn;xe!C=Hf%DJ?BaEfrmMs^Ybt_!+$T$@hzopd^+D8eveowk&db zkfZ*2wDO%*#Y3Uo`OHBv&OY?^Q$cMt>3{z1juW*;>9PMj`ST@%{NMlh=Q-X;Lr>h5zSQ{rjD>?$t#9K7mU>9asLpo}!Ll%f|n|o?k=#@2^Io z{`UiiCGo$@3_gVa-CRg;`2PzjpM#g+r;>Gk@K0jV&RH3&8D;qnvO(w+le(*Re(~yt zCBW>Z#g$8Um6>7Wd7d#9bWFx()18=36H9)Lo^_YO+PargJH?_?_U;OIe%bn(OR~U% zArdd;on8AkIvFkgL}KW_kF)NdAiU<&l~r-HMMov1vJKN?b~6)|_cj%!ZW>ln=P?Wf zQ+wAk)u?>xDtMeR!A9sG10aP56M7Pb%4esgyaORCG^*$gZd}M~?|3 zKP^_8R`*%hRxXByX9eaM{O6HRj0DbBd`Z5gKy;7=XHZ3&w7u~?{rghUQF(1`EEFZrqkQLDQ#!wVknY2~SJ<`%0*$S4c<>|62RjlmYWYXF;(m zSSvR@o15OOJ{SEqJ$PR8n4%djLu=jWUo=>CXA<>Um1oe7jk~AhYZ8=62=54}W62KD1QY@8hx!op?U-*=G)= zMwvQbup*A5!sJ(R;>TpJT*nCRZ@UsN(f@tLJ2oai#Dw5erk=zFVz7KKv(*Qb&E)MS zT`}^v(9>oE%FV^JEma%Y^I5T)6VTOwV-Ta|ujY9|vN;*u3b ze71kDD6K0e0j}u39HR*U{OZ$Em~6Wt zvqAN;7(E+mBdh2ez2n_+>+dVvp*NEKejA123Db&jki-T{>%?O@t5PD`?i;pePh0UE zW--)nYS8A;4Bzp2Nc8IDGYqZJVF-iJ$Hlkf2W*Eg)AlTVMNXKGJP-{;lT)?jJ$C*# z-}BqilSzG)C2&h;f3Fw$s?N#Kz>~<%SNVbny z14}LmKHbEE$qVZe^o$RVHMf>bdq}jp=ec!u9Fqz*>x;Igr&#A2_B2Y*q>{kCa2^OY zlWUt}r+jf(kBzSsz0Ei;@-H6YIgS7V^tQdJSLI7XZ=ve zj>|~MPqT$s>IZKT#oEZpvhm8_@=R*_)wT4|_#mn4z7q@6*;dgA@?%L7IvD$C z|9xrqWm@Eh;-naml~VcA+1q5RyR_rj>x;iAxVz(rOpdHeRweRe^5gHZCULf&GbDy3 zvA!6jQT6vq{|Tkr!+p2hq9m(&Sum+XMYu3koss+R@W_>a<{KpFWZOJjra+^P&uu^zg`Xr89U&;~GkZ7!vHPcGS9>=##ghQzCbyVw3{?fY!D z2QGQyFSt$Kye^8!Zc29Kun-McGY*|L`4Q=Mj9cY+{YnFxY8lp4-4N?Xr4oY>pPfEf zKO9=~^;8fw)xDv6_ZX|FsktC@1gwLYjr~7MxcULW*Vv)7VU3Iy9ksFBy;qbf3^haVjr)Nbq{Zy+;f{vMwD3{+WI)dOp+RTe z?;zqqZvH($RwM;h8fZvVRAW`c9d0X~BI{ z9qqV&pJwJ3>l44n!^rOynpxg(-&&Xni>c3cyL0Gy!By-~*OF#`H-y8TR(B{_OV*OR zgzTi6{4ZlBhU9MxEwP9CWWDFC@mbpEG+VB2+$Jr{m&E3eWO4IOG@KLM&K8@SJ&xST zYv-Xf3qmIx-vJ^<6ZCTnTa}{leWRHF9tDuqxY)kLjx*W{w#*+3BUMz2GIt>oEu6Df z+Sd0tNwCiplS`{M^^wRklIDQH!UvOQ^_9|vckeVt z-kgomZb_4$yMtSYO?y4=^Id|HXk(k9%%b&&5=3=#%z3o3C@~3164~tiV}f(@o)a3i zHLIubG0ZMc8JgBaUK@S8os{*pC18CB6+)n4r-g$Otbwb z-rbcY(prLcR*XCwVa?{ER!?w}+l{NU;@cPs7l=C3Vx4nlQ%oZDpm}zE+LFEN z(1mwSXd!gB=NKyf{g24;*)P5#b3#a05E~B^TWR0!ag=#Ih?uev9nqtRn|kjE&s@HS zq2zuhEoGaAdGMtz{;M-)ZlEX&eNM6M9tbZSF+?vp3+uLM;r+DA1>*k=Mer05dM&a# zSDF%|u<@L@ZRx!N(HCDsbA|RCrA#Gcx{q_SGhzzaSao;&^cj1f9c=Su_{BG4&6Q88 zi6q>7nals8!MRxN+P4$|j)m~#2wghLynt?E&-7A}hS`tzbc;lTg+yt&-#NrEFt*-k z4F93`EMpu0CTqen_JX%1Cl%H#kMxyo@WP9|C0Cy!8XwDB;iby4k8D)ZG<5G{ZGVmm z=c%4Y$!Te^*JFm33|nLGVi9a|7g4ozt#6JL^k^%nsj0Q+$AHvDBhJBzf(~59sh+DJwN}^ww-}&q(KjN4l@RJR2ul=fabFIOaPB&T~ zV+vHvq+@tad-M9&p+X%uIHeff7<}c{D6vGg9{6Fd{5tE!a9p6K$dV!7(9?|hSqa|h zQ8`tjuAmz!r_bEW)xHm75!G7HCa(WGo7AL_b9O@dJ!xmz>sgP-y+10~ zdn)$%UO@GF%ayZ!XN~;YC!6gQ=$?gXwv5mUc%1va=)^7j=F!7b49~tvs5V@=KH4YC zi2l~(@c4X;376UnE+h12n#C0_5AxuSXJeZzQc9(HY{o);sYBB|+x3yMwwnfqtP24< zNFXpWLmKV{aN-ui*e~TnA2M%zRP!H3iFr}52HL*Mn+)i?_UIu|)#MzPz%BOv z-*w7&@9)%Y1az_DhAenKUwHRad9|;*aD4Kv{9afmr$Z@27h3=M%)*7{WY!$r9)qub zV_`hlk3q$K-1^b4GbSR>daeBm+~)RnY_P8R_0rNKaJ$;E%b)$$5@z<+wUM|^`Qgv)m-3w*2c- z?(Kx@R2T+sHYxw_^w{`)?YHt0xsAWb7|p6vHMj%M#*R?*ZV?LWch;fpwW>NWECv3z z8zt2;If|=&96!F*XJ%BBBvH;*AoBZ3tccNUS=5oRIFedSzHpk=I#j_a!A#1Z&Z|W@ zm}B9)tm33W;joiUA$s;hj7~ZUwV-}EA6%UK6QHj#PMUIZu~Hl*@o$~}1o{$sBz{h@ zxmvm2j-?B&pLw!F+{<*PQ{$Oh%o8HasXm7E7i9*yt8@*%qzkMQ`hF5;j%PPHc@3;@ z(pvS^RNb@A)ztr~#g%-tO3IZjKgA?{iuXn+9p;vR(8KGzt#n?pwddYqxz(?u>pxUo zO&l2hMQ%a(F&q2s>ENtPR$N1fep-6ICN|$_R6fdnmw7h&EGl0;O(m;4RVfXPnVg)= zHP--zXDr(An(6k+D9iQhKZ`3=bX=5>24DClC@d1RrUxvmg3t$`JCzATj$oXFZfE_A zJui^KCP1^(7-YQI_|#MuyV>>!!cOY|EthdRz?L_rn2!T*-45-Cm(%1IF3hM@?FK!) zIsFF2r`9ge)k;lIw+)#cDl0-Ji(=%9EQSX87&=TCmWQ$NAS3QE z=T^v3l?Gikbdg|pz?IMS7o?$?MMZUv5uR!FqZP|F;nn~Xiys;eH^BV(@dE*AXv3rR zxh^TDn3uWeSwArn<91h+kt;Nu3em=OKGc{FH;~Jg^^qZ)D3*QpzZHTf&z(T!GY=?R zw5iazh6#Rmewem(#!#L*zFv`*K|k&NwB1R}=#sMavp1oOg@(?J*cU~Ydb57zDe9L+ zJDk#}ZxKu&kS)P3B-Bf^sSX}kGE)Uar+ zW~2!1$VfE7(meD8rK~rjj1{n!Wr>e4PS7=NuXF|K!C^pp8cy^JKnt(^;@$;P zUP)U!+J5KTJ*HzlE2H1-piw^mp57!#LRLC;%s-{H?^{}th9^H13)oF~fOo-MJUG!D_oq#w1yXSE7%32VXX zdyb6~`l6uJ<6@A2EA_H)5;pR?&`6)0=MqAx_BBib%|#C4Z!<1JfF$lAb`>#NO= zdxA9@#F)yjoS$pjnd>WlruummNq>wlS$2y*T274-ShO>LckP^hQ~cP`(6Vb198Q_= zOLQ^611)f@Osmw^DhYZV8Zi9WsbLikNAN^X@+5D8q|<1wGX>M}O?TR54UX<+e1yoG z@+jk@d5p0jgAU{x>SS5&V9JBj53-TZe;zP$TdnsM28@A$L9Y40khr6xBZ5veD3Kw} zoui&K(N=EUInbL0UA!|k@<2geerz)iK}nQlvO5c%~OY&}PM) z!1@Q+ST{ZlJ%BlMmNOu@?FQulgTP)AXh|9x8w1ePjuZZZ@P^hwvZId8^Z{JKqAcZ-M|= za0uqes}&SDZ&~m^|5>h`7}&VCToq%7vnZWqtbi^Lro#vN;FxweW;94iW2)D*S!$|R zLqUNavy{`5k89Pl6!WI!Z4lp=0xi9wYYdj4{?U9CoFYbtVmTO*3K0zofOKXjf-vanGp} z)V6+vBvdn3X&(AsjoK)LRS`x8vyO@RC9HkOm6Vh$uHj((Z9Z5Tw$}VYLXr?64s%Zl z@dWo^XPNI2Gb?@ z=Wu}6Xk+M7_2(N0I13Mb7CS)=r|d5MHu>pCD+p&%fab-}pwnK#O~-h4Sx@^ej+_j4 z1R8GJtgK%S1U9ZWaO6I>S0ymkRjfQyTW=CyRsgfM*}wms6g9Fp`n^h!*GaD}JkXI@ z40n?$?~Oxve5r@?vh5COXVOUq%PfwN2SYEJb+9|5jlmaEG(?!sKaARar~3;3f*D5n zdeexT^y)jxc&%aChOT>KyU~TmdN7gE;bQcWD@BSS=g=$yYRtDA%iMloLmYC=(YH4j z)Nltgj_f8TPo1W9no&Pxvo22#Yk78$LmM=BLiFqn+Zj3G!|idb^_7!GmeDW9P9fnA zd*Q|OF375e+^Tk_uCQyDt72_V9L%(Ru^TWi!Zf%%aXQ@J!A8;ugK#a%zHfEax+o@s z-x8GRd4n{Pb-pw)YuA+NY{Xsc>2L~dgCbr0e^e z29?OW!8C05mN~9H!&v)PjMw>w#6J|+=2JdB}K*LxVU@Re1pb|$Oadj3{*g4K;mS!es?d? zeyxfBM6~#?0!1;OFp$>C?%dXVG5S`Zh)JM_2OHqeq{SBvVW||JtnF~apSEy=c(3}OEP_&l%>c6m1X-v{wvQL7^7 zu~*K1ifBOg#q}^2vM?c@W!MYUa4ymkwMEk+xQ1+TtlstIwGfGXH4@`0z`In0oU18` z$X$n$Yd-9b_luk7xT`G*-mn~x%*l9j ziAl!p=JJgw9Ri1p^*k@zcnK) z+H`RQC{GEjeEU;4luHd>+p6QW_?O4vDCB*f4T`BDC|8{J7K?1=#0!xG4l*qEMXrBw zJpAY6d!PM;&Sry@znZ5O%RR#b(E@OX)KY%zR(gE(mN_6#28@cP)q{p|z;z-9;S|Zc zRY!YO)s+BoBa0G(qOp=o_b^4rN3lH|$Qt>Z)b+ z>t@{yR6bT6F_wL~4|KpW&~JyBzKUx1TR)4rgp`2a7M6g2(kW--c zFrR%p^+fWXbmXm@%uz>>{&>Ml8;Cu3H?Ga7|E>^swSNkNnag8N6A{^hqbyOYCD8Je z;N~V2T-ZT9OLOxKbV;3d)p#a)t9Jm)JCGzBv$R=vqi+7yD|`e+SR6scH z3VuKJ0+XO<=OqE0dDxaol1vl;@m_$JQhk-bK{z`P_OA}m(^)%PH|axkhNR4HAZf|F zu5JQ4Gv)*@5CA@2-jMPGbjocm_aH{ZWf1n(&OV`5heWfTcS)juV4Gdjbc|aj%%60? z?n|ZF&9vS{K2P-Y?aL&dO3G8myWRdNOQqE-0e~a&SagbMPv$Pzz|<^h%C%iKl!`LC z^}(0NT$d#iB{&O;RS)!R>}wKvwu?5$lt5ml(4U-<(G_#J&V*^+%b_*6rLN(YtE8!! z4puoMa5h%1H5KUS>V8J2=+*hKFf&_;z8*HM0?dG5-KF1_!0}<$BIfrbO*dP`NOxRi z{U%&hZg?yJwEE@RvRQV|rfL|Hv@_EBQ7_=NgP=OQPQjA!UV};-Iyb3Io`#a z1d#_=ZeG<>z6#d-Z@$%c++I`*&UgHN6o8KE>mI3}GyZN8_k)9$Ws3B$2Dx%IdBVMn zsQC8osf>hE=KWYLT+KBC~pG*fqKBYV!&B7!DVJq@&(3DRk)sYLsqtpSoEEU@wbf=mvsjpZTnnnw%K3;zBvpYD z&Z)f|sEDO3%@f;XZr8y+m6ln#Yl3Odayu}kw*Emz1@d!`0gOJrz^mv8ifypQL;}{Q?rjEKZwr=%(qn4cU=nfyD0GENRhLj*R%Ay% z%D&%t>5d%`p&MYWdv@W;+0IO31#80UM-lQSBj4bf)Ru<^K$~s7+`3i94bcf_e`2i3 zU7ij)7Ho9B!kelM``|pOcd0r)+mjW8X8PU;@zjs&2#C2r^ub1!TNjiJ9fe&Nq~Cdf z7(4NH2;wRmul|4t;S5H2+CUGRZ!siD4JUq46cmBIIM8_5gCk48W@`JYLqe&ZWvi8n zwNFI=lWcH&wVtIEp)&d^{qDwm5*!}IzqEGhEta#E70ND9y3Ijh9ULEcH*0L{DGahS zYQ45aGU`t+o@nL}Dk}mV($H!zPa4--E8!32D|&bVWtT1%4!k_Zf=2A3yWeRJ&t7&{ ze*E||=rF%g_wsn0oe~C%^8p5?K&1Kz&L!s`tgI3$BIhhY#^TQ_6od>xK?Xzi zVxiXv1Ab2f#OncT`y$~zXJo{H6WEm%xY|Mw)}XvrLx>lFktC?CGyo`XQS0;9rNFJ} zp2(i(uw*({GoAg0;QOC%JqCE)WQeArNpKM7IuR z@uN^bwg10~;I#b706T2Fu#VfnjJde5?}0V>i#5f|m0nNJ=RJ9Y7Lpa5Hk3*2{dQX; zH$mcMTDOz&T48P}_EN6FfRIA2^n~~r#WnqueEp<_7lb|%+O9)ZiP&80H_AuHdj!e|U^mw1hbv_HvJG)KEtX&_)U3>|SB zHm7ej%h-rd0f-CX5hnARfng9STbUS}6Fc#k0Q~`b$tZgT7JWGVhqysR4oF_e<3F3u zjwFE~+roPiIL=83~~N3 zVT=b%q+_5v)xX22=Z&MD@B*9mZIETxRlM%=)w$?yX1hGB1(#EVJ`xhNF;~DM2I%yD zo-p()O`9g(4OeB(@|Al9zR2=)m3!=uFYjWGgZmj54*Wm=u}SUpFsNYLKytSt(>l1A!vYfef{mDz`5SM zRm{pfuD1-I0GfHFw+#9e7?T{VAXAhr7Cp=9wj2cXJpxIp*29*hlH*!ZVQ0v_?br?E$DKt(QnWkJ7iT;tFc<%P_$RAL!B9%DKCR<=RLYnh#Df~k40nQeW`vjno<1?8P zJg>sk1Yr;l8xNc!Bk|;gPUitAl3R=q63=?wUx$4vAzzVofVlD@j?5KR9b}-B0;S_1 zz#x?~rKs!6vRPS1I91I}0(+4|Gn8u?A*;dM=951k(Xs`FbC!06(<~f{B^z$p%ni!* zcN`@X*xDKEvZt9ETnCv?B%@$^CNDeVBm2_)1V}#Im6I4tWh0&m@P6M~UZ!Int;?6Y z^IQyHN|GIqtj17IL?D??T}9-cJP-P<*zh-6NtXMgf#06v6Mq<#r}*vY_<-_7!<`}? zadeBM;1$mb7cP%ury9`&?|LPfEuYpcOdS3o+no)*Xr(S-SR)`W&BFdMEnIJ*gZc~8<3=vV&RjjGx28Bf9 zSt?cEzflUthJ4dy3VrJ6&;DbfRGuO8#Rx{4$TL0g&WD<5%aqJ~uQDB>2-ksJrAsI2 z`s$ZGw-41ze^R*Lo(nz9P3O3`_5u#;R*<)ovJ8%T4x)7K%kEcQ$Z(I)fgk2o{}jp`pO*tE?L%)8Ly8xIm>kx^>k=(v{)* zC)k+XSLFO>;QKZw-W|vnIxBoNG=;lqdcS(vZWQ0zVRgmCV4W`eX=Ol@f}7xPp_9d38H?Cz^(aWPMlrtR>D)|sZS zGL6wmXM%COkJzSOGOw_Hw(fi^Zah}wMX_}ktI=!%gpU&-;D9N1)$D3^+EySRKlO7@ zAHgh!G$rCddjQNpq&BjIGE$MufA+kJoe1>4X^{O1oZ{0|KU@2E15#jyPOZZ(^nKKq zua)%x*O&}eB?)NxZk6YScP}mPcLg*p z7O6`t*@meIQUp%3;Zp3RlHQoTAqysbo8YII-w{SeqQ;Vut#pCa?h5CS(i|aCZ-P9} z#Yg6y#K*JAgPESkR^}B2QO)?Xu?bzYhdRu2Gc0xDQ*H4ACuwGQ&4qU0r=S?QB}e zUw|06u=2|i!CW+&lKM-nTc^`c63NupAVx{VgDH@OQ#FSLTxLAYL@2614wJDqiPLXL zC*teDNQBC)Fc`Rzot_tMJKO%l}x_|qT7U*p^$q1h3XFq)T4H|@*PPqHp*|o z^Rq*!99sQxcQZo;lCv$u4yKAqY(6lSk-I$?ps|&hqL3uH+OmDapds*KmCr6r4~SYX zwlQSFmgI0VPgrZ6w?(jBPw4dcB@~?F7n=UcicAYen}v(GIJNH-=H|9HowbEl*R#%M zXj3tybP;1=P(m;9*spgb<41tXN)EwQ&)5WoX2c#vCa1Hk>9Q;%GO;4Cnr`i2EiuBP zA*CtiV8IY8f1)4hQv7(D6NzhCYy;Oa9SIX0*-8>P<|JQr8ql6>v~D!+jow(K#C&M@kY!khEiw{$PrOGngG!!2^( ze9|+H#ZEFATDTGwtEb6*x)PF4O3eisa`E)a|4d~SA5&N&aK?hCG0{jS+s8-=Uv&>>78ASgP6U% z<7L*AC~qB$Hh*#I&p^{q*rWPjSW?J3bjTzmE57FfbqxbKJgqBV&+NrQ7nj)~IO4(v zn9!=Av46>6up2tI@=LW%HGs3iHUwwid_NTD3E&da0J^TBgwxf4n1z+q#)9(-pz)`Y zQOozin%M!w?6Ru}SZp%Ex|ZyAbcksT`$S$+Uie5CCKOPxs{ne3abTv<+QmlpRHdd$ z0*`}fOmG%%H&9KMRnTW?NO+_`FO*yXM34mbaI>hYK9|jIb}TR}myPLI;Lh#0-*utI z)77MD4HusZrGI~!Lzd+L6n2tM3&PDWkhuj73#SU`prvdrnfM9ZG7?11s=8e2m#KvW zw=zFb@=AV|yFP2942%(&T_vrTRJZgb*&V}#Iy#Jf^ei*$hH9T|nsbl{ugl?PkymLp z-!&*%2_`gVo>FgE7L=3^(3FA}w@5-wC!+bogoV(pafN9CCJG-9e}?SOj-syMA$W28AU$h+xPHE&QlSZn;hMl4Es@$ftZ4jTmz+;ps zedWdz_xM3y4X7uh(Mh(_V>z^x-X`$c-mWCZjp2J`|Dc%De^89Uyt9sE$tUMxLmrKK zf~#@4db-?8oI;F2LBXj!+D_k?O-GsebqD0HYtO~C2eX_H{}r%mP(r#GN{zGswtG`! zj*1jDv+%3lw}sa_Nv2AlD?|&KFjJDI|6Jw> zQkK~H{KA;DOfmNh3%AFy(QLYNQo3vVV|d4=rWqRfpVwHwVtA<K(!|ldV%sl5=+SsUCYJr3WF)S0!~UT9eH&c zEx_FB43=IlYV$AB>TCBC37r-8fFnu)OL`7O9JnVH2sYRQk3D{poH2*jQ&4Mw^kXx>L79Wd8Np-{kSeTJ~WSkeLBCadw2?8L-c zfZg$MVs9)a)0odrp}9u;I*4{w zojYhOTfHYV>v-Q#toYuiV_vR+Z(}_+A7UFF2(&FxsQ!zH)H37VY@sCsrY-IrZZ_z$ zx^7*(kwJ=NqgQ<8s{7$MX`qUg;BjkNq7Uqm40I$_!?45inA{T znmB(t%y~FBCo3mgI0{`xVD!t5JTZ4Qb!CO0zlZEV!4Oyqt<%Vo-?llOpN2R}_FK{5kA|TLk?Foj zszASq0J^-*GE$5x-F6&BcA@T*YX)^;BMzNZb!p#6J`0SFfPD+gKj|eq=_Ew zv_Qwf3w}w%C({ys&#cPbhDD?S{6cj5MqT67RFnQ=+@2*g9v<~YFxX=Y7;41M=f{lxwf9=VYgL+-EUQzGCmqh3xMnQm6D+NJ#jT zrj~q5?4{PBux2f_5G(YhBBH)gpo$%g`7JLJM=xP)4!z& z+x*Z2$|)rZjk)@DX8d?>f(+{$<`cAkpE+ANrgmML@r~bPV9ZZ$fwQX#@vG+_2L%OU z7=C+_%Rio$XR>({zyCebjNHCl(bGUpo-O_526T0^UNTIp`dw&=eZ2X=f7M*$?eD%u zm2%FvX5>DXC)ub!{Pe+8kl0*2sS$huJAjkW{!DcGbksDO!C>I$eFgpal}T-n7rPe& zj=C_n$M07htX1S<($lWkaj70R!(DJpu@o98x+I155h&Gh5xz&LjI@&vq4`7mhfuU@ z$1w4VhxF$IaFfLb>~26gyHa7JgiTFLLzF`fN1znc0_jTI$k*2l0u=W$i^o0?b|nIJ zUvw45KVh2ZLydz8wy)fL`UWYeG3`iM3sZ-l4ZUL~&I9K#yJoRmi|A1~dKS0{vo^M4 zNN*a(xRJf^yb-x@tVzkKw$YjDW*AAiG||Gl?tIHrqt8`Avfw}QQY5|etUs1?M*3!Xu2x=M&xaUKWy0F zo@naSo0yz5IH2;2vKT5&kmja%p?=S1D=98+RPA=&SAjT#-=M~8Eks#ye3uEUrUVwBom5 zghy7TH9jjaBDEJEtqom#2@P!aAp(^onZ>n1LrKTbY9hUQECX}hon-fQ`tBHM^D}NIn{fo`&zabXD&AR{wXZ~sDM8X z>>u`bN|V#tFg;dmd$W(HD{yQ+c=C*0NUho8pfZ}3^Qx-fC4aJG%;m>sycwRAEMA&o z7~IHbP0dve>#mI~d%xzXK_t$m7B${Dfnikru7$BygZx@bdiJP0Bu$#-*fwwJDMXjF>axOt&QWz43T}nU|F$ATF6L7`qai-?& zv3Fmu!$?a>YuDn4e-jAM4+VDf-7o?d1O278iTVHt1_U70@ON5X*F*$gv%B+IAZ>7L z*r(YaIf0Etd4MWu7N(JeOmylk!~buf&O{gn^z?>!F4DJx`K;J@ILCbs*pDvYFj+9_ zRjw8G%fnGt8jt~iKP$hIYz1RH`CUC-LeH>n5GbuL4yeEoNe5q2xS7gmGAo=fAY>(u zfwjE^sPC3Gd~xnFP{+yu0ms-^xJ9xUD^%Fzy8*ed(qX&M9vXF(=vgR?WhiGFCy|bY&_EOosBFs>*G>VQDGu(%~Z={G#@)+D)~sq>bm0AF zLLUc1bbB+rn$2c`{rYu3qygc)Pvt@rYRX(Se;wm(&#t7op#NMW-{^7sI?~=aPQm-` zk5cO@gewR$SR^;YS0a-4*O{&GcbH_O7qmMhzEZIL`rYm9um#*E<+ijOO_hzN6k$G( zp&LS3L4T2!K@~`o&)9h2q4;+B5JdOT@_g9n1|ceT@xSX$|Kza8N(|15rHQI@Sii@# z46of4n!mnpQ05VFTMTYuSs0MbjZ~*nzRsqhY~uQ^X46`5Z^!UucKk&8Wm+kJIn@ui z7eZ?pVRJ(3w4H`-5PU(>D0SiUCK|qjFx|;#% zZlsa!W`^dz<5%b2^YLw5M?6300NbmS$CeKWMxI`3)&xFW!viG&C70X5%!~S^fG`?1SyD zE&_VcBmFnWBg$^=6jlNXMwIHnQG!VhFftRMQ8l~4#Kfdq?^%+3@CWqIUe?qd1J)1E z4he2K*=`z?q6qj(PIHm~yScl5pv5M)l>*!;C}>%LhGffQCU%*|r_8#jAs}vw;V3E5 zHV;_Ms70X{Wl?%l3jzmAxx5Yr_0mkXL|aO^-6m#+Hq=7_UpGz&u7Z};g4>tJb4l)B ze*E|$?TIDZk<9d5?X#tnP5<@VUnZbzt-6v%5W-<#O2?ABJ?)lqBKrHaRbc7~Qv7$5o-{74W!eLUnlyz`@o6pR1V- z@NSO+t&E!gYrc)2*n~9Ow_WIk{|zA-yRMLcA&6Z5K84u52mq$ayAY(R40Y`A9PolH z2OcZ)_Orm6!y(Drd>80}Vi*gwOIkb{DTw%>Eg?WEnG1HaybF3HI5=`qmu1v3Fe*N) ztaAF(^4|Ti849uJt(~EiTkU8h^JL6S=Vt`ly?k@Yp{&*QksApvJi!~ zNs3E1n;eWJ3UF1lHEZ|zjcrj1bHI998v6jZ>6>q$rsrcLH=C>Xaxi{p6gUKyAyD`R zhc#pi-0qk|6ah9C=%ex(YbMlIFNs_^1p$ze>ps)90b&!m@IJ{S-~$_{?n7W9KaFw_ zLE#?#2@I5o;rgI1yKBIsG0jV15j?$2-Z}zWlt3bpG~~H%I!oBHcHu22&b*kv9Z(?XBneCnO4|YjXo~c$YtCL zUn-KV?WMl8m*dU<%5%KRtpA4_j9u-8T;6lz7r_a%$4bmlGjMRC4wUsd)z?_xd%s4a zWY{QcY-->AW(xZpnQ)p$LA%VMo3sX>@c7Kaqstrl+z3Y|>f9FM9ICs_V(^GyBC$ZS zAQ0$BpBav(um9q>!h1AiKc2jPuY^=3@p*PK2&5eKU2TnnL;NR5C6^!K6nBv z4mR`9ZQ^1o7e%t~-x@t}4=W{<3&Sj$fZs1@D2W7K!$?qFbAYscJLj|LgA6*@f@jHFS*3%~$25kpM;U7; z60C6d!pZp?nrZ5bqZ44&JxSY_wsHIa<9PG2SF;`CN+MMujc@RuCdur)?Xzou7Q5LwSZ6 z@kK@^kEVihn59~Yt(7a}=(ocZ`Fq$}z?=lbMPgHT{sBD2@hfs#Vn|D14 zCZPk@Ez38Y=2$v|hUl(w?i<}aCOp~$wG$fO`pBYwwL&;v@7+93UFynlM|awnQZSV4 z;Wi{5^Oe}EKRN~GdAM+is}Tt|jtgYKjR)#^9smP4>+TC3fJBt-x5*CQ`bQlreCFdv zd5}Bxa8|kYid^ph^0?^gK)LDruJWh->0(LSPDry*SzilbNnKBjA7eGDcKYLRvIOjv zrVDluWI%P4>~sdqASIy7Oqk4X0JVwE#UR(@a#zPXRSI0XkA#{oZncJ(Pg-GZ_fh8_0-IpG253w2mSiIm`Z}2Eg>~7F#x?nZdMXDtN)mov| zTsrdeEbn?MmOFRmGk0aE;#uP=fCZ2RASB&MkPs4T2eMmjU=dk<5qY+$)iiZPAspMQ z{-znPPt*xmDj%grw10-{m+v}?YKnE*2|JCE&w2|bV( z6!0Am9Ly8%Oz%!E`jZPlqOa^zuwH4zy@K#$LH0%B_K4e>#>8;Cxgs(|?+ugxT!WFW zeB)UE<%-~*6?f1XpDhooYFxSxv7?my6YXDu7(Dq+I~$8FKiUzf7K_wBq=#p@6^?Cc zgo@C{^1LlJ;P}N%8bzKkohA7RCTI!6Q*qA6`{em;{%d{2gp%`gIju;Vi=Zlrc8P~R zP=^Ont^0sC_DLMzj#Ha1>YAY0n$NDmYGSL^J7S?*gG zSv&K<;ti;035$IMM=uC6lm%2K9Iq_P5|Jp^u#u@7px>>TCyY^Mu5$naLyP$pl;z}t zO&jVkOD%5zGF7y6M-@ys{fGN}e-Mp(K}gYotqaO88Lx-M%}dL7gY`i(<`TGViVrp& z$%csQ`rTvN=O1&6~M&{SB3 z*+Eb%O#&F4LaKpKQp6ug#%|X=&+d zAn-W^_pg7Fqwf+G^%e%KZa%475>?^+T@Jk5$-6Y`Uw1D~(vfrdt|4;Z`H=l5`BGzbWk~pmVu$2~ z_|Qp+H7<;J#U*x1GhUUU^o~^5z(mp8!ujlFbY65i`6S=H=`D!%8wBM(U4Q$xdXtP2 zN`{Wwq|Qt|haBD8td_5HH69wkFn7uyE-}Ps--crh1unRtki>DG)bp47k6d7rNy*dQM zdySc~7f|?Ko~7M9hTQBE-tZJqZldhr4%0to08>?$1);0d%HH!g;D+262A8V(+>MpQ z#U!j5gQuYv=Z%g~L?g&dX@q{AB%7iIp6+MOg#HnP$MxX8vIO$dGqQ5j;yb-YHVpuS z-`QJ8;V~8-&^A~I%Q@q30>2A#3bbNs7Du5_N=g-HhAfB6fIo^e1 zs3%;1R|U;qMA=2jJsYHZZZMr(X0JE>K`b3n2SEMRYtCjHuzfL zNjA#w5uKRuiG?9(7q4~P^cY>=4FpZIV*?;S91WiHDXLz?4P+>z2O4LXl!q{;dDKOX=-f0+s8p3M)*UnKw_yB^>>Zpy| zzr<`3q^Q7I#1C#ku7TOCtGwUua%*Bpz=>ACSlPB{908OpJMF0{paj#xP1ME&&h5m#%!8H7e)`_ZL6ACDXygb z7Hc~{MyyS(L{lc=czZ-3ZFMF&b%APuW@l>fWO-J9aPp=Ats4dTk7uvmYlTLL;Y`iU zwIZ8c%coCb*01+BcHOQ30+$>R6vnrN)X{w<4={QBl7sZw$3BH3Nrq3_0XaU4$9=W~ z3!pXRkLD8*lCNJA1qPAdhWj692KppXPAR|i1H-Os!25pnE!#_A#g5;2bG7Hu+mjkt z56)CCu&%JPapxNSL;&^k?3!_CSM=MMGGbX(b4&CMKpv=I9$r2^zASgt%-u_oo$}PB z9yNcIZ08brb3OkUU`6c815k*+8GEILwqH@?S77Bu{@%;_y??*xk>d3s_sv}=xL%TQ?-c>xh6tZ#J&-`Gfs^4e z&m&A%#FJVuM8(V@!VAV_mzDSXPBc2LQk=0Ifsu0!nBT-MECa3HdP@()4fM7X(mC0eB?=y&fqhSa@89$o=*V)$ zEaRSt_h=6ls5xiNW$Ufd`Rwf=8}XL+8m{I%V3!SAdvzC8C_KE3RGZvmsrJbO10qY1 z=s5+@2P`!620>{fTxC3o+o@RVK1R_1NJIB*OLKk~)o%WPAqC)Xk%EvtzdfHCaIu|M z1zc2xouTBjXdV(^5BNvKH*8z@RRw@Obq21F_W7HudFZh@_Mu-Iq3;5e7-3TA1rCP8 z&=;s-r$;xJM@JJzfEgJ-0JGhxsN4;|cv>)Aqwmy=dGQL|NI*j^vA{~g)Anc;^zWR-qUke(It(lD(*O-e6mziQG{M%8Z1x@XTeilmid8jBfWZH^6 zrX(bbZ?tB>xBE2V=>~3HMTj6;_1;NwN!$Clq*+|}Ycuw$fB@q7v{kh-t+=Qds9CQPY3#%p~>cQ0>8v?T}Vu8UoP> z6X3#HlB&=*S$>3kF+A+lg(1V_(*k&cuY_=SLRN9WzWOdR&~`P+Zdw5e_!-%BW@aXJ zPpbDOn>dgRuCa}<$KnE%*{v=U{^iR~tj5VC+yzM%3x=2$4EDUq0K1JnL$;?ZdVmpd zKo)=ow>7$$O8q-)>T8@|*MO4b)Puda1_b|@`d5c)c`@;yKolEx(`g&`dG_(Z<;2ao z(a|u+)mxKJfN`*om6=emdKFr4Lhb@s*Abfv$ZMfwb(-yW*LjIZD*(w!!RK#PI4FB5PqL)?f!#B3uO*h~20{WjIp zx|>)BB2$>G)lFMAz@k9;GoL&#ox##t1~cW^azYeqE^4S zIG*vAd&?~r#j^O9h&hqmw=#&iWCBL3y@tuPX$>PX?n>nB)hl=Iu|08IfU!;h0D?Ba zoPf&XLDSWAQ$xoEDj^Vk*Ux8AjG$WJd=h--yA3`cbHBpaO~p#sZ)DcHCIip$@(=Ab zy`(Zl49e&gv_3lSJGb8P3LxdwjVVHcCwap8tkf9x`Lc1lwC9kI<02SX>K*|9+GQl& zJWzfB-OrZShJq0;3c9v{5x%r|O-hXnCaOo*v^Pru_32UzljCW5-STOukpR?|5G$(N zKDtp)JHHnIMt%E+Wa<{KdGNhZH`o%0G*s{}GKy)q=4w1$WTPGc_{>7+T1;rfavD{? zMmDdW7K3}G_l2_PD10wI7rl5XZb*j87#%{Up?d$(UPq>tq!=xSGThVWaWQ)5Q-b;NV;29|3|SLLLI6z}D$6Zdx)*&^I7lVm$!4T}XE03yQ5 zkm0%ok9)iB3Y9ru;dLNIwzIboMeUj|WG!C zsxpY1$gZCaxD3CEL|qmGA4}^>S=MjXZZ6aGf%1s^QMGAlD89~@iz|BY{IHqDPx6#O zVd-lopD34|p_aFgvZ@~_=8+W|1Oab;A>hy59Ql*!M>dFGU~1kExI6$(yq>x{4TrHs z7zY=j(_!4jvzY)CUMRDuI&aL61=>N*uAZeN)_++zSlIE41%cSoSRnmy$Y%Cpri-`Lt0x?(O|ZkP?9SJKUXkC+)_D1Tr{rR{Y>1a z>Hf!yG+Hc;hCltLjDBJC>}w{(A8GCRk}St?y3q*3#tu)Orcai7Nn|M7X)z^;>r2FJ;`?J->Z}z{9$|{rq zLKcLLQ8*ZYxlF}c0A3R_J3f?7NWHqFy13aQ1GlkPz5p4l0A({)g1b(TR>S5iP{gNo z?oA+sQ7|2aD{2-$u|rNl#qqcRnE|F(ox#1MR5v=TzcH|jYVH~00)T#TAB+R5&$|#3 zqn_o0cmOI|l`Y=CXM3Yb%W`_&tgOqfdJbT5zJJxaX*Qyxi9%z{#-ha=`yS@@Ph<^P z4|xjIXh@R-l}gp_x5v(RewaW$9fV>3xjRwFM)5FbI;wj zJ0_I)cjBOz-y*72HZyAThbN!Ye@vI3tXPw8Hznoq+K71!Uv?&mHsD?|lrVsi_lPEOhi&u9`CH7rU8hwN|zm&;cnOX{W6$hp<1}c#Zk*4^gt9 zLXeRP3zh(pkD^=S1wBpGwSWx%UGMeAaKzo$HwE1K6W;llx{xz|mNpA((i_(s; zHISmS-~qxr&wzaLc6HKXpCvyb<740rlB@ai41Qn^4BvafztB}*|I4HCi2C}(=tfYP z1SHSjB%$D;*9BNZ;0RncI!*(FVktm6U*{*9y5P_aLdH1a!$Dx&@@5 z;n4$S16nU9!=t2$eH-^8+y7_*Dytd@oU(AzuiCai5bWU4HGqO0s3R>N36A=@*^U}J z(2fJn2k(Jq9M1_lL@2s1nL3OTgg=mrs&|#m(=Y|hl9$qI71$6dPA#{%a|var-R^<8 z5NZfG&6rSp%Te>($JPlD4lMyO9Oi<(qYo9g&t#7$@YF&(Me%+}g_|xl`2h<+1$keKT!2}x2#{RF z!0m@hWCxdBA|V8@4loouX#zCxf$XZzsB2xX=|r!t;pQD4*=knc94M?0l|d4U7o9@p z5FJo*XviU^ay1Ru$|o9j-7Y`e?9(1X-cR1uE&+kKaDsdbDa-|%SdfV04mKgGQUL3J zvaASI~Adqgvq0HXIn21XQKX1EL30oiqAOVLg0a5cKf$U;&vm@qLUAxwBKh1_g zpQMamw?#s4PMQE>I+h8*sGk3T`om{Ft$=L}sUVHMmO`nlH5(L;R%EPnArEM+!5lrSs(Z{MZTpTfGO<-zPsoa`9uoC5)KpN>N$|N~@8t zdo=8>C+nEvD16g1g){Sd%x*R2>b&We3!Hzv?>JplacNCa^*ELU&A3E$bZ)xzp;UzB z^L6j)Y_&Ys)HKFyK8*xn87N2TM6eRwzAwIWW3MUi##W}Y;}-~R^1V0~q3|~!3zPnXigJLb|JS=#Pwme>;|f6k?_ytzwa_oOw}BE{jH?}{^}0#sbD{KOgzi$o7% zN2Xz@MouS(M$tqKs@JrN8XE1^0G%B0!Tsc-c@Tw^F{gKZFd%7O+lNnj7=M2k+oz5R z+7O&MlC$J#U$APXr~~$nJx`C7Y=SZ}Tvxq&QO%b9Lh>`OPLZMXoLXEB&T+B`Iu-WNq^o?XN7iX{?% zzxlGiN!k7BP76r?J)~u>@ZX<(z%K&>$qc2+0@4A3#vxf0I+UF8CExT5>)~QLp=-qW zS<%Fn;^e*Gp?h)UW*qEcuCUvBRiorO;@f=Bj-xH+iX8&yxiL|3QZB_UoSog+9~EX+jQ_sRDJLH=@R( zS2ZFn^v*gAij{N(<{RewBTKa8mXY>LZb~_yjHr$iXH#MD@)!9q2eBVw-e!1)MoRb7_xl)j z=V#2_Qk4x`T5&@y%)C;0>=$kQh%O$O$ot6Hj^z%mTirW~_~W%ZBlx84nFU$94xe1evCgytS-_L~-pSjNClhu7=7p%WA7JWIf|^u#J-Z2jI$)`!uO{^>wzF4fkG@asV0pmT%Wnya_(*^QOt zL9edU#IUV072);O5DUa}@`ph$n7EyHSNX>)K(JzhaK=vYgV7@W^uWjIJ|WHIIEQ~W z3j+h$tn{3qJ3=L`oOn|7(ant0(=FnPT^(=HOs2lj1$IYTTxL1cnl@K%3TzQ(U*VNV z3TS%RzqsR!KAw$sTiZsWh}UKF0P@@{6C;bnOZwJlyzxNy^!IEj*wdTDk`db43;xFn z;+9g5MDIAUw0jSfeek@TUNkvH&hd{@gqE;8<+0<9$Q0SnR36YhAP)?B_|NYedSq1# z{nv{6-{-Qi`vLD?J%7F$v{S*7AcI)GE)25}Li;_ULt^)>LHzM;?^0uO^d&w*jriDG z3Rp`Pi8v2J+05j*GM{JRRul+QCRd>o#pthwGv2gO9!W zh;_{uKR-pU4bqvKfo#r*)@3j0!=pVzGSz!`%q{*KeFI*c`OAOpg001z)QuEX)}KTy zq<23boMYVDW=>Wt4f;Sur#$hKLr~+V#g8$*Y;zt%-3;jK=SsfBq?IRmh4-_c=z||v z#B~VKrE4Y#Z{@3w%FUP_i+wtL0+ZL;Z>Hn~+AB?oKP%bMXxyntdS1Y+L-F}_&V{gd zz?UJ;3g0W^t{LtfUg`r+EBbI>8_}z(0rDqMjTzSztWNyWrHP@r?U;Y`(zl`98Q&ee&0EU zDTOnCtrX$pFuu9LP#zG*TNkBG6wQ307)RY=kIe;@7x~rp+%Bquw`BWV7fy;ETB2}ZAp3R{{bW8 zZ9SuO62B=@;@jQVYj@}dw2g=5B=B+2Y3~aEnqnS*T99g)PX3whR>^lAd{G|5!QJq+ zb6o>XwDg*S)c%1|=4uzZj{JOdo>~irM(aHZeH+h#x_+}+0xAeA;VXUGvQYBWX469s z+!N_&T@6Pox&4u&XtK8T?*5@jJ(wK7P_I1ADc&c3yMc$nJq@Su=M=1^N5W!4v+c~4 zWvm}7HrkZdJipp=>v}GfBbolU86K2<{@dFt`n(xFatB8RhmlTB!Pq=aHbg02*$i85 zO~p%d6-uX1X{=bM@%)Wdv?c#0{v%nsPoM)}`BUz3-s;kFY}TuMt?jg}i~UX<2%)$} zj_Oa<+xpgoWRfO_OFv`?e9h<%$})4*Zd1@WZ%tH<-IAvlBKY2kwGUmA&&(G)`kF89 z_SU!t4;*nt>IR0*+1M$uJSL)I?fHtb{@3`pLDfzz9C19KFZXMqf{2Dkutz&h zX>GEhRtg1pKV+2y<%U&47Eco2?s(d}VVW#YS3%Y7(pDx#ljGSoaK}5*%{EWEL>T}1 zx|9CZ(>!B#nk07@DGS0JAWDEMQGV22PJ|{YZ3W%0m!hCasgA`G`i=AP2zGIfprjJE zTS$mBsjA?m_A4mNHC}pB8H-?ces;3wHSrkY`{%|NE&p5Nq(y7GdHUFQzGZa!UEQV- z8!wD#%lhJwtvWfR>b&M!VOr4SlTE~4^ZB$x$9FU$kZcaUg^@)kMny`cle7W%*FF?E zw+n4%o^(dPl`n4XsfnRs?i*g;#A~2s_pm5>*R3AyXl8Exc40B`4hw;9*ZHX5cz#7I z>19-1DmJCX-$cfLvoMKUs{^js|5(0%zqDjW{ievoSn;d0*p}Z7y|*e2C>cUZv_tz! ziOiW~6dMaKj<;sQl@wqaS}`R;4{T~eZ`;n7y#KTGL+1-&l9@w;`~u(e`vJo^Uu2R; zJ2KoaLfSA2V>*&X#+@z*JPr;BjbgaNLv;KWDIxE*G>bVuHxI-|odUlz)=%0Ec7kJ> zKfH{7_9UGR{23m!(2`ZKAg9%y6Bqj2;}Y4!&s#nG;H$+m%Maw8Txn=pbKmvc?_ZUw zDl%_$s}7AwYw3iGmqu~A&scJQskfhhGeNy@wq`lmMe;x9DbjkR>I#6O2|$7T^srQ8 z?JE%pUJ?tQ7qTT-!iTg&t0xWAS*|woBd{V~aO1e(vUlDH@Hf5$Z4{OaAsP z1H&1Xl<~(AdB#f2zBs0C`OnYC-E24v#Bj8IR&{^K)DA!BD@jn2m`d6kfT)i42Ga+r zEy#P_Lw^afJVkSN7e2PSr%+G(IYcAQnPHE33oqO4A|(&br;Z<!kwf3Aj-v7OnJBhKDBRn8wY&&OhbtIUKInK2GmU`0D;5OLa zu5zjClb%4(_FaR{IV5h}u9uxC(s-6z0VP&s3v6AC*I#bkR3A516d{7zKED3GR3lc~ zqvY_Vm{TFbGQWCvdg7Vs{)mG%;dqLlAE0#q{oVxr6v%exb;8bMsylnH+#Q*ZJEDkBK8CN9sg z6-!M1`5FrT?`8NGR2Y(lyIJM4e!nlP!27$^bYz=kVO1&N1^mqluTA)P?f3wn>Tgjh z=?)iegE;Qe1)U%Z67Zw{F;aB1z;Z5)qwGa$CY+x-OE45$%9v+EqW)1|!h-ukJRLrI zkV|5^{wjf^4qm%)L0h)wY^SS^Heo&*B8qeh- z>^$OS6zVI9w48!tdbe^;&^DRp3fr`Xh@`UG1l?+`l?;_XBd24236*Pck*!g)#+F}( zVHm8@NwD|@86qln8{HIZus+HL0R~Ypuzi(-kC2gUc^SKYeJoR_jzI<13NiS z^xI=fUFdmSx^2d9*4-~%Yil!9Dlzokp=MJ|V#D}2CJSpl>{$_qr2@~SiHzmx$Fn>J^ArtvZ{-y zjV|vJPn(Oo|J#L;I@X2wWvC9RB|7bNC^i?807DK^Es3*qR^G#XOfk%bZ%$>FE2f(% zx{OYs7{nf{Di3ARB~{<#ATbdQu28KjzzCI_C?Ta13;|`m{?*FQl5x|K;Rms?uYUac z^>#&|n4Y`h55nWJ^MD$LZ~Id3nZ3@}K?MaZ&q8IL@E|x5OB~#l#;QgQi;mJ`OGAG5 zG9f)wi9@y4KSjGG>)kK|wbX;)V|I@cY^EJj&S+$ZXMoN)kSN%~=5a|9Bh;vr=6`-97W{>_h+1H? zr&K&zopTc{z#!FQDo;Ql2NY@|?ek zS6%$XNtGu|NmO_8E6YOh)_dj0G=Y)Pnsvhu& z_JYlCe{-z7bEA-uHhhc^&mPjPHJbPq7{~+T2!4BD`aW9qVW?$;hZUpK6(`llyT9JY z**cp2d>Sljg3T|pwlMC#U_0nZD3W@nl9Tc3M0&{XEU{inRd{YhU(Xj7WS=@!Is+1=&1)l7Kk7W^%+!ciAb zQoCPXSJ6drw&ybp53^ZClINajrhp2Js8}PuPK{iZ-Ex^kvdw-C>TJ5NU=0;Y7sZH` z7nEQprF*H6!r>%E()N_YA3ZcjMugN@0W29~`_Kd5(#|lOnxG0^o%NtS3N0H3_Q#7b zUi#kxPK-Z-$%35M2IBCAcw2R>iSSmwrBmblc^45VH-mU(`t-r2Z@`B1+1a+Y7~`2v zmsQ)i+Pr2@j=gCyr-wg#&qM3H1lOzC8sdjBN%V=|?Y{I{1K|N2>E~-S@t3>#dq*s{ zDgJ#pnfN;6=)%-7p;R2){!dAQ@740*lKbwbKi2e^CX6-Uc}}T4^pR44^3KYklTY}& zd~D}?cV4&!F*%$kn1x#{4anpbIzg{&=Ur}ZIW(pg`JUlH^2O~5Z0Aa|11y96OHb^a zpAZJXJ+ahrizAaOg_s>kD#ID<%wj&pb0PJ~VUvl}Uz&v&$hIRYjqt^a$1(4nPM*ob zy-7vMw23Go5`;k8Z$T(`LFH}jF%n9`9D+uhjOo5W?Dgw;mO$~Z&n2fiErd_;2H!?a zU!Ou2TTPFait64ZAd2q3ed{kdP`(P4pQ6MlkAui&K}uFnm4tuz2E}jT>Kiz zaAPS&b2f7!w)ZLDnX9wgk9hGEFKQ{z=arNYwGog1fG}9B1t1bg`IGv;`=?X!|95*D z>vR@X+3hv)_?1d1^5g!Nep_*enf3cz+WJVhLeB?t3L<&&@mep)ipyZ+9W?Jxay%~E zI9u0kv0O>-xX`E&i^ypgG)R6_GroaVj7=6*Y! z{E^CndT!lvn9=>bA=BAQy0s5iw3jGimTvYWZBk==terVPFx-Np5I);13UYX^^NE`1{20RQtX|&M@?5{)O$O1Y#4gv#3sbA z!)hv|g&ob!m&r5A1ws!vP4W`4Qy?0OUxzH8sN(Xp#}dJI8_CWS46Wv&q!ICk2Vyv+ zQ@#9kcT>&^Hb}k^3K7vkd!JN$;~UWFhTX6R?kai)Ys#KM0a< zAMlikl{<=ARC*!Gq*xXfBQJMXXFt7H^77SytlP?LYKVN*s zbJNT%No4lWEbK>=)rjn?IIU{iU_FU^4TJH}jeT61rJ9BCN4Jc!-f|TO|jjeMbI$WSZe&tbhUrR~?M) z44;s2Z8jzU@&l*&2#@uRo#}}6#E|!_g~o5!Jy!obCuz}PJ~}R>ltpe3n_FsdUME6W zc8?dob1LE<-wQ=m83n@|caaM#k%_H-X*Jf_#ZtfD^)f=Rp&`m&G6ZWqU&vM|6hgbE zdia6>@jO=Qb0x6prr2gY97^wwD>L=R7tc;P`%^Cr&-JI^gecIE+0E70m>CLPfgYtZ z@I2^yUiH8AV2-sh?GJeKtvF310F+2p@wpm|4Bi6UEc|fmR zs72Z$Bg@*j9VIg9Xa>wjT zlzR!@=Xb3t7iX-HOo@3}rrcEm$^lHM`4t->g|FkGWQe|&%F`JZ6?l$_O3QJtb=8D8 zVPS(|<3#GbL!Do1^vS?p%1V$K?$+euwS8#X^Rv>aOkNWr6^c#KR61EGQ&cs>$5vAw z?e{+|s;(Lcf{KGU0e=P$dobXN0aMg`z6^(wDVDzP71{#sqE3^*$ft?Whv9!V?1Uu||3GLe3IwpG$b9^E1Mo6#LQE9WCSUuh?5<pf z5b{}ls}ot0+`3nKSks5Mdblj!9V9h~V6;TlUB|+S1Z~OHl?W#k?`unWi{Zk!vK>9! zj);XHl&RhC0Buz9LuCt+q{!cU!cW zM^KfQ;F(44)8p5i24iZyHg||~bSU(tp~c!sqa@ZwXY^TzzaQz@noMr1g53lz{^gV>sG_Q9bG2h9i=S1-|19=?rNFkv?3AI zKby7I6-&>6+WClJhbGq!8;}c=x@A0=V1G+EPDCMwUO?pG7Ew9Z_CR+R5(O5 zh%U>EJU4S2pLHesWzBZGs)PxTj3?FE1nUeQpo^O^D##;2Al1bq$`^$gFqL1<5)ztm z7da_mW?*o*`9l9}hV{N4`vX>Nji0})JuU@K8Da@8J+Qs+B`ltG_rxg@u}YFUMO=#x zc~@)4b8I(za^W;rGVns8k>9L2{YibLNTrA7p5dRqQ)6Wg;Su7xADo6&WS;drNxP_J z-IA=j6cO|AJ-I?cC0Vc)9@^b^?uTMgX&v&A*r@Q?#6rh)T8`+0Pxdv`L<Yy=i}*woZ&;;<{y6 zW@P!f+M??zj_=YlbS0{)D&g{QiPD59`pzkA0Oxy@t3_j z!FT>iq|LYPeXqYskAL@3s^}6nFT*d3aeJpk`5%Ae7G7v)xHj}dl1+(T2+cY)*f+y! z+maLj(i4ZcZ~x}qs0DDjbHb>?X3TIW{=Zk%$KKojXJ;ywCg{C^dAl(=ss)z^fn-H(nLb(*}3yQQ7$XzMbeLLGLXkl5pC> zFp(6?TkFu`!hX9lXc5#o#lFpd)3uej#Ic^lzaQObTZguFa^K!CioqZ?PK`JFYezE@ zcPCa~^Yf#+mvM-aKc$fZdU3Bg3O+1?p7W=Qa-{WCBKzIfp@N{}ZEzKG#8alV$IfIF1Un{3SIjWv)I$RkI@zb30b>tq zA9pvF^s<(mdAQ9}qMdwuI~lhf5TdS0L{XM?%~EMI8@|zL(YMCax^r&Q;V_JRPSVDY zB0;2fi%$vd#?vtD{PV5rLi(T&k_wnr&DfoLV&!?66h@#D+$SdRGU|(uX8Tu9jg^LV zid#M3v$AuV0;$KqlQWIQaa!?iOq-bsubA$Ax!@(MVKo8ggZsxR18dlJ9A!hmw+2YM zj>;>$#^-^8`@?;g&bjrtf2^tpxF}xVZ_`8BmqOX@LOA2M1?$KB=5qY($S>wr&{c