From 870a4bd32be3459f29db52945a199a731db8d0c2 Mon Sep 17 00:00:00 2001 From: Krunal Patel Date: Fri, 9 Jun 2023 18:40:58 +0530 Subject: [PATCH] Add: GitHub Client with Retrofit - Authorization with 0auth - Home Activity - Add UI Components Assets2 - Add Profile and Home Item - Add Profile item - Home feed - Separate Api and Repository for each task - Add update profile feature - Add repository listing - Add create issue - Add logout - Complete parallel and sequential api call - Download release - Add image upload with progress - Retry request - Logout with interceptor --- Demo/app/build.gradle | 19 ++ Demo/app/src/main/AndroidManifest.xml | 25 ++- .../java/com/krunal/demo/DemoApplication.kt | 8 + .../demo/appcomponents/utils/IntentData.kt | 1 + .../demo/githubclient/annotation/Retry.kt | 4 + .../githubclient/data/local/DownloadState.kt | 7 + .../demo/githubclient/data/local/HomeItem.kt | 44 ++++ .../demo/githubclient/data/local/Issue.kt | 36 ++++ .../data/local/NotificationItem.kt | 21 ++ .../githubclient/data/local/ProfileDetail.kt | 122 +++++++++++ .../demo/githubclient/data/local/Release.kt | 19 ++ .../demo/githubclient/data/local/Repo.kt | 50 +++++ .../data/local/UpdateProfileDetail.kt | 82 +++++++ .../data/remote/api/AuthorizationService.kt | 15 ++ .../data/remote/api/FileService.kt | 28 +++ .../data/remote/api/IssueService.kt | 22 ++ .../data/remote/api/NotificationService.kt | 13 ++ .../data/remote/api/RepoService.kt | 27 +++ .../data/remote/api/UserService.kt | 28 +++ .../model/request/AuthorizationRequest.kt | 9 + .../data/remote/model/request/IssueRequest.kt | 9 + .../remote/model/request/LogoutRequest.kt | 5 + .../model/request/UpdateProfileRequest.kt | 12 ++ .../model/response/AuthorizationResponse.kt | 10 + .../remote/model/response/ErrorResponse.kt | 12 ++ .../model/response/ImageUploadResponse.kt | 34 +++ .../remote/model/response/IssueResponse.kt | 60 ++++++ .../response/NotificationsResponseItem.kt | 13 ++ .../data/remote/model/response/PullRequest.kt | 8 + .../remote/model/response/ReleaseResponse.kt | 41 ++++ .../data/remote/model/response/Repository.kt | 52 +++++ .../model/response/RepositoryResponse.kt | 99 +++++++++ .../remote/model/response/UserResponse.kt | 39 ++++ .../repository/AuthorizationRepository.kt | 24 +++ .../data/repository/FileRepository.kt | 41 ++++ .../data/repository/HomeRepository.kt | 45 ++++ .../data/repository/IssueRepository.kt | 42 ++++ .../data/repository/NotificationRepository.kt | 35 +++ .../data/repository/RepoRepository.kt | 109 ++++++++++ .../data/repository/UserRepository.kt | 78 +++++++ .../krunal/demo/githubclient/di/ApiModule.kt | 153 ++++++++++++++ .../krunal/demo/githubclient/di/AppModule.kt | 17 ++ .../extentions/RequestBody+extentions.kt | 33 +++ .../extentions/ResponseBody+extentions.kt | 30 +++ .../factory/RetryCallAdapterFactory.kt | 108 ++++++++++ .../listener/ItemClickListener.kt | 17 ++ .../ui/activity/AuthorizationActivity.kt | 140 ++++++++++++ .../ui/activity/GitHubClientActivity.kt | 109 ++++++++++ .../githubclient/ui/adapter/HomeAdapter.kt | 34 +++ .../ui/adapter/NotificationAdapter.kt | 21 ++ .../githubclient/ui/adapter/ProfileAdapter.kt | 43 ++++ .../ui/adapter/ProfileDetailAdapter.kt | 40 ++++ .../githubclient/ui/adapter/ReleaseAdapter.kt | 21 ++ .../githubclient/ui/adapter/RepoAdapter.kt | 18 ++ .../ui/adapter/RepoDetailAdapter.kt | 19 ++ .../demo/githubclient/ui/base/BaseActivity.kt | 45 ++++ .../demo/githubclient/ui/base/BaseAdapter.kt | 63 ++++++ .../demo/githubclient/ui/base/BaseFragment.kt | 55 +++++ .../githubclient/ui/base/BaseRepository.kt | 30 +++ .../githubclient/ui/base/BaseViewModel.kt | 9 + .../ui/dialog/LogoutConfirmationDialog.kt | 22 ++ .../ui/fragment/ChooseRepositoryFragment.kt | 71 +++++++ .../ui/fragment/CreateIssueFragment.kt | 72 +++++++ .../ui/fragment/ExploreFragment.kt | 21 ++ .../ui/fragment/GitHubHomeFragment.kt | 77 +++++++ .../ui/fragment/NotificationFragment.kt | 57 +++++ .../ui/fragment/ProfileFragment.kt | 93 ++++++++ .../ui/fragment/ReleaseFragment.kt | 80 +++++++ .../ui/fragment/RepositoriesFragment.kt | 66 ++++++ .../ui/fragment/RepositoryDetailFragment.kt | 66 ++++++ .../ui/fragment/UpdateProfileFragment.kt | 21 ++ .../ui/view/SpaceItemDecorator.kt | 27 +++ .../ui/viewmodel/AuthorizationViewModel.kt | 56 +++++ .../ui/viewmodel/ChooseRepositoryViewModel.kt | 49 +++++ .../ui/viewmodel/CreateIssueViewModel.kt | 75 +++++++ .../ui/viewmodel/ExploreViewModel.kt | 7 + .../ui/viewmodel/GitHubClientViewModel.kt | 37 ++++ .../ui/viewmodel/GitHubHomeViewModel.kt | 39 ++++ .../ui/viewmodel/NotificationViewModel.kt | 94 ++++++++ .../ui/viewmodel/ProfileViewModel.kt | 73 +++++++ .../ui/viewmodel/ReleaseViewModel.kt | 74 +++++++ .../ui/viewmodel/RepositoriesViewModel.kt | 49 +++++ .../ui/viewmodel/RepositoryDetailViewModel.kt | 48 +++++ .../ui/viewmodel/UpdateProfileViewModel.kt | 57 +++++ .../demo/githubclient/util/APIInterceptor.kt | 45 ++++ .../githubclient/util/GitHubAuthenticator.kt | 33 +++ .../demo/githubclient/util/GitHubUrls.kt | 20 ++ .../com/krunal/demo/helpers/ResourceHelper.kt | 18 ++ .../repositories/ComponentDetailRepository.kt | 4 + .../adapters/ViewBindingAdapter.kt | 22 +- .../com/krunal/demo/utils/AppConstants.kt | 14 +- .../com/krunal/demo/utils/PreferenceKeys.kt | 5 + .../gsonokhttp/data/apis/UserProfileApi.kt | 2 +- .../ui/viewmodels/UserRegisterViewModel.kt | 2 +- .../krunal/demo/webservices/utils/Resource.kt | 2 +- .../src/main/res/color/github_bottom_bar.xml | 5 + .../res/color/selector_text_input_layout.xml | 7 + Demo/app/src/main/res/drawable/ic_bell_24.xml | 13 ++ .../src/main/res/drawable/ic_bell_fill_24.xml | 5 + .../main/res/drawable/ic_bell_slash_24.xml | 6 + .../res/drawable/ic_discussion_closed_24.xml | 5 + .../drawable/ic_discussion_duplicate_24.xml | 5 + .../drawable/ic_discussion_outdated_24.xml | 5 + .../main/res/drawable/ic_git_pull_request.xml | 6 + .../drawable/ic_git_pull_request_closed.xml | 7 + .../drawable/ic_git_pull_request_draft.xml | 8 + .../src/main/res/drawable/ic_github_mark.xml | 5 + Demo/app/src/main/res/drawable/ic_home.xml | 14 +- Demo/app/src/main/res/drawable/ic_home_24.xml | 5 + .../src/main/res/drawable/ic_home_fill_24.xml | 5 + .../main/res/drawable/ic_issue_closed_24.xml | 6 + .../main/res/drawable/ic_issue_draft_24.xml | 5 + .../main/res/drawable/ic_issue_opened_24.xml | 5 + .../res/drawable/ic_issue_reopened_24.xml | 7 + Demo/app/src/main/res/drawable/ic_link_24.xml | 5 + Demo/app/src/main/res/drawable/ic_logout.xml | 4 + .../src/main/res/drawable/ic_mark_github.xml | 5 + .../main/res/drawable/ic_organization_24.xml | 14 ++ .../src/main/res/drawable/ic_person_24.xml | 5 + .../main/res/drawable/ic_person_fill_24.xml | 5 + Demo/app/src/main/res/drawable/ic_pin_24.xml | 5 + Demo/app/src/main/res/drawable/ic_repo_24.xml | 5 + Demo/app/src/main/res/drawable/ic_star_24.xml | 5 + .../src/main/res/drawable/ic_star_fill_16.xml | 5 + .../src/main/res/drawable/ic_telescope_24.xml | 6 + .../res/drawable/ic_telescope_fill_24.xml | 6 + .../src/main/res/drawable/ic_twitter_16.xml | 8 + Demo/app/src/main/res/drawable/ic_zip.xml | 54 +++++ .../main/res/drawable/notification_dot.xml | 5 + .../main/res/drawable/selector_ic_bell.xml | 5 + .../main/res/drawable/selector_ic_home.xml | 5 + .../main/res/drawable/selector_ic_person.xml | 5 + .../res/drawable/selector_ic_telescope.xml | 5 + .../res/layout/activity_authorization.xml | 74 +++++++ .../res/layout/activity_github_client.xml | 53 +++++ .../res/layout/fragment_choose_repository.xml | 28 +++ .../main/res/layout/fragment_create_issue.xml | 70 ++++++ .../src/main/res/layout/fragment_explore.xml | 18 ++ .../main/res/layout/fragment_github_home.xml | 28 +++ .../main/res/layout/fragment_notification.xml | 28 +++ .../src/main/res/layout/fragment_profile.xml | 41 ++++ .../src/main/res/layout/fragment_release.xml | 106 ++++++++++ .../main/res/layout/fragment_repositories.xml | 28 +++ .../res/layout/fragment_repository_detail.xml | 114 ++++++++++ .../res/layout/fragment_update_profile.xml | 200 ++++++++++++++++++ .../src/main/res/layout/item_user_detail.xml | 10 +- .../main/res/layout/list_item_container.xml | 65 ++++++ .../res/layout/list_item_notification.xml | 102 +++++++++ .../res/layout/list_item_profile_detail.xml | 22 ++ .../res/layout/list_item_profile_info.xml | 45 ++++ .../res/layout/list_item_profile_name.xml | 58 +++++ .../res/layout/list_item_release_assets.xml | 46 ++++ .../res/layout/list_item_repo_container.xml | 65 ++++++ .../main/res/layout/list_item_repository.xml | 57 +++++ .../res/layout/list_item_section_header.xml | 46 ++++ .../src/main/res/layout/list_item_work.xml | 50 +++++ .../src/main/res/menu/github_bottom_nav.xml | 23 ++ .../res/menu/menu_toolbar_create_issue.xml | 9 + .../res/menu/menu_toolbar_github_home.xml | 9 + .../main/res/menu/menu_toolbar_profile.xml | 15 ++ .../main/res/navigation/github_nav_graph.xml | 98 +++++++++ Demo/app/src/main/res/values-night/colors.xml | 12 ++ Demo/app/src/main/res/values-night/themes.xml | 7 + Demo/app/src/main/res/values/colors.xml | 20 ++ Demo/app/src/main/res/values/dimens.xml | 10 + Demo/app/src/main/res/values/strings.xml | 37 ++++ Demo/app/src/main/res/values/styles.xml | 31 +++ Demo/app/src/main/res/values/themes.xml | 26 +++ Demo/build.gradle | 3 + 169 files changed, 5760 insertions(+), 26 deletions(-) create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/annotation/Retry.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/DownloadState.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/HomeItem.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/Issue.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/NotificationItem.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/ProfileDetail.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/Release.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/Repo.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/UpdateProfileDetail.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/AuthorizationService.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/FileService.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/IssueService.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/NotificationService.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/RepoService.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/UserService.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/AuthorizationRequest.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/IssueRequest.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/LogoutRequest.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/UpdateProfileRequest.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/AuthorizationResponse.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/ErrorResponse.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/ImageUploadResponse.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/IssueResponse.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/NotificationsResponseItem.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/PullRequest.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/ReleaseResponse.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/Repository.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/RepositoryResponse.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/UserResponse.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/repository/AuthorizationRepository.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/repository/FileRepository.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/repository/HomeRepository.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/repository/IssueRepository.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/repository/NotificationRepository.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/repository/RepoRepository.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/data/repository/UserRepository.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/di/ApiModule.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/di/AppModule.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/extentions/RequestBody+extentions.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/extentions/ResponseBody+extentions.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/factory/RetryCallAdapterFactory.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/listener/ItemClickListener.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/activity/AuthorizationActivity.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/activity/GitHubClientActivity.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/adapter/HomeAdapter.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/adapter/NotificationAdapter.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/adapter/ProfileAdapter.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/adapter/ProfileDetailAdapter.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/adapter/ReleaseAdapter.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/adapter/RepoAdapter.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/adapter/RepoDetailAdapter.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/base/BaseActivity.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/base/BaseAdapter.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/base/BaseFragment.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/base/BaseRepository.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/base/BaseViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/dialog/LogoutConfirmationDialog.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/fragment/ChooseRepositoryFragment.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/fragment/CreateIssueFragment.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/fragment/ExploreFragment.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/fragment/GitHubHomeFragment.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/fragment/NotificationFragment.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/fragment/ProfileFragment.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/fragment/ReleaseFragment.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/fragment/RepositoriesFragment.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/fragment/RepositoryDetailFragment.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/fragment/UpdateProfileFragment.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/view/SpaceItemDecorator.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/AuthorizationViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/ChooseRepositoryViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/CreateIssueViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/ExploreViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/GitHubClientViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/GitHubHomeViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/NotificationViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/ProfileViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/ReleaseViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/RepositoriesViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/RepositoryDetailViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/ui/viewmodel/UpdateProfileViewModel.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/util/APIInterceptor.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/util/GitHubAuthenticator.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/githubclient/util/GitHubUrls.kt create mode 100644 Demo/app/src/main/java/com/krunal/demo/helpers/ResourceHelper.kt create mode 100644 Demo/app/src/main/res/color/github_bottom_bar.xml create mode 100644 Demo/app/src/main/res/color/selector_text_input_layout.xml create mode 100644 Demo/app/src/main/res/drawable/ic_bell_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_bell_fill_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_bell_slash_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_discussion_closed_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_discussion_duplicate_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_discussion_outdated_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_git_pull_request.xml create mode 100644 Demo/app/src/main/res/drawable/ic_git_pull_request_closed.xml create mode 100644 Demo/app/src/main/res/drawable/ic_git_pull_request_draft.xml create mode 100644 Demo/app/src/main/res/drawable/ic_github_mark.xml create mode 100644 Demo/app/src/main/res/drawable/ic_home_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_home_fill_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_issue_closed_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_issue_draft_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_issue_opened_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_issue_reopened_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_link_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_logout.xml create mode 100644 Demo/app/src/main/res/drawable/ic_mark_github.xml create mode 100644 Demo/app/src/main/res/drawable/ic_organization_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_person_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_person_fill_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_pin_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_repo_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_star_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_star_fill_16.xml create mode 100644 Demo/app/src/main/res/drawable/ic_telescope_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_telescope_fill_24.xml create mode 100644 Demo/app/src/main/res/drawable/ic_twitter_16.xml create mode 100644 Demo/app/src/main/res/drawable/ic_zip.xml create mode 100644 Demo/app/src/main/res/drawable/notification_dot.xml create mode 100644 Demo/app/src/main/res/drawable/selector_ic_bell.xml create mode 100644 Demo/app/src/main/res/drawable/selector_ic_home.xml create mode 100644 Demo/app/src/main/res/drawable/selector_ic_person.xml create mode 100644 Demo/app/src/main/res/drawable/selector_ic_telescope.xml create mode 100644 Demo/app/src/main/res/layout/activity_authorization.xml create mode 100644 Demo/app/src/main/res/layout/activity_github_client.xml create mode 100644 Demo/app/src/main/res/layout/fragment_choose_repository.xml create mode 100644 Demo/app/src/main/res/layout/fragment_create_issue.xml create mode 100644 Demo/app/src/main/res/layout/fragment_explore.xml create mode 100644 Demo/app/src/main/res/layout/fragment_github_home.xml create mode 100644 Demo/app/src/main/res/layout/fragment_notification.xml create mode 100644 Demo/app/src/main/res/layout/fragment_profile.xml create mode 100644 Demo/app/src/main/res/layout/fragment_release.xml create mode 100644 Demo/app/src/main/res/layout/fragment_repositories.xml create mode 100644 Demo/app/src/main/res/layout/fragment_repository_detail.xml create mode 100644 Demo/app/src/main/res/layout/fragment_update_profile.xml create mode 100644 Demo/app/src/main/res/layout/list_item_container.xml create mode 100644 Demo/app/src/main/res/layout/list_item_notification.xml create mode 100644 Demo/app/src/main/res/layout/list_item_profile_detail.xml create mode 100644 Demo/app/src/main/res/layout/list_item_profile_info.xml create mode 100644 Demo/app/src/main/res/layout/list_item_profile_name.xml create mode 100644 Demo/app/src/main/res/layout/list_item_release_assets.xml create mode 100644 Demo/app/src/main/res/layout/list_item_repo_container.xml create mode 100644 Demo/app/src/main/res/layout/list_item_repository.xml create mode 100644 Demo/app/src/main/res/layout/list_item_section_header.xml create mode 100644 Demo/app/src/main/res/layout/list_item_work.xml create mode 100644 Demo/app/src/main/res/menu/github_bottom_nav.xml create mode 100644 Demo/app/src/main/res/menu/menu_toolbar_create_issue.xml create mode 100644 Demo/app/src/main/res/menu/menu_toolbar_github_home.xml create mode 100644 Demo/app/src/main/res/menu/menu_toolbar_profile.xml create mode 100644 Demo/app/src/main/res/navigation/github_nav_graph.xml create mode 100644 Demo/app/src/main/res/values-night/colors.xml diff --git a/Demo/app/build.gradle b/Demo/app/build.gradle index c88fc9a..4cb665e 100644 --- a/Demo/app/build.gradle +++ b/Demo/app/build.gradle @@ -3,6 +3,7 @@ plugins { id 'org.jetbrains.kotlin.android' id 'kotlin-kapt' id 'androidx.navigation.safeargs.kotlin' + id 'com.google.dagger.hilt.android' } android { @@ -37,11 +38,17 @@ android { viewBinding true dataBinding true } + + kapt { + correctErrorTypes true + } } dependencies { def lifecycle_version = "2.6.1" def nav_version = "2.5.3" + def retrofit_version = "2.9.0" + def hilt_version = "2.46.1" implementation 'androidx.core:core-ktx:1.10.1' implementation 'androidx.appcompat:appcompat:1.6.1' @@ -54,6 +61,7 @@ dependencies { implementation "androidx.preference:preference-ktx:1.2.0" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1" implementation 'androidx.fragment:fragment-ktx:1.5.7' + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1" // Navigation implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" @@ -65,6 +73,17 @@ dependencies { // OkHttp3 implementation "com.squareup.okhttp3:okhttp:4.10.0" + // Retrofit2 + implementation "com.squareup.retrofit2:retrofit:$retrofit_version" + implementation "com.squareup.retrofit2:converter-gson:$retrofit_version" + + // Hilt + implementation "com.google.dagger:hilt-android:$hilt_version" + kapt "com.google.dagger:hilt-compiler:$hilt_version" + + // Glide + implementation "com.github.bumptech.glide:glide:4.13.2" + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/Demo/app/src/main/AndroidManifest.xml b/Demo/app/src/main/AndroidManifest.xml index 3a1bbf8..7f07300 100644 --- a/Demo/app/src/main/AndroidManifest.xml +++ b/Demo/app/src/main/AndroidManifest.xml @@ -87,10 +87,33 @@ + android:exported="true" + android:theme="@style/GitHubTheme"> + + + + + + + + + + + + + +) + +sealed interface ProfileDetail { + + val type: DetailType + + data class ProfileName( + val avatar: String, + val username: String, + val name: String? = null, + override val type: DetailType = DetailType.NAME + ) : ProfileDetail + + data class ProfileInfo( + @DrawableRes val icon: Int, + val title: String, + override val type: DetailType = DetailType.INFO + ) : ProfileDetail { + companion object { + + fun from(userResponse: UserResponse) = buildList { + with(userResponse) { + bio?.let { + add(ProfileInfo(R.drawable.ic_info, it)) + } + company?.let { + add(ProfileInfo(R.drawable.ic_chat, it)) + } + blog?.let { + add(ProfileInfo(R.drawable.ic_link_logo, it)) + } + email?.let { + add(ProfileInfo(R.drawable.ic_email, it)) + } + add( + ProfileInfo( + R.drawable.ic_person_24, + ResourceHelper.resources.getString(R.string.follow_info, followers, following) + ) + ) + } + } + } + } +} + +sealed interface ProfileInfo { + val type: ProfileType + + data class ProfileCard( + val profileDetail: List, + override val type: ProfileType = ProfileType.DETAIL + ) : ProfileInfo { + companion object { + + fun from(userResponse: UserResponse): ProfileCard { + val profileName = with(userResponse) { + ProfileDetail.ProfileName(avatarUrl, username, name) + } + val profileDetails: MutableList = + ProfileDetail.ProfileInfo.from(userResponse).toMutableList() + profileDetails.add(0, profileName) + return ProfileCard(profileDetails) + } + } + } + + data class ProfileItem( + @DrawableRes val icon: Int, + @ColorInt val iconBackground: Int, + val title: String, + val count: Int? = null, + override val type: ProfileType = ProfileType.ITEM + ) : ProfileInfo { + + companion object { + fun from(userResponse: UserResponse) = with(userResponse) { + with(ResourceHelper.resources) { + listOf( + ProfileItem( + R.drawable.ic_repo_24, + getColor(R.color.github_pull, null), + getString(R.string.repositories), + publicRepos + ), ProfileItem( + R.drawable.ic_git_pull_request, + getColor(R.color.github_gists, null), + getString(R.string.gists), + publicGists + ), ProfileItem( + R.drawable.ic_organization_24, + getColor(R.color.github_organization, null), + getString(R.string.organizations) + ), ProfileItem( + R.drawable.ic_star_24, + getColor(R.color.github_starred, null), + getString(R.string.starred) + ) + ) + } + } + } + } +} \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/Release.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/Release.kt new file mode 100644 index 0000000..5efba7d --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/Release.kt @@ -0,0 +1,19 @@ +package com.krunal.demo.githubclient.data.local + +import java.util.Date + +data class Release( + val repoFullName: String, + val releaseName: String, + val author: String, + val authorAvatar: String, + val releaseDate: Date, + val releaseAssets: List +) + +data class ReleaseAsset( + val name: String, + val size: Int, + val contentType: String, + val downloadUrl: String, +) \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/Repo.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/Repo.kt new file mode 100644 index 0000000..8a1d95c --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/Repo.kt @@ -0,0 +1,50 @@ +package com.krunal.demo.githubclient.data.local + +import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes +import com.krunal.demo.R +import com.krunal.demo.githubclient.data.remote.model.response.RepositoryResponse +import com.krunal.demo.helpers.ResourceHelper + +data class RepoCard( + val avatar: String, val username: String, val repository: String, val repoFullName: String +) + +data class RepoDetail( + val avatar: String, + val username: String, + val repository: String, + val repoFullName: String, + val description: String?, + val website: String?, + val starCount: Int, + val watchCount: Int?, + val forkCount: Int?, + val repoItems: List = emptyList() +) + +data class RepoDetailItem( + @DrawableRes val icon: Int, + @ColorInt val iconBackground: Int, + val title: String, + val count: Int? = null +) { + companion object { + fun from(repositoryResponse: RepositoryResponse) = with(repositoryResponse) { + with(ResourceHelper.resources) { + listOf( + RepoDetailItem( + R.drawable.ic_git_pull_request, + getColor(R.color.github_pull, null), + getString(R.string.issues), + ), + RepoDetailItem( + R.drawable.ic_git_pull_request, + getColor(R.color.github_pull, null), + getString(R.string.releases) + ), + ) + } + } + } +} diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/UpdateProfileDetail.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/UpdateProfileDetail.kt new file mode 100644 index 0000000..46a1e56 --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/local/UpdateProfileDetail.kt @@ -0,0 +1,82 @@ +package com.krunal.demo.githubclient.data.local + +import androidx.databinding.BaseObservable +import androidx.databinding.Bindable +import com.krunal.demo.BR +import com.krunal.demo.githubclient.data.remote.model.response.UserResponse + +data class UpdateProfileDetail( + private var _avatar: String?, + private var _name: String?, + private var _email: String, + private var _bio: String?, + private var _website: String?, + private var _twitter: String?, + private var _company: String? +) : BaseObservable() { + + @get:Bindable + var avatar: String? = _avatar + set(value) { + _avatar = value + field = value + notifyPropertyChanged(BR.avatar) + } + + @get:Bindable + var name: String? = _name + set(value) { + _name = value + field = value + notifyPropertyChanged(BR.name) + } + + @get:Bindable + var email: String = _email + set(value) { + _email = value + field = value + notifyPropertyChanged(BR.email) + } + + @get:Bindable + var bio: String? = _bio + set(value) { + _bio = value + field = value + notifyPropertyChanged(BR.bio) + } + + @get:Bindable + var website: String? = _website + set(value) { + _website = value + field = value + notifyPropertyChanged(BR.website) + } + + @get:Bindable + var twitter: String? = _twitter + set(value) { + _twitter = value + field = value + notifyPropertyChanged(BR.twitter) + } + + @get:Bindable + var company: String? = _company + set(value) { + _company = value + field = value + notifyPropertyChanged(BR.company) + } + + companion object { + + fun from(userResponse: UserResponse): UpdateProfileDetail = with(userResponse) { + UpdateProfileDetail( + avatarUrl, name, email, bio, blog, twitterUsername, company + ) + } + } +} \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/AuthorizationService.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/AuthorizationService.kt new file mode 100644 index 0000000..5cbfa87 --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/AuthorizationService.kt @@ -0,0 +1,15 @@ +package com.krunal.demo.githubclient.data.remote.api + +import com.krunal.demo.githubclient.data.remote.model.request.AuthorizationRequest +import com.krunal.demo.githubclient.data.remote.model.response.AuthorizationResponse +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.Headers +import retrofit2.http.POST + +interface AuthorizationService { + + @Headers("Accept: application/json") + @POST("access_token") + suspend fun getAuthorizationToken(@Body body: AuthorizationRequest): Response +} \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/FileService.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/FileService.kt new file mode 100644 index 0000000..93eb319 --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/FileService.kt @@ -0,0 +1,28 @@ +package com.krunal.demo.githubclient.data.remote.api + +import com.krunal.demo.githubclient.data.remote.model.response.ImageUploadResponse +import okhttp3.MultipartBody +import okhttp3.ResponseBody +import retrofit2.Response +import retrofit2.http.GET +import retrofit2.http.Multipart +import retrofit2.http.POST +import retrofit2.http.Part +import retrofit2.http.Query +import retrofit2.http.Streaming +import retrofit2.http.Url + +interface FileService { + + @Streaming + @GET + suspend fun downloadFile(@Url url: String): ResponseBody + + @Multipart + @POST("") + suspend fun uploadImageFile( + @Url url: String, + @Query("key") key: String, + @Part image: MultipartBody.Part + ): Response +} \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/IssueService.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/IssueService.kt new file mode 100644 index 0000000..09c24db --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/IssueService.kt @@ -0,0 +1,22 @@ +package com.krunal.demo.githubclient.data.remote.api + +import com.krunal.demo.githubclient.data.remote.model.request.IssueRequest +import com.krunal.demo.githubclient.data.remote.model.response.IssueResponse +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.PATCH +import retrofit2.http.POST +import retrofit2.http.Path + +interface IssueService { + + @POST("repos/{repo}/issues") + suspend fun createIssue(@Path("repo", encoded = true) repo: String, @Body issue: IssueRequest): Response + + @PATCH("repos/{repo}/issues") + suspend fun updateIssue(@Path("repo", encoded = true) repo: String, @Body issue: IssueRequest): Response + + @GET("repos/{repo}/issues/{issueId}") + suspend fun getIssue(@Path("repo", encoded = true) repo: String, @Path("issueId") issueId: Int): Response +} \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/NotificationService.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/NotificationService.kt new file mode 100644 index 0000000..2b774ac --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/NotificationService.kt @@ -0,0 +1,13 @@ +package com.krunal.demo.githubclient.data.remote.api + +import com.krunal.demo.githubclient.data.remote.model.response.NotificationsResponseItem +import com.krunal.demo.githubclient.data.remote.model.response.UserResponse +import retrofit2.Response +import retrofit2.http.GET +import retrofit2.http.Query + +interface NotificationService { + + @GET("notifications") + suspend fun getNotifications(@Query("all") all: Boolean = true, @Query("per_page") pageSize: Int = 10): Response> +} \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/RepoService.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/RepoService.kt new file mode 100644 index 0000000..745e9c9 --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/RepoService.kt @@ -0,0 +1,27 @@ +package com.krunal.demo.githubclient.data.remote.api + +import com.krunal.demo.githubclient.data.local.Release +import com.krunal.demo.githubclient.data.remote.model.response.ReleaseResponse +import com.krunal.demo.githubclient.data.remote.model.response.RepositoryResponse +import retrofit2.Response +import retrofit2.http.GET +import retrofit2.http.PUT +import retrofit2.http.Path + +interface RepoService { + + @GET("user/repos") + suspend fun getAuthorizedUserRepos(): Response> + + @GET("users/{username}/repos") + suspend fun getRepos(@Path("username") username: String): Response> + + @PUT("repos/{repo}/contents/{path}") + suspend fun createFile(@Path("repo", encoded = true) repo: String, @Path("path") filePath: String): Response> + + @GET("repos/{repoName}") + suspend fun getRepo(@Path("repoName", encoded = true) repoName: String): Response + + @GET("repos/{repoName}/releases/latest") + suspend fun getLatestRelease(@Path("repoName", encoded = true) repoName: String): Response +} \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/UserService.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/UserService.kt new file mode 100644 index 0000000..0741544 --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/api/UserService.kt @@ -0,0 +1,28 @@ +package com.krunal.demo.githubclient.data.remote.api + +import com.krunal.demo.githubclient.data.remote.model.request.LogoutRequest +import com.krunal.demo.githubclient.data.remote.model.request.UpdateProfileRequest +import com.krunal.demo.githubclient.data.remote.model.response.UserResponse +import retrofit2.Response +import retrofit2.http.Body +import retrofit2.http.DELETE +import retrofit2.http.GET +import retrofit2.http.HTTP +import retrofit2.http.PATCH +import retrofit2.http.Path + +interface UserService { + + @GET("user") + suspend fun getAuthorizedUser(): Response + + @PATCH("user") + suspend fun updateUser(@Body updateProfileRequest: UpdateProfileRequest): Response + + @HTTP( + method = "DELETE", + path = "applications/{clientId}/token", + hasBody = true + ) + suspend fun logout(@Path("clientId") clientId: String, @Body body: LogoutRequest): Response +} \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/AuthorizationRequest.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/AuthorizationRequest.kt new file mode 100644 index 0000000..567f8bc --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/AuthorizationRequest.kt @@ -0,0 +1,9 @@ +package com.krunal.demo.githubclient.data.remote.model.request + +data class AuthorizationRequest( + val clientId: String, + val clientSecret: String, + val code: String, + val redirectUri: String? = null, + val repositoryId: String? = null +) \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/IssueRequest.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/IssueRequest.kt new file mode 100644 index 0000000..0568b86 --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/IssueRequest.kt @@ -0,0 +1,9 @@ +package com.krunal.demo.githubclient.data.remote.model.request + +data class IssueRequest( + val title: String, + val body: String? = null, + val milestone: String? = null, + val labels: List = emptyList(), + val assignees: List = emptyList() +) \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/LogoutRequest.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/LogoutRequest.kt new file mode 100644 index 0000000..1a331fc --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/LogoutRequest.kt @@ -0,0 +1,5 @@ +package com.krunal.demo.githubclient.data.remote.model.request + +data class LogoutRequest( + val accessToken: String +) \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/UpdateProfileRequest.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/UpdateProfileRequest.kt new file mode 100644 index 0000000..877589d --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/request/UpdateProfileRequest.kt @@ -0,0 +1,12 @@ +package com.krunal.demo.githubclient.data.remote.model.request + +data class UpdateProfileRequest( + val name: String?, + val email: String?, + val blog: String?, + val twitterUsername: String?, + val company: String?, + val location: String?, + val hireable: Boolean?, + val bio: String? +) \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/AuthorizationResponse.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/AuthorizationResponse.kt new file mode 100644 index 0000000..2278161 --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/AuthorizationResponse.kt @@ -0,0 +1,10 @@ +package com.krunal.demo.githubclient.data.remote.model.response + +data class AuthorizationResponse( + val accessToken: String, + val expiresIn: Int, + val refreshToken: String, + val refreshTokenExpiresIn: Int, + val scope: String, + val tokenType: String +) \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/ErrorResponse.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/ErrorResponse.kt new file mode 100644 index 0000000..7ea1d45 --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/ErrorResponse.kt @@ -0,0 +1,12 @@ +package com.krunal.demo.githubclient.data.remote.model.response + +data class AuthorizationErrorResponse( + val error: String, + val errorDescription: String, + val errorUri: String +) + +data class ApiError( + val documentationUrl: String, + val message: String +) \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/ImageUploadResponse.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/ImageUploadResponse.kt new file mode 100644 index 0000000..0250afa --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/ImageUploadResponse.kt @@ -0,0 +1,34 @@ +package com.krunal.demo.githubclient.data.remote.model.response + +data class ImageUploadResponse( + val `data`: Data, val status: Int, val success: Boolean +) + +data class Medium( + val extension: String, val filename: String, val mime: String, val name: String, val url: String +) + +data class Image( + val extension: String, val filename: String, val mime: String, val name: String, val url: String +) + +data class Data( + val deleteUrl: String, + val displayUrl: String, + val expiration: String, + val height: String, + val id: String, + val image: Image, + val medium: Medium, + val size: String, + val thumb: Thumb, + val time: String, + val title: String, + val url: String, + val urlViewer: String, + val width: String +) + +data class Thumb( + val extension: String, val filename: String, val mime: String, val name: String, val url: String +) \ No newline at end of file diff --git a/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/IssueResponse.kt b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/IssueResponse.kt new file mode 100644 index 0000000..94e25f5 --- /dev/null +++ b/Demo/app/src/main/java/com/krunal/demo/githubclient/data/remote/model/response/IssueResponse.kt @@ -0,0 +1,60 @@ +package com.krunal.demo.githubclient.data.remote.model.response + +data class IssueResponse( + val activeLockReason: String, + val assignee: UserResponse, + val assignees: List, + val authorAssociation: String, + val body: String, + val closedAt: Any?, + val closedBy: UserResponse, + val comments: Int, + val commentsUrl: String, + val createdAt: String, + val eventsUrl: String, + val htmlUrl: String, + val id: Int, + val labels: List