Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
changes to enable a delete/clear menu icon on compose screen when the…
…re is message contents to clear - ie a schedule set, text input or attachments added
  • Loading branch information
gavine99 committed Feb 19, 2025
commit a8b02459c474349d205250324e50498bd3b6b806
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ class ComposeActivity : QkThemedActivity(), ComposeView {
override val viewQksmsPlusIntent: Subject<Unit> = PublishSubject.create()
override val backPressedIntent: Subject<Unit> = PublishSubject.create()
override val confirmDeleteIntent: Subject<List<Long>> = PublishSubject.create()
override val confirmClearCurrentMessageIntent: Subject<Unit> = PublishSubject.create()
override val clearCurrentMessageIntent: Subject<Unit> = PublishSubject.create()
override val messageLinkAskIntent: Subject<Uri> by lazy { messageAdapter.messageLinkClicks }
override val speechRecogniserIntent by lazy { speechToTextIcon.clicks() }
override val shadeIntent by lazy { shadeBackground.clicks() }
Expand Down Expand Up @@ -470,7 +472,7 @@ class ComposeActivity : QkThemedActivity(), ComposeView {
&& state.query.isEmpty()
toolbar.menu.findItem(R.id.copy)?.isVisible = !state.editingMode && state.selectedMessages > 0
toolbar.menu.findItem(R.id.details)?.isVisible = !state.editingMode && state.selectedMessages == 1
toolbar.menu.findItem(R.id.delete)?.isVisible = !state.editingMode && state.selectedMessages > 0
toolbar.menu.findItem(R.id.delete)?.isVisible = !state.editingMode && ((state.selectedMessages > 0) || state.canSend)
toolbar.menu.findItem(R.id.forward)?.isVisible = !state.editingMode && state.selectedMessages == 1
toolbar.menu.findItem(R.id.show_status)?.isVisible = !state.editingMode && state.selectedMessages > 0
toolbar.menu.findItem(R.id.previous)?.isVisible = state.selectedMessages == 0 && state.query.isNotEmpty()
Expand Down Expand Up @@ -712,6 +714,17 @@ class ComposeActivity : QkThemedActivity(), ComposeView {
.show()
}

override fun showClearCurrentMessageDialog() {
android.app.AlertDialog.Builder(this)
.setTitle(R.string.dialog_clear_compose_title)
.setMessage(R.string.dialog_clear_compose)
.setPositiveButton(R.string.button_clear) { _, _ ->
clearCurrentMessageIntent.onNext(Unit)
}
.setNegativeButton(R.string.button_cancel, null)
.show()
}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.compose, menu)
return super.onCreateOptionsMenu(menu)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ interface ComposeView : QkView<ComposeState> {
val viewQksmsPlusIntent: Subject<Unit>
val backPressedIntent: Observable<Unit>
val confirmDeleteIntent: Observable<List<Long>>
val confirmClearCurrentMessageIntent: Observable<Unit>
val clearCurrentMessageIntent: Subject<Unit>
val messageLinkAskIntent: Observable<Uri>
val speechRecogniserIntent: Observable<*>
val shadeIntent: Observable<Unit>
Expand Down Expand Up @@ -109,6 +111,7 @@ interface ComposeView : QkView<ComposeState> {
fun scrollToMessage(id: Long)
fun showQksmsPlusSnackbar(@StringRes message: Int)
fun showDeleteDialog( messages: List<Long>)
fun showClearCurrentMessageDialog()
fun startSpeechRecognition()

}
Original file line number Diff line number Diff line change
Expand Up @@ -388,15 +388,21 @@ class ComposeViewModel @Inject constructor(
.autoDisposable(view.scope())
.subscribe { view.showDetails(it) }

// Show the delete message dialog
// Show the delete message dialog if one or more messages selected
view.optionsItemIntent
.filter { it == R.id.delete }
.filter { permissionManager.isDefaultSms().also { if (!it) view.requestDefaultSms() } }
.withLatestFrom(view.messagesSelectedIntent, conversation) { _, messages, conversation ->
view.showDeleteDialog(messages)
}
.autoDisposable(view.scope())
.subscribe()
.filter { it == R.id.delete }
.withLatestFrom(view.messagesSelectedIntent) { _, selectedMessages -> selectedMessages }
.filter { permissionManager.isDefaultSms().also { if (!it) view.requestDefaultSms() } }
.autoDisposable(view.scope())
.subscribe { view.showDeleteDialog(it) }

// show the clear current message dialog if no messages selected
view.optionsItemIntent
.filter { it == R.id.delete }
.withLatestFrom(state) { _, state -> state }
.filter { it.selectedMessages == 0 }
.autoDisposable(view.scope())
.subscribe { view.showClearCurrentMessageDialog() }

// Forward the message
view.optionsItemIntent
Expand Down Expand Up @@ -734,16 +740,22 @@ class ComposeViewModel @Inject constructor(
}
}

// set canSend state depending on if there is text input or an attachment
// set canSend state depending on if there is text input, an attachment or a schedule set
Observables.combineLatest(
view.textChangedIntent, // input message text changed
state
.distinctUntilChanged { state -> state.attachments } // attachments changed
.map { it.attachments.size } // number of attachments
.map { it.attachments.size }, // number of attachments
state.distinctUntilChanged { state -> state.scheduled } // schedule set or not
.map { it.scheduled }
)
.autoDisposable(view.scope())
.subscribe {
newState { copy(canSend = (it.first.isNotBlank() || (it.second > 0))) }
newState {
copy(
canSend = (it.first.isNotBlank() || (it.second > 0)) || (it.third > 0)
)
}
}

// Show the remaining character counter when necessary
Expand Down Expand Up @@ -1045,13 +1057,8 @@ class ComposeViewModel @Inject constructor(
}
}

// configure for new message
view.setDraft("")
newState { copy(attachments = listOf()) }

if (state.editingMode) {
newState { copy(editingMode = false, hasError = !sendAsGroup) }
}
// clear the current message ready for new message composition
view.clearCurrentMessageIntent.onNext(Unit)
}
.autoDisposable(view.scope())
.subscribe()
Expand Down Expand Up @@ -1083,6 +1090,37 @@ class ComposeViewModel @Inject constructor(
.autoDisposable(view.scope())
.subscribe { view.clearSelection() }

view.confirmClearCurrentMessageIntent
.autoDisposable(view.scope())
.subscribe { view.clearCurrentMessageIntent.onNext(Unit) }

// clear the current message schedule, text and attachments
view.clearCurrentMessageIntent
.withLatestFrom(state) { _, state -> state }
.autoDisposable(view.scope())
.subscribe {
view.setDraft("")
// if choosing contacts, don't remove attachments. they may have come from an
// external share
if (it.editingMode)
newState {
copy(
editingMode = false,
hasError = !sendAsGroup,
scheduled = 0,
)
}
else
newState {
copy(
editingMode = false,
hasError = !sendAsGroup,
attachments = listOf(),
scheduled = 0,
)
}
}

// when activity changes visibility, delete old recording cache files in background thread
// generally there won't be any, but under some circumstances some can be left behind
view.activityVisibleIntent
Expand Down
14 changes: 6 additions & 8 deletions presentation/src/main/res/menu/compose.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,24 @@
android:visible="false"
app:showAsAction="always" />

<item
android:id="@+id/info"
android:icon="@drawable/ic_more_vert_black_24dp"
android:title="@string/menu_info"
android:visible="false"
app:showAsAction="always" />

<item
android:id="@+id/details"
android:icon="@drawable/ic_info_black_24dp"
android:title="@string/compose_menu_copy"
android:visible="false"
app:showAsAction="always" />

<item
android:id="@+id/delete"
android:icon="@drawable/ic_delete_white_24dp"
android:title="@string/compose_menu_delete"
android:visible="false"
app:showAsAction="always" />
<item
android:id="@+id/info"
android:icon="@drawable/ic_more_vert_black_24dp"
android:title="@string/menu_info"
android:visible="false"
app:showAsAction="always" />

<item
android:id="@+id/copy"
Expand Down
4 changes: 4 additions & 0 deletions presentation/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@
<item quantity="other">Are you sure you would like to delete %d messages?</item>
</plurals>

<string name="dialog_clear_compose_title">Clear message</string>
<string name="dialog_clear_compose">Clear the message? This action can\'t be undone.</string>

<string-array name="message_options">
<item>Copy text</item>
<item>Forward</item>
Expand Down Expand Up @@ -453,6 +456,7 @@
<string name="button_more">More</string>
<string name="button_set">Set</string>
<string name="button_undo">Undo</string>
<string name="button_clear">Clear</string>

<string name="toast_copied">Copied</string>
<plurals name="toast_archived">
Expand Down