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:
parent
1f21bd45d4
commit
adb9fcf468
|
@ -26,15 +26,19 @@ import androidx.fragment.app.commit
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import app.pachli.appstore.EventHub
|
import app.pachli.appstore.EventHub
|
||||||
import app.pachli.appstore.FilterChangedEvent
|
import app.pachli.appstore.FilterChangedEvent
|
||||||
|
import app.pachli.components.compose.ComposeActivity
|
||||||
import app.pachli.components.timeline.TimelineFragment
|
import app.pachli.components.timeline.TimelineFragment
|
||||||
import app.pachli.components.timeline.TimelineKind
|
import app.pachli.components.timeline.TimelineKind
|
||||||
import app.pachli.databinding.ActivityStatuslistBinding
|
import app.pachli.databinding.ActivityStatuslistBinding
|
||||||
import app.pachli.entity.Filter
|
import app.pachli.entity.Filter
|
||||||
import app.pachli.entity.FilterV1
|
import app.pachli.entity.FilterV1
|
||||||
|
import app.pachli.interfaces.ActionButtonActivity
|
||||||
import app.pachli.interfaces.AppBarLayoutHost
|
import app.pachli.interfaces.AppBarLayoutHost
|
||||||
|
import app.pachli.util.unsafeLazy
|
||||||
import app.pachli.util.viewBinding
|
import app.pachli.util.viewBinding
|
||||||
import at.connyduck.calladapter.networkresult.fold
|
import at.connyduck.calladapter.networkresult.fold
|
||||||
import com.google.android.material.appbar.AppBarLayout
|
import com.google.android.material.appbar.AppBarLayout
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -47,7 +51,7 @@ import javax.inject.Inject
|
||||||
* the user's favourites, bookmarks, etc.
|
* the user's favourites, bookmarks, etc.
|
||||||
*/
|
*/
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class StatusListActivity : BottomSheetActivity(), AppBarLayoutHost {
|
class StatusListActivity : BottomSheetActivity(), AppBarLayoutHost, ActionButtonActivity {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var eventHub: EventHub
|
lateinit var eventHub: EventHub
|
||||||
|
|
||||||
|
@ -57,6 +61,8 @@ class StatusListActivity : BottomSheetActivity(), AppBarLayoutHost {
|
||||||
override val appBarLayout: AppBarLayout
|
override val appBarLayout: AppBarLayout
|
||||||
get() = binding.includedToolbar.appbar
|
get() = binding.includedToolbar.appbar
|
||||||
|
|
||||||
|
override val actionButton: FloatingActionButton? by unsafeLazy { binding.composeButton }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If showing statuses with a hashtag, the hashtag being used, without the
|
* If showing statuses with a hashtag, the hashtag being used, without the
|
||||||
* leading `#`.
|
* leading `#`.
|
||||||
|
@ -103,6 +109,27 @@ class StatusListActivity : BottomSheetActivity(), AppBarLayoutHost {
|
||||||
replace(R.id.fragmentContainer, fragment)
|
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 {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
|
|
@ -260,7 +260,7 @@ class ComposeActivity :
|
||||||
}
|
}
|
||||||
|
|
||||||
setupLanguageSpinner(getInitialLanguages(composeOptions?.language, activeAccount))
|
setupLanguageSpinner(getInitialLanguages(composeOptions?.language, activeAccount))
|
||||||
setupComposeField(sharedPreferencesRepository, viewModel.startingText)
|
setupComposeField(sharedPreferencesRepository, viewModel.startingText, composeOptions)
|
||||||
setupContentWarningField(composeOptions?.contentWarning)
|
setupContentWarningField(composeOptions?.contentWarning)
|
||||||
setupPollView()
|
setupPollView()
|
||||||
applyShareIntent(intent, savedInstanceState)
|
applyShareIntent(intent, savedInstanceState)
|
||||||
|
@ -364,7 +364,11 @@ class ComposeActivity :
|
||||||
binding.composeContentWarningField.doOnTextChanged { _, _, _, _ -> updateVisibleCharactersLeft() }
|
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.setOnReceiveContentListener(this)
|
||||||
|
|
||||||
binding.composeEditField.setOnKeyListener { _, keyCode, event -> this.onKeyDown(keyCode, event) }
|
binding.composeEditField.setOnKeyListener { _, keyCode, event -> this.onKeyDown(keyCode, event) }
|
||||||
|
@ -380,7 +384,13 @@ class ComposeActivity :
|
||||||
binding.composeEditField.setTokenizer(ComposeTokenizer())
|
binding.composeEditField.setTokenizer(ComposeTokenizer())
|
||||||
|
|
||||||
binding.composeEditField.setText(startingText)
|
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
|
val mentionColour = binding.composeEditField.linkTextColors.defaultColor
|
||||||
highlightSpans(binding.composeEditField.text, mentionColour)
|
highlightSpans(binding.composeEditField.text, mentionColour)
|
||||||
|
@ -1305,6 +1315,15 @@ class ComposeActivity :
|
||||||
EDIT_SCHEDULED,
|
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
|
@Parcelize
|
||||||
data class ComposeOptions(
|
data class ComposeOptions(
|
||||||
// Let's keep fields var until all consumers are Kotlin
|
// Let's keep fields var until all consumers are Kotlin
|
||||||
|
@ -1329,6 +1348,7 @@ class ComposeActivity :
|
||||||
var language: String? = null,
|
var language: String? = null,
|
||||||
var statusId: String? = null,
|
var statusId: String? = null,
|
||||||
var kind: ComposeKind? = null,
|
var kind: ComposeKind? = null,
|
||||||
|
var initialCursorPosition: InitialCursorPosition = InitialCursorPosition.END,
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -16,6 +16,15 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
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" />
|
<include layout="@layout/item_status_bottom_sheet" />
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<string name="at_symbol" translatable="false">\@</string>
|
<string name="at_symbol" translatable="false">\@</string>
|
||||||
<string name="hash_symbol" translatable="false">#</string>
|
<string name="hash_symbol" translatable="false">#</string>
|
||||||
<string name="title_tag" translatable="false">#%s</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="emoji_shortcode_format" translatable="false">:%s:</string>
|
||||||
<string name="post_timestamp_with_edited_indicator" translatable="false">%s *</string>
|
<string name="post_timestamp_with_edited_indicator" translatable="false">%s *</string>
|
||||||
|
|
Loading…
Reference in New Issue