feat: Notify the user about severed relationships (#557)

This commit is contained in:
Nik Clayton 2024-03-21 17:27:48 +01:00 committed by GitHub
parent a65e2bd937
commit 783d4e5cca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1527 additions and 36 deletions

View File

@ -707,7 +707,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="92"
line="101"
column="5"/>
</issue>
@ -718,7 +718,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="279"
line="288"
column="5"/>
</issue>
@ -729,7 +729,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="328"
line="339"
column="5"/>
</issue>
@ -740,7 +740,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="447"
line="458"
column="5"/>
</issue>
@ -751,7 +751,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="625"
line="636"
column="5"/>
</issue>
@ -1301,7 +1301,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="94"
line="103"
column="13"/>
</issue>
@ -1312,7 +1312,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="102"
line="111"
column="13"/>
</issue>
@ -1323,7 +1323,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="136"
line="145"
column="13"/>
</issue>
@ -1334,7 +1334,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="195"
line="204"
column="13"/>
</issue>
@ -1345,7 +1345,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="216"
line="225"
column="13"/>
</issue>
@ -1356,7 +1356,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="217"
line="226"
column="13"/>
</issue>
@ -1367,7 +1367,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="240"
line="249"
column="13"/>
</issue>
@ -1378,7 +1378,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="269"
line="278"
column="13"/>
</issue>
@ -1389,7 +1389,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="338"
line="349"
column="13"/>
</issue>
@ -1400,7 +1400,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="378"
line="389"
column="13"/>
</issue>
@ -1411,7 +1411,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="414"
line="425"
column="13"/>
</issue>
@ -1422,7 +1422,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="417"
line="428"
column="13"/>
</issue>
@ -1433,7 +1433,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="418"
line="429"
column="13"/>
</issue>
@ -1444,7 +1444,7 @@
errorLine2=" ~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="419"
line="430"
column="13"/>
</issue>
@ -1455,7 +1455,7 @@
errorLine2=" ~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="420"
line="431"
column="13"/>
</issue>
@ -1466,7 +1466,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="421"
line="432"
column="13"/>
</issue>
@ -1477,7 +1477,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="485"
line="496"
column="13"/>
</issue>
@ -1488,7 +1488,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="486"
line="497"
column="13"/>
</issue>
@ -1499,7 +1499,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="497"
line="508"
column="13"/>
</issue>
@ -1510,7 +1510,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="498"
line="509"
column="13"/>
</issue>
@ -1521,7 +1521,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="499"
line="510"
column="13"/>
</issue>
@ -1532,7 +1532,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="501"
line="512"
column="13"/>
</issue>
@ -1543,7 +1543,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="541"
line="552"
column="13"/>
</issue>
@ -1554,7 +1554,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="582"
line="593"
column="13"/>
</issue>
@ -1565,7 +1565,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="588"
line="599"
column="13"/>
</issue>
@ -1576,7 +1576,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="617"
line="628"
column="13"/>
</issue>
@ -1587,7 +1587,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
line="644"
line="655"
column="13"/>
</issue>

View File

@ -51,6 +51,7 @@ import app.pachli.core.designsystem.R as DR
import app.pachli.core.navigation.ComposeActivityIntent.ComposeOptions
import app.pachli.core.navigation.MainActivityIntent
import app.pachli.core.network.model.Notification
import app.pachli.core.network.model.RelationshipSeveranceEvent
import app.pachli.core.network.parseAsMastodonHtml
import app.pachli.receiver.SendStatusBroadcastReceiver
import app.pachli.viewdata.buildDescription
@ -93,6 +94,7 @@ private const val CHANNEL_SUBSCRIPTIONS = "CHANNEL_SUBSCRIPTIONS"
private const val CHANNEL_SIGN_UP = "CHANNEL_SIGN_UP"
private const val CHANNEL_UPDATES = "CHANNEL_UPDATES"
private const val CHANNEL_REPORT = "CHANNEL_REPORT"
private const val CHANNEL_SEVERED_RELATIONSHIPS = "CHANNEL_SEVERED_RELATIONSHIPS"
private const val CHANNEL_BACKGROUND_TASKS = "CHANNEL_BACKGROUND_TASKS"
/** WorkManager Tag */
@ -503,6 +505,7 @@ fun createNotificationChannelsForAccount(account: AccountEntity, context: Contex
CHANNEL_SIGN_UP + account.identifier,
CHANNEL_UPDATES + account.identifier,
CHANNEL_REPORT + account.identifier,
CHANNEL_SEVERED_RELATIONSHIPS + account.identifier,
)
val channelNames = intArrayOf(
R.string.notification_mention_name,
@ -515,6 +518,7 @@ fun createNotificationChannelsForAccount(account: AccountEntity, context: Contex
R.string.notification_sign_up_name,
R.string.notification_update_name,
R.string.notification_report_name,
R.string.notification_severed_relationships_name,
)
val channelDescriptions = intArrayOf(
R.string.notification_mention_descriptions,
@ -527,6 +531,7 @@ fun createNotificationChannelsForAccount(account: AccountEntity, context: Contex
R.string.notification_sign_up_description,
R.string.notification_update_description,
R.string.notification_report_description,
R.string.notification_severed_relationships_description,
)
val channels: MutableList<NotificationChannel> = ArrayList(6)
val channelGroup = NotificationChannelGroup(account.identifier, account.fullName)
@ -684,7 +689,8 @@ fun filterNotification(
Notification.Type.SIGN_UP -> account.notificationsSignUps
Notification.Type.UPDATE -> account.notificationsUpdates
Notification.Type.REPORT -> account.notificationsReports
else -> false
Notification.Type.SEVERED_RELATIONSHIPS -> account.notificationsSeveredRelationships
Notification.Type.UNKNOWN -> false
}
}
@ -704,7 +710,8 @@ private fun getChannelId(account: AccountEntity, type: Notification.Type): Strin
Notification.Type.SIGN_UP -> CHANNEL_SIGN_UP + account.identifier
Notification.Type.UPDATE -> CHANNEL_UPDATES + account.identifier
Notification.Type.REPORT -> CHANNEL_REPORT + account.identifier
else -> null
Notification.Type.SEVERED_RELATIONSHIPS -> CHANNEL_SEVERED_RELATIONSHIPS + account.identifier
Notification.Type.UNKNOWN -> null
}
}
@ -834,6 +841,13 @@ private fun titleForType(
return context.getString(R.string.notification_report_format, account.domain)
}
Notification.Type.SEVERED_RELATIONSHIPS -> {
return context.getString(
R.string.notification_severed_relationships_format,
notification.relationshipSeveranceEvent?.targetName,
)
}
Notification.Type.UNKNOWN -> return null
}
}
@ -890,6 +904,15 @@ private fun bodyForType(
report.targetAccount.name.unicodeWrap(),
)
}
Notification.Type.SEVERED_RELATIONSHIPS -> {
val resourceId = when (notification.relationshipSeveranceEvent!!.type) {
RelationshipSeveranceEvent.Type.DOMAIN_BLOCK -> R.string.notification_severed_relationships_domain_block_body
RelationshipSeveranceEvent.Type.USER_DOMAIN_BLOCK -> R.string.notification_severed_relationships_user_domain_block_body
RelationshipSeveranceEvent.Type.ACCOUNT_SUSPENSION -> R.string.notification_severed_relationships_account_suspension_body
RelationshipSeveranceEvent.Type.UNKNOWN -> R.string.notification_severed_relationships_unknown_body
}
return context.getString(resourceId)
}
Notification.Type.UNKNOWN -> return null
Notification.Type.UPDATE -> return null

View File

@ -727,4 +727,5 @@ fun Notification.Type.uiString(): Int = when (this) {
Notification.Type.SIGN_UP -> R.string.notification_sign_up_name
Notification.Type.UPDATE -> R.string.notification_update_name
Notification.Type.REPORT -> R.string.notification_report_name
Notification.Type.SEVERED_RELATIONSHIPS -> R.string.notification_severed_relationships_name
}

View File

@ -31,6 +31,7 @@ import app.pachli.core.network.model.Status
import app.pachli.databinding.ItemFollowBinding
import app.pachli.databinding.ItemFollowRequestBinding
import app.pachli.databinding.ItemReportNotificationBinding
import app.pachli.databinding.ItemSeveredRelationshipsBinding
import app.pachli.databinding.ItemStatusBinding
import app.pachli.databinding.ItemStatusNotificationBinding
import app.pachli.databinding.ItemStatusWrapperBinding
@ -51,6 +52,9 @@ enum class NotificationViewKind {
FOLLOW,
FOLLOW_REQUEST,
REPORT,
/** View details of the affected target, number of relationships affected, and the actor */
SEVERED_RELATIONSHIPS,
UNKNOWN,
;
@ -71,6 +75,7 @@ enum class NotificationViewKind {
-> FOLLOW
Notification.Type.FOLLOW_REQUEST -> FOLLOW_REQUEST
Notification.Type.REPORT -> REPORT
Notification.Type.SEVERED_RELATIONSHIPS -> SEVERED_RELATIONSHIPS
null -> UNKNOWN
}
}
@ -181,6 +186,11 @@ class NotificationsPagingAdapter(
notificationActionListener,
)
}
NotificationViewKind.SEVERED_RELATIONSHIPS -> {
SeveredRelationshipsViewHolder(
ItemSeveredRelationshipsBinding.inflate(inflater, parent, false),
)
}
else -> {
FallbackNotificationViewHolder(
SimpleListItem1Binding.inflate(inflater, parent, false),

View File

@ -0,0 +1,66 @@
/*
* Copyright 2024 Pachli Association
*
* This file is a part of Pachli.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Pachli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Pachli; if not,
* see <http://www.gnu.org/licenses>.
*/
package app.pachli.components.notifications
import androidx.core.text.HtmlCompat
import androidx.recyclerview.widget.RecyclerView
import app.pachli.R
import app.pachli.adapter.StatusBaseViewHolder
import app.pachli.core.network.model.RelationshipSeveranceEvent
import app.pachli.databinding.ItemSeveredRelationshipsBinding
import app.pachli.util.StatusDisplayOptions
import app.pachli.util.getRelativeTimeSpanString
import app.pachli.viewdata.NotificationViewData
import java.util.Date
class SeveredRelationshipsViewHolder(
private val binding: ItemSeveredRelationshipsBinding,
) : NotificationsPagingAdapter.ViewHolder, RecyclerView.ViewHolder(binding.root) {
override fun bind(viewData: NotificationViewData, payloads: List<*>?, statusDisplayOptions: StatusDisplayOptions) {
val event = viewData.relationshipSeveranceEvent!!
if (payloads.isNullOrEmpty()) {
binding.notificationTopText.text = HtmlCompat.fromHtml(
itemView.context.getString(
R.string.notification_severed_relationships_format,
event.targetName,
),
HtmlCompat.FROM_HTML_MODE_LEGACY,
)
binding.datetime.text = getRelativeTimeSpanString(itemView.context, event.createdAt.time, Date().time)
binding.notificationSummary.text = itemView.context.resources.getQuantityString(
R.plurals.notification_severed_relationships_summary_report_fmt,
event.relationshipsCount,
event.relationshipsCount,
)
val resourceId = when (event.type) {
RelationshipSeveranceEvent.Type.DOMAIN_BLOCK -> R.string.notification_severed_relationships_domain_block_body
RelationshipSeveranceEvent.Type.USER_DOMAIN_BLOCK -> R.string.notification_severed_relationships_user_domain_block_body
RelationshipSeveranceEvent.Type.ACCOUNT_SUSPENSION -> R.string.notification_severed_relationships_account_suspension_body
RelationshipSeveranceEvent.Type.UNKNOWN -> R.string.notification_severed_relationships_unknown_body
}
binding.notificationCategory.text = itemView.context.getString(resourceId)
} else {
if (payloads.any { it == StatusBaseViewHolder.Key.KEY_CREATED }) {
binding.datetime.text = getRelativeTimeSpanString(itemView.context, event.createdAt.time, Date().time)
}
}
}
}

View File

@ -22,6 +22,7 @@ import app.pachli.core.database.model.TranslatedStatusEntity
import app.pachli.core.database.model.TranslationState
import app.pachli.core.network.model.Filter
import app.pachli.core.network.model.Notification
import app.pachli.core.network.model.RelationshipSeveranceEvent
import app.pachli.core.network.model.Report
import app.pachli.core.network.model.Status
import app.pachli.core.network.model.TimelineAccount
@ -40,6 +41,7 @@ data class NotificationViewData(
val account: TimelineAccount,
var statusViewData: StatusViewData?,
val report: Report?,
val relationshipSeveranceEvent: RelationshipSeveranceEvent?,
) : IStatusViewData {
companion object {
fun from(
@ -62,6 +64,7 @@ data class NotificationViewData(
)
},
notification.report,
notification.relationshipSeveranceEvent,
)
}

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2024 Pachli Association
~
~ This file is a part of Pachli.
~
~ This program is free software; you can redistribute it and/or modify it under the terms of the
~ GNU General Public License as published by the Free Software Foundation; either version 3 of the
~ License, or (at your option) any later version.
~
~ Pachli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
~ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
~ Public License for more details.
~
~ You should have received a copy of the GNU General Public License along with Pachli; if not,
~ see <http://www.gnu.org/licenses>.
-->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/notification_report"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="14dp"
android:paddingRight="14dp">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="28dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_flag_24dp"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/notification_top_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="8dp"
android:gravity="top"
android:textColor="?android:textColorSecondary"
android:textSize="?attr/status_text_medium"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@id/datetime"
app:layout_constraintStart_toEndOf="@+id/icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="Relationship with example.com severed"
tools:ignore="SelectableText" />
<TextView
android:id="@+id/datetime"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/notification_top_text"
tools:text="14h"
tools:ignore="SelectableText" />
<TextView
android:id="@+id/notification_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hyphenationFrequency="full"
android:importantForAccessibility="no"
android:lineSpacingMultiplier="1.1"
android:textColor="?android:textColorTertiary"
android:textSize="?attr/status_text_medium"
app:layout_constraintStart_toStartOf="@+id/notification_top_text"
app:layout_constraintTop_toBottomOf="@+id/notification_top_text"
tools:text="2 relationships"
tools:ignore="SelectableText" />
<TextView
android:id="@+id/notification_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hyphenationFrequency="full"
android:importantForAccessibility="no"
android:lineSpacingMultiplier="1.1"
android:paddingBottom="10dp"
android:textColor="?android:textColorTertiary"
android:textSize="?attr/status_text_medium"
app:layout_constraintStart_toStartOf="@+id/notification_summary"
app:layout_constraintTop_toBottomOf="@id/notification_summary"
tools:text="@string/notification_severed_relationships_domain_block_body"
tools:ignore="SelectableText" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -88,6 +88,15 @@
<string name="notification_subscription_format">%s just posted</string>
<string name="notification_update_format">%s edited their post</string>
<string name="notification_report_format">New report on %s</string>
<string name="notification_severed_relationships_format">Relationship with &lt;b>%1$s&lt;/b> severed</string>
<string name="notification_severed_relationships_domain_block_body">A moderator suspended the domain</string>
<string name="notification_severed_relationships_user_domain_block_body">You blocked the domain</string>
<string name="notification_severed_relationships_account_suspension_body">A moderator suspended the account</string>
<string name="notification_severed_relationships_unknown_body">Unknown reason</string>
<plurals name="notification_severed_relationships_summary_report_fmt">
<item quantity="one">%1$d relationship severed</item>
<item quantity="other">%1$d relationships severed</item>
</plurals>
<string name="notification_header_report_format">%s reported %s</string>
<string name="notification_summary_report_format">%s · %d posts attached</string>
<string name="report_username_format">Report @%s</string>
@ -321,6 +330,8 @@
<string name="notification_update_description">Notifications when posts you\'ve interacted with are edited</string>
<string name="notification_report_name">Reports</string>
<string name="notification_report_description">Notifications about moderation reports</string>
<string name="notification_severed_relationships_name">Severed relationships</string>
<string name="notification_severed_relationships_description">Notifications about severed relationships</string>
<string name="notification_listenable_worker_name">Background activity</string>
<string name="notification_listenable_worker_description">Notifications when Pachli is working in the background</string>
<string name="notification_unknown_name">Unknown</string>

File diff suppressed because it is too large Load Diff

View File

@ -55,11 +55,12 @@ import app.pachli.core.database.model.TranslatedStatusEntity
TranslatedStatusEntity::class,
LogEntryEntity::class,
],
version = 4,
version = 5,
autoMigrations = [
AutoMigration(from = 1, to = 2, spec = AppDatabase.MIGRATE_1_2::class),
AutoMigration(from = 2, to = 3),
AutoMigration(from = 3, to = 4),
AutoMigration(from = 4, to = 5),
],
)
abstract class AppDatabase : RoomDatabase() {

View File

@ -61,6 +61,8 @@ data class AccountEntity(
var notificationsSignUps: Boolean = true,
var notificationsUpdates: Boolean = true,
var notificationsReports: Boolean = true,
@ColumnInfo(defaultValue = "true")
var notificationsSeveredRelationships: Boolean = true,
var notificationSound: Boolean = true,
var notificationVibration: Boolean = true,
var notificationLight: Boolean = true,

View File

@ -31,6 +31,7 @@ data class Notification(
val account: TimelineAccount,
val status: Status?,
val report: Report?,
val relationshipSeveranceEvent: RelationshipSeveranceEvent? = null,
) {
/** From https://docs.joinmastodon.org/entities/Notification/#type */
@ -80,6 +81,10 @@ data class Notification(
/** A new report has been filed */
@Json(name = "admin.report")
REPORT("admin.report"),
/** Some of your follow relationships have been severed as a result of a moderation or block event */
@Json(name = "severed_relationships")
SEVERED_RELATIONSHIPS("severed_relationships"),
;
companion object {
@ -87,7 +92,19 @@ data class Notification(
fun byString(s: String) = entries.firstOrNull { s == it.presentation } ?: UNKNOWN
/** Notification types for UI display (omits UNKNOWN) */
val visibleTypes = listOf(MENTION, REBLOG, FAVOURITE, FOLLOW, FOLLOW_REQUEST, POLL, STATUS, SIGN_UP, UPDATE, REPORT)
val visibleTypes = listOf(
MENTION,
REBLOG,
FAVOURITE,
FOLLOW,
FOLLOW_REQUEST,
POLL,
STATUS,
SIGN_UP,
UPDATE,
REPORT,
SEVERED_RELATIONSHIPS,
)
}
override fun toString(): String {

View File

@ -0,0 +1,65 @@
/*
* Copyright 2024 Pachli Association
*
* This file is a part of Pachli.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Pachli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Pachli; if not,
* see <http://www.gnu.org/licenses>.
*/
package app.pachli.core.network.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import java.util.Date
/**
* Summary of a moderation or block event that caused follow relationships to be severed.
*/
@JsonClass(generateAdapter = true)
data class RelationshipSeveranceEvent(
/** The ID of the relationship severance event in the database. */
val id: String,
/** Type of event. */
val type: Type = Type.UNKNOWN,
/**
* True if the list of severed relationships is unavailable because the underlying
* issue has been purged.
*/
val purged: Boolean,
/**
* Name of the target of the moderation/block event. This is either a domain name or
* a user handle, depending on the event type.
*/
@Json(name = "target_name")
val targetName: String,
/** Number of follow relationships (in either direction) that were severed. */
@Json(name = "relationships_count")
val relationshipsCount: Int = 0,
/** When the event took place. */
@Json(name = "created_at")
val createdAt: Date,
) {
enum class Type {
/** A moderator suspended a whole domain */
@Json(name = "domain_block")
DOMAIN_BLOCK,
/** The user blocked a whole domain */
@Json(name = "user_domain_block")
USER_DOMAIN_BLOCK,
/** A moderator suspended a specific account */
@Json(name = "account_suspension")
ACCOUNT_SUSPENSION,
UNKNOWN,
}
}