Skip to content
This repository has been archived by the owner on Sep 27, 2024. It is now read-only.

Commit

Permalink
[Android] Fix missing link action updates in compose library (#804)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonnyandrew authored Sep 14, 2023
1 parent 6c0e129 commit a75603d
Show file tree
Hide file tree
Showing 15 changed files with 180 additions and 26 deletions.
5 changes: 5 additions & 0 deletions bindings/wysiwyg-ffi/src/ffi_composer_update.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use widestring::Utf16String;

use crate::ffi_link_actions::LinkActionUpdate;
use crate::ffi_menu_state::MenuState;
use crate::ffi_text_update::TextUpdate;
use crate::MenuAction;
Expand Down Expand Up @@ -28,6 +29,10 @@ impl ComposerUpdate {
pub fn menu_action(&self) -> MenuAction {
MenuAction::from(self.inner.menu_action.clone())
}

pub fn link_action(&self) -> LinkActionUpdate {
LinkActionUpdate::from(self.inner.link_action.clone())
}
}

#[cfg(test)]
Expand Down
17 changes: 17 additions & 0 deletions bindings/wysiwyg-ffi/src/ffi_link_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,20 @@ impl From<wysiwyg::LinkAction<Utf16String>> for LinkAction {
}
}
}

#[derive(uniffi::Enum)]
pub enum LinkActionUpdate {
Keep,
Update { link_action: LinkAction },
}

impl From<wysiwyg::LinkActionUpdate<Utf16String>> for LinkActionUpdate {
fn from(inner: wysiwyg::LinkActionUpdate<Utf16String>) -> Self {
match inner {
wysiwyg::LinkActionUpdate::Keep => Self::Keep,
wysiwyg::LinkActionUpdate::Update(action) => Self::Update {
link_action: action.into(),
},
}
}
}
4 changes: 4 additions & 0 deletions crates/wysiwyg/src/composer_model/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::dom::parser::markdown::markdown_html_parser::MarkdownHTMLParser;
use crate::dom::parser::parse;
use crate::dom::to_plain_text::ToPlainText;
use crate::dom::{Dom, DomCreationError, UnicodeString};
use crate::link_action::LinkActionUpdate;
use crate::{
ComposerAction, ComposerUpdate, DomHandle, Location, ToHtml, ToMarkdown,
ToTree,
Expand Down Expand Up @@ -156,6 +157,7 @@ where
self.state.end,
menu_state,
self.compute_menu_action(),
LinkActionUpdate::Update(self.get_link_action()),
)
}

Expand All @@ -169,6 +171,7 @@ where
self.state.end,
self.compute_menu_state(MenuStateComputeType::KeepIfUnchanged),
self.compute_menu_action(),
LinkActionUpdate::Update(self.get_link_action()),
)
}

Expand All @@ -184,6 +187,7 @@ where
self.state.end,
self.compute_menu_state(MenuStateComputeType::AlwaysUpdate),
self.compute_menu_action(),
LinkActionUpdate::Update(self.get_link_action()),
)
}

Expand Down
5 changes: 4 additions & 1 deletion crates/wysiwyg/src/composer_model/replace_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,13 @@ mod test {
use widestring::Utf16String;

use crate::action_state::ActionState;
use crate::link_action::LinkActionUpdate;
use crate::menu_state::MenuStateUpdate;
use crate::tests::testutils_composer_model::cm;
use crate::tests::testutils_conversion::utf16;
use crate::{
ComposerAction, ComposerUpdate, Location, MenuAction, MenuState,
ComposerAction, ComposerUpdate, LinkAction, Location, MenuAction,
MenuState,
};
use strum::IntoEnumIterator;

Expand All @@ -263,6 +265,7 @@ mod test {
action_states: indent_unindent_redo_disabled()
}),
MenuAction::None,
LinkActionUpdate::Update(LinkAction::CreateWithText),
),
);
}
Expand Down
8 changes: 8 additions & 0 deletions crates/wysiwyg/src/composer_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

use crate::dom::UnicodeString;
use crate::link_action::LinkActionUpdate;
use crate::{
Location, MenuAction, MenuState, ReplaceAll, Selection, TextUpdate,
};
Expand All @@ -25,6 +26,7 @@ where
pub text_update: TextUpdate<S>,
pub menu_state: MenuState,
pub menu_action: MenuAction,
pub link_action: LinkActionUpdate<S>,
}

impl<S> ComposerUpdate<S>
Expand All @@ -36,6 +38,7 @@ where
text_update: TextUpdate::<S>::Keep,
menu_state: MenuState::Keep,
menu_action: MenuAction::Keep,
link_action: LinkActionUpdate::Keep,
}
}

Expand All @@ -47,6 +50,7 @@ where
text_update: TextUpdate::<S>::Keep,
menu_state,
menu_action,
link_action: LinkActionUpdate::Keep,
}
}

Expand All @@ -55,11 +59,13 @@ where
end: Location,
menu_state: MenuState,
menu_action: MenuAction,
link_action: LinkActionUpdate<S>,
) -> Self {
Self {
text_update: TextUpdate::<S>::Select(Selection { start, end }),
menu_state,
menu_action,
link_action,
}
}

Expand All @@ -69,6 +75,7 @@ where
end: Location,
menu_state: MenuState,
menu_action: MenuAction,
link_action: LinkActionUpdate<S>,
) -> Self {
Self {
text_update: TextUpdate::ReplaceAll(ReplaceAll {
Expand All @@ -78,6 +85,7 @@ where
}),
menu_state,
menu_action,
link_action,
}
}
}
1 change: 1 addition & 0 deletions crates/wysiwyg/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub use crate::dom::UnicodeString;
pub use crate::dom::{MarkdownError, ToMarkdown};
pub use crate::format_type::InlineFormatType;
pub use crate::link_action::LinkAction;
pub use crate::link_action::LinkActionUpdate;
pub use crate::list_type::ListType;
pub use crate::location::Location;
pub use crate::menu_action::MenuAction;
Expand Down
8 changes: 7 additions & 1 deletion crates/wysiwyg/src/link_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@

use crate::UnicodeString;

#[derive(Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LinkActionUpdate<S: UnicodeString> {
Keep,
Update(LinkAction<S>),
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LinkAction<S: UnicodeString> {
CreateWithText,
Create,
Expand Down
2 changes: 1 addition & 1 deletion platforms/android/.idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withText
import io.element.android.wysiwyg.compose.testutils.ComposerActions.DEFAULT_ACTIONS
import io.element.android.wysiwyg.compose.testutils.EditorActions
import io.element.android.wysiwyg.compose.testutils.StateFactory.createState
import io.element.android.wysiwyg.compose.testutils.ViewMatchers.isRichTextEditor
import io.element.android.wysiwyg.compose.testutils.copy
import io.element.android.wysiwyg.compose.testutils.showContent
import io.element.android.wysiwyg.view.models.LinkAction
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Rule
Expand Down Expand Up @@ -128,4 +130,26 @@ class RichTextEditorTest {
assertEquals("Hello, <a href=\"https://matrix.org\">element</a>", state.messageHtml)
assertEquals("Hello, [element](<https://matrix.org>)", state.messageMarkdown)
}

@Test
fun testLinkActionUpdates() = runTest {
val state = createState()
composeTestRule.showContent(state)

composeTestRule.runOnUiThread {
state.setHtml("<a href=\"https://matrix.org\">matrix</a> <a href=\"https://element.io\">element</a> plain")
}

onView(withText("matrix element plain")).perform(EditorActions.setSelection(0, 0))
assertEquals(LinkAction.SetLink("https://matrix.org"), state.linkAction)

onView(withText("matrix element plain")).perform(EditorActions.setSelection(8, 8))
assertEquals(LinkAction.SetLink("https://element.io"), state.linkAction)

onView(withText("matrix element plain")).perform(EditorActions.setSelection(16, 16))
assertEquals(LinkAction.InsertLink, state.linkAction)

onView(withText("matrix element plain")).perform(EditorActions.setSelection(16, 20))
assertEquals(LinkAction.SetLink(null), state.linkAction)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.element.android.wysiwyg.compose.testutils

import android.view.View
import androidx.appcompat.widget.AppCompatEditText
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import org.hamcrest.Matcher

object Editor {
class SetSelection(
private val start: Int,
private val end: Int,
) : ViewAction {
override fun getConstraints(): Matcher<View> = isDisplayed()

override fun getDescription(): String = "Set selection to $start, $end"

override fun perform(uiController: UiController?, view: View?) {
val editor = view as? AppCompatEditText ?: return
editor.setSelection(start, end)
}
}

}

object EditorActions {
fun setSelection(start: Int, end: Int) = Editor.SetSelection(start, end)
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ private fun RealEditor(
menuActionListener = EditorEditText.OnMenuActionChangedListener { menuAction ->
state.menuAction = menuAction
}
linkActionChangedListener = EditorEditText.OnLinkActionChangedListener { linkAction ->
state.linkAction = linkAction
}
onFocusChangeListener =
View.OnFocusChangeListener { _, hasFocus -> state.hasFocus = hasFocus }

Expand All @@ -89,7 +92,6 @@ private fun RealEditor(
state.messageHtml = getContentAsMessageHtml()
state.messageMarkdown = getMarkdown()
state.lineCount = lineCount
state.linkAction = getLinkAction()
}

applyDefaultStyle()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ class EditorEditText : AppCompatEditText {
fun onMenuActionChanged(menuAction: MenuAction)
}

fun interface OnLinkActionChangedListener {
fun onLinkActionChanged(linkAction: LinkAction?)
}

/**
* Set the mention display handler to display mentions in a custom way.
*/
Expand All @@ -131,6 +135,18 @@ class EditorEditText : AppCompatEditText {
}
}

/**
* Set the link action listener to be notified when the available link action changes.
*/
var linkActionChangedListener: OnLinkActionChangedListener? = null
set(value) {
field = value

viewModel.linkActionCallback = { linkAction ->
value?.onLinkActionChanged(linkAction)
}
}

/**
* When not null, it will serve as an error callback for the client integrating this lib.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.element.android.wysiwyg.internal.view.models


import io.element.android.wysiwyg.view.models.LinkAction
import uniffi.wysiwyg_composer.LinkAction as InternalLinkAction

internal fun InternalLinkAction.toApiModel(): LinkAction? =
when (this) {
is InternalLinkAction.Edit -> LinkAction.SetLink(currentUrl = url)
is InternalLinkAction.Create -> LinkAction.SetLink(currentUrl = null)
is InternalLinkAction.CreateWithText -> LinkAction.InsertLink
is InternalLinkAction.Disabled -> null
}
Loading

0 comments on commit a75603d

Please sign in to comment.