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

Commit ec5f5e5

Browse files
committed
Merge branch 'develop' into conf/droidcon-turin-2018
2 parents acab9a8 + 2567ae8 commit ec5f5e5

37 files changed

Lines changed: 423 additions & 143 deletions

app/src/debug/java/net/squanchy/support/debug/DebugActivity.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,9 @@ class DebugActivity : AppCompatActivity() {
108108
"0",
109109
0,
110110
"UI",
111-
Option(generateColor()),
112-
Option(generateColor()),
113-
Option.empty()
111+
generateColor(),
112+
generateColor(),
113+
null
114114
)
115115

116116
private fun generateColor(): String {

app/src/main/java/net/squanchy/eventdetails/widget/EventDetailsCoordinatorLayout.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ class EventDetailsCoordinatorLayout @JvmOverloads constructor(
2121
eventDetailsLayout.updateWith(event)
2222

2323
if (event.canBeFavorited) {
24-
val favoriteImage = if (event.favorite) R.drawable.ic_favorite_filled else R.drawable.ic_favorite_empty
25-
favoriteFab.setImageResource(favoriteImage)
24+
// Updates the FAB image state to trigger an AVD animation.
25+
val stateSet = intArrayOf(android.R.attr.state_checked * if (event.favorite) 1 else -1)
26+
favoriteFab.setImageState(stateSet, true)
2627
favoriteFab.setOnClickListener { listener.onFavoriteClick() }
2728
favoriteFab.isVisible = true
2829
} else {

app/src/main/java/net/squanchy/eventdetails/widget/EventDetailsLayout.kt

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package net.squanchy.eventdetails.widget
22

33
import android.content.Context
4-
import android.content.res.Resources
4+
import android.graphics.Color
55
import android.support.annotation.AttrRes
66
import android.support.annotation.ColorInt
77
import android.support.constraint.ConstraintLayout
@@ -10,15 +10,17 @@ import android.text.SpannableStringBuilder
1010
import android.text.Spanned
1111
import android.text.style.ForegroundColorSpan
1212
import android.util.AttributeSet
13-
import android.util.TypedValue
1413
import android.view.View
14+
import android.widget.TextView
1515
import androidx.view.isVisible
1616
import arrow.core.Option
1717
import kotlinx.android.synthetic.main.merge_event_details_layout.view.*
1818
import net.squanchy.R
1919
import net.squanchy.eventdetails.domain.view.ExperienceLevel
2020
import net.squanchy.schedule.domain.view.Event
2121
import net.squanchy.schedule.domain.view.Place
22+
import net.squanchy.schedule.domain.view.Track
23+
import net.squanchy.support.content.res.getColorFromAttribute
2224
import net.squanchy.support.lang.getOrThrow
2325
import net.squanchy.support.text.parseHtml
2426
import org.joda.time.DateTimeZone
@@ -42,7 +44,8 @@ class EventDetailsLayout @JvmOverloads constructor(
4244
fun updateWith(event: Event) {
4345
updateWhen(event.startTime, event.timeZone)
4446
updateWhere(event.place)
45-
updateLevel(event.experienceLevel)
47+
updateLevel(event.experienceLevel, event.type)
48+
updateTrack(event.track)
4649
updateDescription(event.description)
4750
}
4851

@@ -77,34 +80,48 @@ class EventDetailsLayout @JvmOverloads constructor(
7780
return builder
7881
}
7982

80-
private fun updateLevel(level: Option<ExperienceLevel>) {
81-
if (level.isDefined()) {
82-
levelGroup.isVisible = true
83+
private fun createColorSpan(targetView: View, @AttrRes attributeResId: Int): ForegroundColorSpan {
84+
val color = targetView.context.theme.getColorFromAttribute(attributeResId)
85+
return ForegroundColorSpan(color)
86+
}
8387

84-
val experienceLevel = level.getOrThrow()
85-
levelValue.setText(experienceLevel.labelStringResId)
86-
tintCompoundDrawableEnd(experienceLevel)
87-
} else {
88-
levelGroup.isVisible = false
88+
private fun updateLevel(level: Option<ExperienceLevel>, type: Event.Type) {
89+
when {
90+
type == Event.Type.KEYNOTE -> {
91+
levelGroup.isVisible = false
92+
}
93+
level.isDefined() -> {
94+
levelGroup.isVisible = true
95+
96+
val experienceLevel = level.getOrThrow()
97+
levelValue.setText(experienceLevel.labelStringResId)
98+
99+
val experienceColor = ContextCompat.getColor(context, experienceLevel.colorResId)
100+
levelValue.tintCompoundDrawableEnd(experienceColor)
101+
}
102+
else -> levelGroup.isVisible = false
89103
}
90104
}
91105

92-
private fun tintCompoundDrawableEnd(experienceLevel: ExperienceLevel) {
93-
val compoundDrawables = levelValue.compoundDrawablesRelative
94-
val endCompoundDrawable = compoundDrawables[2]
95-
endCompoundDrawable?.setTint(ContextCompat.getColor(context, experienceLevel.colorResId))
96-
}
106+
private fun updateTrack(trackOption: Option<Track>) {
107+
if (trackOption.isDefined()) {
108+
trackGroup.isVisible = true
97109

98-
private fun createColorSpan(targetView: View, @AttrRes attributeResId: Int): ForegroundColorSpan {
99-
val color = getColorFromTheme(targetView.context.theme, attributeResId)
100-
return ForegroundColorSpan(color)
110+
val track = trackOption.getOrThrow()
111+
trackValue.text = track.name
112+
track.accentColor?.let {
113+
val trackColor = Color.parseColor(it)
114+
trackValue.tintCompoundDrawableEnd(trackColor)
115+
}
116+
} else {
117+
trackGroup.isVisible = false
118+
}
101119
}
102120

103-
@ColorInt
104-
private fun getColorFromTheme(theme: Resources.Theme, @AttrRes attributeId: Int): Int {
105-
val typedValue = TypedValue()
106-
theme.resolveAttribute(attributeId, typedValue, true)
107-
return typedValue.data
121+
private fun TextView.tintCompoundDrawableEnd(@ColorInt color: Int) {
122+
val compoundDrawables = compoundDrawablesRelative
123+
val endCompoundDrawable = compoundDrawables[2]
124+
endCompoundDrawable?.setTint(color)
108125
}
109126

110127
private fun updateDescription(description: Option<String>) {

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package net.squanchy.favorites.view
22

33
import android.content.Context
44
import android.os.Build
5-
import android.support.annotation.DrawableRes
65
import android.support.annotation.RequiresApi
76
import android.support.constraint.ConstraintLayout
87
import android.support.design.widget.Snackbar
@@ -30,22 +29,22 @@ class FavoritesSignedInEmptyLayout @JvmOverloads constructor(
3029
this.counter = counter
3130
}
3231

33-
override fun setButtonImage(@DrawableRes resId: Int) = favoriteFab.setImageResource(resId)
32+
override fun setButtonState(favorited: Boolean) {
33+
// Updates the FAB image state to trigger an AVD animation.
34+
val stateSet = intArrayOf(android.R.attr.state_checked * if (favorited) 1 else -1)
35+
favoriteFab.setImageState(stateSet, true)
36+
}
3437

3538
@RequiresApi(Build.VERSION_CODES.N)
3639
override fun showAchievement(message: String) {
3740
Snackbar.make(this, message.parseHtml(), Snackbar.LENGTH_LONG).show()
3841
}
3942

4043
private val favoriteButtonClickListener = View.OnClickListener {
41-
presentButtonIcon(counter, this, ::favoritesFilledIconId, ::favoritesEmptyIconId)
44+
presentButtonIcon(counter, this)
4245
presentAchievementMessage(counter, this, ::initialAchieventMessage, ::perseveranceAchievementMessage)
4346
}
4447

45-
private fun favoritesFilledIconId() = R.drawable.ic_favorite_filled
46-
47-
private fun favoritesEmptyIconId() = R.drawable.ic_favorite_empty
48-
4948
private fun initialAchieventMessage() = resources.getString(R.string.favorites_achievement_fast_learner)
5049

5150
private fun perseveranceAchievementMessage() = resources.getString(R.string.favorites_achievement_persevering)

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ private const val TAPS_TO_TRIGGER_INITIAL_ACHIEVEMENT = 5
44
private const val TAPS_TO_TRIGGER_PERSEVERANCE_ACHIEVEMENT = 15
55

66
private typealias AchievementMessageProvider = () -> String
7-
private typealias ResIdProvider = () -> Int
87

9-
internal fun presentButtonIcon(counter: Int, view: FavoritesSignedInEmptyLayoutView, filledIconId: ResIdProvider, emptyIconId: ResIdProvider) {
10-
11-
if (counter % 2 == 0) view.setButtonImage(filledIconId()) else view.setButtonImage(emptyIconId())
12-
}
8+
internal fun presentButtonIcon(
9+
counter: Int,
10+
view: FavoritesSignedInEmptyLayoutView
11+
) = view.setButtonState(counter % 2 == 0)
1312

1413
internal fun presentAchievementMessage(
1514
counter: Int,
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package net.squanchy.favorites.view
22

3-
import android.support.annotation.DrawableRes
4-
53
interface FavoritesSignedInEmptyLayoutView {
64

75
fun updateCounter(counter: Int)
86

9-
fun setButtonImage(@DrawableRes resId: Int)
7+
fun setButtonState(favorited: Boolean)
108

119
fun showAchievement(message: String)
1210
}

app/src/main/java/net/squanchy/home/HomeActivity.kt

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ import android.content.Context
55
import android.content.Intent
66
import android.content.res.Resources
77
import android.os.Bundle
8-
import android.support.annotation.AttrRes
98
import android.support.annotation.ColorInt
109
import android.support.transition.Fade
1110
import android.support.transition.TransitionManager
1211
import android.support.v7.app.AppCompatActivity
13-
import android.util.TypedValue
1412
import android.view.View
1513
import androidx.view.isInvisible
1614
import androidx.view.isVisible
@@ -22,6 +20,7 @@ import net.squanchy.home.deeplink.HomeActivityDeepLinkCreator
2220
import net.squanchy.home.deeplink.HomeActivityIntentParser
2321
import net.squanchy.navigation.Navigator
2422
import net.squanchy.signin.SignInOrigin
23+
import net.squanchy.support.content.res.getColorFromAttribute
2524
import net.squanchy.support.widget.InterceptingBottomNavigationView
2625

2726
class HomeActivity : AppCompatActivity() {
@@ -108,8 +107,8 @@ class HomeActivity : AppCompatActivity() {
108107
bottomNavigationView.selectItemAt(section.ordinal)
109108

110109
val theme = getThemeFor(section)
111-
bottomNavigationView.setBackgroundColor(getColorFromTheme(theme, android.support.design.R.attr.colorPrimary))
112-
window.statusBarColor = getColorFromTheme(theme, android.R.attr.statusBarColor)
110+
bottomNavigationView.setBackgroundColor(theme.getColorFromAttribute(android.support.design.R.attr.colorPrimary))
111+
window.statusBarColor = theme.getColorFromAttribute(android.R.attr.statusBarColor)
113112

114113
currentSection = section
115114
}
@@ -125,8 +124,8 @@ class HomeActivity : AppCompatActivity() {
125124
swapPageTo(section)
126125

127126
val theme = getThemeFor(section)
128-
animateStatusBarColorTo(getColorFromTheme(theme, android.R.attr.statusBarColor))
129-
bottomNavigationView.colorProvider = { getColorFromTheme(theme, android.support.design.R.attr.colorPrimary) }
127+
animateStatusBarColorTo(theme.getColorFromAttribute(android.R.attr.statusBarColor))
128+
bottomNavigationView.colorProvider = { theme.getColorFromAttribute(android.support.design.R.attr.colorPrimary) }
130129

131130
currentSection = section
132131

@@ -147,13 +146,6 @@ class HomeActivity : AppCompatActivity() {
147146
}
148147
}
149148

150-
@ColorInt
151-
private fun getColorFromTheme(theme: Resources.Theme, @AttrRes attributeId: Int): Int {
152-
val typedValue = TypedValue()
153-
theme.resolveAttribute(attributeId, typedValue, true)
154-
return typedValue.data
155-
}
156-
157149
private fun animateStatusBarColorTo(@ColorInt color: Int) {
158150
val currentStatusBarColor = window.statusBarColor
159151

app/src/main/java/net/squanchy/notification/NotificationCreator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class NotificationCreator(private val context: Context) {
127127

128128
private fun getTrackColor(event: Event): Int {
129129
return event.track
130-
.map { (_, _, _, accentColor) -> Color.parseColor(accentColor.or(ARGB_TRANSPARENT)) }
130+
.map { Color.parseColor(it.accentColor ?: ARGB_TRANSPARENT) }
131131
.or(Color.TRANSPARENT)
132132
}
133133

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package net.squanchy.schedule.domain.view
22

3-
import arrow.core.Option
4-
53
data class Track(
64
val id: String,
75
val numericId: Long,
86
val name: String,
9-
val accentColor: Option<String> = Option.empty(),
10-
val textColor: Option<String> = Option.empty(),
11-
val iconUrl: Option<String> = Option.empty()
7+
val accentColor: String? = null,
8+
val textColor: String? = null,
9+
val iconUrl: String? = null
1210
)

app/src/main/java/net/squanchy/schedule/tracksfilter/TracksFilterAdapter.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import android.view.ViewGroup
1111
import net.squanchy.R
1212
import net.squanchy.schedule.domain.view.Track
1313
import net.squanchy.schedule.tracksfilter.widget.FilterChipView
14-
import net.squanchy.support.lang.getOrThrow
15-
import net.squanchy.support.lang.or
1614

1715
internal class TracksFilterAdapter(
1816
context: Context,
@@ -57,9 +55,11 @@ internal class TrackViewHolder(val item: FilterChipView) : RecyclerView.ViewHold
5755
item.apply {
5856
text = track.name
5957

60-
color = track.accentColor
61-
.map { Color.parseColor(track.accentColor.getOrThrow()) }
62-
.or(ContextCompat.getColor(context, R.color.chip_default_background_tint))
58+
if (track.accentColor != null) {
59+
color = Color.parseColor(track.accentColor)
60+
} else {
61+
color = ContextCompat.getColor(context, R.color.chip_default_background_tint)
62+
}
6363

6464
onCheckedChangeListener = { _, checked -> listener.invoke(track, checked) }
6565
isChecked = selected

0 commit comments

Comments
 (0)