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

Commit 995806f

Browse files
committed
merge with develop
2 parents f4bd865 + efc9c00 commit 995806f

62 files changed

Lines changed: 423 additions & 920 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.circleci/config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919

2020
# Restore cached dependencies (if any)
2121
- restore_cache:
22-
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
22+
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
2323

2424
# Prepare the container for the build
2525
- run:
@@ -47,7 +47,7 @@ jobs:
4747

4848
# Gradle dependencies
4949
- ~/.gradle
50-
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
50+
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
5151

5252
# Collect static analysis reports as build artifacts
5353
- store_artifacts:

.idea/inspectionProfiles/Squanchy.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ detailed instructions.
1212

1313
Please note that this app uses some third party services:
1414
* Firebase (Firestore, Push messages, etc.)
15-
* Fabric: Crashlytics and Twitter
15+
* Fabric: Crashlytics
1616

1717
While not all of them are strictly necessary for the app to work (with the exception of Firebase's RTDB), it is currently not possible for the code to
1818
work without them. We plan on eventually abstracting away the implementations so that they would simply be disabled if there is no API configured, but

app/build.gradle

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,9 @@ dependencies {
127127
implementation project(':renderthread')
128128

129129
implementation libraries.app.androidKtx
130+
implementation libraries.app.arrowCore
130131

131132
implementation libraries.app.crashlytics
132-
implementation(libraries.app.findbugsAnnotations) {
133-
exclude group: 'net.jcip'
134-
exclude group: 'com.google.code.findbugs'
135-
}
136133
implementation(libraries.app.firebase) {
137134
exclude group: 'com.android.support'
138135
}
@@ -150,7 +147,6 @@ dependencies {
150147

151148
implementation libraries.app.flexbox
152149

153-
annotationProcessor libraries.app.glideCompiler
154150
kapt libraries.app.glideCompiler
155151
implementation libraries.app.glide
156152
implementation libraries.app.glideOkHttp3
@@ -170,7 +166,6 @@ dependencies {
170166
implementation libraries.app.moshi
171167
implementation libraries.app.moshiKotlin
172168

173-
annotationProcessor libraries.app.daggerCompiler
174169
kapt libraries.app.daggerCompiler
175170
implementation libraries.app.dagger
176171

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.support.design.widget.Snackbar
66
import android.support.v4.app.NotificationManagerCompat
77
import android.support.v7.app.AppCompatActivity
88
import android.view.View
9+
import arrow.core.Option
910
import net.squanchy.R
1011
import net.squanchy.eventdetails.domain.view.ExperienceLevel
1112
import net.squanchy.notification.NotificationCreator
@@ -15,7 +16,6 @@ import net.squanchy.schedule.domain.view.Event
1516
import net.squanchy.schedule.domain.view.Place
1617
import net.squanchy.schedule.domain.view.Track
1718
import net.squanchy.speaker.domain.view.Speaker
18-
import net.squanchy.support.lang.Optional
1919
import org.joda.time.DateTimeZone
2020
import org.joda.time.LocalDateTime
2121
import java.util.ArrayList
@@ -72,18 +72,18 @@ class DebugActivity : AppCompatActivity() {
7272
endTime = end,
7373
title = "A very interesting talk",
7474
place = createPlace(),
75-
experienceLevel = Optional.of(ExperienceLevel.ADVANCED),
75+
experienceLevel = Option(ExperienceLevel.ADVANCED),
7676
speakers = createTalkSpeakers(),
7777
type = Event.Type.TALK,
7878
favorited = true,
79-
description = Optional.absent(),
80-
track = Optional.of(createTrack()),
79+
description = Option.empty(),
80+
track = Option(createTrack()),
8181
timeZone = DateTimeZone.forID("Europe/Rome")
8282
)
8383
}
8484

85-
private fun createPlace(): Optional<Place> = Optional.of(
86-
Place("1", "That room over there", Optional.absent())
85+
private fun createPlace(): Option<Place> = Option(
86+
Place("1", "That room over there", Option.empty())
8787
)
8888

8989
private fun createTalkSpeakers(): List<Speaker> {
@@ -94,11 +94,11 @@ class DebugActivity : AppCompatActivity() {
9494
numericId = 101L,
9595
name = "Ajeje Brazorf",
9696
bio = "An Android dev",
97-
companyName = Optional.absent(),
98-
companyUrl = Optional.absent(),
99-
personalUrl = Optional.absent(),
100-
photoUrl = Optional.of("https://yt3.ggpht.com/-d35Rq8vqvmE/AAAAAAAAAAAA/zy1VyiRTNec/s900-c-k-no-mo-rj-c0xffffff/photo.jpg"),
101-
twitterUsername = Optional.absent()
97+
companyName = Option.empty(),
98+
companyUrl = Option.empty(),
99+
personalUrl = Option.empty(),
100+
photoUrl = Option("https://yt3.ggpht.com/-d35Rq8vqvmE/AAAAAAAAAAAA/zy1VyiRTNec/s900-c-k-no-mo-rj-c0xffffff/photo.jpg"),
101+
twitterUsername = Option.empty()
102102
)
103103
)
104104
return speakers
@@ -108,9 +108,9 @@ class DebugActivity : AppCompatActivity() {
108108
"0",
109109
0,
110110
"UI",
111-
Optional.of(generateColor()),
112-
Optional.of(generateColor()),
113-
Optional.of("gs://droidcon-italy-2017.appspot.com/tracks/0.webp")
111+
Option(generateColor()),
112+
Option(generateColor()),
113+
Option("gs://droidcon-italy-2017.appspot.com/tracks/0.webp")
114114
)
115115

116116
private fun generateColor(): String {

app/src/main/java/net/squanchy/eventdetails/EventDetailsService.kt

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package net.squanchy.eventdetails
22

3+
import arrow.core.Option
34
import io.reactivex.Completable
45
import io.reactivex.Observable
56
import io.reactivex.Single
67
import net.squanchy.schedule.domain.view.Event
78
import net.squanchy.service.repository.AuthService
89
import net.squanchy.service.repository.EventRepository
910
import net.squanchy.service.repository.User
10-
import net.squanchy.support.lang.Optional
11+
import net.squanchy.support.lang.or
1112

1213
internal class EventDetailsService(
1314
private val eventRepository: EventRepository,
@@ -21,15 +22,13 @@ internal class EventDetailsService(
2122
fun toggleFavorite(event: Event): Single<FavoriteResult> {
2223
return currentUser()
2324
.flatMap { optionalUser ->
24-
optionalUser
25-
.map {
26-
if (it.isAnonymous) {
27-
Single.just(FavoriteResult.MUST_AUTHENTICATE)
28-
} else {
29-
toggleFavoriteOn(event).andThen(Single.just(FavoriteResult.SUCCESS))
30-
}
25+
optionalUser.map { user ->
26+
if (user.isAnonymous) {
27+
Single.just(FavoriteResult.MUST_AUTHENTICATE)
28+
} else {
29+
toggleFavoriteOn(event).andThen(Single.just(FavoriteResult.SUCCESS))
3130
}
32-
.or(Single.just(FavoriteResult.MUST_AUTHENTICATE))
31+
}.or(Single.just(FavoriteResult.MUST_AUTHENTICATE))
3332
}
3433
}
3534

@@ -49,7 +48,7 @@ internal class EventDetailsService(
4948
return authService.ifUserSignedInThenCompletableFrom { userId -> eventRepository.addFavorite(eventId, userId) }
5049
}
5150

52-
private fun currentUser(): Single<Optional<User>> = authService.currentUser().firstOrError()
51+
private fun currentUser(): Single<Option<User>> = authService.currentUser().firstOrError()
5352

5453
internal enum class FavoriteResult {
5554
SUCCESS,

app/src/main/java/net/squanchy/eventdetails/domain/view/ExperienceLevel.kt

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

33
import android.support.annotation.ColorRes
44
import android.support.annotation.StringRes
5+
import arrow.core.Option
56
import net.squanchy.R
6-
import net.squanchy.support.lang.Optional
77
import timber.log.Timber
88
import java.util.Locale
99

@@ -18,22 +18,22 @@ enum class ExperienceLevel(
1818

1919
companion object {
2020

21-
fun tryParsingFrom(rawLevel: String?): Optional<ExperienceLevel> =
21+
fun tryParsingFrom(rawLevel: String?): Option<ExperienceLevel> =
2222
rawLevel?.let {
2323
try {
24-
Optional.of(fromRawLevel(it))
24+
Option(fromRawLevel(it))
2525
} catch (e: IllegalArgumentException) {
2626
Timber.d(e)
27-
Optional.absent<ExperienceLevel>()
27+
null
2828
}
29-
} ?: Optional.absent()
29+
} ?: Option.empty()
3030

3131
private fun fromRawLevel(rawLevel: String) =
3232
when (rawLevel.toLowerCase(Locale.US)) {
3333
BEGINNER.rawLevel -> BEGINNER
3434
INTERMEDIATE.rawLevel -> INTERMEDIATE
3535
ADVANCED.rawLevel -> ADVANCED
36-
else -> throw IllegalArgumentException("Invalid raw level description: " + rawLevel)
36+
else -> throw IllegalArgumentException("Invalid raw level description: $rawLevel")
3737
}
3838
}
3939
}

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

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

3-
import android.annotation.TargetApi
43
import android.content.Context
54
import android.content.res.Resources
6-
import android.os.Build
75
import android.support.annotation.AttrRes
86
import android.support.annotation.ColorInt
97
import android.support.v4.content.ContextCompat
10-
import android.text.Html
118
import android.text.SpannableStringBuilder
129
import android.text.Spanned
1310
import android.text.style.ForegroundColorSpan
1411
import android.util.AttributeSet
1512
import android.util.TypedValue
1613
import android.view.View
1714
import android.widget.LinearLayout
15+
import arrow.core.Option
1816
import kotlinx.android.synthetic.main.merge_event_details_layout.view.*
1917
import net.squanchy.R
2018
import net.squanchy.eventdetails.domain.view.ExperienceLevel
2119
import net.squanchy.schedule.domain.view.Event
2220
import net.squanchy.schedule.domain.view.Place
23-
import net.squanchy.support.lang.Optional
21+
import net.squanchy.support.lang.getOrThrow
22+
import net.squanchy.support.text.parseHtml
2423
import org.joda.time.format.DateTimeFormat
2524

2625
// TODO flatten this layout as a ConstraintLayout
@@ -58,18 +57,18 @@ class EventDetailsLayout @JvmOverloads constructor(
5857
}
5958

6059
private fun updateWhere(event: Event) {
61-
if (event.place.isPresent) {
60+
if (event.place.isDefined()) {
6261
whereContainer.visibility = View.VISIBLE
63-
whereTextView.text = placeTextFrom(event.place.get())
62+
whereTextView.text = placeTextFrom(event.place.getOrThrow())
6463
} else {
6564
whereContainer.visibility = View.GONE
6665
}
6766
}
6867

6968
private fun placeTextFrom(place: Place): CharSequence {
7069
val builder = SpannableStringBuilder(place.name)
71-
if (place.floor.isPresent) {
72-
val floorLabel = place.floor.get()
70+
if (place.floor.isDefined()) {
71+
val floorLabel = place.floor.getOrThrow()
7372
builder.append(" ")
7473
.append(floorLabel)
7574
.setSpan(
@@ -82,11 +81,11 @@ class EventDetailsLayout @JvmOverloads constructor(
8281
return builder
8382
}
8483

85-
private fun updateLevel(level: Optional<ExperienceLevel>) {
86-
if (level.isPresent) {
84+
private fun updateLevel(level: Option<ExperienceLevel>) {
85+
if (level.isDefined()) {
8786
levelContainer.visibility = View.VISIBLE
8887

89-
val experienceLevel = level.get()
88+
val experienceLevel = level.getOrThrow()
9089
levelTextView.setText(experienceLevel.labelStringResId)
9190
tintCompoundDrawableEnd(experienceLevel)
9291
} else {
@@ -112,28 +111,17 @@ class EventDetailsLayout @JvmOverloads constructor(
112111
return typedValue.data
113112
}
114113

115-
private fun updateDescription(description: Optional<String>) {
116-
if (description.isPresent) {
114+
private fun updateDescription(description: Option<String>) {
115+
if (description.isDefined()) {
117116
descriptionHeader.visibility = View.VISIBLE
118117
descriptionTextView.visibility = View.VISIBLE
119-
descriptionTextView.text = parseHtml(description.get())
118+
descriptionTextView.text = parseHtml(description.getOrThrow())
120119
} else {
121120
descriptionHeader.visibility = View.GONE
122121
descriptionTextView.visibility = View.GONE
123122
}
124123
}
125124

126-
@TargetApi(Build.VERSION_CODES.N) // The older fromHtml() is only called pre-24
127-
private fun parseHtml(description: String): Spanned {
128-
// TODO handle this properly
129-
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
130-
Html.fromHtml(description, Html.FROM_HTML_MODE_LEGACY)
131-
} else {
132-
@Suppress("DEPRECATION") // This is a "compat" method call, we only use this on pre-N
133-
Html.fromHtml(description)
134-
}
135-
}
136-
137125
companion object {
138126

139127
private const val WHEN_DATE_TIME_FORMAT = "EEEE, d MMMM 'at' HH:mm"

app/src/main/java/net/squanchy/favorites/FavoritesService.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import net.squanchy.favorites.view.FavoritesItem
55
import net.squanchy.schedule.ScheduleService
66
import net.squanchy.schedule.domain.view.Event
77
import net.squanchy.service.repository.AuthService
8+
import net.squanchy.support.lang.or
89

910
interface FavoritesService {
1011

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import net.squanchy.home.HomeActivity
1919
import net.squanchy.schedule.domain.view.Event
2020
import net.squanchy.speaker.domain.view.Speaker
2121
import net.squanchy.support.android
22+
import net.squanchy.support.lang.getOrThrow
23+
import net.squanchy.support.lang.or
2224

2325
class NotificationCreator(private val context: Context) {
2426

@@ -120,7 +122,7 @@ class NotificationCreator(private val context: Context) {
120122
}
121123

122124
private fun getPlaceName(event: Event): String? {
123-
return if (event.place.isPresent) event.place.get().name else null
125+
return event.place.orNull()?.name
124126
}
125127

126128
private fun getTrackColor(event: Event): Int {
@@ -172,11 +174,11 @@ class NotificationCreator(private val context: Context) {
172174
.setBigContentTitle(bigContentTitle)
173175

174176
for (event in events) {
175-
if (event.place.isPresent) {
177+
if (event.place.isDefined()) {
176178
richNotification.addLine(
177179
context.getString(
178180
R.string.room_event_notification,
179-
event.place.get().name,
181+
event.place.getOrThrow().name,
180182
event.title
181183
)
182184
)
@@ -189,8 +191,7 @@ class NotificationCreator(private val context: Context) {
189191
}
190192

191193
private fun createSummaryTitle(talksCount: Int): String {
192-
val quantityString = context.resources
193-
.getQuantityString(R.plurals.event_notification_count_starting, talksCount)
194+
val quantityString = context.resources.getQuantityString(R.plurals.event_notification_count_starting, talksCount)
194195
return String.format(quantityString, talksCount)
195196
}
196197

0 commit comments

Comments
 (0)