feat: Display compose button when viewing hashtags (#254)

Display the "compose" FAB when viewing a hashtag list. Tapping the
button will open `ComposeActivity` prepopulated with the hashtag at the
end of the post with the cursor at the start.

Fixes #228
This commit is contained in:
sanao 2023-11-21 03:19:51 +09:00 committed by GitHub
parent 1f21bd45d4
commit adb9fcf468
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 6 deletions

View File

@ -26,15 +26,19 @@ import androidx.fragment.app.commit
import androidx.lifecycle.lifecycleScope
import app.pachli.appstore.EventHub
import app.pachli.appstore.FilterChangedEvent
import app.pachli.components.compose.ComposeActivity
import app.pachli.components.timeline.TimelineFragment
import app.pachli.components.timeline.TimelineKind
import app.pachli.databinding.ActivityStatuslistBinding
import app.pachli.entity.Filter
import app.pachli.entity.FilterV1
import app.pachli.interfaces.ActionButtonActivity
import app.pachli.interfaces.AppBarLayoutHost
import app.pachli.util.unsafeLazy
import app.pachli.util.viewBinding
import at.connyduck.calladapter.networkresult.fold
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
@ -47,7 +51,7 @@ import javax.inject.Inject
* the user's favourites, bookmarks, etc.
*/
@AndroidEntryPoint
class StatusListActivity : BottomSheetActivity(), AppBarLayoutHost {
class StatusListActivity : BottomSheetActivity(), AppBarLayoutHost, ActionButtonActivity {
@Inject
lateinit var eventHub: EventHub
@ -57,6 +61,8 @@ class StatusListActivity : BottomSheetActivity(), AppBarLayoutHost {
override val appBarLayout: AppBarLayout
get() = binding.includedToolbar.appbar
override val actionButton: FloatingActionButton? by unsafeLazy { binding.composeButton }
/**
* If showing statuses with a hashtag, the hashtag being used, without the
* leading `#`.
@ -103,6 +109,27 @@ class StatusListActivity : BottomSheetActivity(), AppBarLayoutHost {
replace(R.id.fragmentContainer, fragment)
}
}
val composeIntent = when (timelineKind) {
is TimelineKind.Tag -> {
val tag = (timelineKind as TimelineKind.Tag).tags.first()
ComposeActivity.startIntent(
this,
ComposeActivity.ComposeOptions(
content = getString(R.string.title_tag_with_initial_position).format(tag),
initialCursorPosition = ComposeActivity.InitialCursorPosition.START,
),
)
}
else -> null
}
if (composeIntent == null) {
binding.composeButton.hide()
} else {
binding.composeButton.setOnClickListener { startActivity(composeIntent) }
binding.composeButton.show()
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {

View File

@ -260,7 +260,7 @@ class ComposeActivity :
}
setupLanguageSpinner(getInitialLanguages(composeOptions?.language, activeAccount))
setupComposeField(sharedPreferencesRepository, viewModel.startingText)
setupComposeField(sharedPreferencesRepository, viewModel.startingText, composeOptions)
setupContentWarningField(composeOptions?.contentWarning)
setupPollView()
applyShareIntent(intent, savedInstanceState)
@ -364,7 +364,11 @@ class ComposeActivity :
binding.composeContentWarningField.doOnTextChanged { _, _, _, _ -> updateVisibleCharactersLeft() }
}
private fun setupComposeField(preferences: SharedPreferencesRepository, startingText: String?) {
private fun setupComposeField(
preferences: SharedPreferencesRepository,
startingText: String?,
composeOptions: ComposeOptions?,
) {
binding.composeEditField.setOnReceiveContentListener(this)
binding.composeEditField.setOnKeyListener { _, keyCode, event -> this.onKeyDown(keyCode, event) }
@ -380,7 +384,13 @@ class ComposeActivity :
binding.composeEditField.setTokenizer(ComposeTokenizer())
binding.composeEditField.setText(startingText)
binding.composeEditField.setSelection(binding.composeEditField.length())
when (composeOptions?.initialCursorPosition ?: InitialCursorPosition.END) {
InitialCursorPosition.START -> binding.composeEditField.setSelection(0)
InitialCursorPosition.END -> binding.composeEditField.setSelection(
binding.composeEditField.length(),
)
}
val mentionColour = binding.composeEditField.linkTextColors.defaultColor
highlightSpans(binding.composeEditField.text, mentionColour)
@ -1305,6 +1315,15 @@ class ComposeActivity :
EDIT_SCHEDULED,
}
/**
* Initial position of the cursor in EditText when the compose button is clicked
* in a hashtag timeline
*/
enum class InitialCursorPosition {
START,
END,
}
@Parcelize
data class ComposeOptions(
// Let's keep fields var until all consumers are Kotlin
@ -1329,6 +1348,7 @@ class ComposeActivity :
var language: String? = null,
var statusId: String? = null,
var kind: ComposeKind? = null,
var initialCursorPosition: InitialCursorPosition = InitialCursorPosition.END,
) : Parcelable
companion object {

View File

@ -16,6 +16,15 @@
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/composeButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fabMargin"
android:contentDescription="@string/action_compose"
app:layout_anchor="@id/fragmentContainer"
app:layout_anchorGravity="bottom|end"
app:srcCompat="@drawable/ic_create_24dp" />
<include layout="@layout/item_status_bottom_sheet" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -9,6 +9,7 @@
<string name="at_symbol" translatable="false">\@</string>
<string name="hash_symbol" translatable="false">#</string>
<string name="title_tag" translatable="false">#%s</string>
<string name="title_tag_with_initial_position" translatable="false">" #%s"</string>
<string name="emoji_shortcode_format" translatable="false">:%s:</string>
<string name="post_timestamp_with_edited_indicator" translatable="false">%s *</string>

View File

@ -841,7 +841,7 @@
<string name="update_dialog_title">An update is available</string>
<string name="update_dialog_neutral">Don\'t remind me for this version</string>
<string name="update_dialog_negative">Never remind me</string>
<string name="translating">Translating…</string>
<string name="translation_provider_fmt">%1$s</string>
<string name="translation_provider_fmt">%1$s</string>
</resources>