diff --git a/app/schemas/com.keylesspalace.tusky.db.AppDatabase/51.json b/app/schemas/com.keylesspalace.tusky.db.AppDatabase/51.json
index 32c5eeee9..48a58392b 100644
--- a/app/schemas/com.keylesspalace.tusky.db.AppDatabase/51.json
+++ b/app/schemas/com.keylesspalace.tusky.db.AppDatabase/51.json
@@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 51,
- "identityHash": "446158bf571fbd08787628bb829fa3c0",
+ "identityHash": "a1f530a7165bdd0e44932d9bb12ea4d3",
"entities": [
{
"tableName": "DraftEntity",
@@ -104,7 +104,7 @@
},
{
"tableName": "AccountEntity",
- "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `domain` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `clientId` TEXT, `clientSecret` TEXT, `isActive` INTEGER NOT NULL, `accountId` TEXT NOT NULL, `username` TEXT NOT NULL, `displayName` TEXT NOT NULL, `profilePictureUrl` TEXT NOT NULL, `notificationsEnabled` INTEGER NOT NULL, `notificationsMentioned` INTEGER NOT NULL, `notificationsFollowed` INTEGER NOT NULL, `notificationsFollowRequested` INTEGER NOT NULL, `notificationsReblogged` INTEGER NOT NULL, `notificationsFavorited` INTEGER NOT NULL, `notificationsPolls` INTEGER NOT NULL, `notificationsSubscriptions` INTEGER NOT NULL, `notificationsSignUps` INTEGER NOT NULL, `notificationsUpdates` INTEGER NOT NULL, `notificationsReports` INTEGER NOT NULL, `notificationSound` INTEGER NOT NULL, `notificationVibration` INTEGER NOT NULL, `notificationLight` INTEGER NOT NULL, `defaultPostPrivacy` INTEGER NOT NULL, `defaultMediaSensitivity` INTEGER NOT NULL, `defaultPostLanguage` TEXT NOT NULL, `alwaysShowSensitiveMedia` INTEGER NOT NULL, `alwaysOpenSpoiler` INTEGER NOT NULL, `mediaPreviewEnabled` INTEGER NOT NULL, `lastNotificationId` TEXT NOT NULL, `notificationMarkerId` TEXT NOT NULL DEFAULT '0', `emojis` TEXT NOT NULL, `tabPreferences` TEXT NOT NULL, `notificationsFilter` TEXT NOT NULL, `oauthScopes` TEXT NOT NULL, `unifiedPushUrl` TEXT NOT NULL, `pushPubKey` TEXT NOT NULL, `pushPrivKey` TEXT NOT NULL, `pushAuth` TEXT NOT NULL, `pushServerKey` TEXT NOT NULL, `lastVisibleHomeTimelineStatusId` TEXT)",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `domain` TEXT NOT NULL, `accessToken` TEXT NOT NULL, `clientId` TEXT, `clientSecret` TEXT, `isActive` INTEGER NOT NULL, `accountId` TEXT NOT NULL, `username` TEXT NOT NULL, `displayName` TEXT NOT NULL, `profilePictureUrl` TEXT NOT NULL, `notificationsEnabled` INTEGER NOT NULL, `notificationsMentioned` INTEGER NOT NULL, `notificationsFollowed` INTEGER NOT NULL, `notificationsFollowRequested` INTEGER NOT NULL, `notificationsReblogged` INTEGER NOT NULL, `notificationsFavorited` INTEGER NOT NULL, `notificationsPolls` INTEGER NOT NULL, `notificationsSubscriptions` INTEGER NOT NULL, `notificationsSignUps` INTEGER NOT NULL, `notificationsUpdates` INTEGER NOT NULL, `notificationsReports` INTEGER NOT NULL, `notificationSound` INTEGER NOT NULL, `notificationVibration` INTEGER NOT NULL, `notificationLight` INTEGER NOT NULL, `defaultPostPrivacy` INTEGER NOT NULL, `defaultMediaSensitivity` INTEGER NOT NULL, `defaultPostLanguage` TEXT NOT NULL, `alwaysShowSensitiveMedia` INTEGER NOT NULL, `alwaysOpenSpoiler` INTEGER NOT NULL, `mediaPreviewEnabled` INTEGER NOT NULL, `lastNotificationId` TEXT NOT NULL, `notificationMarkerId` TEXT NOT NULL DEFAULT '0', `emojis` TEXT NOT NULL, `tabPreferences` TEXT NOT NULL, `notificationsFilter` TEXT NOT NULL, `oauthScopes` TEXT NOT NULL, `unifiedPushUrl` TEXT NOT NULL, `pushPubKey` TEXT NOT NULL, `pushPrivKey` TEXT NOT NULL, `pushAuth` TEXT NOT NULL, `pushServerKey` TEXT NOT NULL, `lastVisibleHomeTimelineStatusId` TEXT, `appendText` TEXT NOT NULL DEFAULT '', `appendTextEnabled` INTEGER NOT NULL DEFAULT FALSE)",
"fields": [
{
"fieldPath": "id",
@@ -358,6 +358,20 @@
"columnName": "lastVisibleHomeTimelineStatusId",
"affinity": "TEXT",
"notNull": false
+ },
+ {
+ "fieldPath": "appendText",
+ "columnName": "appendText",
+ "affinity": "TEXT",
+ "notNull": true,
+ "defaultValue": "''"
+ },
+ {
+ "fieldPath": "appendTextEnabled",
+ "columnName": "appendTextEnabled",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "FALSE"
}
],
"primaryKey": {
@@ -996,7 +1010,7 @@
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
- "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '446158bf571fbd08787628bb829fa3c0')"
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a1f530a7165bdd0e44932d9bb12ea4d3')"
]
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt
index 2f77423b9..fe68a88df 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeActivity.kt
@@ -31,6 +31,7 @@ import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.provider.MediaStore
+import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.URLSpan
import android.util.Log
@@ -141,6 +142,7 @@ class ComposeActivity :
private lateinit var addMediaBehavior: BottomSheetBehavior<*>
private lateinit var emojiBehavior: BottomSheetBehavior<*>
private lateinit var scheduleBehavior: BottomSheetBehavior<*>
+ private lateinit var appendTextBehavior: BottomSheetBehavior<*>
/** The account that is being used to compose the status */
private lateinit var activeAccount: AccountEntity
@@ -281,6 +283,7 @@ class ComposeActivity :
setupComposeField(preferences, viewModel.startingText)
setupContentWarningField(composeOptions?.contentWarning)
setupPollView()
+ setupAppendTextField()
applyShareIntent(intent, savedInstanceState)
/* Finally, overwrite state with data from saved instance state. */
@@ -382,6 +385,13 @@ class ComposeActivity :
binding.composeContentWarningField.doOnTextChanged { _, _, _, _ -> updateVisibleCharactersLeft() }
}
+ private fun setupAppendTextField() {
+ binding.composeAppendTextView.setup(activeAccount.appendTextEnabled, activeAccount.appendText)
+
+ binding.composeAppendTextView.onEnabledChange { _, enabled -> updateAppendTextEnabled(enabled) }
+ binding.composeAppendTextView.onTextChange { text -> updateAppendText(text.toString()) }
+ }
+
private fun setupComposeField(preferences: SharedPreferences, startingText: String?) {
binding.composeEditField.setOnReceiveContentListener(this)
@@ -495,6 +505,7 @@ class ComposeActivity :
addMediaBehavior = BottomSheetBehavior.from(binding.addMediaBottomSheet)
scheduleBehavior = BottomSheetBehavior.from(binding.composeScheduleView)
emojiBehavior = BottomSheetBehavior.from(binding.emojiView)
+ appendTextBehavior = BottomSheetBehavior.from(binding.composeAppendTextView)
enableButton(binding.composeEmojiButton, clickable = false, colorActive = false)
@@ -508,6 +519,7 @@ class ComposeActivity :
binding.composeScheduleButton.setOnClickListener { onScheduleClick() }
binding.composeScheduleView.setResetOnClickListener { resetSchedule() }
binding.composeScheduleView.setListener(this)
+ binding.composeAppendTextButton.setOnClickListener { showAppendText() }
binding.atButton.setOnClickListener { atButtonClicked() }
binding.hashButton.setOnClickListener { hashButtonClicked() }
binding.descriptionMissingWarningButton.setOnClickListener {
@@ -538,12 +550,14 @@ class ComposeActivity :
if (composeOptionsBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
addMediaBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
emojiBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
- scheduleBehavior.state == BottomSheetBehavior.STATE_EXPANDED
+ scheduleBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
+ appendTextBehavior.state == BottomSheetBehavior.STATE_EXPANDED
) {
composeOptionsBehavior.state = BottomSheetBehavior.STATE_HIDDEN
addMediaBehavior.state = BottomSheetBehavior.STATE_HIDDEN
emojiBehavior.state = BottomSheetBehavior.STATE_HIDDEN
scheduleBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ appendTextBehavior.state = BottomSheetBehavior.STATE_HIDDEN
return
}
@@ -763,6 +777,7 @@ class ComposeActivity :
composeOptionsBehavior.state = BottomSheetBehavior.STATE_EXPANDED
addMediaBehavior.state = BottomSheetBehavior.STATE_HIDDEN
emojiBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ appendTextBehavior.state = BottomSheetBehavior.STATE_HIDDEN
scheduleBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
} else {
composeOptionsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
@@ -782,6 +797,7 @@ class ComposeActivity :
scheduleBehavior.state = BottomSheetBehavior.STATE_EXPANDED
composeOptionsBehavior.state = BottomSheetBehavior.STATE_HIDDEN
addMediaBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ appendTextBehavior.state = BottomSheetBehavior.STATE_HIDDEN
emojiBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
} else {
scheduleBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
@@ -798,6 +814,7 @@ class ComposeActivity :
emojiBehavior.state = BottomSheetBehavior.STATE_EXPANDED
composeOptionsBehavior.state = BottomSheetBehavior.STATE_HIDDEN
addMediaBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ appendTextBehavior.state = BottomSheetBehavior.STATE_HIDDEN
scheduleBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
} else {
emojiBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
@@ -806,11 +823,38 @@ class ComposeActivity :
}
}
+ private fun showAppendText() {
+ if (appendTextBehavior.state == BottomSheetBehavior.STATE_HIDDEN || appendTextBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) {
+ appendTextBehavior.state = BottomSheetBehavior.STATE_EXPANDED
+ composeOptionsBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ addMediaBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ emojiBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ scheduleBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
+ } else {
+ appendTextBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
+ }
+ }
+
+ private fun updateAppendTextEnabled(enabled: Boolean) {
+ activeAccount.appendTextEnabled = enabled
+ updateVisibleCharactersLeft()
+ accountManager.saveAccount(activeAccount)
+ }
+
+ private fun updateAppendText(text: String) {
+ activeAccount.appendText = text
+ if (activeAccount.appendTextEnabled) {
+ updateVisibleCharactersLeft()
+ }
+ accountManager.saveAccount(activeAccount)
+ }
+
private fun openPickDialog() {
if (addMediaBehavior.state == BottomSheetBehavior.STATE_HIDDEN || addMediaBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) {
addMediaBehavior.state = BottomSheetBehavior.STATE_EXPANDED
composeOptionsBehavior.state = BottomSheetBehavior.STATE_HIDDEN
emojiBehavior.state = BottomSheetBehavior.STATE_HIDDEN
+ appendTextBehavior.state = BottomSheetBehavior.STATE_HIDDEN
scheduleBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
} else {
addMediaBehavior.setState(BottomSheetBehavior.STATE_HIDDEN)
@@ -893,8 +937,13 @@ class ComposeActivity :
@VisibleForTesting
fun calculateTextLength(): Int {
+ val text = SpannableStringBuilder(binding.composeEditField.text)
+ if (activeAccount.appendTextEnabled && activeAccount.appendText.isNotEmpty()) {
+ text.append(" ${activeAccount.appendText}")
+ }
+
return statusLength(
- binding.composeEditField.text,
+ text,
binding.composeContentWarningField.text,
charactersReservedPerUrl
)
@@ -950,7 +999,11 @@ class ComposeActivity :
private fun sendStatus() {
enableButtons(false, viewModel.editing)
- val contentText = binding.composeEditField.text.toString()
+ var contentText = binding.composeEditField.text.toString()
+ if (activeAccount.appendTextEnabled && activeAccount.appendText.isNotEmpty()) {
+ contentText += " ${activeAccount.appendText}"
+ }
+
var spoilerText = ""
if (viewModel.showContentWarning.value) {
spoilerText = binding.composeContentWarningField.text.toString()
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/compose/view/ComposeAppendTextView.kt b/app/src/main/java/com/keylesspalace/tusky/components/compose/view/ComposeAppendTextView.kt
new file mode 100644
index 000000000..9b10c3e69
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/components/compose/view/ComposeAppendTextView.kt
@@ -0,0 +1,28 @@
+package com.keylesspalace.tusky.components.compose.view
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.widget.doAfterTextChanged
+import com.keylesspalace.tusky.databinding.ViewComposeAppendTextBinding
+
+class ComposeAppendTextView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : ConstraintLayout(context, attrs, defStyleAttr) {
+
+ private val binding = ViewComposeAppendTextBinding.inflate(
+ (context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater),
+ this,
+ )
+
+ val onEnabledChange = binding.switchAppendText::setOnCheckedChangeListener
+ val onTextChange = binding.editAppendText::doAfterTextChanged
+
+ fun setup(enabled: Boolean, appendText: String) {
+ binding.switchAppendText.isChecked = enabled
+ binding.editAppendText.setText(appendText)
+ }
+}
diff --git a/app/src/main/java/com/keylesspalace/tusky/db/AccountEntity.kt b/app/src/main/java/com/keylesspalace/tusky/db/AccountEntity.kt
index cdde765f7..9baa1a8ee 100644
--- a/app/src/main/java/com/keylesspalace/tusky/db/AccountEntity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/db/AccountEntity.kt
@@ -100,7 +100,12 @@ data class AccountEntity(
* ID of the status at the top of the visible list in the home timeline when the
* user navigated away.
*/
- var lastVisibleHomeTimelineStatusId: String? = null
+ var lastVisibleHomeTimelineStatusId: String? = null,
+
+ @ColumnInfo(defaultValue = "")
+ var appendText: String = "",
+ @ColumnInfo(defaultValue = "FALSE")
+ var appendTextEnabled: Boolean = false,
) {
val identifier: String
diff --git a/app/src/main/res/layout/activity_compose.xml b/app/src/main/res/layout/activity_compose.xml
index 367d88baa..9268ce621 100644
--- a/app/src/main/res/layout/activity_compose.xml
+++ b/app/src/main/res/layout/activity_compose.xml
@@ -278,6 +278,20 @@
app:behavior_peekHeight="0dp"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior" />
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_height="match_parent"
+ android:layout_weight="1">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/yuito.xml b/app/src/main/res/values/yuito.xml
new file mode 100644
index 000000000..b2af0c37f
--- /dev/null
+++ b/app/src/main/res/values/yuito.xml
@@ -0,0 +1,5 @@
+
+
+ Append Text
+ Append fixed text at the end of every posts
+