Skip to content

Commit

Permalink
feat: Fetch settings and divide events view model (#2101) (#2083)
Browse files Browse the repository at this point in the history
  • Loading branch information
liveHarshit committed Jul 15, 2019
1 parent 1a3ecec commit 67cb46f
Show file tree
Hide file tree
Showing 14 changed files with 2,240 additions and 116 deletions.
1,973 changes: 1,973 additions & 0 deletions app/schemas/org.fossasia.openevent.general.OpenEventDatabase/8.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import org.fossasia.openevent.general.sessions.SessionDao
import org.fossasia.openevent.general.sessions.microlocation.MicroLocationConverter
import org.fossasia.openevent.general.sessions.sessiontype.SessionTypeConverter
import org.fossasia.openevent.general.sessions.track.TrackConverter
import org.fossasia.openevent.general.settings.Settings
import org.fossasia.openevent.general.settings.SettingsDao
import org.fossasia.openevent.general.social.SocialLink
import org.fossasia.openevent.general.social.SocialLinksDao
import org.fossasia.openevent.general.speakercall.SpeakersCallConverter
Expand All @@ -49,7 +51,8 @@ import org.fossasia.openevent.general.ticket.TicketIdConverter

@Database(entities = [Event::class, User::class, SocialLink::class, Ticket::class, Attendee::class,
EventTopic::class, Order::class, CustomForm::class, Speaker::class, SpeakerWithEvent::class, Sponsor::class,
SponsorWithEvent::class, Session::class, SpeakersCall::class, Feedback::class, Notification::class], version = 7)
SponsorWithEvent::class, Session::class, SpeakersCall::class, Feedback::class, Notification::class,
Settings::class], version = 8)
@TypeConverters(EventIdConverter::class, EventTopicConverter::class, EventTypeConverter::class,
EventSubTopicConverter::class, TicketIdConverter::class, MicroLocationConverter::class, UserIdConverter::class,
AttendeeIdConverter::class, ListAttendeeIdConverter::class, SessionTypeConverter::class, TrackConverter::class,
Expand Down Expand Up @@ -85,4 +88,6 @@ abstract class OpenEventDatabase : RoomDatabase() {
abstract fun feedbackDao(): FeedbackDao

abstract fun notificationDao(): NotificationDao

abstract fun settingsDao(): SettingsDao
}
119 changes: 119 additions & 0 deletions app/src/main/java/org/fossasia/openevent/general/StartupViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package org.fossasia.openevent.general

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.plusAssign
import org.fossasia.openevent.general.auth.AuthHolder
import org.fossasia.openevent.general.auth.AuthService
import org.fossasia.openevent.general.auth.RequestPasswordReset
import org.fossasia.openevent.general.auth.forgot.PasswordReset
import org.fossasia.openevent.general.common.SingleLiveEvent
import org.fossasia.openevent.general.data.Preference
import org.fossasia.openevent.general.data.Resource
import org.fossasia.openevent.general.event.NEW_NOTIFICATIONS
import org.fossasia.openevent.general.notification.NotificationService
import org.fossasia.openevent.general.settings.SettingsService
import org.fossasia.openevent.general.utils.HttpErrors
import org.fossasia.openevent.general.utils.extensions.withDefaultSchedulers
import retrofit2.HttpException
import timber.log.Timber

class StartupViewModel(
private val preference: Preference,
private val resource: Resource,
private val authHolder: AuthHolder,
private val authService: AuthService,
private val notificationService: NotificationService,
private val settingsService: SettingsService
) : ViewModel() {
private val compositeDisposable = CompositeDisposable()
val mutableNewNotifications = MutableLiveData<Boolean>()
val newNotifications: LiveData<Boolean> = mutableNewNotifications
private val mutableDialogProgress = MutableLiveData<Boolean>()
val dialogProgress: LiveData<Boolean> = mutableDialogProgress
private val mutableIsRefresh = MutableLiveData<Boolean>()
val isRefresh: LiveData<Boolean> = mutableIsRefresh
private val mutableResetPasswordEmail = MutableLiveData<String>()
val resetPasswordEmail: LiveData<String> = mutableResetPasswordEmail
private val mutableMessage = SingleLiveEvent<String>()
val message: LiveData<String> = mutableMessage

fun isLoggedIn() = authHolder.isLoggedIn()

fun getId() = authHolder.getId()

fun syncNotifications() {
if (!isLoggedIn())
return
compositeDisposable += notificationService.syncNotifications(getId())
.withDefaultSchedulers()
.subscribe({ list ->
list?.forEach {
if (!it.isRead) {
preference.putBoolean(NEW_NOTIFICATIONS, true)
mutableNewNotifications.value = true
}
}
}, {
if (it is HttpException) {
if (authHolder.isLoggedIn() && it.code() == HttpErrors.UNAUTHORIZED) {
logoutAndRefresh()
}
}
Timber.e(it, "Error fetching notifications")
})
}

private fun logoutAndRefresh() {
compositeDisposable += authService.logout()
.withDefaultSchedulers()
.subscribe({
mutableIsRefresh.value = true
}, {
Timber.e(it, "Error while logout")
mutableMessage.value = resource.getString(R.string.error)
})
}

fun checkAndReset(token: String, newPassword: String) {
val resetRequest = RequestPasswordReset(PasswordReset(token, newPassword))
if (authHolder.isLoggedIn()) {
compositeDisposable += authService.logout()
.withDefaultSchedulers()
.doOnSubscribe {
mutableDialogProgress.value = true
}.subscribe {
resetPassword(resetRequest)
}
} else
resetPassword(resetRequest)
}

private fun resetPassword(resetRequest: RequestPasswordReset) {
compositeDisposable += authService.resetPassword(resetRequest)
.withDefaultSchedulers()
.doOnSubscribe {
mutableDialogProgress.value = true
}.doFinally {
mutableDialogProgress.value = false
}.subscribe({
Timber.e(it.toString())
mutableMessage.value = resource.getString(R.string.reset_password_message)
mutableResetPasswordEmail.value = it.email
}, {
Timber.e(it, "Failed to reset password")
})
}

fun fetchSettings() {
compositeDisposable += settingsService.fetchSettings()
.withDefaultSchedulers()
.subscribe({
Timber.d("Settings fetched successfully")
}, {
Timber.e(it, "Error in fetching settings form API")
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ import java.util.Calendar
import java.util.Currency
import kotlin.collections.ArrayList

private const val COUNT_DOWN_TIME = 15 // in minutes

class AttendeeFragment : Fragment(), ComplexBackPressFragment {

private lateinit var rootView: View
Expand Down Expand Up @@ -260,9 +258,13 @@ class AttendeeFragment : Fragment(), ComplexBackPressFragment {
.observe(viewLifecycleOwner, Observer {
loadEventDetailsUI(it)
setupPaymentOptions(it)
if (attendeeViewModel.pendingOrder.value != null) {
setupCountDownTimer(it)
}
})

attendeeViewModel.getSettings()
attendeeViewModel.orderExpiryTime
.nonNull()
.observe(viewLifecycleOwner, Observer {
setupCountDownTimer(it)
})

val currentEvent = attendeeViewModel.event.value
Expand All @@ -271,33 +273,22 @@ class AttendeeFragment : Fragment(), ComplexBackPressFragment {
else {
setupPaymentOptions(currentEvent)
loadEventDetailsUI(currentEvent)
if (attendeeViewModel.pendingOrder.value != null) {
setupCountDownTimer(currentEvent)
}
}
}

private fun setupPendingOrder() {
attendeeViewModel.pendingOrder
.nonNull()
.observe(viewLifecycleOwner, Observer {
attendeeViewModel.event.value?.let {
setupCountDownTimer(it)
}
})

val currentPendingOrder = attendeeViewModel.pendingOrder.value
if (currentPendingOrder == null) {
attendeeViewModel.initializeOrder(safeArgs.eventId)
}
}

private fun setupCountDownTimer(event: Event) {
private fun setupCountDownTimer(orderExpiryTime: Int) {
rootView.timeoutCounterLayout.visibility = View.VISIBLE
rootView.timeoutInfoTextView.text =
getString(R.string.ticket_timeout_info_message, event.orderExpiryTime.toString())
getString(R.string.ticket_timeout_info_message, orderExpiryTime.toString())

val timeLeft: Long = if (attendeeViewModel.timeout == -1L) COUNT_DOWN_TIME * 60 * 1000L
val timeLeft: Long = if (attendeeViewModel.timeout == -1L) orderExpiryTime * 60 * 1000L
else attendeeViewModel.timeout
timer = object : CountDownTimer(timeLeft, 1000) {
override fun onFinish() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import org.fossasia.openevent.general.order.Charge
import org.fossasia.openevent.general.order.ConfirmOrder
import org.fossasia.openevent.general.order.Order
import org.fossasia.openevent.general.order.OrderService
import org.fossasia.openevent.general.settings.SettingsService
import org.fossasia.openevent.general.ticket.Ticket
import org.fossasia.openevent.general.ticket.TicketService
import org.fossasia.openevent.general.utils.HttpErrors
Expand All @@ -38,6 +39,7 @@ const val PAYMENT_MODE_ONSITE = "onsite"
const val PAYMENT_MODE_CHEQUE = "cheque"
const val PAYMENT_MODE_PAYPAL = "paypal"
const val PAYMENT_MODE_STRIPE = "stripe"
private const val ORDER_EXPIRY_TIME = 15

class AttendeeViewModel(
private val attendeeService: AttendeeService,
Expand All @@ -46,6 +48,7 @@ class AttendeeViewModel(
private val orderService: OrderService,
private val ticketService: TicketService,
private val authService: AuthService,
private val settingsService: SettingsService,
private val resource: Resource
) : ViewModel() {

Expand All @@ -71,6 +74,8 @@ class AttendeeViewModel(
val pendingOrder: LiveData<Order> = mutablePendingOrder
private val mutableStripeOrderMade = MutableLiveData<Boolean>()
val stripeOrderMade: LiveData<Boolean> = mutableStripeOrderMade
private val mutableOrderExpiryTime = MutableLiveData<Int>()
val orderExpiryTime: LiveData<Int> = mutableOrderExpiryTime

val attendees = ArrayList<Attendee>()
private val attendeesForOrder = ArrayList<Attendee>()
Expand Down Expand Up @@ -391,6 +396,21 @@ class AttendeeViewModel(
return true
}

fun getSettings() {
compositeDisposable += settingsService.fetchSettings()
.withDefaultSchedulers()
.doOnSubscribe {
mutableProgress.value = true
}.doFinally {
mutableProgress.value = false
}.subscribe({
mutableOrderExpiryTime.value = it.orderExpiryTime
}, {
mutableOrderExpiryTime.value = ORDER_EXPIRY_TIME
Timber.e(it, "Error fetching settings")
})
}

override fun onCleared() {
super.onCleared()
compositeDisposable.clear()
Expand Down
21 changes: 18 additions & 3 deletions app/src/main/java/org/fossasia/openevent/general/di/Modules.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import org.fossasia.openevent.general.BuildConfig
import org.fossasia.openevent.general.OpenEventDatabase
import org.fossasia.openevent.general.StartupViewModel
import org.fossasia.openevent.general.about.AboutEventViewModel
import org.fossasia.openevent.general.attendees.Attendee
import org.fossasia.openevent.general.attendees.AttendeeApi
Expand Down Expand Up @@ -90,6 +91,9 @@ import org.fossasia.openevent.general.sessions.SessionViewModel
import org.fossasia.openevent.general.sessions.microlocation.MicroLocation
import org.fossasia.openevent.general.sessions.sessiontype.SessionType
import org.fossasia.openevent.general.sessions.track.Track
import org.fossasia.openevent.general.settings.Settings
import org.fossasia.openevent.general.settings.SettingsApi
import org.fossasia.openevent.general.settings.SettingsService
import org.fossasia.openevent.general.settings.SettingsViewModel
import org.fossasia.openevent.general.social.SocialLink
import org.fossasia.openevent.general.social.SocialLinkApi
Expand Down Expand Up @@ -194,6 +198,10 @@ val apiModule = module {
val retrofit: Retrofit = get()
retrofit.create(DiscountApi::class.java)
}
single {
val retrofit: Retrofit = get()
retrofit.create(SettingsApi::class.java)
}

factory { AuthHolder(get()) }
factory { AuthService(get(), get(), get(), get(), get()) }
Expand All @@ -208,19 +216,21 @@ val apiModule = module {
factory { SessionService(get(), get()) }
factory { NotificationService(get(), get()) }
factory { FeedbackService(get(), get()) }
factory { SettingsService(get(), get()) }
}

val viewModelModule = module {
viewModel { LoginViewModel(get(), get(), get()) }
viewModel { EventsViewModel(get(), get(), get(), get(), get(), get(), get(), get()) }
viewModel { EventsViewModel(get(), get(), get(), get(), get()) }
viewModel { StartupViewModel(get(), get(), get(), get(), get(), get()) }
viewModel { ProfileViewModel(get(), get()) }
viewModel { SignUpViewModel(get(), get(), get()) }
viewModel {
EventDetailsViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get()) }
viewModel { SessionViewModel(get(), get(), get()) }
viewModel { SearchViewModel(get(), get()) }
viewModel { SearchResultsViewModel(get(), get(), get(), get(), get()) }
viewModel { AttendeeViewModel(get(), get(), get(), get(), get(), get(), get()) }
viewModel { AttendeeViewModel(get(), get(), get(), get(), get(), get(), get(), get()) }
viewModel { SearchLocationViewModel(get(), get()) }
viewModel { SearchTimeViewModel(get()) }
viewModel { SearchTypeViewModel(get(), get(), get()) }
Expand Down Expand Up @@ -292,7 +302,7 @@ val networkModule = module {
EventSubTopic::class.java, Feedback::class.java, Speaker::class.java,
Session::class.java, SessionType::class.java, MicroLocation::class.java, SpeakersCall::class.java,
Sponsor::class.java, EventFAQ::class.java, Notification::class.java, Track::class.java,
DiscountCode::class.java)
DiscountCode::class.java, Settings::class.java)

Retrofit.Builder()
.client(get())
Expand Down Expand Up @@ -385,4 +395,9 @@ val databaseModule = module {
val database: OpenEventDatabase = get()
database.notificationDao()
}

factory {
val database: OpenEventDatabase = get()
database.settingsDao()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ data class Event(
val latitude: Double? = null,
val longitude: Double? = null,
val refundPolicy: String? = null,
val orderExpiryTime: Int = 10,

val canPayByStripe: Boolean = false,
val canPayByCheque: Boolean = false,
Expand Down
Loading

0 comments on commit 67cb46f

Please sign in to comment.