├── .editorconfig
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── chore.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
├── auto_label.yml
├── dependabot.yml
├── issue_label_bot.yaml
└── release-drafter.yml
├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
├── schemas
│ └── org.fossasia.openevent.general.OpenEventDatabase
│ │ ├── 4.json
│ │ ├── 5.json
│ │ ├── 6.json
│ │ ├── 7.json
│ │ ├── 8.json
│ │ └── 9.json
└── src
│ ├── androidTest
│ └── java
│ │ └── org
│ │ └── fossasia
│ │ └── openevent
│ │ └── general
│ │ └── ExampleInstrumentedTest.java
│ ├── fdroid
│ └── java
│ │ └── org
│ │ └── fossasia
│ │ └── openevent
│ │ └── general
│ │ ├── auth
│ │ ├── SmartAuthUtil.kt
│ │ └── SmartAuthViewModel.kt
│ │ ├── di
│ │ └── FlavorSpecificModules.kt
│ │ └── search
│ │ └── location
│ │ ├── GeoLocationViewModel.kt
│ │ └── LocationServiceImpl.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-web.png
│ ├── java
│ │ └── org
│ │ │ └── fossasia
│ │ │ └── openevent
│ │ │ └── general
│ │ │ ├── CircleTransform.kt
│ │ │ ├── MainActivity.kt
│ │ │ ├── OpenEventDatabase.kt
│ │ │ ├── OpenEventGeneral.kt
│ │ │ ├── RotateBitmap.kt
│ │ │ ├── StartupViewModel.kt
│ │ │ ├── about
│ │ │ ├── AboutEventFragment.kt
│ │ │ └── AboutEventViewModel.kt
│ │ │ ├── attendees
│ │ │ ├── Attendee.kt
│ │ │ ├── AttendeeApi.kt
│ │ │ ├── AttendeeConverter.kt
│ │ │ ├── AttendeeDao.kt
│ │ │ ├── AttendeeFragment.kt
│ │ │ ├── AttendeeRecyclerAdapter.kt
│ │ │ ├── AttendeeService.kt
│ │ │ ├── AttendeeViewHolder.kt
│ │ │ ├── AttendeeViewModel.kt
│ │ │ ├── ListAttendeeConverter.kt
│ │ │ └── forms
│ │ │ │ ├── CustomForm.kt
│ │ │ │ └── FormIdentifier.kt
│ │ │ ├── auth
│ │ │ ├── AuthApi.kt
│ │ │ ├── AuthFragment.kt
│ │ │ ├── AuthHolder.kt
│ │ │ ├── AuthService.kt
│ │ │ ├── AuthViewModel.kt
│ │ │ ├── CheckEmailResponse.kt
│ │ │ ├── CropImageFragment.kt
│ │ │ ├── EditProfileFragment.kt
│ │ │ ├── EditProfileViewModel.kt
│ │ │ ├── EmailVerificationResponse.kt
│ │ │ ├── ImageResponse.kt
│ │ │ ├── Login.kt
│ │ │ ├── LoginFragment.kt
│ │ │ ├── LoginResponse.kt
│ │ │ ├── LoginViewModel.kt
│ │ │ ├── ProfileFragment.kt
│ │ │ ├── ProfileViewModel.kt
│ │ │ ├── RequestAuthenticator.kt
│ │ │ ├── RequestEmailVerification.kt
│ │ │ ├── RequestPasswordReset.kt
│ │ │ ├── ResetPasswordResponse.kt
│ │ │ ├── SignUp.kt
│ │ │ ├── SignUpFragment.kt
│ │ │ ├── SignUpViewModel.kt
│ │ │ ├── Token.kt
│ │ │ ├── UploadImage.kt
│ │ │ ├── User.kt
│ │ │ ├── UserDao.kt
│ │ │ ├── UserId.kt
│ │ │ ├── UserIdConverter.kt
│ │ │ ├── change
│ │ │ │ ├── ChangeRequestToken.kt
│ │ │ │ ├── ChangeRequestTokenResponse.kt
│ │ │ │ └── Password.kt
│ │ │ └── forgot
│ │ │ │ ├── Email.kt
│ │ │ │ ├── PasswordReset.kt
│ │ │ │ ├── RequestToken.kt
│ │ │ │ └── RequestTokenResponse.kt
│ │ │ ├── common
│ │ │ ├── EventsDiffCallback.kt
│ │ │ ├── RecyclerViewCallbacks.kt
│ │ │ └── SingleLiveEvent.kt
│ │ │ ├── connectivity
│ │ │ └── MutableConnectionLiveData.kt
│ │ │ ├── data
│ │ │ ├── Network.kt
│ │ │ ├── Preference.kt
│ │ │ └── Resource.kt
│ │ │ ├── di
│ │ │ ├── HostSelectionInterceptor.kt
│ │ │ └── Modules.kt
│ │ │ ├── discount
│ │ │ ├── DiscountApi.kt
│ │ │ └── DiscountCode.kt
│ │ │ ├── event
│ │ │ ├── Event.kt
│ │ │ ├── EventApi.kt
│ │ │ ├── EventDao.kt
│ │ │ ├── EventDetailsFragment.kt
│ │ │ ├── EventDetailsViewModel.kt
│ │ │ ├── EventId.kt
│ │ │ ├── EventIdConverter.kt
│ │ │ ├── EventService.kt
│ │ │ ├── EventUtils.kt
│ │ │ ├── EventViewHolder.kt
│ │ │ ├── EventsFragment.kt
│ │ │ ├── EventsListAdapter.kt
│ │ │ ├── EventsViewModel.kt
│ │ │ ├── codeofconduct
│ │ │ │ └── ConductCodeFragment.kt
│ │ │ ├── faq
│ │ │ │ ├── EventFAQ.kt
│ │ │ │ ├── EventFAQApi.kt
│ │ │ │ ├── EventFAQFragment.kt
│ │ │ │ ├── EventFAQViewModel.kt
│ │ │ │ ├── FAQRecyclerAdapter.kt
│ │ │ │ └── FAQViewHolder.kt
│ │ │ ├── location
│ │ │ │ ├── EventLocation.kt
│ │ │ │ └── EventLocationApi.kt
│ │ │ ├── paging
│ │ │ │ ├── EventsDataSource.kt
│ │ │ │ ├── EventsDataSourceFactory.kt
│ │ │ │ ├── SimilarEventsDataSource.kt
│ │ │ │ └── SimilarEventsDataSourceFactory.kt
│ │ │ ├── similarevent
│ │ │ │ ├── SimilarEventViewHolder.kt
│ │ │ │ └── SimilarEventsListAdapter.kt
│ │ │ ├── subtopic
│ │ │ │ ├── EventSubTopic.kt
│ │ │ │ └── EventSubTopicConverter.kt
│ │ │ ├── tax
│ │ │ │ ├── Tax.kt
│ │ │ │ ├── TaxApi.kt
│ │ │ │ ├── TaxDao.kt
│ │ │ │ └── TaxService.kt
│ │ │ ├── topic
│ │ │ │ ├── EventTopic.kt
│ │ │ │ ├── EventTopicApi.kt
│ │ │ │ ├── EventTopicConverter.kt
│ │ │ │ └── EventTopicsDao.kt
│ │ │ └── types
│ │ │ │ ├── EventType.kt
│ │ │ │ ├── EventTypeConverter.kt
│ │ │ │ └── EventTypesApi.kt
│ │ │ ├── favorite
│ │ │ ├── FavoriteEvent.kt
│ │ │ ├── FavoriteEventApi.kt
│ │ │ ├── FavoriteEventViewHolder.kt
│ │ │ ├── FavoriteEventsListAdapter.kt
│ │ │ ├── FavoriteEventsViewModel.kt
│ │ │ └── FavoriteFragment.kt
│ │ │ ├── feedback
│ │ │ ├── Feedback.kt
│ │ │ ├── FeedbackApi.kt
│ │ │ ├── FeedbackDao.kt
│ │ │ ├── FeedbackFragment.kt
│ │ │ ├── FeedbackRecyclerAdapter.kt
│ │ │ ├── FeedbackService.kt
│ │ │ ├── FeedbackViewHolder.kt
│ │ │ └── FeedbackViewModel.kt
│ │ │ ├── location
│ │ │ └── LocationExceptions.kt
│ │ │ ├── notification
│ │ │ ├── Notification.kt
│ │ │ ├── NotificationApi.kt
│ │ │ ├── NotificationDao.kt
│ │ │ ├── NotificationFragment.kt
│ │ │ ├── NotificationService.kt
│ │ │ ├── NotificationViewModel.kt
│ │ │ ├── NotificationsRecyclerAdapter.kt
│ │ │ └── NotificationsViewHolder.kt
│ │ │ ├── order
│ │ │ ├── Charge.kt
│ │ │ ├── ConfirmOrder.kt
│ │ │ ├── ExpiredOrderFragment.kt
│ │ │ ├── Order.kt
│ │ │ ├── OrderApi.kt
│ │ │ ├── OrderCompletedFragment.kt
│ │ │ ├── OrderCompletedViewModel.kt
│ │ │ ├── OrderDao.kt
│ │ │ ├── OrderDataSource.kt
│ │ │ ├── OrderDataSourceFactory.kt
│ │ │ ├── OrderDetailsFragment.kt
│ │ │ ├── OrderDetailsRecyclerAdapter.kt
│ │ │ ├── OrderDetailsViewHolder.kt
│ │ │ ├── OrderDetailsViewModel.kt
│ │ │ ├── OrderService.kt
│ │ │ ├── OrdersPagedListAdapter.kt
│ │ │ ├── OrdersUnderUserFragment.kt
│ │ │ ├── OrdersUnderUserViewModel.kt
│ │ │ ├── OrdersViewHolder.kt
│ │ │ ├── QrCode.kt
│ │ │ └── invoice
│ │ │ │ └── DownloadInvoiceService.kt
│ │ │ ├── paypal
│ │ │ ├── Paypal.kt
│ │ │ ├── PaypalApi.kt
│ │ │ └── PaypalPaymentResponse.kt
│ │ │ ├── search
│ │ │ ├── SearchEventsDataSource.kt
│ │ │ ├── SearchEventsDataSourceFactory.kt
│ │ │ ├── SearchFilterFragment.kt
│ │ │ ├── SearchFragment.kt
│ │ │ ├── SearchPagedListAdapter.kt
│ │ │ ├── SearchResultsFragment.kt
│ │ │ ├── SearchResultsViewModel.kt
│ │ │ ├── SearchViewModel.kt
│ │ │ ├── location
│ │ │ │ ├── LocationAdapter.kt
│ │ │ │ ├── LocationService.kt
│ │ │ │ ├── LocationViewHolder.kt
│ │ │ │ ├── PlaceSuggestionViewHolder.kt
│ │ │ │ ├── PlaceSuggestionsAdapter.kt
│ │ │ │ ├── SearchLocationFragment.kt
│ │ │ │ └── SearchLocationViewModel.kt
│ │ │ ├── recentsearch
│ │ │ │ ├── RecentSearchAdapter.kt
│ │ │ │ └── RecentSearchViewHolder.kt
│ │ │ ├── time
│ │ │ │ ├── SearchTimeFragment.kt
│ │ │ │ └── SearchTimeViewModel.kt
│ │ │ └── type
│ │ │ │ ├── SearchTypeAdapter.kt
│ │ │ │ ├── SearchTypeFragment.kt
│ │ │ │ └── SearchTypeViewModel.kt
│ │ │ ├── sessions
│ │ │ ├── Session.kt
│ │ │ ├── SessionApi.kt
│ │ │ ├── SessionDao.kt
│ │ │ ├── SessionFragment.kt
│ │ │ ├── SessionRecyclerAdapter.kt
│ │ │ ├── SessionService.kt
│ │ │ ├── SessionViewHolder.kt
│ │ │ ├── SessionViewModel.kt
│ │ │ ├── microlocation
│ │ │ │ ├── MicroLocation.kt
│ │ │ │ └── MicroLocationConverter.kt
│ │ │ ├── sessiontype
│ │ │ │ ├── SessionType.kt
│ │ │ │ └── SessionTypeConverter.kt
│ │ │ └── track
│ │ │ │ ├── Track.kt
│ │ │ │ └── TrackConverter.kt
│ │ │ ├── settings
│ │ │ ├── Settings.kt
│ │ │ ├── SettingsApi.kt
│ │ │ ├── SettingsDao.kt
│ │ │ ├── SettingsFragment.kt
│ │ │ ├── SettingsService.kt
│ │ │ └── SettingsViewModel.kt
│ │ │ ├── social
│ │ │ ├── SocialLink.kt
│ │ │ ├── SocialLinkApi.kt
│ │ │ ├── SocialLinksDao.kt
│ │ │ ├── SocialLinksRecyclerAdapter.kt
│ │ │ ├── SocialLinksService.kt
│ │ │ └── SocialLinksViewHolder.kt
│ │ │ ├── speakercall
│ │ │ ├── EditSpeakerFragment.kt
│ │ │ ├── EditSpeakerViewModel.kt
│ │ │ ├── Proposal.kt
│ │ │ ├── SpeakersCall.kt
│ │ │ ├── SpeakersCallConverter.kt
│ │ │ ├── SpeakersCallDao.kt
│ │ │ ├── SpeakersCallFragment.kt
│ │ │ ├── SpeakersCallProposalFragment.kt
│ │ │ ├── SpeakersCallProposalViewModel.kt
│ │ │ ├── SpeakersCallViewModel.kt
│ │ │ └── form
│ │ │ │ ├── SessionIdentifier.kt
│ │ │ │ └── SpeakerIdentifier.kt
│ │ │ ├── speakers
│ │ │ ├── ListSpeakerIdConverter.kt
│ │ │ ├── Speaker.kt
│ │ │ ├── SpeakerApi.kt
│ │ │ ├── SpeakerDao.kt
│ │ │ ├── SpeakerFragment.kt
│ │ │ ├── SpeakerId.kt
│ │ │ ├── SpeakerRecyclerAdapter.kt
│ │ │ ├── SpeakerService.kt
│ │ │ ├── SpeakerViewHolder.kt
│ │ │ ├── SpeakerViewModel.kt
│ │ │ ├── SpeakerWithEvent.kt
│ │ │ └── SpeakerWithEventDao.kt
│ │ │ ├── sponsor
│ │ │ ├── Sponsor.kt
│ │ │ ├── SponsorApi.kt
│ │ │ ├── SponsorDao.kt
│ │ │ ├── SponsorRecyclerAdapter.kt
│ │ │ ├── SponsorService.kt
│ │ │ ├── SponsorUtil.kt
│ │ │ ├── SponsorViewHolder.kt
│ │ │ ├── SponsorWIthEvent.kt
│ │ │ ├── SponsorWithEventDao.kt
│ │ │ ├── SponsorsDetailAdapter.kt
│ │ │ ├── SponsorsFragment.kt
│ │ │ └── SponsorsViewModel.kt
│ │ │ ├── ticket
│ │ │ ├── Ticket.kt
│ │ │ ├── TicketApi.kt
│ │ │ ├── TicketDao.kt
│ │ │ ├── TicketDetailsRecyclerAdapter.kt
│ │ │ ├── TicketDetailsViewHolder.kt
│ │ │ ├── TicketId.kt
│ │ │ ├── TicketIdAndQtyWrapper.kt
│ │ │ ├── TicketIdConverter.kt
│ │ │ ├── TicketPriceRange.kt
│ │ │ ├── TicketService.kt
│ │ │ ├── TicketViewHolder.kt
│ │ │ ├── TicketsFragment.kt
│ │ │ ├── TicketsRecyclerAdapter.kt
│ │ │ └── TicketsViewModel.kt
│ │ │ ├── utils
│ │ │ ├── AppLinkData.kt
│ │ │ ├── AppLinkUtils.kt
│ │ │ ├── DataBindingAdapters.kt
│ │ │ ├── DateTimeUtils.kt
│ │ │ ├── Error.kt
│ │ │ ├── ErrorUtils.kt
│ │ │ ├── HttpErrors.kt
│ │ │ ├── ImageUtils.kt
│ │ │ ├── JWTUtils.java
│ │ │ ├── StringUtils.kt
│ │ │ ├── Utils.kt
│ │ │ └── extensions
│ │ │ │ ├── FragmentExt.kt
│ │ │ │ ├── LiveDataExtensions.kt
│ │ │ │ ├── RxExtensions.kt
│ │ │ │ └── ViewExt.kt
│ │ │ └── welcome
│ │ │ └── WelcomeFragment.kt
│ └── res
│ │ ├── anim
│ │ ├── fade_in.xml
│ │ ├── fade_out.xml
│ │ ├── slide_down.xml
│ │ ├── slide_in_left.xml
│ │ ├── slide_in_right.xml
│ │ ├── slide_out_left.xml
│ │ ├── slide_out_right.xml
│ │ └── slide_up.xml
│ │ ├── color
│ │ ├── navigation_item.xml
│ │ └── text_color_chip_state_list.xml
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── background_fragment.xml
│ │ ├── background_fragment_search.xml
│ │ ├── background_splash.xml
│ │ ├── border.xml
│ │ ├── border_background_ticket_timer.xml
│ │ ├── border_curved.xml
│ │ ├── border_order_status.xml
│ │ ├── circle_shape.xml
│ │ ├── curved_border.xml
│ │ ├── filled_border.xml
│ │ ├── foreground_black_blur.xml
│ │ ├── header.png
│ │ ├── ic_account_circle_grey.xml
│ │ ├── ic_arrow_back_black.xml
│ │ ├── ic_arrow_back_white_cct.png
│ │ ├── ic_bank.xml
│ │ ├── ic_baseline_arrow_forward.xml
│ │ ├── ic_baseline_calendar.xml
│ │ ├── ic_baseline_event.xml
│ │ ├── ic_baseline_event_grey.xml
│ │ ├── ic_baseline_favorite.xml
│ │ ├── ic_baseline_favorite_border.xml
│ │ ├── ic_baseline_favorite_border_white.xml
│ │ ├── ic_baseline_favorite_white.xml
│ │ ├── ic_baseline_refund.xml
│ │ ├── ic_baseline_tick.xml
│ │ ├── ic_baseline_ticket.xml
│ │ ├── ic_bio.xml
│ │ ├── ic_blogger.xml
│ │ ├── ic_camera.xml
│ │ ├── ic_cash.xml
│ │ ├── ic_check_black.xml
│ │ ├── ic_checked.xml
│ │ ├── ic_cheque.xml
│ │ ├── ic_circle.xml
│ │ ├── ic_clear.xml
│ │ ├── ic_credit_card.xml
│ │ ├── ic_crop.xml
│ │ ├── ic_edit.xml
│ │ ├── ic_email.xml
│ │ ├── ic_email_black.xml
│ │ ├── ic_event.xml
│ │ ├── ic_exit_to_app_black.xml
│ │ ├── ic_expand_icon.xml
│ │ ├── ic_facebook.xml
│ │ ├── ic_faq.xml
│ │ ├── ic_filter.xml
│ │ ├── ic_flickr.xml
│ │ ├── ic_github.xml
│ │ ├── ic_google_plus.xml
│ │ ├── ic_image.xml
│ │ ├── ic_language_black.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_link_black.xml
│ │ ├── ic_linkedin.xml
│ │ ├── ic_location_on_black.xml
│ │ ├── ic_location_pin.xml
│ │ ├── ic_location_world.xml
│ │ ├── ic_lock_black.xml
│ │ ├── ic_mail_outline_black.xml
│ │ ├── ic_map_black.xml
│ │ ├── ic_no_internet.xml
│ │ ├── ic_notifications_none.xml
│ │ ├── ic_notifications_white.xml
│ │ ├── ic_open_event.png
│ │ ├── ic_organization.xml
│ │ ├── ic_outline_account_circle.xml
│ │ ├── ic_outline_ticket.xml
│ │ ├── ic_paypal.xml
│ │ ├── ic_person.xml
│ │ ├── ic_person_add.xml
│ │ ├── ic_person_black.xml
│ │ ├── ic_position.xml
│ │ ├── ic_search_grey.xml
│ │ ├── ic_search_white.xml
│ │ ├── ic_settings.xml
│ │ ├── ic_share_grey.xml
│ │ ├── ic_share_white.xml
│ │ ├── ic_speakers_call.xml
│ │ ├── ic_speakers_call_closed.xml
│ │ ├── ic_speakers_call_open.xml
│ │ ├── ic_star_border.xml
│ │ ├── ic_tick_inside_circle.xml
│ │ ├── ic_time.xml
│ │ ├── ic_track.xml
│ │ ├── ic_trash.xml
│ │ ├── ic_twitter.xml
│ │ ├── ic_website.xml
│ │ ├── ic_wikipedia.xml
│ │ ├── ic_youtube.xml
│ │ ├── round_background.xml
│ │ ├── round_image.xml
│ │ ├── round_shape.xml
│ │ ├── scrim_shape.xml
│ │ └── splash_logo.png
│ │ ├── layout-land
│ │ ├── fragment_search.xml
│ │ ├── fragment_welcome.xml
│ │ └── item_card_order_details.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── content_event.xml
│ │ ├── content_fetching_event_error.xml
│ │ ├── content_no_internet.xml
│ │ ├── dialog_api_configuration.xml
│ │ ├── dialog_change_password.xml
│ │ ├── dialog_confirm_delete_account.xml
│ │ ├── dialog_delete_account.xml
│ │ ├── dialog_edit_profile_image.xml
│ │ ├── dialog_feedback.xml
│ │ ├── dialog_filter_order.xml
│ │ ├── dialog_login_to_like.xml
│ │ ├── dialog_rate_us.xml
│ │ ├── dialog_reset_password.xml
│ │ ├── event_type_list.xml
│ │ ├── fragment_about_event.xml
│ │ ├── fragment_attendee.xml
│ │ ├── fragment_auth.xml
│ │ ├── fragment_conduct_code.xml
│ │ ├── fragment_crop_image.xml
│ │ ├── fragment_edit_profile.xml
│ │ ├── fragment_event.xml
│ │ ├── fragment_event_faq.xml
│ │ ├── fragment_events.xml
│ │ ├── fragment_expired_order.xml
│ │ ├── fragment_favorite.xml
│ │ ├── fragment_feedback.xml
│ │ ├── fragment_login.xml
│ │ ├── fragment_notification.xml
│ │ ├── fragment_order_completed.xml
│ │ ├── fragment_order_details.xml
│ │ ├── fragment_orders_under_user.xml
│ │ ├── fragment_profile.xml
│ │ ├── fragment_proposal_speaker.xml
│ │ ├── fragment_search.xml
│ │ ├── fragment_search_filter.xml
│ │ ├── fragment_search_location.xml
│ │ ├── fragment_search_results.xml
│ │ ├── fragment_search_time.xml
│ │ ├── fragment_search_type.xml
│ │ ├── fragment_session.xml
│ │ ├── fragment_signup.xml
│ │ ├── fragment_speaker.xml
│ │ ├── fragment_speakers_call.xml
│ │ ├── fragment_speakers_call_proposal.xml
│ │ ├── fragment_sponsors.xml
│ │ ├── fragment_tickets.xml
│ │ ├── fragment_welcome.xml
│ │ ├── item_attendee.xml
│ │ ├── item_card_events.xml
│ │ ├── item_card_favorite_event.xml
│ │ ├── item_card_notification.xml
│ │ ├── item_card_order.xml
│ │ ├── item_card_order_details.xml
│ │ ├── item_card_similar_events.xml
│ │ ├── item_enlarged_qr.xml
│ │ ├── item_faq.xml
│ │ ├── item_feedback.xml
│ │ ├── item_location_text.xml
│ │ ├── item_place_suggestion.xml
│ │ ├── item_recent_search.xml
│ │ ├── item_session.xml
│ │ ├── item_social_link.xml
│ │ ├── item_speaker.xml
│ │ ├── item_sponsor.xml
│ │ ├── item_sponsor_detail.xml
│ │ ├── item_ticket.xml
│ │ ├── item_ticket_details.xml
│ │ ├── placeholder_item_card_events.xml
│ │ ├── placeholder_item_card_notification.xml
│ │ ├── placeholder_item_card_search.xml
│ │ ├── placeholder_item_card_similar_events.xml
│ │ ├── placeholder_item_card_tickets.xml
│ │ ├── placeholder_item_event_location.xml
│ │ └── placeholder_item_event_type.xml
│ │ ├── menu
│ │ ├── event_details.xml
│ │ ├── navigation.xml
│ │ ├── order_completed.xml
│ │ └── order_detail.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── navigation
│ │ └── navigation_graph.xml
│ │ ├── values-bn-rIN
│ │ └── strings.xml
│ │ ├── values-hi-rIN
│ │ └── strings.xml
│ │ ├── values-land
│ │ ├── dimens.xml
│ │ ├── integers.xml
│ │ └── strings.xml
│ │ ├── values-sw600dp-land
│ │ └── integers.xml
│ │ ├── values-sw600dp
│ │ ├── dimens.xml
│ │ └── integers.xml
│ │ ├── values-ur-rPK
│ │ └── strings.xml
│ │ ├── values-vi
│ │ └── strings.xml
│ │ ├── values
│ │ ├── arrays.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── integers.xml
│ │ ├── strings-country-name.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ │ └── xml
│ │ ├── file_provider.xml
│ │ └── settings.xml
│ ├── playStore
│ └── java
│ │ └── org
│ │ └── fossasia
│ │ └── openevent
│ │ └── general
│ │ ├── auth
│ │ ├── SmartAuthUtil.kt
│ │ └── SmartAuthViewModel.kt
│ │ └── search
│ │ └── location
│ │ ├── GeoLocationViewModel.kt
│ │ └── LocationServiceImpl.kt
│ └── test
│ └── java
│ └── org
│ └── fossasia
│ └── openevent
│ └── general
│ ├── AppLinkUtilsTest.kt
│ ├── DependencyTest.kt
│ └── event
│ └── EventUtilsTest.kt
├── build.gradle
├── docs
└── images
│ ├── ic_fdroid.png
│ └── ic_play_store.png
├── fastlane
├── Appfile
├── Fastfile
└── metadata
│ └── android
│ └── en-US
│ ├── changelogs
│ ├── 10.txt
│ ├── 11.txt
│ ├── 12.txt
│ ├── 13.txt
│ ├── 14.txt
│ ├── 15.txt
│ ├── 16.txt
│ ├── 17.txt
│ ├── 6.txt
│ ├── 7.txt
│ └── 9.txt
│ ├── full_description.txt
│ ├── images
│ ├── icon.png
│ └── phoneScreenshots
│ │ ├── screenshot_1.jpg
│ │ ├── screenshot_2.jpg
│ │ ├── screenshot_3.jpg
│ │ ├── screenshot_4.jpg
│ │ ├── screenshot_5.jpg
│ │ ├── screenshot_6.jpg
│ │ ├── screenshot_8.jpg
│ │ └── screenshot_9.jpg
│ ├── short_description.txt
│ ├── title.txt
│ └── video.txt
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── scripts
├── prep-key.sh
├── secrets.tar.enc
└── update-apk.sh
└── settings.gradle
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | end_of_line = lf
6 | insert_final_newline = true
7 |
8 | [*.{kt,kts}]
9 | indent_size=4
10 | continuation_indent_size=4
11 | max_line_length=120
12 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a bug report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 |
9 |
10 | **To Reproduce**
11 |
16 |
17 | **Expected behavior**
18 |
19 |
20 | **Logs**
21 |
22 |
23 | **Screenshots**
24 |
25 |
26 | **Smartphone Info:**
27 |
28 | | | |
29 | |---------------|-|
30 | |Device ||
31 | |Android Version| |
32 |
33 | **Additional context**
34 |
35 |
36 | **Would you like to work on the issue?**
37 |
38 | - [ ] Yes
39 | - [ ] No
40 | - Other:
41 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/chore.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Chore
3 | about: Issues related to docs, workflow, dependency and others
4 |
5 | ---
6 |
7 | **Describe the chore**
8 |
9 |
10 | **Would you like to work on the issue?**
11 |
12 | - [ ] Yes
13 | - [ ] No
14 | - Other:
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Describe the feature you'd like**
8 |
9 |
10 | **Screenshots**
11 |
12 |
13 | **Additional context**
14 |
15 |
16 | **Would you like to work on the issue?**
17 |
18 | - [ ] Yes
19 | - [ ] No
20 | - Other:
21 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Fixes #[Add issue number here. If you do not solve the issue entirely, please change the message e.g. "First steps for issues #IssueNumber]
2 |
3 | Changes: [Add here what changes were made in this issue and if possible provide links.]
4 |
5 | Screenshots for the change:
--------------------------------------------------------------------------------
/.github/auto_label.yml:
--------------------------------------------------------------------------------
1 | labels: [fix, chore, ui]
2 | labelMapping:
3 | feat: [feature]
4 | fix(ui): [fix, ui]
5 | feat(ui): [feat, ui]
6 | refactor: [chore, refactor]
7 | chore(refactor): [chore, refactor]
8 | chore(deps): [dependencies]
9 | chore(docs): [chore, docs]
10 | docs: [chore, docs]
11 | test: [chore, test]
12 | chore(ci): [chore, tools, ci]
13 | chore(tools): [chore, tools]
14 | chore(release): [chore, release]
15 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: gradle
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: "21:00"
8 | open-pull-requests-limit: 10
9 | ignore:
10 | - dependency-name: com.stripe:stripe-android
11 | versions:
12 | - 16.2.0
13 | - 16.2.1
14 | - 16.3.0
15 | - 16.3.1
16 | - 16.4.0
17 | - 16.4.1
18 | - 16.4.3
19 | - 16.5.0
20 | - dependency-name: com.fasterxml.jackson.module:jackson-module-kotlin
21 | versions:
22 | - 2.12.1
23 | - 2.12.2
24 | - dependency-name: com.google.android.material:material
25 | versions:
26 | - 1.3.0
27 | - 1.3.0-rc01
28 | - 1.4.0-alpha01
29 |
--------------------------------------------------------------------------------
/.github/issue_label_bot.yaml:
--------------------------------------------------------------------------------
1 | label-alias:
2 | bug: 'bug'
3 | feature_request: 'feature'
4 | question: 'question'
5 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | name-template: Release v$NEXT_MINOR_VERSION 🌈
2 | tag-template: v$NEXT_MINOR_VERSION
3 | categories:
4 | - title: 🚀 Features
5 | label: feature
6 | - title: 🐛 Bug Fixes
7 | label: fix
8 | - title: 🧰 Maintenance
9 | label: chore
10 | - title: Dependencies and Libraries
11 | label: dependencies
12 | change-template: '- $TITLE (#$NUMBER) - @$AUTHOR'
13 | template: |
14 | ## Changes
15 |
16 | $CHANGES
17 |
18 | ## Contributors
19 |
20 | Thanks a lot to our contributors for making this release possible:
21 | $CONTRIBUTORS
22 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 | dist: trusty
3 | sudo: false
4 | jdk:
5 | - oraclejdk8
6 | android:
7 | components:
8 | - tools
9 | - android-28
10 | - build-tools-28.0.3
11 | - platform-tools
12 | before_cache:
13 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
14 | cache:
15 | directories:
16 | - "${TRAVIS_BUILD_DIR}/gradle/caches/"
17 | - "${TRAVIS_BUILD_DIR}/gradle/wrapper/dists/"
18 | - "$HOME/.gradle/caches/"
19 | - "$HOME/.gradle/wrapper/"
20 | before_script:
21 | - bash scripts/prep-key.sh
22 | script:
23 | - ./gradlew spotlessCheck
24 | - ./gradlew build
25 | after_success:
26 | - bash scripts/update-apk.sh
27 |
28 | branches:
29 | only:
30 | - master
31 | - development
32 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/org/fossasia/openevent/general/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general;
2 |
3 | import android.content.Context;
4 | import androidx.test.InstrumentationRegistry;
5 | import androidx.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.example.nikit.eventsapp", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/fdroid/java/org/fossasia/openevent/general/auth/SmartAuthUtil.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | import android.app.Activity
4 |
5 | object SmartAuthUtil {
6 | fun getCredentialsClient(activity: Activity): Any {
7 | return Unit
8 | }
9 |
10 | fun handleResolvableApiException(rae: Any, activity: Activity, value: Any) {
11 | }
12 | fun getEmailAddressFromIntent(intent: Any?): String? {
13 | return null
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/fdroid/java/org/fossasia/openevent/general/auth/SmartAuthViewModel.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.MutableLiveData
5 | import androidx.lifecycle.ViewModel
6 |
7 | const val RC_CREDENTIALS_READ = 2
8 | class SmartAuthViewModel : ViewModel() {
9 |
10 | val mutableId = MutableLiveData()
11 | val id: LiveData = mutableId
12 | private val mutablePassword = MutableLiveData()
13 | val password: LiveData = mutablePassword
14 | private val mutableProgress = MutableLiveData()
15 | val progress: LiveData = mutableProgress
16 | private val mutableApiExceptionRequestCodePair = MutableLiveData>()
17 | val apiExceptionCodePair: LiveData> = mutableApiExceptionRequestCodePair
18 | private val mutableStatus = MutableLiveData()
19 | val isCredentialStored: LiveData = mutableStatus
20 |
21 | fun requestCredentials(any: Any) {
22 | return
23 | }
24 |
25 | fun saveCredential(any1: Any, any2: Any, any3: Any) {
26 | return
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/fdroid/java/org/fossasia/openevent/general/di/FlavorSpecificModules.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.di
2 |
3 | import org.koin.dsl.module
4 |
5 | val flavorSpecificModule = module { }
6 |
--------------------------------------------------------------------------------
/app/src/fdroid/java/org/fossasia/openevent/general/search/location/GeoLocationViewModel.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.search.location
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.ViewModel
5 | import io.reactivex.disposables.CompositeDisposable
6 | import io.reactivex.rxkotlin.plusAssign
7 | import java.lang.IllegalArgumentException
8 | import org.fossasia.openevent.general.common.SingleLiveEvent
9 |
10 | class GeoLocationViewModel(private val locationService: LocationService) : ViewModel() {
11 | private val mutableLocation = SingleLiveEvent()
12 | val location: LiveData = mutableLocation
13 | private val mutableErrorMessage = SingleLiveEvent()
14 | val errorMessage: SingleLiveEvent = mutableErrorMessage
15 | private val compositeDisposable = CompositeDisposable()
16 |
17 | fun configure() {
18 | compositeDisposable += locationService.getAdministrativeArea()
19 | .subscribe({
20 | mutableLocation.value = it
21 | }, {
22 | mutableErrorMessage.value = if (it is IllegalArgumentException) "No area found"
23 | else "Something went wrong"
24 | })
25 | }
26 |
27 | override fun onCleared() {
28 | super.onCleared()
29 | compositeDisposable.clear()
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fossasia/open-event-attendee-android/9e3afa05753332f9ca3edebb118bae9d7b224554/app/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/attendees/AttendeeApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.attendees
2 |
3 | import io.reactivex.Completable
4 | import io.reactivex.Single
5 | import org.fossasia.openevent.general.attendees.forms.CustomForm
6 | import retrofit2.http.Body
7 | import retrofit2.http.DELETE
8 | import retrofit2.http.GET
9 | import retrofit2.http.POST
10 | import retrofit2.http.Path
11 | import retrofit2.http.Query
12 |
13 | interface AttendeeApi {
14 |
15 | @POST("attendees?include=event,ticket&fields[event]=id&fields[ticket]=id")
16 | fun postAttendee(@Body attendee: Attendee): Single
17 |
18 | @DELETE("attendees/{attendeeId}")
19 | fun deleteAttendee(@Path("attendeeId") id: Long): Completable
20 |
21 | @GET("events/{id}/custom-forms")
22 | fun getCustomFormsForAttendees(
23 | @Path("id") id: Long,
24 | @Query("filter") filter: String,
25 | @Query("page[size]") pageSize: Int = 22
26 | ): Single>
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/attendees/AttendeeConverter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.attendees
2 |
3 | import androidx.room.TypeConverter
4 | import com.fasterxml.jackson.databind.ObjectMapper
5 | import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
6 |
7 | class AttendeeConverter {
8 |
9 | @TypeConverter
10 | fun toAttendee(json: String): Attendee? {
11 | return jacksonObjectMapper().readerFor(Attendee::class.java).readValue(json)
12 | }
13 |
14 | @TypeConverter
15 | fun toJson(attendee: Attendee?) = ObjectMapper().writeValueAsString(attendee)
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/attendees/AttendeeDao.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.attendees
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.OnConflictStrategy
6 | import androidx.room.Query
7 | import io.reactivex.Single
8 |
9 | @Dao
10 | interface AttendeeDao {
11 | @Insert(onConflict = OnConflictStrategy.REPLACE)
12 | fun insertAttendees(attendees: List)
13 |
14 | @Insert(onConflict = OnConflictStrategy.REPLACE)
15 | fun insertAttendee(attendee: Attendee)
16 |
17 | @Query("DELETE FROM Attendee")
18 | fun deleteAllAttendees()
19 |
20 | @Query("SELECT * from Attendee WHERE id in (:ids)")
21 | fun getAttendeesWithIds(ids: List): Single>
22 |
23 | @Query("SELECT * FROM Attendee")
24 | fun getAllAttendees(): Single>
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/attendees/ListAttendeeConverter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.attendees
2 |
3 | import androidx.room.TypeConverter
4 | import com.fasterxml.jackson.core.type.TypeReference
5 | import com.fasterxml.jackson.databind.ObjectMapper
6 | import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
7 |
8 | class ListAttendeeConverter {
9 |
10 | @TypeConverter
11 | fun fromListAttendee(attendees: List): String {
12 | val objectMapper = ObjectMapper()
13 | return objectMapper.writeValueAsString(attendees)
14 | }
15 |
16 | @TypeConverter
17 | fun toListAttendee(attendees: String): List {
18 | val objectMapper = jacksonObjectMapper()
19 | val mapType = object : TypeReference>() {}
20 | return objectMapper.readValue(attendees, mapType)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/attendees/forms/CustomForm.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.attendees.forms
2 |
3 | import androidx.room.Entity
4 | import androidx.room.ForeignKey
5 | import androidx.room.PrimaryKey
6 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
7 | import com.fasterxml.jackson.databind.annotation.JsonNaming
8 | import com.github.jasminb.jsonapi.IntegerIdHandler
9 | import com.github.jasminb.jsonapi.annotations.Id
10 | import com.github.jasminb.jsonapi.annotations.Relationship
11 | import com.github.jasminb.jsonapi.annotations.Type
12 | import org.fossasia.openevent.general.event.Event
13 | import org.fossasia.openevent.general.event.EventId
14 |
15 | @Type("custom-form")
16 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
17 | @Entity(foreignKeys = [(ForeignKey(entity = Event::class, parentColumns = ["id"],
18 | childColumns = ["event"], onDelete = ForeignKey.CASCADE))])
19 | data class CustomForm(
20 | @Id(IntegerIdHandler::class)
21 | @PrimaryKey
22 | val id: Long,
23 | val form: String,
24 | val fieldIdentifier: String,
25 | val type: String,
26 | val isRequired: Boolean = false,
27 | val isIncluded: Boolean = false,
28 | val isFixed: Boolean? = false,
29 | val ticketsNumber: Int? = null,
30 | @Relationship("event")
31 | var event: EventId? = null
32 | )
33 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/attendees/forms/FormIdentifier.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.attendees.forms
2 |
3 | object FormIdentifier {
4 | val FIRST_NAME = "firstname"
5 | val LAST_NAME = "lastname"
6 | val EMAIL = "email"
7 | val ADDRESS = "address"
8 | val CITY = "city"
9 | val STATE = "state"
10 | val COUNTRY = "country"
11 | val JOB_TITLE = "jobTitle"
12 | val PHONE = "phone"
13 | val TAX_INFO = "taxBusinessInfo"
14 | val BILLING_ADDRESS = "billingAddress"
15 | val HOME_ADDRESS = "homeAddress"
16 | val SHIPPING_ADDRESS = "shippingAddress"
17 | val COMPANY = "company"
18 | val WORK_ADDRESS = "workAddress"
19 | val WORK_PHONE = "workPhone"
20 | val WEBSITE = "website"
21 | val BLOG = "blog"
22 | val TWITTER = "twitter"
23 | val FACEBOOK = "facebook"
24 | val GITHUB = "github"
25 | val GENDER = "gender"
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/AuthHolder.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | import org.fossasia.openevent.general.data.Preference
4 | import org.fossasia.openevent.general.utils.JWTUtils
5 |
6 | private const val TOKEN_KEY = "TOKEN"
7 |
8 | class AuthHolder(private val preference: Preference) {
9 |
10 | var token: String? = null
11 | get() {
12 | return preference.getString(TOKEN_KEY)
13 | }
14 | set(value) {
15 | if (value != null && JWTUtils.isExpired(value))
16 | throw IllegalStateException("Cannot set expired token")
17 | field = value
18 | preference.putString(TOKEN_KEY, value)
19 | }
20 |
21 | fun getAuthorization(): String? {
22 | if (!isLoggedIn())
23 | return null
24 | return "JWT $token"
25 | }
26 |
27 | fun isLoggedIn(): Boolean {
28 | if (token == null || JWTUtils.isExpired(token)) {
29 | token = null
30 | return false
31 | }
32 |
33 | return true
34 | }
35 |
36 | fun getId(): Long {
37 | return if (!isLoggedIn()) -1 else JWTUtils.getIdentity(token)
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/CheckEmailResponse.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | class CheckEmailResponse(
4 | val result: Boolean
5 | )
6 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/EmailVerificationResponse.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | class EmailVerificationResponse(
4 | val message: String? = null
5 | )
6 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/ImageResponse.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | data class ImageResponse(var url: String? = null)
4 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/Login.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | data class Login(val email: String, val password: String)
4 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/LoginResponse.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
4 | import com.fasterxml.jackson.databind.annotation.JsonNaming
5 |
6 | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class)
7 | data class LoginResponse(val accessToken: String)
8 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/RequestAuthenticator.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | import okhttp3.Interceptor
4 | import okhttp3.Response
5 |
6 | class RequestAuthenticator(private val authHolder: AuthHolder) : Interceptor {
7 |
8 | override fun intercept(chain: Interceptor.Chain): Response {
9 | val authorization = authHolder.getAuthorization()
10 | val original = chain.request()
11 | return if (authorization != null) {
12 | val request = original.newBuilder()
13 | .header("Authorization", authorization)
14 | .build()
15 | chain.proceed(request)
16 | } else
17 | chain.proceed(original)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/RequestEmailVerification.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | data class RequestEmailVerification(val data: Token)
4 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/RequestPasswordReset.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | import org.fossasia.openevent.general.auth.forgot.PasswordReset
4 |
5 | class RequestPasswordReset(
6 | val data: PasswordReset
7 | )
8 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/ResetPasswordResponse.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | import com.github.jasminb.jsonapi.LongIdHandler
4 | import com.github.jasminb.jsonapi.annotations.Id
5 |
6 | class ResetPasswordResponse(
7 | @Id(LongIdHandler::class)
8 | val id: Long? = null,
9 | val email: String? = null,
10 | val name: String? = null
11 | )
12 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/SignUp.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
4 | import com.fasterxml.jackson.databind.annotation.JsonNaming
5 | import com.github.jasminb.jsonapi.IntegerIdHandler
6 | import com.github.jasminb.jsonapi.annotations.Id
7 | import com.github.jasminb.jsonapi.annotations.Type
8 |
9 | @Type("user")
10 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
11 | data class SignUp(
12 | @Id(IntegerIdHandler::class)
13 | val firstName: String? = null,
14 | val lastName: String? = null,
15 | val email: String? = null,
16 | val password: String? = null
17 | )
18 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/Token.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | data class Token(val token: String)
4 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/UploadImage.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | data class UploadImage(var data: String? = null)
4 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/UserDao.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.OnConflictStrategy.REPLACE
6 | import androidx.room.Query
7 | import io.reactivex.Single
8 |
9 | @Dao
10 | interface UserDao {
11 | @Insert(onConflict = REPLACE)
12 | fun insertUser(user: User)
13 |
14 | @Query("DELETE FROM User WHERE id = :id")
15 | fun deleteUser(id: Long)
16 |
17 | @Query("SELECT * from User WHERE id = :id")
18 | fun getUser(id: Long): Single
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/UserId.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | import com.github.jasminb.jsonapi.IntegerIdHandler
4 | import com.github.jasminb.jsonapi.annotations.Id
5 | import com.github.jasminb.jsonapi.annotations.Type
6 |
7 | @Type("user")
8 | data class UserId(
9 | @Id(IntegerIdHandler::class)
10 | val id: Long
11 | )
12 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/UserIdConverter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth
2 |
3 | import androidx.room.TypeConverter
4 |
5 | class UserIdConverter {
6 | @TypeConverter
7 | fun fromUserId(userId: UserId?): Long? {
8 | return userId?.id
9 | }
10 |
11 | @TypeConverter
12 | fun toUserId(id: Long?): UserId? {
13 | return id?.let {
14 | UserId(it)
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/change/ChangeRequestToken.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth.change
2 |
3 | data class ChangeRequestToken(val data: Password)
4 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/change/ChangeRequestTokenResponse.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth.change
2 |
3 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
4 | import com.fasterxml.jackson.databind.annotation.JsonNaming
5 |
6 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
7 | data class ChangeRequestTokenResponse(val email: String, val id: Long, val name: String, val passwordChanged: Boolean)
8 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/change/Password.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth.change
2 |
3 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
4 | import com.fasterxml.jackson.databind.annotation.JsonNaming
5 |
6 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
7 | data class Password(val oldPassword: String, val newPassword: String)
8 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/forgot/Email.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth.forgot
2 |
3 | data class Email(val email: String)
4 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/forgot/PasswordReset.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth.forgot
2 |
3 | class PasswordReset(
4 | val token: String,
5 | val password: String
6 | )
7 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/forgot/RequestToken.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth.forgot
2 |
3 | data class RequestToken(val data: Email)
4 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/auth/forgot/RequestTokenResponse.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.auth.forgot
2 |
3 | data class RequestTokenResponse(val message: String)
4 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/common/EventsDiffCallback.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.common
2 |
3 | import androidx.recyclerview.widget.DiffUtil
4 | import org.fossasia.openevent.general.event.Event
5 |
6 | /**
7 | * The DiffUtil ItemCallback class for the [Event] model class.
8 | * This enables proper diffing of items in Recycler Views using [DiffUtil]
9 | */
10 | class EventsDiffCallback : DiffUtil.ItemCallback() {
11 |
12 | override fun areItemsTheSame(oldItem: Event, newItem: Event): Boolean {
13 | return oldItem.id == newItem.id
14 | }
15 |
16 | override fun areContentsTheSame(oldItem: Event, newItem: Event): Boolean {
17 | return oldItem == newItem
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/connectivity/MutableConnectionLiveData.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.connectivity
2 |
3 | import android.content.BroadcastReceiver
4 | import android.content.Context
5 | import android.content.Intent
6 | import android.content.IntentFilter
7 | import android.net.ConnectivityManager
8 | import androidx.lifecycle.MutableLiveData
9 | import org.fossasia.openevent.general.OpenEventGeneral
10 | import org.fossasia.openevent.general.utils.Utils
11 |
12 | class MutableConnectionLiveData : MutableLiveData() {
13 | private val context by lazy {
14 | OpenEventGeneral.appContext
15 | }
16 |
17 | private val broadcastReceiver = object : BroadcastReceiver() {
18 | override fun onReceive(context: Context?, intent: Intent?) {
19 | postValue(Utils.isNetworkConnected(context))
20 | }
21 | }
22 |
23 | override fun onActive() {
24 | super.onActive()
25 | val intentFilter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
26 | context?.registerReceiver(broadcastReceiver, intentFilter)
27 | }
28 |
29 | override fun onInactive() {
30 | super.onInactive()
31 | context?.unregisterReceiver(broadcastReceiver)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/data/Network.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.data
2 |
3 | import android.content.Context
4 | import android.net.ConnectivityManager
5 | import org.fossasia.openevent.general.OpenEventGeneral
6 |
7 | class Network {
8 |
9 | private val context by lazy {
10 | OpenEventGeneral.appContext
11 | }
12 |
13 | private val connectivityManager by lazy {
14 | context?.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
15 | }
16 |
17 | fun isNetworkConnected(): Boolean {
18 | return connectivityManager?.activeNetworkInfo != null
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/data/Resource.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.data
2 |
3 | import androidx.annotation.ColorRes
4 | import androidx.annotation.StringRes
5 | import org.fossasia.openevent.general.OpenEventGeneral
6 |
7 | class Resource {
8 |
9 | private val context by lazy {
10 | OpenEventGeneral.appContext
11 | }
12 |
13 | fun getString(@StringRes resId: Int) = context?.getString(resId)
14 |
15 | fun getString(@StringRes resId: Int, vararg args: Any?) = context?.getString(resId, args)
16 |
17 | fun getColor(@ColorRes resId: Int) = context?.resources?.getColor(resId)
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/di/HostSelectionInterceptor.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.di
2 |
3 | import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
4 | import okhttp3.Interceptor
5 | import okhttp3.Response
6 | import org.fossasia.openevent.general.BuildConfig
7 | import org.fossasia.openevent.general.data.Preference
8 | import org.fossasia.openevent.general.settings.API_URL
9 |
10 | class HostSelectionInterceptor(private val preference: Preference) : Interceptor {
11 |
12 | override fun intercept(chain: Interceptor.Chain): Response {
13 | var original = chain.request()
14 | val httpUrl = preference.getString(API_URL)?.toHttpUrlOrNull()
15 | if (original.url.host == BuildConfig.DEFAULT_BASE_URL.toHttpUrlOrNull()?.host && httpUrl != null) {
16 | val newUrl =
17 | original.url.newBuilder()
18 | .scheme(httpUrl.scheme)
19 | .host(httpUrl.host)
20 | .port(httpUrl.port)
21 | .build()
22 | original = original.newBuilder()
23 | .url(newUrl)
24 | .build()
25 | }
26 | return chain.proceed(original)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/discount/DiscountApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.discount
2 |
3 | import io.reactivex.Single
4 | import retrofit2.http.GET
5 | import retrofit2.http.Path
6 | import retrofit2.http.Query
7 |
8 | interface DiscountApi {
9 |
10 | @GET("events/{eventId}/discount-codes/{code}?include=event,tickets")
11 | fun getDiscountCodes(
12 | @Path("eventId") eventId: Long,
13 | @Path("code") code: String,
14 | @Query("filter") filter: String
15 | ): Single
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/discount/DiscountCode.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.discount
2 |
3 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
4 | import com.fasterxml.jackson.databind.annotation.JsonNaming
5 | import com.github.jasminb.jsonapi.IntegerIdHandler
6 | import com.github.jasminb.jsonapi.annotations.Id
7 | import com.github.jasminb.jsonapi.annotations.Relationship
8 | import com.github.jasminb.jsonapi.annotations.Type
9 | import org.fossasia.openevent.general.event.EventId
10 | import org.fossasia.openevent.general.ticket.TicketId
11 |
12 | @Type("discount-code")
13 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
14 | data class DiscountCode(
15 | @Id(IntegerIdHandler::class)
16 | val id: Int,
17 | val code: String,
18 | val validFrom: String? = null,
19 | val minQuantity: Int? = null,
20 | val createdAt: String? = null,
21 | val ticketsNumber: Int? = null,
22 | val value: Float? = null,
23 | val maxQuantity: Int? = null,
24 | val isActive: Boolean = false,
25 | val usedFor: String,
26 | val validTill: String? = null,
27 | val discountUrl: String? = null,
28 | val type: String,
29 | @Relationship("event")
30 | val eventId: EventId? = null,
31 | @Relationship("tickets")
32 | val tickets: List? = null
33 | )
34 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/EventApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event
2 |
3 | import io.reactivex.Single
4 | import org.fossasia.openevent.general.sessions.track.Track
5 | import org.fossasia.openevent.general.speakercall.SpeakersCall
6 | import retrofit2.http.GET
7 | import retrofit2.http.Path
8 | import retrofit2.http.Query
9 |
10 | interface EventApi {
11 |
12 | @GET
13 | fun getEvent(id: Long): Single
14 |
15 | @GET("/v1/events/{eventIdentifier}")
16 | fun getEventFromApi(@Path("eventIdentifier") eventIdentifier: String): Single
17 |
18 | @GET("events")
19 | fun eventsWithQuery(@Query("filter") filter: String): Single>
20 |
21 | @GET("events/{eventId}/speakers-call")
22 | fun getSpeakerCallForEvent(@Path("eventId") id: Long): Single
23 |
24 | @GET("events?include=event-sub-topic,event-topic,event-type")
25 | fun searchEventsPaged(
26 | @Query("sort") sort: String,
27 | @Query("filter") eventName: String,
28 | @Query("page[number]") page: Int,
29 | @Query("page[size]") pageSize: Int = 5
30 | ): Single>
31 |
32 | @GET("events")
33 | fun eventsByQuery(@Query("filter") filter: String): Single>
34 |
35 | @GET("events/{eventId}/tracks")
36 | fun fetchTracksUnderEvent(@Path("eventId") eventId: Long): Single>
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/EventId.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event
2 |
3 | import com.github.jasminb.jsonapi.LongIdHandler
4 | import com.github.jasminb.jsonapi.annotations.Id
5 | import com.github.jasminb.jsonapi.annotations.Type
6 |
7 | @Type("event")
8 | data class EventId(
9 | @Id(LongIdHandler::class)
10 | val id: Long
11 | )
12 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/EventIdConverter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event
2 |
3 | import androidx.room.TypeConverter
4 |
5 | class EventIdConverter {
6 |
7 | @TypeConverter
8 | fun fromEventId(eventId: EventId?): Long? {
9 | return eventId?.id
10 | }
11 |
12 | @TypeConverter
13 | fun toEventId(id: Long?): EventId? {
14 | return id?.let {
15 | EventId(it)
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/faq/EventFAQ.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.faq
2 |
3 | import com.github.jasminb.jsonapi.LongIdHandler
4 | import com.github.jasminb.jsonapi.annotations.Id
5 | import com.github.jasminb.jsonapi.annotations.Type
6 |
7 | @Type("faq")
8 | data class EventFAQ(
9 | @Id(LongIdHandler::class)
10 | val id: Long,
11 | val question: String,
12 | val answer: String
13 | )
14 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/faq/EventFAQApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.faq
2 |
3 | import io.reactivex.Single
4 | import retrofit2.http.GET
5 | import retrofit2.http.Path
6 |
7 | interface EventFAQApi {
8 |
9 | @GET("events/{id}/faqs?sort=question")
10 | fun getEventFAQ(@Path("id") id: Long): Single>
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/faq/FAQRecyclerAdapter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.faq
2 |
3 | import android.view.LayoutInflater
4 | import android.view.ViewGroup
5 | import androidx.recyclerview.widget.RecyclerView
6 | import org.fossasia.openevent.general.R
7 |
8 | class FAQRecyclerAdapter : RecyclerView.Adapter() {
9 | val faqList = ArrayList()
10 |
11 | fun addAll(faqList: List) {
12 | if (faqList.isNotEmpty())
13 | this.faqList.clear()
14 | this.faqList.addAll(faqList)
15 | notifyDataSetChanged()
16 | }
17 |
18 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FAQViewHolder {
19 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item_faq, parent, false)
20 | return FAQViewHolder(view)
21 | }
22 |
23 | override fun onBindViewHolder(holder: FAQViewHolder, position: Int) {
24 | val faq = faqList[position]
25 |
26 | holder.bind(faq)
27 | }
28 |
29 | override fun getItemCount(): Int {
30 | return faqList.size
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/faq/FAQViewHolder.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.faq
2 |
3 | import android.view.View
4 | import androidx.recyclerview.widget.RecyclerView
5 | import kotlinx.android.synthetic.main.item_faq.view.answerTv
6 | import kotlinx.android.synthetic.main.item_faq.view.questiontv
7 |
8 | class FAQViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
9 |
10 | fun bind(faq: EventFAQ) {
11 | itemView.questiontv.text = faq.question
12 | itemView.answerTv.text = faq.answer
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/location/EventLocation.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.location
2 |
3 | import com.github.jasminb.jsonapi.LongIdHandler
4 | import com.github.jasminb.jsonapi.annotations.Id
5 | import com.github.jasminb.jsonapi.annotations.Type
6 |
7 | @Type("event-location")
8 | data class EventLocation(
9 | @Id(LongIdHandler::class)
10 | val id: Long,
11 | val name: String,
12 | val slug: String
13 | )
14 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/location/EventLocationApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.location
2 |
3 | import io.reactivex.Single
4 | import retrofit2.http.GET
5 |
6 | interface EventLocationApi {
7 |
8 | @GET("event-locations?sort=name")
9 | fun getEventLocation(): Single>
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/paging/EventsDataSourceFactory.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.paging
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import androidx.paging.DataSource
5 | import io.reactivex.disposables.CompositeDisposable
6 | import org.fossasia.openevent.general.event.Event
7 | import org.fossasia.openevent.general.event.EventService
8 |
9 | class EventsDataSourceFactory(
10 | private val compositeDisposable: CompositeDisposable,
11 | private val eventService: EventService,
12 | private val query: String?,
13 | private val mutableProgress: MutableLiveData
14 | ) : DataSource.Factory() {
15 | override fun create(): DataSource {
16 | return EventsDataSource(
17 | eventService,
18 | compositeDisposable,
19 | query,
20 | mutableProgress
21 | )
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/paging/SimilarEventsDataSourceFactory.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.paging
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import androidx.paging.DataSource
5 | import io.reactivex.disposables.CompositeDisposable
6 | import org.fossasia.openevent.general.event.Event
7 | import org.fossasia.openevent.general.event.EventService
8 |
9 | class SimilarEventsDataSourceFactory(
10 | private val compositeDisposable: CompositeDisposable,
11 | private val topicId: Long,
12 | private val location: String?,
13 | private val eventId: Long,
14 | private val mutableProgress: MutableLiveData,
15 | private val eventService: EventService
16 | ) : DataSource.Factory() {
17 | override fun create(): DataSource {
18 | return SimilarEventsDataSource(
19 | compositeDisposable, topicId, location, eventId, mutableProgress, eventService
20 | )
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/subtopic/EventSubTopic.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.subtopic
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.ForeignKey
6 | import androidx.room.PrimaryKey
7 | import com.github.jasminb.jsonapi.LongIdHandler
8 | import com.github.jasminb.jsonapi.annotations.Id
9 | import com.github.jasminb.jsonapi.annotations.Relationship
10 | import com.github.jasminb.jsonapi.annotations.Type
11 | import org.fossasia.openevent.general.event.Event
12 | import org.fossasia.openevent.general.event.EventId
13 |
14 | @Type("event-sub-topic")
15 | @Entity(foreignKeys = [(ForeignKey(entity = Event::class, parentColumns = ["id"],
16 | childColumns = ["event"], onDelete = ForeignKey.CASCADE))])
17 | data class EventSubTopic(
18 | @Id(LongIdHandler::class)
19 | @PrimaryKey
20 | val id: Long,
21 | val name: String,
22 | val slug: String,
23 | @ColumnInfo(index = true)
24 | @Relationship("event")
25 | var event: EventId? = null
26 | )
27 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/subtopic/EventSubTopicConverter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.subtopic
2 |
3 | import androidx.room.TypeConverter
4 | import com.fasterxml.jackson.databind.ObjectMapper
5 | import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
6 |
7 | class EventSubTopicConverter {
8 |
9 | @TypeConverter
10 | fun toEventSubTopic(json: String): EventSubTopic? {
11 | return jacksonObjectMapper().readerFor(EventSubTopic::class.java).readValue(json)
12 | }
13 |
14 | @TypeConverter
15 | fun toJson(eventSubTopic: EventSubTopic?) = ObjectMapper().writeValueAsString(eventSubTopic)
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/tax/Tax.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.tax
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.PrimaryKey
6 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
7 | import com.fasterxml.jackson.databind.annotation.JsonNaming
8 | import com.github.jasminb.jsonapi.IntegerIdHandler
9 | import com.github.jasminb.jsonapi.annotations.Id
10 | import com.github.jasminb.jsonapi.annotations.Relationship
11 | import com.github.jasminb.jsonapi.annotations.Type
12 | import org.fossasia.openevent.general.event.EventId
13 |
14 | @Type("tax")
15 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
16 | @Entity
17 | class Tax(
18 | @Id(IntegerIdHandler::class)
19 | @PrimaryKey
20 | val id: Int? = null,
21 | val name: String? = null,
22 | val rate: Float? = null,
23 | val taxId: String? = null,
24 | val registeredCompany: String? = null,
25 | val address: String? = null,
26 | val city: String? = null,
27 | val stare: String? = null,
28 | val zip: String? = null,
29 | val invoiceFooter: String? = null,
30 | val isInvoiceSend: Boolean = false,
31 | val isTaxIncludedInPrice: Boolean = false,
32 | val shouldSendInvoice: Boolean = false,
33 | @ColumnInfo(index = true)
34 | @Relationship("event")
35 | val eventId: EventId? = null
36 | )
37 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/tax/TaxApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.tax
2 |
3 | import io.reactivex.Single
4 | import retrofit2.http.GET
5 | import retrofit2.http.Path
6 |
7 | interface TaxApi {
8 |
9 | @GET("events/{event_identifier}/tax?include=event")
10 | fun getTaxDetails(@Path("event_identifier") identifier: String): Single
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/tax/TaxDao.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.tax
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.OnConflictStrategy
6 | import androidx.room.Query
7 | import io.reactivex.Single
8 |
9 | @Dao
10 | interface TaxDao {
11 |
12 | @Insert(onConflict = OnConflictStrategy.REPLACE)
13 | fun insertTax(tax: Tax)
14 |
15 | @Query("SELECT * from Tax WHERE eventId = :eventId")
16 | fun getTaxDetails(eventId: Long): Single
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/tax/TaxService.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.tax
2 |
3 | import io.reactivex.Single
4 | import timber.log.Timber
5 |
6 | class TaxService(
7 | private val taxApi: TaxApi,
8 | private val taxDao: TaxDao
9 | ) {
10 |
11 | fun getTax(eventId: Long): Single {
12 | return taxApi.getTaxDetails(eventId.toString())
13 | .onErrorResumeNext {
14 | Timber.e(it, "Error fetching tax")
15 | taxDao.getTaxDetails(eventId)
16 | }.map {
17 | taxDao.insertTax(it)
18 | it
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/topic/EventTopic.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.topic
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.ForeignKey
6 | import androidx.room.PrimaryKey
7 | import com.github.jasminb.jsonapi.LongIdHandler
8 | import com.github.jasminb.jsonapi.annotations.Id
9 | import com.github.jasminb.jsonapi.annotations.Relationship
10 | import com.github.jasminb.jsonapi.annotations.Type
11 | import org.fossasia.openevent.general.event.Event
12 | import org.fossasia.openevent.general.event.EventId
13 |
14 | @Type("event-topic")
15 | @Entity(foreignKeys = [(ForeignKey(entity = Event::class, parentColumns = ["id"],
16 | childColumns = ["event"], onDelete = ForeignKey.CASCADE))])
17 | data class EventTopic(
18 | @Id(LongIdHandler::class)
19 | @PrimaryKey
20 | val id: Long,
21 | val name: String,
22 | val slug: String,
23 | @ColumnInfo(index = true)
24 | @Relationship("event")
25 | var event: EventId? = null
26 | )
27 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/topic/EventTopicApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.topic
2 |
3 | import io.reactivex.Single
4 | import org.fossasia.openevent.general.event.Event
5 | import retrofit2.http.GET
6 | import retrofit2.http.Path
7 | import retrofit2.http.Query
8 |
9 | interface EventTopicApi {
10 |
11 | @GET("event-topics/{id}/events?include=event-topic")
12 | fun getEventsUnderTopicIdPaged(
13 | @Path("id") id: Long,
14 | @Query("filter") filter: String,
15 | @Query("page[number]") page: Int,
16 | @Query("page[size]") pageSize: Int = 5
17 | ): Single>
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/topic/EventTopicConverter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.topic
2 |
3 | import androidx.room.TypeConverter
4 | import com.fasterxml.jackson.databind.ObjectMapper
5 | import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
6 |
7 | class EventTopicConverter {
8 | @TypeConverter
9 | fun toEventTopic(json: String): EventTopic? {
10 | return jacksonObjectMapper().readerFor(EventTopic::class.java).readValue(json)
11 | }
12 |
13 | @TypeConverter
14 | fun toJson(eventTopic: EventTopic?) = ObjectMapper().writeValueAsString(eventTopic)
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/topic/EventTopicsDao.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.topic
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.OnConflictStrategy
6 | import androidx.room.Query
7 | import io.reactivex.Flowable
8 |
9 | @Dao
10 | interface EventTopicsDao {
11 |
12 | @Insert(onConflict = OnConflictStrategy.REPLACE)
13 | fun insertEventTopics(eventTopic: List)
14 |
15 | @Query("SELECT * from EventTopic")
16 | fun getAllEventTopics(): Flowable>
17 |
18 | @Query("DELETE FROM EventTopic")
19 | fun deleteAll()
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/types/EventType.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.types
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.Entity
5 | import androidx.room.PrimaryKey
6 | import com.github.jasminb.jsonapi.LongIdHandler
7 | import com.github.jasminb.jsonapi.annotations.Id
8 | import com.github.jasminb.jsonapi.annotations.Relationship
9 | import com.github.jasminb.jsonapi.annotations.Type
10 | import org.fossasia.openevent.general.event.EventId
11 |
12 | @Type("event-type")
13 | @Entity
14 | data class EventType(
15 | @Id(LongIdHandler::class)
16 | @PrimaryKey
17 | val id: Long,
18 | val name: String,
19 | val slug: String,
20 | @ColumnInfo(index = true)
21 | @Relationship("event")
22 | var event: EventId? = null
23 | )
24 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/types/EventTypeConverter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.types
2 |
3 | import androidx.room.TypeConverter
4 | import com.fasterxml.jackson.databind.ObjectMapper
5 | import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
6 |
7 | class EventTypeConverter {
8 | @TypeConverter
9 | fun toEventType(json: String): EventType? {
10 | return jacksonObjectMapper().readerFor(EventType::class.java).readValue(json)
11 | }
12 |
13 | @TypeConverter
14 | fun toJson(eventType: EventType?) = ObjectMapper().writeValueAsString(eventType)
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/event/types/EventTypesApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.event.types
2 |
3 | import io.reactivex.Single
4 | import retrofit2.http.GET
5 |
6 | interface EventTypesApi {
7 |
8 | @GET("event-types?sort=name")
9 | fun getEventTypes(): Single>
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/favorite/FavoriteEvent.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.favorite
2 |
3 | import androidx.room.ColumnInfo
4 | import androidx.room.PrimaryKey
5 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
6 | import com.fasterxml.jackson.databind.annotation.JsonNaming
7 | import com.github.jasminb.jsonapi.LongIdHandler
8 | import com.github.jasminb.jsonapi.annotations.Id
9 | import com.github.jasminb.jsonapi.annotations.Relationship
10 | import com.github.jasminb.jsonapi.annotations.Type
11 | import org.fossasia.openevent.general.event.EventId
12 |
13 | @Type("user-favourite-event")
14 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
15 | data class FavoriteEvent(
16 | @Id(LongIdHandler::class)
17 | @PrimaryKey
18 | val id: Long,
19 | @ColumnInfo(index = true)
20 | @Relationship("event", resolve = true)
21 | val event: EventId? = null
22 | )
23 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/favorite/FavoriteEventApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.favorite
2 |
3 | import io.reactivex.Completable
4 | import io.reactivex.Single
5 | import retrofit2.http.Body
6 | import retrofit2.http.DELETE
7 | import retrofit2.http.GET
8 | import retrofit2.http.Header
9 | import retrofit2.http.POST
10 | import retrofit2.http.Path
11 |
12 | interface FavoriteEventApi {
13 | @GET("user-favourite-events?include=event")
14 | fun getFavorites(): Single>
15 |
16 | @POST("user-favourite-events")
17 | fun addFavorite(
18 | @Body favorite: FavoriteEvent,
19 | @Header("Content-Type") header: String = "application/vnd.api+json"
20 | ): Single
21 |
22 | @DELETE("user-favourite-events/{favoriteEventId}")
23 | fun removeFavorite(
24 | @Path("favoriteEventId") eventId: Long,
25 | @Header("Content-Type") header: String = "application/vnd.api+json"
26 | ): Completable
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/feedback/Feedback.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.feedback
2 |
3 | import androidx.room.Entity
4 | import androidx.room.PrimaryKey
5 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
6 | import com.fasterxml.jackson.databind.annotation.JsonNaming
7 | import com.github.jasminb.jsonapi.LongIdHandler
8 | import com.github.jasminb.jsonapi.annotations.Id
9 | import com.github.jasminb.jsonapi.annotations.Relationship
10 | import com.github.jasminb.jsonapi.annotations.Type
11 | import org.fossasia.openevent.general.auth.UserId
12 | import org.fossasia.openevent.general.event.EventId
13 |
14 | @Type("feedback")
15 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
16 | @Entity
17 | data class Feedback(
18 | @Id(LongIdHandler::class)
19 | @PrimaryKey
20 | val id: Long? = null,
21 | val rating: String?,
22 | val comment: String?,
23 | @Relationship("event")
24 | var event: EventId? = null,
25 | @Relationship("user")
26 | var user: UserId? = null
27 | )
28 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/feedback/FeedbackApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.feedback
2 |
3 | import io.reactivex.Single
4 | import retrofit2.http.Body
5 | import retrofit2.http.GET
6 | import retrofit2.http.POST
7 | import retrofit2.http.Path
8 | import retrofit2.http.Query
9 |
10 | interface FeedbackApi {
11 |
12 | @GET("events/{eventId}/feedbacks?include=event")
13 | fun getEventFeedback(
14 | @Path("eventId") eventId: Long,
15 | @Query("sort") sort: String = "rating",
16 | @Query("filter") eventName: String = "[]"
17 | ): Single>
18 |
19 | @POST("feedbacks")
20 | fun postfeedback(@Body feedback: Feedback): Single
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/feedback/FeedbackDao.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.feedback
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.OnConflictStrategy.REPLACE
6 | import androidx.room.Query
7 | import io.reactivex.Single
8 |
9 | @Dao
10 | interface FeedbackDao {
11 |
12 | @Insert(onConflict = REPLACE)
13 | fun insertFeedback(feedbacks: List)
14 |
15 | @Insert(onConflict = REPLACE)
16 | fun insertSingleFeedback(feedback: Feedback)
17 |
18 | @Query("SELECT * FROM feedback WHERE event = :eventId")
19 | fun getAllFeedbackUnderEvent(eventId: Long): Single>
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/feedback/FeedbackService.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.feedback
2 |
3 | import io.reactivex.Single
4 |
5 | class FeedbackService(
6 | private val feedbackDao: FeedbackDao,
7 | private val feedbackApi: FeedbackApi
8 | ) {
9 | fun getFeedbackUnderEventFromDb(eventId: Long): Single> =
10 | feedbackDao.getAllFeedbackUnderEvent(eventId)
11 |
12 | fun getEventFeedback(id: Long): Single> =
13 | feedbackApi.getEventFeedback(id).doOnSuccess {
14 | feedbackDao.insertFeedback(it)
15 | }
16 |
17 | fun submitFeedback(feedback: Feedback): Single =
18 | feedbackApi.postfeedback(feedback).doOnSuccess {
19 | feedbackDao.insertSingleFeedback(it)
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/feedback/FeedbackViewHolder.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.feedback
2 |
3 | import android.view.View
4 | import androidx.recyclerview.widget.RecyclerView
5 | import kotlinx.android.synthetic.main.item_feedback.view.commentTv
6 | import kotlinx.android.synthetic.main.item_feedback.view.ratingBar
7 |
8 | const val MAX_COMMENT_LINE = 3
9 |
10 | class FeedbackViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
11 |
12 | fun bind(feedback: Feedback) {
13 | itemView.commentTv.text = feedback.comment
14 | itemView.ratingBar.rating = feedback.rating?.toFloat() ?: 0f
15 |
16 | itemView.commentTv.setOnClickListener {
17 | itemView.commentTv.maxLines =
18 | if (itemView.commentTv.maxLines == MAX_COMMENT_LINE) Int.MAX_VALUE else MAX_COMMENT_LINE
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/location/LocationExceptions.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.location
2 |
3 | /**
4 | * Thrown when there isn't a location source available.
5 | * */
6 | class NoLocationSourceException : Exception()
7 |
8 | /**
9 | * Thrown when the user hasn't granted permission necessary to complete an action.
10 | * */
11 | class LocationPermissionException : Exception()
12 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/notification/Notification.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.notification
2 |
3 | import androidx.room.Entity
4 | import androidx.room.PrimaryKey
5 | import com.fasterxml.jackson.annotation.JsonProperty
6 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
7 | import com.fasterxml.jackson.databind.annotation.JsonNaming
8 | import com.github.jasminb.jsonapi.IntegerIdHandler
9 | import com.github.jasminb.jsonapi.annotations.Id
10 | import com.github.jasminb.jsonapi.annotations.Type
11 | import io.reactivex.annotations.NonNull
12 |
13 | @Type("notification")
14 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
15 | @Entity
16 | data class Notification(
17 | @Id(IntegerIdHandler::class)
18 | @NonNull
19 | @PrimaryKey
20 | val id: Int,
21 | val message: String? = null,
22 | val receivedAt: String? = null,
23 | @get:JsonProperty("is-read")
24 | var isRead: Boolean = false,
25 | val title: String? = null,
26 | val deletedAt: String? = null
27 | )
28 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/notification/NotificationApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.notification
2 |
3 | import io.reactivex.Single
4 | import retrofit2.http.Body
5 | import retrofit2.http.GET
6 | import retrofit2.http.PATCH
7 | import retrofit2.http.Path
8 |
9 | interface NotificationApi {
10 |
11 | @GET("users/{userId}/notifications?sort=received-at")
12 | fun getNotifications(@Path("userId") userId: Long): Single>
13 |
14 | @PATCH("notifications/{notification_id}")
15 | fun updateNotification(
16 | @Path("notification_id") notificationId: Int,
17 | @Body notification: Notification
18 | ): Single
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/notification/NotificationDao.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.notification
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.OnConflictStrategy.REPLACE
6 | import androidx.room.Query
7 | import io.reactivex.Single
8 |
9 | @Dao
10 | interface NotificationDao {
11 | @Insert(onConflict = REPLACE)
12 | fun insertNotifications(notifications: List)
13 |
14 | @Insert(onConflict = REPLACE)
15 | fun insertNotification(notification: Notification)
16 |
17 | @Query("SELECT * FROM Notification")
18 | fun getNotifications(): Single>
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/notification/NotificationService.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.notification
2 |
3 | import io.reactivex.Single
4 |
5 | class NotificationService(
6 | private val notificationApi: NotificationApi,
7 | private val notificationDao: NotificationDao
8 | ) {
9 |
10 | fun getNotifications(userId: Long): Single> {
11 | return notificationDao.getNotifications()
12 | .onErrorResumeNext {
13 | notificationApi.getNotifications(userId).map {
14 | notificationDao.insertNotifications(it)
15 | it
16 | }
17 | }
18 | }
19 |
20 | fun syncNotifications(userId: Long): Single> {
21 | return notificationApi.getNotifications(userId).map {
22 | notificationDao.insertNotifications(it)
23 | it
24 | }
25 | }
26 |
27 | fun updateNotification(notification: Notification): Single {
28 | return notificationApi.updateNotification(notification.id, notification).map {
29 | notificationDao.insertNotification(it)
30 | it
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/notification/NotificationsRecyclerAdapter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.notification
2 |
3 | import android.view.LayoutInflater
4 | import android.view.ViewGroup
5 | import androidx.recyclerview.widget.RecyclerView
6 | import org.fossasia.openevent.general.R
7 |
8 | class NotificationsRecyclerAdapter : RecyclerView.Adapter() {
9 |
10 | private val notificationList = ArrayList()
11 |
12 | fun addAll(list: List) {
13 | notificationList.clear()
14 | notificationList.addAll(list)
15 | }
16 |
17 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotificationsViewHolder {
18 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item_card_notification, parent, false)
19 | return NotificationsViewHolder(view)
20 | }
21 |
22 | override fun onBindViewHolder(holder: NotificationsViewHolder, position: Int) {
23 | holder.bind(notificationList[position])
24 | }
25 |
26 | override fun getItemCount(): Int {
27 | return notificationList.size
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/notification/NotificationsViewHolder.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.notification
2 |
3 | import android.text.Html
4 | import android.text.method.LinkMovementMethod
5 | import android.view.View
6 | import androidx.recyclerview.widget.RecyclerView
7 | import kotlinx.android.synthetic.main.item_card_notification.view.*
8 | import org.fossasia.openevent.general.event.EventUtils
9 |
10 | class NotificationsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
11 |
12 | fun bind(
13 | notification: Notification
14 |
15 | ) {
16 | itemView.title.text = notification.title
17 | itemView.message.movementMethod = LinkMovementMethod.getInstance()
18 | itemView.message.text = Html.fromHtml(notification.message)
19 | notification.receivedAt?.let {
20 | val dayDiff = EventUtils.getDayDifferenceFromToday(it)
21 | val formattedDateTime = EventUtils.getEventDateTime(it)
22 | itemView.time.text = when (dayDiff) {
23 | 0L -> EventUtils.getFormattedTime(formattedDateTime)
24 | in 1..6 -> EventUtils.getFormattedWeekDay(formattedDateTime)
25 | else -> EventUtils.getFormattedDateWithoutWeekday(formattedDateTime)
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/order/Charge.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.order
2 |
3 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
4 | import com.fasterxml.jackson.databind.annotation.JsonNaming
5 | import com.github.jasminb.jsonapi.IntegerIdHandler
6 | import com.github.jasminb.jsonapi.annotations.Id
7 | import com.github.jasminb.jsonapi.annotations.Type
8 |
9 | @Type("charge")
10 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
11 | data class Charge(
12 | @Id(IntegerIdHandler::class)
13 | val id: Int,
14 | val stripe: String? = null,
15 | val paypal: String? = null,
16 | val paypalPayerId: String? = null,
17 | val paypalPaymentId: String? = null,
18 | val message: String? = null,
19 | val status: Boolean? = null
20 | )
21 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/order/ConfirmOrder.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.order
2 |
3 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
4 | import com.fasterxml.jackson.databind.annotation.JsonNaming
5 | import com.github.jasminb.jsonapi.annotations.Id
6 | import com.github.jasminb.jsonapi.annotations.Type
7 |
8 | @Type("order")
9 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
10 | data class ConfirmOrder(
11 | @Id
12 | val id: String,
13 | val status: String? = null,
14 | val orderNotes: String? = null
15 | )
16 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/order/OrderDao.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.order
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.OnConflictStrategy
6 | import androidx.room.Query
7 | import io.reactivex.Single
8 |
9 | @Dao
10 | interface OrderDao {
11 | @Insert(onConflict = OnConflictStrategy.REPLACE)
12 | fun insertOrders(orders: List)
13 |
14 | @Insert(onConflict = OnConflictStrategy.REPLACE)
15 | fun insertOrder(order: Order)
16 |
17 | @Query("SELECT * FROM `order`")
18 | fun getAllOrders(): Single>
19 |
20 | @Query("SELECT * FROM `order` WHERE isExpired = :expired")
21 | fun getOrders(expired: Boolean): Single>
22 |
23 | @Query("DELETE FROM `order`")
24 | fun deleteAllOrders()
25 |
26 | @Query("SELECT * FROM `order` WHERE id = :orderId")
27 | fun getOrderById(orderId: Long): Single
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/order/QrCode.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.order
2 |
3 | import android.graphics.Bitmap
4 | import com.google.zxing.BarcodeFormat
5 | import com.google.zxing.EncodeHintType
6 | import com.google.zxing.MultiFormatWriter
7 | import com.google.zxing.WriterException
8 | import com.journeyapps.barcodescanner.BarcodeEncoder
9 | import timber.log.Timber
10 |
11 | class QrCode {
12 | private val multiFormatWriter = MultiFormatWriter()
13 | private val barcodeEncoder = BarcodeEncoder()
14 |
15 | fun generateQrBitmap(text: String?, width: Int, height: Int): Bitmap? {
16 | try {
17 | val hint = HashMap()
18 | hint[EncodeHintType.MARGIN] = 1
19 | val bitMatrix = multiFormatWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hint)
20 | return barcodeEncoder.createBitmap(bitMatrix)
21 | } catch (e: WriterException) {
22 | Timber.d(e, "Writer Exception")
23 | }
24 | return null
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/paypal/Paypal.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.paypal
2 |
3 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
4 | import com.fasterxml.jackson.databind.annotation.JsonNaming
5 | import com.github.jasminb.jsonapi.annotations.Id
6 | import com.github.jasminb.jsonapi.annotations.Type
7 |
8 | @Type("order")
9 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
10 | class Paypal(
11 | @Id
12 | val id: Int? = null,
13 | val paymentId: String
14 | )
15 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/paypal/PaypalApi.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.paypal
2 |
3 | import io.reactivex.Single
4 | import retrofit2.http.Body
5 | import retrofit2.http.POST
6 | import retrofit2.http.Path
7 |
8 | interface PaypalApi {
9 |
10 | @POST("orders/{orderIdentifier}/verify-mobile-paypal-payment")
11 | fun verifyPaypalPayment(
12 | @Path("orderIdentifier") orderIdentifier: String,
13 | @Body paypal: Paypal
14 | ): Single
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/paypal/PaypalPaymentResponse.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.paypal
2 |
3 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
4 | import com.fasterxml.jackson.databind.annotation.JsonNaming
5 |
6 | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class)
7 | data class PaypalPaymentResponse(
8 | val status: Boolean,
9 | val error: String? = null
10 | )
11 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/search/SearchEventsDataSourceFactory.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.search
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import androidx.paging.DataSource
5 | import io.reactivex.disposables.CompositeDisposable
6 | import org.fossasia.openevent.general.event.Event
7 | import org.fossasia.openevent.general.event.EventService
8 |
9 | data class SearchEventsDataSourceFactory(
10 | private val compositeDisposable: CompositeDisposable,
11 | private val eventService: EventService,
12 | private val query: String,
13 | private val sortBy: String,
14 | private val mutableProgress: MutableLiveData
15 | ) : DataSource.Factory() {
16 | override fun create(): DataSource {
17 | return SearchEventsDataSource(
18 | eventService,
19 | compositeDisposable,
20 | query,
21 | sortBy,
22 | mutableProgress
23 | )
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/search/location/LocationService.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.search.location
2 |
3 | import io.reactivex.Single
4 |
5 | /**
6 | * Implementations of this interface provide functionality related to the user location.
7 | * */
8 | interface LocationService {
9 |
10 | /**
11 | * Gives the administrative area of the current location the user is in.
12 | * */
13 | fun getAdministrativeArea(): Single
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/search/location/LocationViewHolder.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.search.location
2 |
3 | import android.view.View
4 | import androidx.recyclerview.widget.RecyclerView
5 | import kotlinx.android.synthetic.main.item_location_text.view.locationText
6 |
7 | class LocationViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
8 |
9 | fun bind(location: String, listener: TextClickListener?) {
10 | itemView.locationText.text = location
11 | itemView.setOnClickListener {
12 | listener?.onTextClick(location)
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/search/recentsearch/RecentSearchViewHolder.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.search.recentsearch
2 |
3 | import android.view.View
4 | import androidx.recyclerview.widget.RecyclerView
5 | import kotlinx.android.synthetic.main.item_recent_search.view.clearRecent
6 | import kotlinx.android.synthetic.main.item_recent_search.view.recentSearchLocation
7 | import kotlinx.android.synthetic.main.item_recent_search.view.recentSearchText
8 |
9 | class RecentSearchViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
10 |
11 | fun bind(
12 | searches: Pair,
13 | position: Int,
14 | listener: RecentSearchListener?
15 | ) {
16 | itemView.recentSearchText.text = searches.first
17 | itemView.recentSearchLocation.text = searches.second
18 | itemView.setOnClickListener {
19 | listener?.clickSearch(searches.first, searches.second)
20 | }
21 | itemView.clearRecent.setOnClickListener {
22 | listener?.removeSearch(position, searches)
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/search/time/SearchTimeViewModel.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.search.time
2 |
3 | import androidx.lifecycle.ViewModel
4 | import org.fossasia.openevent.general.data.Preference
5 |
6 | const val SAVED_TIME = "TIME"
7 |
8 | class SearchTimeViewModel(private val preference: Preference) : ViewModel() {
9 |
10 | fun saveTime(query: String) {
11 | preference.putString(SAVED_TIME, query)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/sessions/SessionDao.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.sessions
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.room.Dao
5 | import androidx.room.Insert
6 | import androidx.room.OnConflictStrategy.REPLACE
7 | import androidx.room.Query
8 | import io.reactivex.Flowable
9 |
10 | @Dao
11 | interface SessionDao {
12 |
13 | @Insert(onConflict = REPLACE)
14 | fun insertSessions(sessions: List)
15 |
16 | @Insert(onConflict = REPLACE)
17 | fun insertSession(session: Session)
18 |
19 | @Query("SELECT * FROM Session WHERE id =:id")
20 | fun getSessionById(id: Long): Flowable
21 |
22 | @Query("SELECT * FROM Session")
23 | fun getAllSessions(): LiveData>
24 |
25 | @Query("DELETE FROM Session")
26 | fun deleteCurrentSessions()
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/sessions/SessionRecyclerAdapter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.sessions
2 |
3 | import android.view.LayoutInflater
4 | import android.view.ViewGroup
5 | import androidx.recyclerview.widget.RecyclerView
6 | import org.fossasia.openevent.general.R
7 | import org.fossasia.openevent.general.common.SessionClickListener
8 |
9 | class SessionRecyclerAdapter : RecyclerView.Adapter() {
10 | private val sessionList = ArrayList()
11 | var onSessionClick: SessionClickListener? = null
12 |
13 | fun addAll(sessionList: List) {
14 | if (sessionList.isNotEmpty())
15 | this.sessionList.clear()
16 | this.sessionList.addAll(sessionList)
17 | notifyDataSetChanged()
18 | }
19 |
20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SessionViewHolder {
21 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item_session, parent, false)
22 | return SessionViewHolder(view)
23 | }
24 |
25 | override fun onBindViewHolder(holder: SessionViewHolder, position: Int) {
26 | val session = sessionList[position]
27 |
28 | holder.apply {
29 | bind(session)
30 | sessionClickListener = onSessionClick
31 | }
32 | }
33 |
34 | override fun getItemCount(): Int {
35 | return sessionList.size
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/sessions/microlocation/MicroLocation.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.sessions.microlocation
2 |
3 | import androidx.room.Entity
4 | import androidx.room.PrimaryKey
5 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
6 | import com.fasterxml.jackson.databind.annotation.JsonNaming
7 | import com.github.jasminb.jsonapi.LongIdHandler
8 | import com.github.jasminb.jsonapi.annotations.Id
9 | import com.github.jasminb.jsonapi.annotations.Type
10 |
11 | @Type("microlocation")
12 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
13 | @Entity
14 | data class MicroLocation(
15 | @Id(LongIdHandler::class)
16 | @PrimaryKey
17 | val id: Long,
18 | val name: String,
19 | val room: String?,
20 | val latitude: String?,
21 | val longitude: String?,
22 | val floor: String?,
23 | val deletedAt: String?
24 | )
25 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/sessions/microlocation/MicroLocationConverter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.sessions.microlocation
2 |
3 | import androidx.room.TypeConverter
4 | import com.fasterxml.jackson.databind.ObjectMapper
5 | import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
6 |
7 | class MicroLocationConverter {
8 | @TypeConverter
9 | fun toMicroLoation(json: String) =
10 | jacksonObjectMapper().readerFor(MicroLocation::class.java).readValue(json)
11 |
12 | @TypeConverter
13 | fun toJson(microLocation: MicroLocation?) = ObjectMapper().writeValueAsString(microLocation)
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/sessions/sessiontype/SessionType.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.sessions.sessiontype
2 |
3 | import androidx.room.Entity
4 | import androidx.room.PrimaryKey
5 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
6 | import com.fasterxml.jackson.databind.annotation.JsonNaming
7 | import com.github.jasminb.jsonapi.LongIdHandler
8 | import com.github.jasminb.jsonapi.annotations.Id
9 | import com.github.jasminb.jsonapi.annotations.Type
10 |
11 | @Type("session-type")
12 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
13 | @Entity
14 | data class SessionType(
15 | @Id(LongIdHandler::class)
16 | @PrimaryKey
17 | val id: Long,
18 | val name: String,
19 | val length: String?,
20 | val deletedAt: String?
21 | )
22 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/sessions/sessiontype/SessionTypeConverter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.sessions.sessiontype
2 |
3 | import androidx.room.TypeConverter
4 | import com.fasterxml.jackson.databind.ObjectMapper
5 | import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
6 |
7 | class SessionTypeConverter {
8 |
9 | @TypeConverter
10 | fun toSessionType(json: String): SessionType? =
11 | jacksonObjectMapper().readerFor(SessionType::class.java).readValue(json)
12 |
13 | @TypeConverter
14 | fun toJson(sessionType: SessionType?) = ObjectMapper().writeValueAsString(sessionType)
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/sessions/track/Track.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.sessions.track
2 |
3 | import androidx.room.Entity
4 | import androidx.room.PrimaryKey
5 | import com.fasterxml.jackson.databind.PropertyNamingStrategy
6 | import com.fasterxml.jackson.databind.annotation.JsonNaming
7 | import com.github.jasminb.jsonapi.LongIdHandler
8 | import com.github.jasminb.jsonapi.annotations.Id
9 | import com.github.jasminb.jsonapi.annotations.Type
10 |
11 | @Type("track")
12 | @JsonNaming(PropertyNamingStrategy.KebabCaseStrategy::class)
13 | @Entity
14 | data class Track(
15 | @Id(LongIdHandler::class)
16 | @PrimaryKey
17 | val id: Long,
18 | val name: String,
19 | val description: String?,
20 | val color: String,
21 | val fontColor: String?
22 | )
23 |
--------------------------------------------------------------------------------
/app/src/main/java/org/fossasia/openevent/general/sessions/track/TrackConverter.kt:
--------------------------------------------------------------------------------
1 | package org.fossasia.openevent.general.sessions.track
2 |
3 | import androidx.room.TypeConverter
4 | import com.fasterxml.jackson.databind.ObjectMapper
5 | import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
6 |
7 | class TrackConverter {
8 |
9 | @TypeConverter
10 | fun toTrack(json: String): Track? =
11 | jacksonObjectMapper().readerFor(Track::class.java).readValue