Skip to content
This repository was archived by the owner on Feb 17, 2020. It is now read-only.

Commit 4e4d009

Browse files
authored
Merge pull request #561 from squanchy-dev/favourites_in_schedule_config
Setting to show favourites in schedule
2 parents 432ea01 + 3caf33e commit 4e4d009

14 files changed

Lines changed: 154 additions & 51 deletions

File tree

app/src/main/java/net/squanchy/analytics/Analytics.kt

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,10 @@ class Analytics internal constructor(
4646
}
4747

4848
private fun trackItemSelectedOnFirebaseAnalytics(contentType: ContentType, itemId: String) {
49-
val params = Bundle()
50-
params.putString(FirebaseAnalytics.Param.CONTENT_TYPE, contentType.rawContentType)
51-
params.putString(FirebaseAnalytics.Param.ITEM_ID, itemId)
49+
val params = Bundle().apply {
50+
putString(FirebaseAnalytics.Param.CONTENT_TYPE, contentType.rawContentType)
51+
putString(FirebaseAnalytics.Param.ITEM_ID, itemId)
52+
}
5253
firebaseAnalytics.logEvent(FirebaseAnalytics.Event.SELECT_CONTENT, params)
5354
}
5455

@@ -81,12 +82,26 @@ class Analytics internal constructor(
8182

8283
fun trackNotificationsEnabled() {
8384
firebaseAnalytics.setUserProperty("notifications_status", "enabled")
85+
firebaseAnalytics.logEvent("notifications_status_changed", flagEnabled(TRUE))
8486
}
8587

8688
fun trackNotificationsDisabled() {
8789
firebaseAnalytics.setUserProperty("notifications_status", "disabled")
90+
firebaseAnalytics.logEvent("notifications_status_changed", flagEnabled(FALSE))
91+
}
92+
93+
fun trackFavoritesInScheduleEnabled() {
94+
firebaseAnalytics.setUserProperty("favorites_in_schedule", "enable")
95+
firebaseAnalytics.logEvent("favorites_in_schedule_changed", flagEnabled(TRUE))
96+
}
97+
98+
fun trackFavoritesInScheduleDisabled() {
99+
firebaseAnalytics.setUserProperty("favorites_in_schedule", "disabled")
100+
firebaseAnalytics.logEvent("favorites_in_schedule_changed", flagEnabled(FALSE))
88101
}
89102

103+
private fun flagEnabled(value: String) = Bundle().apply { putString("enabled", value) }
104+
90105
fun trackUserNotLoggedIn() {
91106
setUserLoginProperty(LoginStatus.NOT_LOGGED_IN)
92107
}
@@ -105,9 +120,15 @@ class Analytics internal constructor(
105120
}
106121

107122
fun trackWifiConfigurationEvent(isSuccess: Boolean, wifiConfigOrigin: WifiConfigOrigin) {
108-
val params = Bundle()
109-
params.putString("origin", wifiConfigOrigin.rawOrigin)
110-
params.putBoolean("success", isSuccess)
123+
val params = Bundle().apply {
124+
putString("origin", wifiConfigOrigin.rawOrigin)
125+
putBoolean("success", isSuccess)
126+
}
111127
firebaseAnalytics.logEvent("wifi_config", params)
112128
}
129+
130+
companion object {
131+
private const val TRUE = "true"
132+
private const val FALSE = "false"
133+
}
113134
}

app/src/main/java/net/squanchy/favorites/view/FavoritesAdapter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ internal class FavoritesAdapter(
6464

6565
@Deprecated(
6666
message = "Use updateWith() instead",
67-
replaceWith = ReplaceWith("updateWith(list, showRoom, eventClickListener)"),
67+
replaceWith = ReplaceWith("updateWith(list, showRoom, favoriteClickListener)"),
6868
level = DeprecationLevel.ERROR
6969
)
7070
override fun submitList(list: MutableList<FavoritesItem>?) {

app/src/main/java/net/squanchy/schedule/SchedulePageView.kt

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
package net.squanchy.schedule
22

33
import android.content.Context
4-
import android.support.design.widget.CoordinatorLayout
4+
import android.support.constraint.ConstraintLayout
55
import android.support.design.widget.TabLayout
66
import android.text.Spanned
77
import android.util.AttributeSet
88
import androidx.view.isVisible
9+
import arrow.core.Tuple3
910
import io.reactivex.Observable
1011
import io.reactivex.android.schedulers.AndroidSchedulers
1112
import io.reactivex.disposables.CompositeDisposable
12-
import io.reactivex.functions.BiFunction
13+
import io.reactivex.functions.Function3
1314
import io.reactivex.schedulers.Schedulers
1415
import kotlinx.android.synthetic.main.view_page_schedule.view.*
1516
import net.squanchy.R
@@ -21,6 +22,7 @@ import net.squanchy.remoteconfig.FeatureFlags
2122
import net.squanchy.schedule.domain.view.Event
2223
import net.squanchy.schedule.domain.view.Schedule
2324
import net.squanchy.schedule.view.ScheduleViewPagerAdapter
25+
import net.squanchy.settings.preferences.showFavoritesInScheduleObservable
2426
import net.squanchy.support.system.CurrentTime
2527
import net.squanchy.support.text.applyTypeface
2628
import net.squanchy.support.text.getFontFor
@@ -33,7 +35,7 @@ class SchedulePageView @JvmOverloads constructor(
3335
context: Context,
3436
attrs: AttributeSet,
3537
defStyleAttr: Int = 0
36-
) : CoordinatorLayout(context, attrs, defStyleAttr), Loadable {
38+
) : ConstraintLayout(context, attrs, defStyleAttr), Loadable {
3739

3840
private val viewPagerAdapter: ScheduleViewPagerAdapter
3941
private val service: ScheduleService
@@ -57,7 +59,7 @@ class SchedulePageView @JvmOverloads constructor(
5759
override fun onFinishInflate() {
5860
super.onFinishInflate()
5961

60-
tabstrip.setupWithViewPager(viewpager)
62+
tabstrip.setupWithViewPager(viewPager)
6163
hackToApplyTypefaces(tabstrip)
6264

6365
setupToolbar()
@@ -89,38 +91,41 @@ class SchedulePageView @JvmOverloads constructor(
8991

9092
override fun startLoading() {
9193
subscriptions.add(
92-
Observable.combineLatest(service.schedule(), featureFlags.showEventRoomInSchedule.toObservable(), combineInPair())
94+
Observable.combineLatest(
95+
service.schedule(),
96+
featureFlags.showEventRoomInSchedule.toObservable(),
97+
showFavoritesInScheduleObservable(context),
98+
Function3<Schedule, Boolean, Boolean, Tuple3<Schedule, Boolean, Boolean>>(::Tuple3)
99+
)
93100
.subscribeOn(Schedulers.io())
94101
.observeOn(AndroidSchedulers.mainThread())
95102
.subscribe(
96-
{ updateWith(it.first, it.second, ::onEventClicked) },
103+
{ updateWith(it.a, it.b, it.c, ::onEventClicked) },
97104
Timber::e
98105
)
99106
)
100107
}
101108

102-
private fun combineInPair(): BiFunction<Schedule, Boolean, Pair<Schedule, Boolean>> = BiFunction(::Pair)
103-
104-
private fun updateWith(schedule: Schedule, showRoom: Boolean, onEventClicked: (Event) -> Unit) {
105-
progressbar.isVisible = false
109+
private fun updateWith(schedule: Schedule, showRoom: Boolean, showFavorites: Boolean, onEventClicked: (Event) -> Unit) {
110+
progressBar.isVisible = false
106111

107112
if (schedule.isEmpty) {
108-
viewpager.isVisible = false
113+
viewPager.isVisible = false
109114
tabstrip.isVisible = false
110115
emptyView.isVisible = true
111116
return
112117
}
113118

114-
viewpager.isVisible = true
119+
viewPager.isVisible = true
115120
tabstrip.isVisible = true
116121
emptyView.isVisible = false
117122

118-
viewPagerAdapter.updateWith(schedule.pages, showRoom, onEventClicked)
119-
if (viewpager.adapter == null) {
120-
viewpager.adapter = viewPagerAdapter
123+
viewPagerAdapter.updateWith(schedule.pages, showRoom, showFavorites, onEventClicked)
124+
if (viewPager.adapter == null) {
125+
viewPager.adapter = viewPagerAdapter
121126
}
122127

123-
progressbar.isVisible = false
128+
progressBar.isVisible = false
124129
}
125130

126131
private fun onEventClicked(event: Event) {

app/src/main/java/net/squanchy/schedule/view/EventsAdapter.kt

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,20 @@ internal class EventsAdapter(context: Context) : ListAdapter<Event, EventViewHol
1717

1818
private val layoutInflater: LayoutInflater = LayoutInflater.from(context)
1919
private var showRoom = false
20+
private var showFavorites = false
2021
private var eventClickListener: OnEventClickListener? = null
2122

22-
fun updateWith(list: List<Event>, showRoom: Boolean, listener: OnEventClickListener) {
23+
fun updateWith(list: List<Event>, showRoom: Boolean, showFavorites: Boolean, listener: OnEventClickListener) {
2324
this.showRoom = showRoom
2425
this.eventClickListener = listener
26+
27+
if (this.showFavorites != showFavorites) {
28+
// We want to refresh the favourite visualization too which is not part of the model and thus
29+
// would get ignored by the DiffCallback when comparing things. We go nuclear and trigger
30+
// a full dataset change notification.
31+
this.showFavorites = showFavorites
32+
notifyDataSetChanged()
33+
}
2534
super.submitList(list)
2635
}
2736

@@ -52,7 +61,7 @@ internal class EventsAdapter(context: Context) : ListAdapter<Event, EventViewHol
5261
}
5362

5463
override fun onBindViewHolder(holder: EventViewHolder, position: Int) {
55-
holder.updateWith(getItem(position), showRoom, eventClickListener)
64+
holder.updateWith(getItem(position), showRoom, showFavorites, eventClickListener)
5665
}
5766

5867
@Deprecated(
@@ -67,8 +76,8 @@ internal class EventsAdapter(context: Context) : ListAdapter<Event, EventViewHol
6776

6877
internal class EventViewHolder(itemView: EventItemView) : RecyclerView.ViewHolder(itemView) {
6978

70-
fun updateWith(event: Event, showRoom: Boolean, listener: OnEventClickListener?) {
71-
(itemView as EventItemView).updateWith(event, showRoom)
79+
fun updateWith(event: Event, showRoom: Boolean, showFavorites: Boolean, listener: OnEventClickListener?) {
80+
(itemView as EventItemView).updateWith(event, showRoom = showRoom, showFavorite = showFavorites)
7281
itemView.setOnClickListener { listener?.invoke(event) }
7382
}
7483
}

app/src/main/java/net/squanchy/schedule/view/ScheduleDayPageView.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ class ScheduleDayPageView @JvmOverloads constructor(
2929
addItemDecoration(CardSpacingItemDecorator(horizontalSpacing, verticalSpacing))
3030
}
3131

32-
fun updateWith(newData: List<Event>, showRoom: Boolean, listener: (Event) -> Unit) {
32+
fun updateWith(newData: List<Event>, showRoom: Boolean, showFavorites: Boolean, listener: (Event) -> Unit) {
3333
setAdapterIfNone(adapter)
34-
adapter.updateWith(newData, showRoom, listener)
34+
adapter.updateWith(newData, showRoom, showFavorites, listener)
3535
}
3636
}

app/src/main/java/net/squanchy/schedule/view/ScheduleViewPagerAdapter.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ class ScheduleViewPagerAdapter(context: Context) : ViewPagerAdapter<ScheduleDayP
2020
private val inflater = LayoutInflater.from(context)
2121
private val viewPool = RecyclerView.RecycledViewPool()
2222
private var showRoom: Boolean = false
23+
private var showFavorites: Boolean = false
2324

24-
fun updateWith(pages: List<SchedulePage>, showRoom: Boolean, listener: (Event) -> Unit) {
25+
fun updateWith(pages: List<SchedulePage>, showRoom: Boolean, showFavorites: Boolean, listener: (Event) -> Unit) {
2526
this.pages = pages
26-
this.listener = listener
2727
this.showRoom = showRoom
28+
this.showFavorites = showFavorites
29+
this.listener = listener
2830
notifyDataSetChanged()
2931
}
3032

@@ -38,7 +40,7 @@ class ScheduleViewPagerAdapter(context: Context) : ViewPagerAdapter<ScheduleDayP
3840

3941
override fun bindView(view: ScheduleDayPageView, position: Int) {
4042
val events = pages[position].events
41-
view.updateWith(events, showRoom, listener)
43+
view.updateWith(events, showRoom, showFavorites, listener)
4244
}
4345

4446
override fun getPageTitle(position: Int): CharSequence? {

app/src/main/java/net/squanchy/settings/SettingsFragment.kt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,6 @@ class SettingsFragment : PreferenceFragment() {
4040
private lateinit var accountEmailPreference: Preference
4141
private lateinit var accountSignInSignOutPreference: Preference
4242

43-
private val viewOrThrow: View
44-
get() = this.view ?: throw IllegalStateException("You cannot access the fragment's view when it doesn't exist yet")
45-
4643
override fun onCreate(savedInstanceState: Bundle?) {
4744
super.onCreate(savedInstanceState)
4845

@@ -85,6 +82,16 @@ class SettingsFragment : PreferenceFragment() {
8582
true
8683
}
8784

85+
val favoritesInSchedulePreference = findPreference(getString(R.string.favorites_in_schedule_preference_key))
86+
favoritesInSchedulePreference.setOnPreferenceChangeListener { _, enabled ->
87+
if (enabled as Boolean) {
88+
analytics.trackFavoritesInScheduleEnabled()
89+
} else {
90+
analytics.trackFavoritesInScheduleDisabled()
91+
}
92+
true
93+
}
94+
8895
setupWifiConfigPreference()
8996
}
9097

@@ -170,6 +177,9 @@ class SettingsFragment : PreferenceFragment() {
170177
}
171178
}
172179

180+
private val viewOrThrow: View
181+
get() = this.view ?: throw IllegalStateException("You cannot access the fragment's view when it doesn't exist yet")
182+
173183
private fun onSignedOut() {
174184
accountCategory.removePreference(accountEmailPreference)
175185

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package net.squanchy.settings.preferences
2+
3+
import android.content.Context
4+
import android.content.SharedPreferences
5+
import android.preference.PreferenceManager
6+
import io.reactivex.Observable
7+
8+
fun showFavoritesInScheduleObservable(context: Context) =
9+
context.defaultSharedPreferences.observeFlag("favorites_in_schedule_preference_key", false)
10+
11+
private val Context.defaultSharedPreferences
12+
get() = PreferenceManager.getDefaultSharedPreferences(this)
13+
14+
private fun SharedPreferences.observeFlag(key: String, defaultValue: Boolean = false): Observable<Boolean> = Observable.create { emitter ->
15+
val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, changedKey ->
16+
if (key == changedKey) {
17+
emitter.onNext(getBoolean(key, defaultValue))
18+
}
19+
}
20+
21+
emitter.onNext(getBoolean(key, defaultValue))
22+
registerOnSharedPreferenceChangeListener(listener)
23+
emitter.setCancellable { unregisterOnSharedPreferenceChangeListener(listener) }
24+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24.0"
5+
android:viewportHeight="24.0">
6+
<path
7+
android:fillColor="@color/selector_color_primary"
8+
android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z" />
9+
</vector>

app/src/main/res/layout/view_page_schedule.xml

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,55 @@
99
tools:context="net.squanchy.home.HomeActivity">
1010

1111
<android.support.design.widget.AppBarLayout
12+
android:id="@+id/appBarLayout"
1213
style="@style/Squanchy.Appbar"
1314
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
14-
android:layout_width="match_parent"
15-
android:layout_height="wrap_content">
15+
android:layout_width="@dimen/match_constraint"
16+
android:layout_height="wrap_content"
17+
app:layout_constraintStart_toStartOf="parent"
18+
app:layout_constraintTop_toTopOf="parent"
19+
app:layout_constraintEnd_toEndOf="parent">
1620

1721
<android.support.v7.widget.Toolbar
1822
android:id="@+id/toolbar"
1923
android:layout_width="match_parent"
20-
android:layout_height="?attr/actionBarSize" />
24+
android:layout_height="wrap_content" />
2125

2226
<android.support.design.widget.TabLayout
2327
android:id="@+id/tabstrip"
2428
style="@style/Squanchy.Tabs.Schedule"
2529
android:layout_width="match_parent"
26-
android:layout_height="?attr/actionBarSize" />
30+
android:layout_height="wrap_content" />
2731

2832
</android.support.design.widget.AppBarLayout>
2933

3034
<android.support.v4.view.ViewPager
31-
android:id="@+id/viewpager"
32-
android:layout_width="match_parent"
33-
android:layout_height="match_parent"
34-
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
35+
android:id="@+id/viewPager"
36+
android:layout_width="@dimen/match_constraint"
37+
android:layout_height="@dimen/match_constraint"
38+
app:layout_constraintStart_toStartOf="parent"
39+
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
40+
app:layout_constraintEnd_toEndOf="parent"
41+
app:layout_constraintBottom_toBottomOf="parent" />
3542

3643
<ProgressBar
37-
android:id="@+id/progressbar"
44+
android:id="@+id/progressBar"
3845
android:layout_width="wrap_content"
3946
android:layout_height="wrap_content"
40-
android:layout_gravity="center" />
47+
app:layout_constraintStart_toStartOf="parent"
48+
app:layout_constraintTop_toTopOf="@+id/viewPager"
49+
app:layout_constraintEnd_toEndOf="parent"
50+
app:layout_constraintBottom_toBottomOf="parent" />
4151

4252
<TextView
4353
android:id="@+id/emptyView"
4454
style="@style/Schedule.EmptyView"
4555
android:layout_width="wrap_content"
4656
android:layout_height="wrap_content"
47-
android:layout_gravity="center"
48-
android:visibility="gone" />
57+
android:visibility="gone"
58+
app:layout_constraintStart_toStartOf="parent"
59+
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
60+
app:layout_constraintEnd_toEndOf="parent"
61+
app:layout_constraintBottom_toBottomOf="parent" />
4962

5063
</net.squanchy.schedule.SchedulePageView>

0 commit comments

Comments
 (0)