diff --git a/app/build.gradle b/app/build.gradle
index ed4623b3..28929ca4 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -27,7 +27,7 @@ android {
defaultConfig {
applicationId APP_ID
namespace "com.keylesspalace.tusky"
- minSdk 23
+ minSdk 24
targetSdk 33
versionCode 113
versionName "23.0"
diff --git a/app/lint-baseline.xml b/app/lint-baseline.xml
index 88124ee8..0af47faa 100644
--- a/app/lint-baseline.xml
+++ b/app/lint-baseline.xml
@@ -36,7 +36,7 @@
-
-
-
-
+ message="Unnecessary; SDK_INT is always >= 24"
+ errorLine1=" if (Build.VERSION.SDK_INT > 23) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ file="src/main/java/com/keylesspalace/tusky/fragment/ViewVideoFragment.kt"
+ line="252"
+ column="13"/>
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1114,7 +1136,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
@@ -1125,7 +1147,7 @@
errorLine2=" ~~~~~~~~~~~~~">
@@ -1136,7 +1158,7 @@
errorLine2=" ~~~~~~~">
@@ -1147,7 +1169,7 @@
errorLine2=" ~~~~~~~">
@@ -1158,7 +1180,7 @@
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
@@ -1169,7 +1191,7 @@
errorLine2=" ~~~~~~~~~~~~~">
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f88f1fc8..53831a1c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -188,8 +188,7 @@
android:icon="@drawable/ic_quicksettings"
android:label="@string/tusky_compose_post_quicksetting_label"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
- android:exported="true"
- tools:targetApi="24">
+ android:exported="true">
diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java
index a73b52ef..17946454 100644
--- a/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java
+++ b/app/src/main/java/com/keylesspalace/tusky/adapter/NotificationsAdapter.java
@@ -679,17 +679,12 @@ public class NotificationsAdapter extends RecyclerView.Adapter emojis = actionable.getEmojis();
boolean sensitive = !TextUtils.isEmpty(spoilerText);
@@ -764,7 +764,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
if (payloads == null) {
Status actionable = status.getActionable();
setDisplayName(actionable.getAccount().getName(), actionable.getAccount().getEmojis(), statusDisplayOptions);
- setUsername(status.getUsername());
+ setUsername(actionable.getAccount().getUsername());
setMetaData(status, statusDisplayOptions, listener);
setIsReply(actionable.getInReplyToId() != null);
setReplyCount(actionable.getRepliesCount(), statusDisplayOptions.showStatsInline());
@@ -860,11 +860,11 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
String description = context.getString(R.string.description_status,
actionable.getAccount().getDisplayName(),
getContentWarningDescription(context, status),
- (TextUtils.isEmpty(status.getSpoilerText()) || !actionable.getSensitive() || status.isExpanded() ? status.getContent() : ""),
+ (TextUtils.isEmpty(actionable.getSpoilerText()) || !actionable.getSensitive() || status.isExpanded() ? status.getContent() : ""),
getCreatedAtDescription(actionable.getCreatedAt(), statusDisplayOptions),
actionable.getEditedAt() != null ? context.getString(R.string.description_post_edited) : "",
getReblogDescription(context, status),
- status.getUsername(),
+ actionable.getAccount().getUsername(),
actionable.getReblogged() ? context.getString(R.string.description_post_reblogged) : "",
actionable.getFavourited() ? context.getString(R.string.description_post_favourited) : "",
actionable.getBookmarked() ? context.getString(R.string.description_post_bookmarked) : "",
@@ -911,8 +911,8 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
private static CharSequence getContentWarningDescription(Context context,
@NonNull StatusViewData.Concrete status) {
- if (!TextUtils.isEmpty(status.getSpoilerText())) {
- return context.getString(R.string.description_post_cw, status.getSpoilerText());
+ if (!TextUtils.isEmpty(status.getActionable().getSpoilerText())) {
+ return context.getString(R.string.description_post_cw, status.getActionable().getSpoilerText());
} else {
return "";
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java
index 5dc0bf98..3c3103e0 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java
+++ b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java
@@ -78,7 +78,7 @@ public class ConversationViewHolder extends StatusBaseViewHolder {
if (payloads == null) {
TimelineAccount account = status.getAccount();
- setupCollapsedState(statusViewData.isCollapsible(), statusViewData.isCollapsed(), statusViewData.isExpanded(), statusViewData.getSpoilerText(), listener);
+ setupCollapsedState(statusViewData.isCollapsible(), statusViewData.isCollapsed(), statusViewData.isExpanded(), status.getSpoilerText(), listener);
setDisplayName(account.getDisplayName(), account.getEmojis(), statusDisplayOptions);
setUsername(account.getUsername());
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationHelper.java b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationHelper.java
index f15d44d2..f7292391 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationHelper.java
+++ b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationHelper.java
@@ -201,8 +201,7 @@ public class NotificationHelper {
builder.setLargeIcon(accountAvatar);
// Reply to mention action; RemoteInput is available from KitKat Watch, but buttons are available from Nougat
- if (body.getType() == Notification.Type.MENTION
- && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ if (body.getType() == Notification.Type.MENTION) {
RemoteInput replyRemoteInput = new RemoteInput.Builder(KEY_REPLY)
.setLabel(context.getString(R.string.label_quick_reply))
.build();
@@ -859,7 +858,7 @@ public class NotificationHelper {
if (mutable) {
return PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_MUTABLE : 0);
} else {
- return PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0);
+ return PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE;
}
}
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt b/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt
index 0ee7ec5d..21e1f51a 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/report/adapter/StatusViewHolder.kt
@@ -103,15 +103,15 @@ class StatusViewHolder(
shouldTrimStatus(viewdata.content),
viewState.isCollapsed(viewdata.id, true),
viewState.isContentShow(viewdata.id, viewdata.status.sensitive),
- viewdata.spoilerText
+ viewdata.status.spoilerText
)
- if (viewdata.spoilerText.isBlank()) {
+ if (viewdata.status.spoilerText.isBlank()) {
setTextVisible(true, viewdata.content, viewdata.status.mentions, viewdata.status.tags, viewdata.status.emojis, adapterHandler)
binding.statusContentWarningButton.hide()
binding.statusContentWarningDescription.hide()
} else {
- val emojiSpoiler = viewdata.spoilerText.emojify(viewdata.status.emojis, binding.statusContentWarningDescription, statusDisplayOptions.animateEmojis)
+ val emojiSpoiler = viewdata.status.spoilerText.emojify(viewdata.status.emojis, binding.statusContentWarningDescription, statusDisplayOptions.animateEmojis)
binding.statusContentWarningDescription.text = emojiSpoiler
binding.statusContentWarningDescription.show()
binding.statusContentWarningButton.show()
diff --git a/app/src/main/java/com/keylesspalace/tusky/service/TuskyTileService.kt b/app/src/main/java/com/keylesspalace/tusky/service/TuskyTileService.kt
index 2bf761f9..9d1b90a2 100644
--- a/app/src/main/java/com/keylesspalace/tusky/service/TuskyTileService.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/service/TuskyTileService.kt
@@ -15,7 +15,6 @@
package com.keylesspalace.tusky.service
-import android.annotation.TargetApi
import android.content.Intent
import android.service.quicksettings.TileService
import com.keylesspalace.tusky.MainActivity
@@ -25,8 +24,6 @@ import com.keylesspalace.tusky.components.compose.ComposeActivity
* Small Addition that adds in a QuickSettings tile
* opens the Compose activity or shows an account selector when multiple accounts are present
*/
-
-@TargetApi(24)
class TuskyTileService : TileService() {
override fun onClick() {
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/ListStatusAccessibilityDelegate.kt b/app/src/main/java/com/keylesspalace/tusky/util/ListStatusAccessibilityDelegate.kt
index 9402edd0..077ec008 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/ListStatusAccessibilityDelegate.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/util/ListStatusAccessibilityDelegate.kt
@@ -48,7 +48,7 @@ class ListStatusAccessibilityDelegate(
val pos = recyclerView.getChildAdapterPosition(host)
val status = statusProvider.getStatus(pos) ?: return
if (status is StatusViewData.Concrete) {
- if (status.spoilerText.isNotEmpty()) {
+ if (status.status.spoilerText.isNotEmpty()) {
info.addAction(if (status.isExpanded) collapseCwAction else expandCwAction)
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/SmartLengthInputFilter.kt b/app/src/main/java/com/keylesspalace/tusky/util/SmartLengthInputFilter.kt
index c7b583e5..9a9c19bf 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/SmartLengthInputFilter.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/util/SmartLengthInputFilter.kt
@@ -15,6 +15,7 @@
package com.keylesspalace.tusky.util
+import android.icu.text.BreakIterator
import android.text.InputFilter
import android.text.SpannableStringBuilder
import android.text.Spanned
@@ -72,20 +73,10 @@ object SmartLengthInputFilter : InputFilter {
if (source[keep].isLetterOrDigit()) {
var boundary: Int
- // Android N+ offer a clone of the ICU APIs in Java for better internationalization and
- // unicode support. Using the ICU version of BreakIterator grants better support for
- // those without having to add the ICU4J library at a minimum Api trade-off.
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
- val iterator = android.icu.text.BreakIterator.getWordInstance()
- iterator.setText(source.toString())
- boundary = iterator.following(keep)
- if (keep - boundary > RUNWAY) boundary = iterator.preceding(keep)
- } else {
- val iterator = java.text.BreakIterator.getWordInstance()
- iterator.setText(source.toString())
- boundary = iterator.following(keep)
- if (keep - boundary > RUNWAY) boundary = iterator.preceding(keep)
- }
+ val iterator = BreakIterator.getWordInstance()
+ iterator.setText(source.toString())
+ boundary = iterator.following(keep)
+ if (keep - boundary > RUNWAY) boundary = iterator.preceding(keep)
keep = boundary
} else {
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/StatusParsingHelper.kt b/app/src/main/java/com/keylesspalace/tusky/util/StatusParsingHelper.kt
index b8c3c6a0..117a44e2 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/StatusParsingHelper.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/util/StatusParsingHelper.kt
@@ -18,7 +18,6 @@
package com.keylesspalace.tusky.util
import android.text.Html.TagHandler
-import android.text.SpannableStringBuilder
import android.text.Spanned
import androidx.core.text.parseAsHtml
@@ -36,31 +35,3 @@ fun String.parseAsMastodonHtml(tagHandler: TagHandler? = null): Spanned {
* most status contents do, so it should be trimmed. */
.trimTrailingWhitespace()
}
-
-fun replaceCrashingCharacters(content: Spanned): Spanned {
- return replaceCrashingCharacters(content as CharSequence) as Spanned
-}
-
-fun replaceCrashingCharacters(content: CharSequence): CharSequence? {
- var replacing = false
- var builder: SpannableStringBuilder? = null
- val length = content.length
- for (index in 0 until length) {
- val character = content[index]
-
- // If there are more than one or two, switch to a map
- if (character == SOFT_HYPHEN) {
- if (!replacing) {
- replacing = true
- builder = SpannableStringBuilder(content, 0, index)
- }
- builder!!.append(ASCII_HYPHEN)
- } else if (replacing) {
- builder!!.append(character)
- }
- }
- return if (replacing) builder else content
-}
-
-private const val SOFT_HYPHEN = '\u00ad'
-private const val ASCII_HYPHEN = '-'
diff --git a/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.kt b/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.kt
index 18e504ec..870d7b16 100644
--- a/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.kt
@@ -14,12 +14,10 @@
* see . */
package com.keylesspalace.tusky.viewdata
-import android.os.Build
import android.text.Spanned
import com.keylesspalace.tusky.entity.Filter
import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.util.parseAsMastodonHtml
-import com.keylesspalace.tusky.util.replaceCrashingCharacters
import com.keylesspalace.tusky.util.shouldTrimStatus
/**
@@ -48,17 +46,15 @@ sealed class StatusViewData {
override val id: String
get() = status.id
+ val content: Spanned = status.actionableStatus.content.parseAsMastodonHtml()
+
/**
* Specifies whether the content of this post is long enough to be automatically
* collapsed or if it should show all content regardless.
*
* @return Whether the post is collapsible or never collapsed.
*/
- val isCollapsible: Boolean
-
- val content: Spanned
- val spoilerText: String
- val username: String
+ val isCollapsible: Boolean = shouldTrimStatus(this.content)
val actionable: Status
get() = status.actionableStatus
@@ -76,22 +72,6 @@ sealed class StatusViewData {
val rebloggingStatus: Status?
get() = if (status.reblog != null) status else null
- init {
- if (Build.VERSION.SDK_INT == 23) {
- // https://github.com/tuskyapp/Tusky/issues/563
- this.content = replaceCrashingCharacters(status.actionableStatus.content.parseAsMastodonHtml())
- this.spoilerText =
- replaceCrashingCharacters(status.actionableStatus.spoilerText).toString()
- this.username =
- replaceCrashingCharacters(status.actionableStatus.account.username).toString()
- } else {
- this.content = status.actionableStatus.content.parseAsMastodonHtml()
- this.spoilerText = status.actionableStatus.spoilerText
- this.username = status.actionableStatus.account.username
- }
- this.isCollapsible = shouldTrimStatus(this.content)
- }
-
/** Helper for Java */
fun copyWithStatus(status: Status): Concrete {
return copy(status = status)
diff --git a/app/src/main/res/color-v24/launcher_shadow_gradient.xml b/app/src/main/res/color-v24/launcher_shadow_gradient.xml
deleted file mode 100644
index 98ce8338..00000000
--- a/app/src/main/res/color-v24/launcher_shadow_gradient.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable-v24/ic_notoemoji.xml b/app/src/main/res/drawable-v24/ic_notoemoji.xml
deleted file mode 100644
index d016e35c..00000000
--- a/app/src/main/res/drawable-v24/ic_notoemoji.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/ic_notoemoji.xml b/app/src/main/res/drawable/ic_notoemoji.xml
deleted file mode 100644
index 55628c01..00000000
--- a/app/src/main/res/drawable/ic_notoemoji.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-