Skip to content

Commit

Permalink
MBL-1710: Entry Point: Push Notification navigation (#2172)
Browse files Browse the repository at this point in the history
  • Loading branch information
leighdouglas authored Nov 19, 2024
1 parent f7f29a1 commit aeeb7d6
Show file tree
Hide file tree
Showing 14 changed files with 162 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ class DebugPushNotificationsView @JvmOverloads constructor(context: Context, att
findViewById<Button>(R.id.simulate_burst_button).setOnClickListener {
simulateBurstClick()
}

findViewById<Button>(R.id.simulate_pledge_redemption_button).setOnClickListener {
simulatePledgeRedemptionButtonClick()
}
}

fun registerDeviceButtonClick() {
Expand Down Expand Up @@ -226,6 +230,25 @@ class DebugPushNotificationsView @JvmOverloads constructor(context: Context, att
pushNotifications?.add(envelope)
}

fun simulatePledgeRedemptionButtonClick() {
val gcm = GCM.builder()
.title("Pledge Management")
.alert("Omg we need you to check this pledge!")
.build()
val envelope: PushNotificationEnvelope = PushNotificationEnvelope.builder()
.gcm(gcm)
.pledgeRedemption(
PushNotificationEnvelope
.PledgeRedemption
.builder()
.id(18249339L)
.pledgeRedemptionPath("/projects/:creator_param/:project_param/backing/redeem")
.build()
)
.build()
pushNotifications?.add(envelope)
}

fun simulateProjectUpdateButtonClick() {
val gcm = GCM.builder()
.title("News from Taylor Moore")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,15 @@
android:text="@string/debug_push_notifications_simulate_burst"
style="@style/BorderButton" />

<Button
android:id="@+id/simulate_pledge_redemption_button"
android:layout_marginTop="@dimen/grid_1_half"
android:layout_marginBottom="@dimen/grid_1_half"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/debug_push_notifications_pledge_redemption"
style="@style/BorderButton" />

</LinearLayout>

</com.kickstarter.ui.views.DebugPushNotificationsView>
13 changes: 10 additions & 3 deletions app/src/main/assets/json/server-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,7 @@
"pledge_amount_pledged_on_pledge_date": "<b>%{pledge_amount}</b> pledged on %{pledge_date}",
"Pledge_any_amount_to_help_bring_this_project_to_life": "Pledge any amount to help bring this project to life.",
"Pledge_details": "Pledge details",
"Pledge_management": "Pledge management",
"Pledged_on_date": "<b>Pledged</b> on %{pledge_date}",
"Pledge_to_projects_and_view_all_your_saved_and_backed_projects_in_one_place": "Pledge to projects and view all your saved and backed projects in one place.",
"Pledge_to_your_favorites_then_view_all_the_projects": "Pledge to your favorites, then view all the projects you’ve backed here.",
Expand Down Expand Up @@ -3082,6 +3083,7 @@
"pledge_amount_pledged_on_pledge_date": "<b>%{pledge_amount}</b> beigetragen am %{pledge_date}",
"Pledge_any_amount_to_help_bring_this_project_to_life": "Du kannst jeden beliebigen Betrag eingeben, um das Projekt zu unterstützen.",
"Pledge_details": "Dein Finanzierungsbeitrag",
"Pledge_management": "Beitragsverwaltung",
"Pledged_on_date": "<b>Beitrag geleistet</b> am %{pledge_date}",
"Pledge_to_projects_and_view_all_your_saved_and_backed_projects_in_one_place": "Unterstütze Projekte und sehe alle deine Projekte auf einen Blick.",
"Pledge_to_your_favorites_then_view_all_the_projects": "Unterstütze deine Favoriten - alle von dir unterstützten Projekte werden hier angezeigt.",
Expand Down Expand Up @@ -5612,6 +5614,7 @@
"pledge_amount_pledged_on_pledge_date": "<b>%{pledge_amount}</b> contribuidos el %{pledge_date}",
"Pledge_any_amount_to_help_bring_this_project_to_life": "Puedes contribuir un monto de libre selección para apoyar este proyecto.",
"Pledge_details": "Detalles de la contribución",
"Pledge_management": "Gestión de contribución",
"Pledged_on_date": "<b>Contribuido</b> el %{pledge_date}",
"Pledge_to_projects_and_view_all_your_saved_and_backed_projects_in_one_place": "Haz contribuciones a proyectos y revisa todos tus proyectos guardados y patrocinados - todo en un mismo lugar.",
"Pledge_to_your_favorites_then_view_all_the_projects": "Patrocina tus favoritos y ve todos tus proyectos en un solo lugar.",
Expand Down Expand Up @@ -7982,8 +7985,8 @@
"Keep_up_with_future_live_streams": "Soyez informé des prochaines diffusions en direct",
"Keep_in_touch_after_your_campaign": "Une façon de garder le contact après votre campagne et de prévoir votre prochain projet.",
"Kickstarter_Arts": "L'art chez Kickstarter",
"Kickstarter_Games": "Kickstarter Games",
"Kickstarter_Invent": "Kickstarter Invent",
"Kickstarter_Games": "Jeux Kickstarter",
"Kickstarter_Invent": "Kickstarter invente",
"Kickstarter_if_funded": "Kickstarter (si le projet est financé)",
"Kickstarter_payment_summary": "Kickstarter",
"Kickstarter_is_not_a_store": "Kickstarter n'est pas un magasin.",
Expand Down Expand Up @@ -8142,6 +8145,7 @@
"pledge_amount_pledged_on_pledge_date": "<b>%{pledge_amount}</b> engagés le %{pledge_date}",
"Pledge_any_amount_to_help_bring_this_project_to_life": "Choisissez le montant de votre engagement à soutenir ce projet.",
"Pledge_details": "Détails de mon engagement",
"Pledge_management": "Gestion des engagements",
"Pledged_on_date": "<b>Engagement</b> du %{pledge_date}",
"Pledge_to_projects_and_view_all_your_saved_and_backed_projects_in_one_place": "Soutenez des projets et consultez la liste de vos projets enregistrés et soutenus.",
"Pledge_to_your_favorites_then_view_all_the_projects": "Engagez-vous à soutenir vos préférés, puis redécouvrez-les tous ici.",
Expand Down Expand Up @@ -8973,7 +8977,7 @@
"music": "Kickstarter Music",
"music_newsletter": "Une lettre d'information bimensuelle où vous retrouverez un orchestre d'instruments à vent mongoliens, la bande-son d'un film d'horreur inexistant, un opéra sur les insectes et d'autres choses à la fois insolites et inédites.",
"news_event": "Actualités et événements",
"publishing": "Kickstarter Reads",
"publishing": "Lectures Kickstarter",
"publishing_newsletter": "Tous les mois, l'équipe Éditions de Kickstarter met à l'honneur dans une lettre d'information des projets intéressants, des témoignages de créateurs et les actualités littéraires à ne pas manquer.",
"opt_in": {
"title": "Dernière étape !",
Expand Down Expand Up @@ -10672,6 +10676,7 @@
"pledge_amount_pledged_on_pledge_date": "<b>%{pledge_amount}</b> pledged on %{pledge_date}",
"Pledge_any_amount_to_help_bring_this_project_to_life": "Pledge any amount to help bring this project to life.",
"Pledge_details": "Pledge details",
"Pledge_management": "Pledge management",
"Pledged_on_date": "<b>Pledged</b> on %{pledge_date}",
"Pledge_to_projects_and_view_all_your_saved_and_backed_projects_in_one_place": "Pledge to projects and view all your saved and backed projects in one place.",
"Pledge_to_your_favorites_then_view_all_the_projects": "Pledge to your favorites, then view all the projects you’ve backed here.",
Expand Down Expand Up @@ -13202,6 +13207,7 @@
"pledge_amount_pledged_on_pledge_date": "%{pledge_date} に<b>%{pledge_amount}</b>のプレッジをしました",
"Pledge_any_amount_to_help_bring_this_project_to_life": "プレッジでプロジェクトに生命を。",
"Pledge_details": "プレッジ詳細",
"Pledge_management": "プレッジ管理",
"Pledged_on_date": "%{pledge_date} に<b>プレッジ</b>",
"Pledge_to_projects_and_view_all_your_saved_and_backed_projects_in_one_place": "プロジェクトを探す、プロジェクトにプレッジする、プロジェクトを保存する、全て一つの場所で。",
"Pledge_to_your_favorites_then_view_all_the_projects": "ここにバックした全プロジェクトが表示されます。",
Expand Down Expand Up @@ -15732,6 +15738,7 @@
"pledge_amount_pledged_on_pledge_date": "<b>%{pledge_amount}</b> pledged on %{pledge_date}",
"Pledge_any_amount_to_help_bring_this_project_to_life": "Pledge any amount to help bring this project to life.",
"Pledge_details": "Pledge details",
"Pledge_management": "Pledge management",
"Pledged_on_date": "<b>Pledged</b> on %{pledge_date}",
"Pledge_to_projects_and_view_all_your_saved_and_backed_projects_in_one_place": "Pledge to projects and view all your saved and backed projects in one place.",
"Pledge_to_your_favorites_then_view_all_the_projects": "Pledge to your favorites, then view all the projects you’ve backed here.",
Expand Down
46 changes: 41 additions & 5 deletions app/src/main/java/com/kickstarter/libs/PushNotifications.kt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,19 @@ class PushNotifications(
)
}
)
subscriptions.add(
notifications
.filter { obj: PushNotificationEnvelope -> obj.isPledgeRedemption() }
.filter {
isNotNull()
}
.observeOn(Schedulers.newThread())
.subscribe {
this.displayNotificationFromPledgeRedemption(
it
)
}
)
}

fun add(envelope: PushNotificationEnvelope) {
Expand Down Expand Up @@ -210,6 +223,13 @@ class PushNotifications(
NotificationManager.IMPORTANCE_DEFAULT
)
)
channels.add(
getNotificationChannel(
CHANNEL_PLEDGE_REDEMPTION,
R.string.Pledge_management,
NotificationManager.IMPORTANCE_HIGH
)
)
val followingChannel = getNotificationChannel(
CHANNEL_FOLLOWING,
R.string.Following,
Expand Down Expand Up @@ -324,11 +344,23 @@ class PushNotifications(
) {
val gcm = envelope.gcm()

val survey = envelope.survey() ?: return
val surveyUrlPath = envelope.survey()?.urls()?.web()?.survey() ?: return

val notification = notificationBuilder(gcm.title(), gcm.alert(), CHANNEL_SURVEY)
.setContentIntent(surveyResponseContentIntent(envelope, surveyUrlPath))
.setContentIntent(surveyResponseContentIntent(envelope, surveyUrlPath, IntentKey.NOTIFICATION_SURVEY_RESPONSE))
.build()
notificationManager().notify(envelope.signature(), notification)
}

private fun displayNotificationFromPledgeRedemption(
envelope: PushNotificationEnvelope,
) {
val gcm = envelope.gcm()

val pledgeRedemptionPath = envelope.pledgeRedemption()?.pledgeRedemptionPath() ?: return

val notification = notificationBuilder(gcm.title(), gcm.alert(), CHANNEL_PLEDGE_REDEMPTION)
.setContentIntent(surveyResponseContentIntent(envelope, pledgeRedemptionPath, IntentKey.NOTIFICATION_PLEDGE_REDEMPTION))
.build()
notificationManager().notify(envelope.signature(), notification)
}
Expand Down Expand Up @@ -435,12 +467,13 @@ class PushNotifications(

private fun surveyResponseContentIntent(
envelope: PushNotificationEnvelope,
surveyUrlPath: String
urlPath: String,
intentKey: String
): PendingIntent {
val activityFeedIntent = Intent(this.context, ActivityFeedActivity::class.java)

val surveyResponseIntent = Intent(this.context, SurveyResponseActivity::class.java)
.putExtra(IntentKey.NOTIFICATION_SURVEY_RESPONSE, surveyUrlPath)
.putExtra(intentKey, urlPath)

val taskStackBuilder = TaskStackBuilder.create(this.context)
.addNextIntentWithParentStack(activityFeedIntent)
Expand Down Expand Up @@ -560,14 +593,17 @@ class PushNotifications(
private const val CHANNEL_PROJECT_REMINDER = "PROJECT_REMINDER"
private const val CHANNEL_PROJECT_UPDATES = "PROJECT_UPDATES"
private const val CHANNEL_SURVEY = "SURVEY"
private const val CHANNEL_PLEDGE_REDEMPTION = "PLEDGE_REDEMPTION"

private val NOTIFICATION_CHANNELS = arrayOf(
CHANNEL_ERRORED_PLEDGES,
CHANNEL_FOLLOWING,
CHANNEL_MESSAGES,
CHANNEL_PROJECT_ACTIVITY,
CHANNEL_PROJECT_REMINDER,
CHANNEL_PROJECT_UPDATES,
CHANNEL_SURVEY
CHANNEL_SURVEY,
CHANNEL_PLEDGE_REDEMPTION
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ class PushNotificationEnvelope private constructor(
private val message: Message?,
private val project: Project?,
private val survey: Survey?,
private val pledgeRedemption: PledgeRedemption?,

) : Parcelable {
fun activity() = this.activity
fun erroredPledge() = this.erroredPledge
fun gcm() = this.gcm
fun message() = this.message
fun project() = this.project
fun survey() = this.survey
fun pledgeRedemption() = this.pledgeRedemption

@Parcelize
data class Builder(
Expand All @@ -30,21 +33,24 @@ class PushNotificationEnvelope private constructor(
private var gcm: GCM = GCM.builder().build(),
private var message: Message? = null,
private var project: Project? = null,
private var survey: Survey? = null
private var survey: Survey? = null,
private var pledgeRedemption: PledgeRedemption? = null
) : Parcelable {
fun activity(activity: Activity?) = apply { this.activity = activity }
fun erroredPledge(erroredPledge: ErroredPledge?) = apply { this.erroredPledge = erroredPledge }
fun gcm(gcm: GCM) = apply { this.gcm = gcm }
fun message(message: Message?) = apply { this.message = message }
fun project(project: Project?) = apply { this.project = project }
fun survey(survey: Survey?) = apply { this.survey = survey }
fun pledgeRedemption(pledgeRedemption: PledgeRedemption?) = apply { this.pledgeRedemption = pledgeRedemption }
fun build() = PushNotificationEnvelope(
activity = activity,
erroredPledge = erroredPledge,
gcm = gcm,
message = message,
project = project,
survey = survey
survey = survey,
pledgeRedemption = pledgeRedemption,
)
}

Expand All @@ -54,7 +60,8 @@ class PushNotificationEnvelope private constructor(
gcm = gcm,
message = message,
project = project,
survey = survey
survey = survey,
pledgeRedemption = pledgeRedemption
)

override fun equals(other: Any?): Boolean {
Expand All @@ -65,6 +72,7 @@ class PushNotificationEnvelope private constructor(
gcm() == other.gcm() &&
message() == other.message() &&
project() == other.project() &&
pledgeRedemption() == other.pledgeRedemption() &&
survey() == other.survey()
}
return equals
Expand All @@ -88,6 +96,8 @@ class PushNotificationEnvelope private constructor(

fun isSurvey() = survey() != null

fun isPledgeRedemption() = pledgeRedemption() != null

fun signature(): Int {
// When we display an Android notification, we can give it a id. If the server sends a notification with the same
// id, Android updates the existing notification with new information rather than creating a new notification.
Expand Down Expand Up @@ -260,6 +270,50 @@ class PushNotificationEnvelope private constructor(
}
}

@Parcelize
class PledgeRedemption private constructor(
private val id: Long,
private val pledgeRedemptionPath: String?
) : Parcelable {
fun id() = this.id
fun pledgeRedemptionPath() = this.pledgeRedemptionPath

@Parcelize
data class Builder(
private var id: Long = 0L,
private var pledgeRedemptionPath: String? = null

) : Parcelable {
fun id(id: Long) = apply { this.id = id }
fun pledgeRedemptionPath(pledgeRedemptionPath: String?) = apply { pledgeRedemptionPath?.let { this.pledgeRedemptionPath = it } }
fun build() = PledgeRedemption(
id = id,
pledgeRedemptionPath = pledgeRedemptionPath
)
}

fun toBuilder() = Builder(
id = id,
pledgeRedemptionPath = pledgeRedemptionPath
)

override fun equals(other: Any?): Boolean {
var equals = super.equals(other)
if (other is PledgeRedemption) {
equals = id() == other.id() &&
pledgeRedemptionPath() == other.pledgeRedemptionPath()
}
return equals
}

companion object {
@JvmStatic
fun builder(): Builder {
return Builder()
}
}
}

@Parcelize
class Urls private constructor(
private val web: Web
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/com/kickstarter/ui/IntentKey.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ object IntentKey {
const val SURVEY_RESPONSE = "com.kickstarter.kickstarter.survey_response"
const val NOTIFICATION_SURVEY_RESPONSE = "com.kickstarter.kickstarter.survey_response"
const val DEEPLINK_SURVEY_RESPONSE = "com.kickstarter.kickstarter.deeplink_survey_response"
const val NOTIFICATION_PLEDGE_REDEMPTION = "com.kickstarter.kickstarter.notification_pledge_redeption"
const val TOOLBAR_TITLE = "com.kickstarter.kickstarter.intent_toolbar_title"
const val TRACKING_CLIENT_TYPE_TAG = "com.kickstarter.kickstarter.intent_tracking_client_tag"
const val UPDATE = "com.kickstarter.kickstarter.intent_update"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ interface SurveyResponseViewModel {
it.urls()?.web()?.survey() ?: ""
}

val pledgeRedemptionUrl = intent()
.filter {
it.hasExtra(IntentKey.NOTIFICATION_PLEDGE_REDEMPTION) && it.getParcelableExtra<SurveyResponse>(IntentKey.NOTIFICATION_PLEDGE_REDEMPTION).isNotNull()
}
.map { requireNotNull(it.getParcelableExtra(IntentKey.NOTIFICATION_PLEDGE_REDEMPTION)) }
.ofType(String::class.java)
.map { UrlUtils.appendPath(environment.webEndpoint(), it) }

val surveyNotificationUrl = intent()
.filter {
it.hasExtra(IntentKey.NOTIFICATION_SURVEY_RESPONSE) && !it.getStringExtra(IntentKey.NOTIFICATION_SURVEY_RESPONSE)
Expand All @@ -96,7 +104,7 @@ interface SurveyResponseViewModel {
.ofType(String::class.java)
.map { environment.webEndpoint() + it.toUri().path() }

val surveyUrl = Observable.merge(surveyActivityUrl, surveyNotificationUrl, surveyDeeplinkUrl)
val surveyUrl = Observable.merge(surveyActivityUrl, surveyNotificationUrl, surveyDeeplinkUrl, pledgeRedemptionUrl)

surveyUrl
.subscribe {
Expand All @@ -117,7 +125,8 @@ interface SurveyResponseViewModel {
)
}
.compose(Transformers.ignoreValuesV2())
.subscribe(showConfirmationDialog)
.subscribe { showConfirmationDialog.onNext(it) }
.addToDisposable(disposables)

goBack = okButtonClicked
}
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-de/strings_i18n.xml
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ Antippen und erneut versuchen</string>
<string name="Pledge_amount_pledged" formatted="false">%{pledge_amount} beigetragen</string>
<string name="Pledge_any_amount_to_help_bring_this_project_to_life" formatted="false">Du kannst jeden beliebigen Betrag eingeben, um das Projekt zu unterstützen.</string>
<string name="Pledge_details" formatted="false">Dein Finanzierungsbeitrag</string>
<string name="Pledge_management" formatted="false">Beitragsverwaltung</string>
<string name="Pledge_to_projects_and_view_all_your_saved_and_backed_projects_in_one_place" formatted="false">Unterstütze Projekte und sehe alle deine Projekte auf einen Blick.</string>
<string name="Pledge_to_your_favorites_then_view_all_the_projects" formatted="false">Unterstütze deine Favoriten - alle von dir unterstützten Projekte werden hier angezeigt.</string>
<string name="Pledge_was_dropped" formatted="false">Finanzierungsbeitrag wurde nicht übernommen.</string>
Expand Down
Loading

0 comments on commit aeeb7d6

Please sign in to comment.