Skip to content

feat: Reply with euria - #2986

Open
solrubado wants to merge 37 commits into
mainfrom
reply-with-euria
Open

feat: Reply with euria#2986
solrubado wants to merge 37 commits into
mainfrom
reply-with-euria

Conversation

@solrubado

Copy link
Copy Markdown
Contributor

No description provided.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an Euria-assisted reply flow from message threads, reusing the existing AI prompt and proposition UI.

Changes:

  • Adds an AI Reply action and prompt bottom sheet.
  • Reuses AI proposition generation with message context arguments.
  • Extracts the AI prompt into a reusable custom view.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
new_message_navigation.xml Adds the optional message UID argument.
main_navigation.xml Registers the reply prompt and proposition destinations.
view_ai_prompt.xml Hosts the reusable prompt view.
view_ai_prompt_content.xml Updates the prompt layout header.
bottom_sheet_ask_euria_actions.xml Adds the Reply action.
ic_reply_euria.xml Adds the Euria reply icon.
AiPromptView.kt Encapsulates prompt UI behavior.
AiPropositionFragment.kt Supports generation from a thread message.
AiPromptFragment.kt Adopts the reusable prompt view.
ThreadFragment.kt Coordinates the new reply navigation flow.
EuriaPromptBottomSheet.kt Implements the thread reply prompt.
AskEuriaBottomSheetDialog.kt Handles Reply action selection.

Comment thread app/src/main/java/com/infomaniak/mail/ui/newMessage/AiPropositionFragment.kt Outdated
Comment thread app/src/main/java/com/infomaniak/mail/ui/newMessage/AiPropositionFragment.kt Outdated
Comment thread app/src/main/java/com/infomaniak/mail/views/AiPromptView.kt Outdated
Comment thread app/src/main/res/drawable/ic_reply_euria.xml
@Elouan1411
Elouan1411 marked this pull request as ready for review July 24, 2026 10:56
@Elouan1411
Elouan1411 requested a review from Copilot July 24, 2026 10:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (2)

app/src/main/java/com/infomaniak/mail/ui/newMessage/AiPropositionFragment.kt:325

  • This conversion treats every body as HTML. For text/plain messages, htmlToText() removes newline characters before parsing, which concatenates lines; for HTML replies it also retains quoted history instead of using the existing quote-aware conversion in NewMessageViewModel. Reuse a shared Body.asPlainText() implementation so Euria receives the same clean context as the composer flow.
                aiViewModel.previousMessageBodyPlainText = message?.body?.value?.htmlToText()

app/src/main/java/com/infomaniak/mail/ui/newMessage/AiPropositionFragment.kt:152

  • Reading currentMailbox.value only once can leave mailbox uninitialized when this destination is restored before the asynchronous LiveData query emits. Generation then accesses mailbox.uuid and crashes. Await a non-null mailbox (or initialize and generate in one coroutine) instead of returning permanently on the initial null value.
                mainViewModel.currentMailbox.value ?: return@launch

Comment thread app/src/main/java/com/infomaniak/mail/ui/newMessage/AiPropositionFragment.kt Outdated
Comment thread app/src/main/java/com/infomaniak/mail/views/AiPromptView.kt Outdated
@Elouan1411
Elouan1411 force-pushed the reply-with-euria branch 3 times, most recently from a6f568a to dd955e6 Compare July 27, 2026 14:56
Comment thread app/src/main/java/com/infomaniak/mail/data/LocalSettings.kt Outdated
Comment thread app/src/main/java/com/infomaniak/mail/views/AiPromptView.kt Outdated
) : FrameLayout(context, attrs, defStyleAttr) {

private val binding = ViewAiPromptContentBinding.inflate(LayoutInflater.from(context), this, true)
private var onPromptChanged: ((String) -> Unit)? = null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove this variable and directly use the one you pass as argument in the doAfterTextChanged.

Also as bind could theoretically be called several time you would stack listeners to the button because they aren't cleared before adding.
(But this would be a dev error, so i'm not for complexifying the code to avoid a simple dev error)

}

if (binding.reply.trailingContent != TrailingContent.None) {
binding.reply.setOnClickListener {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think opening the kSuite bottomsheet should dismiss this one.
Like the mail or threadActionBottomsheet

Comment thread app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt Outdated
Comment thread app/src/main/java/com/infomaniak/mail/ui/newMessage/AiPromptFragment.kt Outdated
private val navigationArgs: AiPropositionFragmentArgs by navArgs()

private var currentRequestJob: Job? = null
lateinit var mailbox: Mailbox

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never use lateinit, it's "old code" and it's crash prone.
Use a nullable variable if it's absolutely necessary

But here you can just use a by lazy (in a lot of cases lateinit can be replace by by lazy)

@FabianDevel FabianDevel Aug 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still pretty annoyed by the fact that we use this fragment in both activities instead of opening this from the newMessageActivity directly :/

And this force us to do this kind of manipulation with mailbox from one or the other viewModel

Comment thread app/src/main/java/com/infomaniak/mail/ui/newMessage/AiPropositionFragment.kt Outdated
val mailbox = mainViewModel.currentMailbox.value
val kSuite = mailbox?.kSuite

val matomoName = MatomoName.ReplyWithEuria.value

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need this variable anymore

Summarize("summarize"),
Translate("translate"),
AskEuria("askEuria"),
AskEuriaShortCut("askEuriaShortCut"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AskEuriaQuickAction

Comment on lines +110 to +112
suspend fun Body.asPlainText(): String? {
// TODO: When the API handles blank characters, remove ifBlank
return when (type) {

@FabianDevel FabianDevel Aug 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it programmed that the back support this ?

Comment thread app/src/main/java/com/infomaniak/mail/ui/newMessage/AiPropositionFragment.kt Outdated
Comment thread app/src/main/java/com/infomaniak/mail/utils/KSuiteNavUtils.kt
Comment thread app/src/main/java/com/infomaniak/mail/utils/KSuiteNavUtils.kt Outdated
isAdmin = mailbox?.isAdmin ?: false,
matomoName = matomoName,
substituteClassName = ThreadListFragment::class.java.name,
onAvailable = { handleStandardReplyAction(messageUid) }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onAvailable isn't really clear, maybe onFeatureAvailable ?

Elouan1411 and others added 2 commits August 12, 2026 12:42
…n opening euria prompt dialog

# Conflicts:
#	app/src/main/java/com/infomaniak/mail/ui/main/thread/ThreadFragment.kt
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants