Skip to content
Permalink
Browse files

merge with develop

  • Loading branch information...
quiro91 committed Apr 4, 2018
1 parent 32cae4b commit 9465ea8f58fa576c40714b08f8458f4f0e34b067
Showing with 2,447 additions and 933 deletions.
  1. +2 −0 app/build.gradle
  2. +1 −0 app/src/debug/java/net/squanchy/support/debug/DebugActivity.kt
  3. +1 −1 app/src/debug/java/net/squanchy/support/injection/CurrentTimeModule.kt
  4. +11 −0 app/src/main/java/net/squanchy/SquanchyApplication.kt
  5. +16 −11 app/src/main/java/net/squanchy/about/licenses/Libraries.kt
  6. +5 −2 app/src/main/java/net/squanchy/about/licenses/License.kt
  7. +3 −5 app/src/main/java/net/squanchy/favorites/FavoritesComponent.kt
  8. +17 −0 app/src/main/java/net/squanchy/favorites/FavoritesModule.kt
  9. +46 −33 app/src/main/java/net/squanchy/favorites/FavoritesPageView.kt
  10. +45 −0 app/src/main/java/net/squanchy/favorites/FavoritesService.kt
  11. +30 −97 app/src/main/java/net/squanchy/favorites/view/FavoritesAdapter.kt
  12. +30 −0 app/src/main/java/net/squanchy/favorites/view/FavoritesItem.kt
  13. +6 −6 app/src/main/java/net/squanchy/favorites/view/FavoritesListView.kt
  14. +31 −0 app/src/main/java/net/squanchy/favorites/view/FavoritesViewHolders.kt
  15. +1 −1 app/src/main/java/net/squanchy/home/BottomNavigationHelper.kt
  16. +3 −4 app/src/main/java/net/squanchy/home/HomeComponent.kt
  17. +1 −1 app/src/main/java/net/squanchy/injection/ApplicationComponent.kt
  18. +1 −1 app/src/main/java/net/squanchy/notification/NotificationCreator.kt
  19. +2 −2 app/src/main/java/net/squanchy/schedule/ScheduleModule.kt
  20. +1 −8 app/src/main/java/net/squanchy/schedule/ScheduleService.kt
  21. +1 −0 app/src/main/java/net/squanchy/schedule/domain/view/Track.kt
  22. +11 −0 app/src/main/java/net/squanchy/schedule/tracksfilter/CheckableTrack.kt
  23. +111 −91 app/src/main/java/net/squanchy/schedule/tracksfilter/ScheduleTracksFilter.kt
  24. +68 −0 app/src/main/java/net/squanchy/schedule/tracksfilter/TracksFilterAdapter.kt
  25. +240 −0 app/src/main/java/net/squanchy/schedule/tracksfilter/widget/FilterChipView.kt
  26. +28 −21 app/src/main/java/net/squanchy/schedule/view/EventsAdapter.kt
  27. +15 −19 app/src/main/java/net/squanchy/schedule/view/ScheduleDayPageView.kt
  28. +7 −10 app/src/main/java/net/squanchy/schedule/view/ScheduleViewPagerAdapter.kt
  29. +1 −1 app/src/main/java/net/squanchy/search/view/SearchAdapter.java
  30. +4 −2 app/src/main/java/net/squanchy/search/view/SearchRecyclerView.java
  31. +4 −3 app/src/main/java/net/squanchy/service/firebase/FirestoreMappers.kt
  32. +1 −1 app/src/main/java/net/squanchy/service/repository/firestore/FirestoreEventRepository.kt
  33. +1 −1 app/src/main/java/net/squanchy/service/repository/firestore/FirestoreSpeakerRepository.kt
  34. +3 −3 app/src/main/java/net/squanchy/service/repository/firestore/FirestoreTracksRepository.kt
  35. +7 −6 app/src/main/java/net/squanchy/service/repository/injection/RepositoryModule.kt
  36. +1 −1 app/src/main/java/net/squanchy/signin/SignInComponent.kt
  37. +1 −1 app/src/main/java/net/squanchy/support/{lang → checksum}/Checksum.kt
  38. +11 −0 app/src/main/java/net/squanchy/support/checksum/ChecksumModule.kt
  39. +9 −10 app/src/main/java/net/squanchy/support/config/DialogLayoutParameters.kt
  40. +0 −12 app/src/main/java/net/squanchy/support/config/FormFactorChecker.kt
  41. +55 −20 app/src/main/java/net/squanchy/support/graphics/Color.kt
  42. +0 −13 app/src/main/java/net/squanchy/support/injection/ChecksumModule.kt
  43. +0 −9 app/src/main/java/net/squanchy/support/kotlin/ViewHelper.kt
  44. +2 −0 app/src/main/java/net/squanchy/support/system/CurrentTime.kt
  45. +7 −0 app/src/main/java/net/squanchy/support/view/RecyclerViewUtils.kt
  46. +7 −7 app/src/main/java/net/squanchy/support/widget/CardLayout.kt
  47. +1 −1 app/src/main/java/net/squanchy/support/widget/SpeakerView.kt
  48. +32 −20 app/src/main/java/net/squanchy/tweets/TweetsPageView.kt
  49. +28 −14 app/src/main/java/net/squanchy/tweets/view/TweetsAdapter.kt
  50. +9 −16 app/src/main/res/drawable/chip_background.xml
  51. +0 −303 app/src/main/res/drawable/empty_favorites_signed_out.xml
  52. +24 −0 app/src/main/res/drawable/ic_favorites_empty_not_signed_in.xml
  53. +14 −0 app/src/main/res/drawable/ic_twitter_empty.xml
  54. +6 −6 app/src/main/res/layout/activity_track_filters.xml
  55. +1 −1 app/src/main/res/layout/track_filters_item.xml
  56. +3 −3 app/src/main/res/layout/view_page_favorites.xml
  57. +1 −3 app/src/main/res/layout/view_page_tweets.xml
  58. +27 −0 app/src/main/res/values/attrs_filter_chip_view.xml
  59. +5 −1 app/src/main/res/values/dimens.xml
  60. +8 −0 app/src/main/res/values/integers.xml
  61. +1,080 −3 app/src/main/res/values/licenses.xml
  62. +1 −0 app/src/main/res/values/palette.xml
  63. +17 −7 app/src/main/res/values/styles.xml
  64. +1 −1 app/src/release/java/net/squanchy/support/injection/CurrentTimeModule.kt
  65. +110 −0 app/src/test/java/net/squanchy/favorites/FirestoreFavoritesServiceTest.kt
  66. +15 −0 app/src/test/java/net/squanchy/favorites/ListItemFixtures.kt
  67. +1 −1 app/src/test/java/net/squanchy/schedule/FirestoreScheduleServiceTest.kt
  68. +2 −0 app/src/test/java/net/squanchy/schedule/domain/view/ScheduleFixtures.kt
  69. +25 −24 app/src/test/java/net/squanchy/service/firebase/FirestoreEventMapperTest.kt
  70. +1 −1 app/src/test/java/net/squanchy/service/firebase/FirestoreSpeakerMapperTest.kt
  71. +30 −8 app/src/test/java/net/squanchy/service/firebase/FirestoreTrackMapperTest.kt
  72. +23 −8 app/src/test/java/net/squanchy/service/firebase/model/schedule/FirestoreTracksRepositoryTest.kt
  73. +4 −1 build.gradle
  74. +8 −7 dependencies.gradle
  75. +27 −0 renderthread/build.gradle
  76. +2 −0 renderthread/src/main/AndroidManifest.xml
  77. 0 {app → renderthread}/src/main/java/me/eugeniomarletti/renderthread/CanvasProperty.java
  78. 0 {app → renderthread}/src/main/java/me/eugeniomarletti/renderthread/CanvasUtils.java
  79. 0 {app → renderthread}/src/main/java/me/eugeniomarletti/renderthread/HardwareCanvasProperty.java
  80. +16 −16 {app → renderthread}/src/main/java/me/eugeniomarletti/renderthread/RenderThread.java
  81. +67 −72 {app → renderthread}/src/main/java/me/eugeniomarletti/renderthread/RenderThreadDelegate.java
  82. 0 {app → renderthread}/src/main/java/me/eugeniomarletti/renderthread/RenderThreadDelegateHw.java
  83. +5 −3 {app → renderthread}/src/main/java/me/eugeniomarletti/renderthread/RenderThreadMethods.java
  84. 0 {app → renderthread}/src/main/java/me/eugeniomarletti/renderthread/SoftwareCanvasProperty.java
  85. 0 ... → renderthread}/src/main/java/me/eugeniomarletti/renderthread/typeannotation/CanvasProperty.java
  86. 0 ...renderthread}/src/main/java/me/eugeniomarletti/renderthread/typeannotation/DisplayListCanvas.java
  87. 0 ...enderthread}/src/main/java/me/eugeniomarletti/renderthread/typeannotation/RenderNodeAnimator.java
  88. +3 −0 renderthread/src/main/res/values/strings.xml
  89. +1 −1 settings.gradle
  90. +1 −1 team-props/ktlint.gradle
  91. +0 −3 team-props/static-analysis/checkstyle-suppressions.xml
  92. +0 −4 team-props/static-analysis/findbugs-excludes.xml
  93. +0 −1 team-props/static-analysis/pmd-rules.xml
@@ -124,6 +124,8 @@ project.afterEvaluate {
}

dependencies {
implementation project(':renderthread')

implementation libraries.app.androidKtx

implementation libraries.app.crashlytics
@@ -106,6 +106,7 @@ class DebugActivity : AppCompatActivity() {

private fun createTrack() = Track(
"0",
0,
"UI",
Optional.of(generateColor()),
Optional.of(generateColor()),
@@ -9,5 +9,5 @@ import net.squanchy.support.system.DebugCurrentTime
class CurrentTimeModule {

@Provides
internal fun provideCurrentTime(): CurrentTime = DebugCurrentTime()
internal fun currentTime(): CurrentTime = DebugCurrentTime()
}
@@ -52,6 +52,7 @@ class SquanchyApplication : Application() {
private fun initializeFirebase() {
FirebaseDatabase.getInstance().setPersistenceEnabled(true)
preloadRemoteConfig()
preloadTracks()
}

@SuppressLint("CheckResult") // This is a fire-and-forget operation
@@ -64,4 +65,14 @@ class SquanchyApplication : Application() {
{ throwable -> Timber.e(throwable, "Unable to preload the remote config") }
)
}

@SuppressLint("CheckResult") // This is a fire-and-forget operation
private fun preloadTracks() {
applicationComponent.tracksRepository()
.tracks()
.subscribe(
{ Timber.d("Tracks prefetched: $it") },
{ throwable -> Timber.e(throwable, "Unable to preload the tracks") }
)
}
}
@@ -2,25 +2,30 @@ package net.squanchy.about.licenses

internal object Libraries {

//TODO update to include the new libraries
val LIBRARIES = listOf(
Library("Squanchy", "the Squanchy Contributors", License.APACHE_2),
Library("Android", "Google Inc. and the Open Handset Alliance", License.APACHE_2),
Library("Kotlin", "JetBrains s.r.o. and the Kotlin contributors", License.APACHE_2),
Library("Android Support Library", "Google Inc. and the Open Handset Alliance", License.APACHE_2),
Library("Dagger", "the Dagger Authors", License.APACHE_2),
Library("Checkstyle", "the Checkstyle Authors", License.GNU_LGPL_2_1),
Library("Detekt", "the Detekt contributors", License.APACHE_2),
Library("Firebase-UI", "Google Inc.", License.APACHE_2),
Library("Findbugs", "the Findbugs Authors", License.GNU_LGPL_3),
Library("Flexbox-layout", "Google Inc.", License.APACHE_2),
Library("Glide", "Google Inc.", License.GLIDE),
Library("Joda-Time", "Joda.org", License.APACHE_2),
Library("Joda-Time-Android", "Daniel Lew", License.APACHE_2),
Library("Gradle Build Properties plugin", "Novoda, Ltd.", License.APACHE_2),
Library("Gradle Play Publisher plugin", "Christian Becker and Björn Hurling", License.MIT),
Library("Gradle Static Analysis plugin", "Novoda, Ltd.", License.APACHE_2),
Library("JodaTime Android", "Daniel Lew", License.APACHE_2),
Library("JUnit 4", "JUnit.org", License.ECLIPSE_PUBLIC_LICENSE),
Library("Kotlin", "JetBrains s.r.o. and the Kotlin contributors", License.APACHE_2),
Library("KtLint", "the KtLint contributors", License.MIT),
Library("Mockito", "the Mockito Contributors", License.MIT),
Library("PMD", "the PMD Contributors", License.PMD),
Library("RxJava", "RxJava Contributors", License.APACHE_2),
Library("RxAndroid", "the RxAndroid authors", License.APACHE_2),
Library("Android Support Library", "Google Inc. and the Open Handset Alliance", License.APACHE_2),
Library("Timber", "Jake Wharton", License.APACHE_2),
Library("ViewPagerAdapter", "Novoda Ltd.", License.APACHE_2),
Library("Dagger", "the Dagger Authors", License.APACHE_2),
Library("gradle-build-properties-plugin", "Novoda, Ltd.", License.APACHE_2),
Library("gradle-play-publisher", "Christian Becker and Björn Hurling", License.MIT),
Library("Fest Assertions 2.x", "the Fest Assertions Authors", License.APACHE_2),
Library("JUnit 4", "JUnit.org", License.ECLIPSE_PUBLIC_LICENSE),
Library("Mockito", "the Mockito Contributors", License.MIT),
Library("League Spartan", "Micah Rich, Caroline Hadilaksono, and Tyler Finck", License.OPEN_FONT_LICENSE),
Library("Quicksand", "the Quicksand Project Authors", License.OPEN_FONT_LICENSE),
Library("VT323", "the VT323 Project Authors", License.OPEN_FONT_LICENSE)
@@ -10,8 +10,11 @@ internal enum class License(
) {
@SuppressWarnings("EnumNaming")
APACHE_2("Apache 2.0 License", R.string.license_notice_apache_2),
GLIDE("BSD, part MIT and Apache 2.0 licenses", R.string.license_notice_glide),
ECLIPSE_PUBLIC_LICENSE("Eclipse Public License 1.0", R.string.license_notice_eclipse_public_license),
GLIDE("BSD, part MIT and Apache 2.0 licenses", R.string.license_notice_glide),
GNU_LGPL_2_1("GNU LGPL 2.1", R.string.license_notice_lgpl_2_1),
GNU_LGPL_3("GNU LGPL 3.0", R.string.license_notice_lgpl_3),
OPEN_FONT_LICENSE("Open Font License 1.1", R.string.license_notice_open_font_license),
MIT("MIT License", R.string.license_notice_mit),
OPEN_FONT_LICENSE("Open Font License 1.1", R.string.license_notice_open_font_license);
PMD("PMD BSD-style License", R.string.license_notice_pmd)
}
@@ -9,14 +9,12 @@ import net.squanchy.injection.ApplicationComponent
import net.squanchy.injection.applicationComponent
import net.squanchy.navigation.NavigationModule
import net.squanchy.navigation.Navigator
import net.squanchy.schedule.ScheduleModule
import net.squanchy.schedule.ScheduleService

@ActivityLifecycle
@Component(modules = [ScheduleModule::class, NavigationModule::class], dependencies = [ApplicationComponent::class])
@Component(modules = [FavoritesModule::class, NavigationModule::class], dependencies = [ApplicationComponent::class])
internal interface FavoritesComponent {

fun scheduleService(): ScheduleService
fun favoritesService(): FavoritesService

fun navigator(): Navigator

@@ -26,7 +24,7 @@ internal interface FavoritesComponent {
internal fun favoritesComponent(activity: AppCompatActivity): FavoritesComponent {
return DaggerFavoritesComponent.builder()
.applicationComponent(activity.application.applicationComponent)
.scheduleModule(ScheduleModule())
.favoritesModule(FavoritesModule())
.navigationModule(NavigationModule())
.activityContextModule(ActivityContextModule(activity))
.build()
@@ -0,0 +1,17 @@
package net.squanchy.favorites

import dagger.Module
import dagger.Provides
import net.squanchy.schedule.ScheduleModule
import net.squanchy.schedule.ScheduleService
import net.squanchy.service.firebase.FirebaseAuthService

@Module(includes = [ScheduleModule::class])
class FavoritesModule {

@Provides
internal fun favoritesService(
authService: FirebaseAuthService,
scheduleService: ScheduleService
): FavoritesService = FirestoreFavoritesService(authService, scheduleService)
}
@@ -4,7 +4,7 @@ import android.content.Context
import android.support.design.widget.CoordinatorLayout
import android.util.AttributeSet
import android.view.MenuItem
import android.view.View
import androidx.view.isVisible
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
@@ -13,12 +13,11 @@ import kotlinx.android.synthetic.main.view_page_favorites.view.*
import net.squanchy.R
import net.squanchy.analytics.Analytics
import net.squanchy.analytics.ContentType
import net.squanchy.favorites.view.FavoritesItem
import net.squanchy.home.HomeActivity
import net.squanchy.home.Loadable
import net.squanchy.navigation.Navigator
import net.squanchy.schedule.ScheduleService
import net.squanchy.schedule.domain.view.Event
import net.squanchy.schedule.domain.view.Schedule
import net.squanchy.support.unwrapToActivityContext

class FavoritesPageView @JvmOverloads constructor(
@@ -27,12 +26,20 @@ class FavoritesPageView @JvmOverloads constructor(
defStyleAttr: Int = 0
) : CoordinatorLayout(context, attrs, defStyleAttr), Loadable {

private val favoritesComponent = favoritesComponent(unwrapToActivityContext(context))
private val scheduleService: ScheduleService = favoritesComponent.scheduleService()
private val navigator: Navigator = favoritesComponent.navigator()
private val analytics: Analytics = favoritesComponent.analytics()
private lateinit var favoritesService: FavoritesService
private lateinit var navigator: Navigator
private lateinit var analytics: Analytics

private val disposable = CompositeDisposable()

init {
with(favoritesComponent(unwrapToActivityContext(context))) {
favoritesService = favoritesService()
navigator = navigator()
analytics = analytics()
}
}

override fun onFinishInflate() {
super.onFinishInflate()

@@ -52,9 +59,9 @@ class FavoritesPageView @JvmOverloads constructor(
override fun startLoading() {
disposable.add(
Observable.combineLatest(
scheduleService.schedule(onlyFavorites = true),
scheduleService.currentUserIsSignedIn(),
BiFunction<Schedule, Boolean, LoadScheduleResult>(::LoadScheduleResult)
favoritesService.favorites(),
favoritesService.currentUserIsSignedIn(),
BiFunction<List<FavoritesItem>, Boolean, LoadResult>(::LoadResult)
)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(::handleLoadSchedule)
@@ -65,48 +72,54 @@ class FavoritesPageView @JvmOverloads constructor(

private fun onMenuItemClickListener(menuItem: MenuItem): Boolean {
return when (menuItem.itemId) {
R.id.action_search -> { showSearch(); true }
R.id.action_settings -> { showSettings(); true }
R.id.action_filter -> { navigator.toScheduleFiltering(context); true }
R.id.action_search -> {
showSearch()
true
}
R.id.action_settings -> {
showSettings()
true
}
R.id.action_filter -> {
navigator.toScheduleFiltering(context)
true
}
else -> false
}
}

private fun handleLoadSchedule(result: LoadScheduleResult) {
private fun handleLoadSchedule(result: LoadResult) {
when {
result.schedule.hasFavorites -> showSchedule(result.schedule)
result.favoriteItems.isNotEmpty() -> showFavorites(result.favoriteItems)
result.signedIn -> promptToFavorite()
else -> promptToSign()
}
}

private val Schedule.hasFavorites
get() = !isEmpty

private fun showSchedule(schedule: Schedule) {
favoritesListView.updateWith(schedule, ::showEventDetails)
favoritesListView.visibility = View.VISIBLE
emptyViewSignedIn.visibility = View.GONE
emptyViewSignedOut.visibility = View.GONE
private fun showFavorites(favorites: List<FavoritesItem>) {
favoritesListView.updateWith(favorites, ::navigateToEventDetails)
favoritesListView.isVisible = true
emptyViewSignedIn.isVisible = false
emptyViewSignedOut.isVisible = false
}

private fun showEventDetails(event: Event) {
private fun navigateToEventDetails(event: Event) {
analytics.trackItemSelected(ContentType.FAVORITES_ITEM, event.id)
navigator.toEventDetails(event.id)
}

private fun promptToSign() {
emptyViewSignedOut.visibility = View.VISIBLE
favoritesListView.visibility = View.GONE
progressBar.visibility = View.GONE
emptyViewSignedIn.visibility = View.GONE
emptyViewSignedOut.isVisible = true
favoritesListView.isVisible = false
progressBar.isVisible = false
emptyViewSignedIn.isVisible = false
}

private fun promptToFavorite() {
emptyViewSignedIn.visibility = View.VISIBLE
favoritesListView.visibility = View.GONE
progressBar.visibility = View.GONE
emptyViewSignedOut.visibility = View.GONE
emptyViewSignedIn.isVisible = true
favoritesListView.isVisible = false
progressBar.isVisible = false
emptyViewSignedOut.isVisible = false
}

private fun showSignIn() {
@@ -121,5 +134,5 @@ class FavoritesPageView @JvmOverloads constructor(

private fun showSettings() = navigator.toSettings()

private data class LoadScheduleResult(val schedule: Schedule, val signedIn: Boolean)
private data class LoadResult(val favoriteItems: List<FavoritesItem>, val signedIn: Boolean)
}
@@ -0,0 +1,45 @@
package net.squanchy.favorites

import io.reactivex.Observable
import net.squanchy.favorites.view.FavoritesItem
import net.squanchy.schedule.ScheduleService
import net.squanchy.schedule.domain.view.Event
import net.squanchy.service.firebase.FirebaseAuthService

interface FavoritesService {

fun favorites(): Observable<List<FavoritesItem>>

fun currentUserIsSignedIn(): Observable<Boolean>
}

internal class FirestoreFavoritesService(
private val authService: FirebaseAuthService,
private val scheduleService: ScheduleService
) : FavoritesService {

override fun favorites(): Observable<List<FavoritesItem>> {
return scheduleService.schedule(onlyFavorites = true)
.map { schedule -> schedule.pages }
.flatMap { pages ->
val flattenedItems = pages.map { page ->
val eventsAsFavoriteItems = page.events.map { it.toFavoriteItem() }

if (eventsAsFavoriteItems.isNotEmpty()) {
return@map listOf(FavoritesItem.Header(page.date)) + eventsAsFavoriteItems
} else {
return@map emptyList<FavoritesItem>()
}
}.flatten()

return@flatMap Observable.just(flattenedItems)
}
}

override fun currentUserIsSignedIn(): Observable<Boolean> {
return authService.currentUser()
.map { optionalUser -> optionalUser.map { user -> !user.isAnonymous }.or(false) }
}

private fun Event.toFavoriteItem(): FavoritesItem.Favorite = FavoritesItem.Favorite(this)
}
Oops, something went wrong.

0 comments on commit 9465ea8

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.