Skip to content

Commit

Permalink
[#80] Show 'Not found' bubble when rating is not found.
Browse files Browse the repository at this point in the history
Updated RatingDisplayer logic a bit to accommodate a 404 rating bubble. Decided to use a dummy 'MovieRating' for 404 with a constant id.
Added a toggle in settings as 'app setting' so it's disabled by default.
Streamlined some code in NetflixReaderService.
GA labels and events added for 404 flow.
  • Loading branch information
jayrambhia committed Jan 26, 2019
1 parent dcc44ac commit 32fa074
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.fenchtose.movieratings

import android.accessibilityservice.AccessibilityService
import android.annotation.SuppressLint
import android.os.Looper
import android.util.Log
import android.view.accessibility.AccessibilityEvent
Expand Down Expand Up @@ -31,7 +32,7 @@ import io.reactivex.subjects.PublishSubject
import retrofit2.HttpException
import java.util.concurrent.TimeUnit


@SuppressLint("CheckResult")
class NetflixReaderService : AccessibilityService() {

private var title: String? = null
Expand Down Expand Up @@ -286,26 +287,24 @@ class NetflixReaderService : AccessibilityService() {

GaEvents.GET_RATINGS.withLabelArg(request.appName).track()
val useFlutterApi = preferences?.isAppEnabled(UserPreferences.USE_FLUTTER_API) ?: true
provider?.let {
it.useFlutterApi(useFlutterApi)
it.getMovieRating(request)
.subscribeOn(Schedulers.io())
.observeOn(myScheduler)
.subscribe({
if (it.imdbId.isNotEmpty()) {
showRating(it)
historyPublisher.onNext(request)
}
}, {
if (it is HttpException) {
if (it.code() == 404) {
GaEvents.RATING_NOT_FOUND.withLabelArg(if (useFlutterApi) GaLabels.FLUTTER_API else GaLabels.OMDB_API).track()
update404(request.title, request.year)
}
}
it.printStackTrace()
})
}
val provider = provider ?: return

provider.useFlutterApi(useFlutterApi)
provider.getMovieRating(request)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.filter { it.imdbId.isNotEmpty() }
.doOnNext { historyPublisher.onNext(request) }
.subscribe(::showRating) { error ->
if (error is HttpException && error.code() == 404) {
GaEvents.RATING_NOT_FOUND.withLabelArg(if (useFlutterApi) GaLabels.FLUTTER_API else GaLabels.OMDB_API).track()
update404(request.title, request.year)
}

if (BuildConfig.DEBUG) {
error.printStackTrace()
}
}
}

private fun updateHistory(imdbId: String, appName: String) {
Expand All @@ -324,6 +323,9 @@ class NetflixReaderService : AccessibilityService() {

private fun update404(title: String, year: String?) {
provider?.report404(title, year)
if (preferences?.isSettingEnabled(UserPreferences.OPEN_404) == true) {
displayer?.show404(title)
}
}

private fun checkForSupportPrompt() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class GaEvents {
val OPEN_NOTIFICATION = GaEvent(GaCategory.SERVICE, "open notification", "%s")
val DISMISS_RATING = GaEvent(GaCategory.SERVICE, "dismiss", "rating")
val RATING_OPEN_MOVIE = GaEvent(GaCategory.SERVICE, "open movie", "%s")
val RATING_OPEN_404 = GaEvent(GaCategory.SERVICE, "open 404", "movie not found")

val SPEAK_RATING = GaEvent(GaCategory.SERVICE, "tts", "rating", true)

Expand Down Expand Up @@ -141,5 +142,6 @@ class GaLabels {
const val ITEM_PERSONAL = "personal"
const val ITEM_COLLECTIONS = "collections"
const val ITEM_INFO = "info"
const val RATING_404 = "rating 404"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,20 @@ class RatingDisplayer(ctx: Context,
}

fun showRatingWindow(rating: MovieRating) {
if (rating.imdbId.isEmpty() || rating.rating <= 0f) {
if (rating.imdbId.isEmpty() || (rating.rating <= 0f && !rating.is404())) {
removeView()
return
}

val bubbleColor = preferences.getBubbleColor(ContextCompat.getColor(context, R.color.floating_rating_color))
val bubbleSize = if (preferences.isAppEnabled(UserPreferences.RATING_DETAILS)) BubbleSize.BIG else BubbleSize.SMALL
val bubbleSize = if (preferences.isAppEnabled(UserPreferences.RATING_DETAILS) || rating.is404()) BubbleSize.BIG else BubbleSize.SMALL

if (!AccessibilityUtils.canDrawOverWindow(context)) {
if (rating.is404()) {
// No point in showing a toast.
return
}

Log.e(TAG, "no drawing permission")
ToastUtils.showMovieRating(context, rating, bubbleColor)
trackEvent(GaEvents.SHOW_RATINGS.withLabel(GaLabels.TOAST))
Expand All @@ -76,10 +81,13 @@ class RatingDisplayer(ctx: Context,
it.updateColor(bubbleColor)
it.updateSize(bubbleSize)
resetAutoDismissRunners()

val label = when(bubbleSize) {
BubbleSize.SMALL -> GaLabels.BUBBLE_SMALL
BubbleSize.BIG -> GaLabels.BUBBLE_BIG

val label = when {
rating.is404() -> GaLabels.RATING_404
else -> when(bubbleSize) {
BubbleSize.SMALL -> GaLabels.BUBBLE_SMALL
BubbleSize.BIG -> GaLabels.BUBBLE_BIG
}
}

trackEvent(GaEvents.SHOW_RATINGS.withLabel(label))
Expand All @@ -97,6 +105,15 @@ class RatingDisplayer(ctx: Context,

}

fun show404(title: String) {
if (title.isBlank()) {
removeView()
return
}

showRatingWindow(MovieRating.create404Dummy(title))
}

@SuppressLint("RtlHardcoded")
private fun addViewToWindow(bubble: RatingBubble): Boolean {
val manager = getWindowManager()
Expand Down Expand Up @@ -184,29 +201,39 @@ class RatingDisplayer(ctx: Context,
}
}

private fun openBubble() {
val openInApp = preferences.isAppEnabled(UserPreferences.OPEN_MOVIE_IN_APP)
val label = when(floatingRating?.rating?.source) {
"MAL" -> "mal"
"IMDB" -> if (openInApp) "app" else "imdb"
else -> null
}
override fun updatePosition(bubble: RatingBubble?, y: Int, left: Boolean) {
preferences.setBubblePosition(y, left)
resetAutoDismissRunners()
}

label?.let {
trackEvent(GaEvents.RATING_OPEN_MOVIE.withLabel(it))
}
}

val opened = IntentUtils.openMovie(context, floatingRating?.rating, openInApp)
if (opened) {
removeView()
}
private fun openBubble() {
val rating = floatingRating?.rating ?: return
val opened = when {
rating.is404() -> openImdbSearch(rating.title)
else -> openTitle(rating)
}

override fun updatePosition(bubble: RatingBubble?, y: Int, left: Boolean) {
preferences.setBubblePosition(y, left)
resetAutoDismissRunners()
if (opened) {
removeView()
}
}

private fun openImdbSearch(title: String): Boolean {
return IntentUtils.openImdbSearch(context, title)
}

private fun openTitle(rating: MovieRating): Boolean {
val openInApp = preferences.isAppEnabled(UserPreferences.OPEN_MOVIE_IN_APP)
val label = when(rating.source) {
"MAL" -> "mal"
"IMDB" -> if (openInApp) "app" else "imdb"
else -> null
}

label?.let { trackEvent(GaEvents.RATING_OPEN_MOVIE.withLabel(it)) }
return IntentUtils.openMovie(context, rating, openInApp)
}

private fun trackEvent(event: Event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class RatingBubbleSectionFragment: BaseFragment() {

settingsHelper?.addAppToggle(R.id.open_movie_toggle, UserPreferences.OPEN_MOVIE_IN_APP)
settingsHelper?.addAppToggle(R.id.rating_details_toggle, UserPreferences.RATING_DETAILS)
settingsHelper?.addSettingToggle(R.id.open_404_toggle, UserPreferences.OPEN_404)

val savedBubbleColor = preferences.getBubbleColor(ContextCompat.getColor(requireContext(), R.color.floating_rating_color))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.fenchtose.movieratings.features.stickyview

import android.content.Context
import android.support.annotation.ColorInt
import android.view.View
import com.fenchtose.movieratings.R
import com.fenchtose.movieratings.model.entity.MovieRating
import com.fenchtose.movieratings.widgets.RatingBubble
Expand All @@ -29,17 +28,24 @@ class FloatingRating(private val context: Context, val color: Int, var size: Bub
}

private fun updateRating(rating: MovieRating) {
if (size == BubbleSize.BIG) {
val builder = StringBuilder(rating.title)
rating.displayYear().takeIf { it.isNotBlank() }?.let {
builder.append("\n$it")
val text = when {
rating.is404() -> context.getString(R.string.floating_rating_404_content)
else -> when(size) {
BubbleSize.BIG -> {
val builder = StringBuilder()
builder.append(rating.title)
rating.displayYear().takeIf { it.isNotBlank() }?.let {
builder.append("\n$it")
}
builder.append("\n")
builder.append(rating.displayRating())
builder.toString()
}
BubbleSize.SMALL -> context.getString(R.string.floating_rating_content, rating.displayRating())
}
builder.append("\n")
builder.append(rating.displayRating())
bubble.setText(builder)
} else {
bubble.setText(context.resources.getString(R.string.floating_rating_content, rating.displayRating()))
}

bubble.setText(text)
}

fun getBubbleView(): RatingBubble = bubble
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import com.fenchtose.movieratings.util.FixTitleUtils
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass

private const val MOVIE_ID_404 = "404movie"

@JsonClass(generateAdapter = true)
data class MovieRating(
@Json(name="id")
Expand Down Expand Up @@ -50,11 +52,11 @@ data class MovieRating(
}

fun displayRating(): String {
if (source != "IMDB" && source.isNotBlank()) {
return "%.1f (%s)".format(rating, source)
return when {
is404() -> "Not found. Search on Imdb?"
isImdb() -> "%.1f".format(rating)
else -> "%.1f (%s)".format(rating, source)
}

return "%.1f".format(rating)
}

fun displayYear(): String {
Expand All @@ -73,11 +75,18 @@ data class MovieRating(
return "($startYear - $endYear)"
}

fun is404() = imdbId == MOVIE_ID_404
fun isImdb() = source == "IMDB"

companion object {
fun empty(): MovieRating {
return MovieRating("", -1f, -1, "", "", "", "",-1, -1)
}

fun create404Dummy(title: String): MovieRating {
return MovieRating(MOVIE_ID_404, -1f, -1, title, "", "", "", -1, -1)
}

fun fromMovie(movie: OmdbMovie): MovieRating {

movie.ratings.firstOrNull {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ interface UserPreferences {
const val USE_FLUTTER_API = "use_flutter_api"
const val OPEN_MOVIE_IN_APP = "open_movie_in_app"
const val RATING_DETAILS = "rating_details"
const val OPEN_404 = "open_404"
}

/**
Expand Down
16 changes: 16 additions & 0 deletions app/src/main/java/com/fenchtose/movieratings/util/IntentUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -175,5 +175,21 @@ class IntentUtils {

return false
}

fun openImdbSearch(context: Context, title: String, newTask: Boolean = true): Boolean {
val uri = Uri.Builder()
.scheme("https")
.appendPath("www.imdb.com")
.appendPath("find")
.appendQueryParameter("q", title)
.build()

val intent = Intent(Intent.ACTION_VIEW, uri)
if (newTask) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
context.startActivity(Intent.createChooser(intent, "Open IMDb search with").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
return true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,26 @@
android:layout_height="1dp"
android:background="@color/divider_color"/>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/Text.Dark.Secondary"
android:text="@string/settings_rating_bubble_404_info"
android:padding="@dimen/gutter"/>

<android.support.v7.widget.SwitchCompat
android:id="@+id/open_404_toggle"
android:padding="@dimen/gutter"
android:text="@string/settings_rating_bubble_404_title"
android:textAppearance="@style/Text.Dark"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider_color"/>

<LinearLayout
android:id="@+id/draw_permission_container"
android:layout_width="match_parent"
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@
<string name="settings_rating_bubble_toast_cta">Open permission settings</string>
<string name="settings_rating_bubble_details_title">Show title details</string>
<string name="settings_rating_bubble_details_info">Choose between a minimalistic or a detailed version of title ratings.</string>
<string name="settings_rating_bubble_404_info">The bubble will open Imdb search for the title, if the app is unable to find the rating for that title. It will be shown only the first time.</string>
<string name="settings_rating_bubble_404_title">Show \'Not found\' bubble</string>

<string name="menu_action_settings">Settings</string>
<string name="menu_action_fav">Favorites</string>
Expand All @@ -137,6 +139,7 @@
<string name="menu_action_trending">Trending</string>

<string name="floating_rating_content">Flutter - %1$s</string>
<string name="floating_rating_404_content">Rating not found.\nTap to search on Imdb.</string>

<string name="info_screen_content_no_accessibility">Flutter can help you decide what you want to watch today! When you are browsing Netflix, Prime Video and other supported apps, it will show you movie ratings on your screen (just like Fb Messenger chat).\n\nClick on <b>\'Activate Flutter\'</b> at the bottom to get started with Flutter!\n\nGo to <b>Settings</b> to check out what you can configure.</string>
<string name="info_screen_content_with_accessibility">Flutter is active now. When you are browsing Netflix, Prime Video and other supported apps, it will show you the movie ratings on the screen.\n\nYou may also use Flutter to search for movies and TV shows and create your own collections.</string>
Expand Down

0 comments on commit 32fa074

Please sign in to comment.