add more options to default reply visibility setting (#4568)
This adds `direct` and `match_default_post_visibility` as options to the default reply visibility setting. `match_default_post_visibility` will be the default for new accounts. closes https://github.com/tuskyapp/Tusky/issues/4555 <img src="https://github.com/user-attachments/assets/b256ff32-cd49-4274-903b-96da96451e0e" width="320"/>
This commit is contained in:
parent
18b943fef5
commit
892801b83a
13 changed files with 135 additions and 35 deletions
|
|
@ -390,7 +390,7 @@ class ComposeViewModel @Inject constructor(
|
|||
val tootToSend = StatusToSend(
|
||||
text = content,
|
||||
warningText = spoilerText,
|
||||
visibility = _statusVisibility.value.serverString,
|
||||
visibility = _statusVisibility.value.stringValue,
|
||||
sensitive = attachedMedia.isNotEmpty() && (_markMediaAsSensitive.value || _showContentWarning.value),
|
||||
media = attachedMedia,
|
||||
scheduledAt = _scheduledAt.value,
|
||||
|
|
@ -487,12 +487,15 @@ class ComposeViewModel @Inject constructor(
|
|||
inReplyToId = composeOptions?.inReplyToId
|
||||
|
||||
val activeAccount = accountManager.activeAccount!!
|
||||
val preferredVisibility =
|
||||
if (inReplyToId != null) activeAccount.defaultReplyPrivacy else activeAccount.defaultPostPrivacy
|
||||
val preferredVisibility = if (inReplyToId != null) {
|
||||
activeAccount.defaultReplyPrivacy.toVisibilityOr(activeAccount.defaultPostPrivacy)
|
||||
} else {
|
||||
activeAccount.defaultPostPrivacy
|
||||
}
|
||||
|
||||
val replyVisibility = composeOptions?.replyVisibility ?: Status.Visibility.UNKNOWN
|
||||
startingVisibility = Status.Visibility.byNum(
|
||||
preferredVisibility.num.coerceAtLeast(replyVisibility.num)
|
||||
startingVisibility = Status.Visibility.fromInt(
|
||||
preferredVisibility.int.coerceAtLeast(replyVisibility.int)
|
||||
)
|
||||
|
||||
modifiedInitialState = composeOptions?.modifiedInitialState == true
|
||||
|
|
@ -534,7 +537,7 @@ class ComposeViewModel @Inject constructor(
|
|||
postLanguage = composeOptions?.language
|
||||
|
||||
val tootVisibility = composeOptions?.visibility ?: Status.Visibility.UNKNOWN
|
||||
if (tootVisibility.num != Status.Visibility.UNKNOWN.num) {
|
||||
if (tootVisibility.int != Status.Visibility.UNKNOWN.int) {
|
||||
startingVisibility = tootVisibility
|
||||
}
|
||||
_statusVisibility.value = startingVisibility
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import android.os.Bundle
|
|||
import android.util.Log
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import at.connyduck.calladapter.networkresult.fold
|
||||
import com.google.android.material.color.MaterialColors
|
||||
|
|
@ -43,6 +44,7 @@ import com.keylesspalace.tusky.entity.Account
|
|||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.settings.AccountPreferenceDataStore
|
||||
import com.keylesspalace.tusky.settings.DefaultReplyVisibility
|
||||
import com.keylesspalace.tusky.settings.PrefKeys
|
||||
import com.keylesspalace.tusky.settings.listPreference
|
||||
import com.keylesspalace.tusky.settings.makePreferenceScreen
|
||||
|
|
@ -183,13 +185,15 @@ class AccountPreferencesFragment : PreferenceFragmentCompat() {
|
|||
isSingleLineTitle = false
|
||||
setSummaryProvider { entry }
|
||||
val visibility = accountManager.activeAccount?.defaultPostPrivacy ?: Status.Visibility.PUBLIC
|
||||
value = visibility.serverString
|
||||
value = visibility.stringValue
|
||||
setIcon(getIconForVisibility(visibility))
|
||||
isPersistent = false // its saved to the account and shouldn't be in shared preferences
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
setIcon(
|
||||
getIconForVisibility(Status.Visibility.byString(newValue as String))
|
||||
)
|
||||
val icon = getIconForVisibility(Status.Visibility.fromStringValue(newValue as String))
|
||||
setIcon(icon)
|
||||
if (accountManager.activeAccount?.defaultReplyPrivacy == DefaultReplyVisibility.MATCH_DEFAULT_POST_VISIBILITY) {
|
||||
findPreference<ListPreference>(PrefKeys.DEFAULT_REPLY_PRIVACY)?.setIcon(icon)
|
||||
}
|
||||
syncWithServer(visibility = newValue)
|
||||
true
|
||||
}
|
||||
|
|
@ -199,18 +203,18 @@ class AccountPreferencesFragment : PreferenceFragmentCompat() {
|
|||
if (activeAccount != null) {
|
||||
listPreference {
|
||||
setTitle(R.string.pref_default_reply_privacy)
|
||||
setEntries(R.array.post_privacy_names)
|
||||
setEntryValues(R.array.post_privacy_values)
|
||||
setEntries(R.array.reply_privacy_names)
|
||||
setEntryValues(R.array.reply_privacy_values)
|
||||
key = PrefKeys.DEFAULT_REPLY_PRIVACY
|
||||
isSingleLineTitle = false
|
||||
setSummaryProvider { entry }
|
||||
val visibility = activeAccount.defaultReplyPrivacy
|
||||
value = visibility.serverString
|
||||
setIcon(getIconForVisibility(visibility))
|
||||
value = visibility.stringValue
|
||||
setIcon(getIconForVisibility(visibility.toVisibilityOr(activeAccount.defaultPostPrivacy)))
|
||||
isPersistent = false // its saved to the account and shouldn't be in shared preferences
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val newVisibility = Status.Visibility.byString(newValue as String)
|
||||
setIcon(getIconForVisibility(newVisibility))
|
||||
val newVisibility = DefaultReplyVisibility.fromStringValue(newValue as String)
|
||||
setIcon(getIconForVisibility(newVisibility.toVisibilityOr(activeAccount.defaultPostPrivacy)))
|
||||
activeAccount.defaultReplyPrivacy = newVisibility
|
||||
accountManager.saveAccount(activeAccount)
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
|
|
@ -219,6 +223,10 @@ class AccountPreferencesFragment : PreferenceFragmentCompat() {
|
|||
true
|
||||
}
|
||||
}
|
||||
preference {
|
||||
setSummary(R.string.pref_default_reply_privacy_explanation)
|
||||
isEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
listPreference {
|
||||
|
|
|
|||
|
|
@ -846,7 +846,7 @@ public abstract class AppDatabase extends RoomDatabase {
|
|||
public static final Migration MIGRATION_60_62 = new Migration(60, 62) {
|
||||
@Override
|
||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `defaultReplyPrivacy` INTEGER NOT NULL DEFAULT 2");
|
||||
database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `defaultReplyPrivacy` INTEGER NOT NULL DEFAULT 0");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import com.keylesspalace.tusky.entity.HashTag
|
|||
import com.keylesspalace.tusky.entity.NewPoll
|
||||
import com.keylesspalace.tusky.entity.Poll
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.settings.DefaultReplyVisibility
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.adapter
|
||||
import java.net.URLDecoder
|
||||
|
|
@ -56,12 +57,22 @@ class Converters @Inject constructor(
|
|||
|
||||
@TypeConverter
|
||||
fun visibilityToInt(visibility: Status.Visibility?): Int {
|
||||
return visibility?.num ?: Status.Visibility.UNKNOWN.num
|
||||
return visibility?.int ?: Status.Visibility.UNKNOWN.int
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun intToVisibility(visibility: Int): Status.Visibility {
|
||||
return Status.Visibility.byNum(visibility)
|
||||
return Status.Visibility.fromInt(visibility)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun defaultReplyVisibilityToInt(visibility: DefaultReplyVisibility?): Int {
|
||||
return visibility?.int ?: DefaultReplyVisibility.MATCH_DEFAULT_POST_VISIBILITY.int
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun intToDefaultReplyVisibility(visibility: Int): DefaultReplyVisibility {
|
||||
return DefaultReplyVisibility.fromInt(visibility)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import com.keylesspalace.tusky.db.Converters
|
|||
import com.keylesspalace.tusky.defaultTabs
|
||||
import com.keylesspalace.tusky.entity.Emoji
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.settings.DefaultReplyVisibility
|
||||
|
||||
@Entity(
|
||||
indices = [
|
||||
|
|
@ -63,7 +64,7 @@ data class AccountEntity(
|
|||
var notificationVibration: Boolean = true,
|
||||
var notificationLight: Boolean = true,
|
||||
var defaultPostPrivacy: Status.Visibility = Status.Visibility.PUBLIC,
|
||||
var defaultReplyPrivacy: Status.Visibility = Status.Visibility.UNLISTED,
|
||||
var defaultReplyPrivacy: DefaultReplyVisibility = DefaultReplyVisibility.MATCH_DEFAULT_POST_VISIBILITY,
|
||||
var defaultMediaSensitivity: Boolean = false,
|
||||
var defaultPostLanguage: String = "",
|
||||
var alwaysShowSensitiveMedia: Boolean = false,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ data class Status(
|
|||
get() = reblog ?: this
|
||||
|
||||
@JsonClass(generateAdapter = false)
|
||||
enum class Visibility(val num: Int) {
|
||||
enum class Visibility(val int: Int) {
|
||||
UNKNOWN(0),
|
||||
|
||||
@Json(name = "public")
|
||||
|
|
@ -83,7 +83,7 @@ data class Status(
|
|||
@Json(name = "direct")
|
||||
DIRECT(4);
|
||||
|
||||
val serverString: String
|
||||
val stringValue: String
|
||||
get() = when (this) {
|
||||
PUBLIC -> "public"
|
||||
UNLISTED -> "unlisted"
|
||||
|
|
@ -93,10 +93,8 @@ data class Status(
|
|||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
fun byNum(num: Int): Visibility {
|
||||
return when (num) {
|
||||
fun fromInt(int: Int): Visibility {
|
||||
return when (int) {
|
||||
4 -> DIRECT
|
||||
3 -> PRIVATE
|
||||
2 -> UNLISTED
|
||||
|
|
@ -106,8 +104,7 @@ data class Status(
|
|||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun byString(s: String): Visibility {
|
||||
fun fromStringValue(s: String): Visibility {
|
||||
return when (s) {
|
||||
"public" -> PUBLIC
|
||||
"unlisted" -> UNLISTED
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
|
|||
StatusToSend(
|
||||
text = text,
|
||||
warningText = spoiler,
|
||||
visibility = visibility.serverString,
|
||||
visibility = visibility.stringValue,
|
||||
sensitive = false,
|
||||
media = emptyList(),
|
||||
scheduledAt = null,
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ class SendStatusService : Service() {
|
|||
content = status.text,
|
||||
contentWarning = status.warningText,
|
||||
sensitive = status.sensitive,
|
||||
visibility = Status.Visibility.byString(status.visibility),
|
||||
visibility = Status.Visibility.fromStringValue(status.visibility),
|
||||
mediaUris = status.media.map { it.uri },
|
||||
mediaDescriptions = status.media.map { it.description },
|
||||
mediaFocus = status.media.map { it.focus },
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package com.keylesspalace.tusky.settings
|
||||
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
|
||||
enum class DefaultReplyVisibility(val int: Int) {
|
||||
MATCH_DEFAULT_POST_VISIBILITY(0),
|
||||
PUBLIC(1),
|
||||
UNLISTED(2),
|
||||
PRIVATE(3),
|
||||
DIRECT(4);
|
||||
|
||||
val stringValue: String
|
||||
get() = when (this) {
|
||||
MATCH_DEFAULT_POST_VISIBILITY -> "match_default_post_visibility"
|
||||
PUBLIC -> "public"
|
||||
UNLISTED -> "unlisted"
|
||||
PRIVATE -> "private"
|
||||
DIRECT -> "direct"
|
||||
}
|
||||
|
||||
fun toVisibilityOr(default: Status.Visibility): Status.Visibility {
|
||||
return when (this) {
|
||||
PUBLIC -> Status.Visibility.PUBLIC
|
||||
UNLISTED -> Status.Visibility.UNLISTED
|
||||
PRIVATE -> Status.Visibility.PRIVATE
|
||||
DIRECT -> Status.Visibility.DIRECT
|
||||
else -> default
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun fromInt(int: Int): DefaultReplyVisibility {
|
||||
return when (int) {
|
||||
4 -> DIRECT
|
||||
3 -> PRIVATE
|
||||
2 -> UNLISTED
|
||||
1 -> PUBLIC
|
||||
else -> MATCH_DEFAULT_POST_VISIBILITY
|
||||
}
|
||||
}
|
||||
fun fromStringValue(s: String): DefaultReplyVisibility {
|
||||
return when (s) {
|
||||
"public" -> PUBLIC
|
||||
"unlisted" -> UNLISTED
|
||||
"private" -> PRIVATE
|
||||
"direct" -> DIRECT
|
||||
else -> MATCH_DEFAULT_POST_VISIBILITY
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue