Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable user to share community channel #18271

Closed
wants to merge 48 commits into from

Conversation

Pau1fitz
Copy link
Collaborator

Fixes #17994

Enable user to share a community channel using a share sheet

Screen.Recording.2023-12-21.at.14.33.46.mov

Figma design

iOS
Android

Testing notes:
Navigate to an individual community channels
click on ellipsis in top right corner
on bottom sheet that opens press share channel

Navigate to list of community channels
Long press on one of them
on bottom sheet that opens press share channel

channel-id (subs chat-id constants/community-id-length)]
{:json-rpc/call [{:method "wakuext_shareCommunityChannelURLWithData"
:params [{:CommunityID community-id :ChannelID channel-id}]
:on-success #(share/open {:url %})
Copy link
Contributor

@OmarBasem OmarBasem Dec 22, 2023

Choose a reason for hiding this comment

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

As per the designs, the share menu needs to have a title as Channel on Status and needs to have a sub-title which is the url (FYI, this is supported only on iOS). You can check the format in status-im.contexts.wallet.account.tabs.about.view (that one doesn't have a sub-title tho)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I am still waiting on access to the designs. I was unable to find a subtitle option in the docs.

I pushed the changes to use ActivityItemSources. Let me know if they are not matching what the design expects.


(rf/reg-event-fx :communities/share-community-channel-url-with-data
(fn [_ [chat-id]]
(let [community-id (subs chat-id 0 constants/community-id-length)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this logic to decode the IDs from the chat-id should be a proper function, it would be cleaner.

(require '[legacy.status.im.data-store.chats :as data-store.chats])

(let [{:keys [community-id channel-id]} (data-store.chats/decode-chat-id chat-id)]
  ...)

And also have a simple unit test for the function decode-chat-id.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

moved this to it's own function and have added a test.

{:json-rpc/call [{:method "wakuext_shareCommunityChannelURLWithData"
:params [{:CommunityID community-id :ChannelID channel-id}]
:on-success #(share/open {:url %})
:on-error #(log/error "failed to retrieve community channel url with data" %)}]})))
Copy link
Contributor

Choose a reason for hiding this comment

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

We try to log more descriptive errors, where the second argument to log/error is a map containing whatever could be useful to diagnose the error. Error messages coming from status-go can be very cryptic depending where the failure happened over there. See other calls to log/error, for example:

(log/error "Failed to migrate the keychain password"
{:error err
:key-uid key-uid
:event :keychain/password-hash-migration}))))))

We can at least log the chat-id alongside the error.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated to log the chat-id along with more error details

:on-press not-implemented/alert
:label (i18n/label :t/share-channel)})
[chat-id]
{:icon :i/share
Copy link
Contributor

Choose a reason for hiding this comment

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

Running make lint-fix should fix the indentation issues in the PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

👍🏻 done

channel-id (subs chat-id constants/community-id-length)]
{:json-rpc/call [{:method "wakuext_shareCommunityChannelURLWithData"
:params [{:CommunityID community-id :ChannelID channel-id}]
:on-success #(share/open {:url %})
Copy link
Contributor

Choose a reason for hiding this comment

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

The default error handling in share/open shouldn't be a no-op (line 7 below), we should at least log errors, but given this is not your PR's responsibility, I suggest we at least call share/open with an on-error callback that logs the error. Swallowing rejections is never a good idea.

(open options #() #()))
([options on-success on-error]
(-> ^js react-native-share
(.open (clj->js options))
(.then on-success)
(.catch on-error))))

(if platform/ios?
{:activityItemSources [{:placeholderItem {:type "text"
:content
"Channel on Status"}
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please relocate 'Channel on Status' text to the translations file?

Copy link
Contributor

@J-Son89 J-Son89 Jan 2, 2024

Choose a reason for hiding this comment

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

just to share how this is done. We have the file en.json. Add your key there (anywhere in the file) and it's corresponding translation.
It can then be used with i18n/label function.
e.g require [utils.i18n :as i18n]
and
:content (i18n/label :t/channel-on-status) assuming that you added "channel-on-status" as your translation key in en.json file 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

👍

:content %}}
:linkMetadata {:title
"Channel on Status"}}]}
{:title "Channel on Status"
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess these strings should also be i18n labels too 👍

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

👍🏻

@Pau1fitz
Copy link
Collaborator Author

Pau1fitz commented Jan 3, 2024

@OmarBasem @ilmotta feedback should be addressed if you want to take a second look.

@pavloburykh pavloburykh self-assigned this Jan 10, 2024
@status-im-auto
Copy link
Member

77% of end-end tests have passed

Total executed tests: 48
Failed tests: 9
Expected to fail tests: 2
Passed tests: 37
IDs of failed tests: 702809,702733,702948,702936,703391,702786,702947,702845,703629 
IDs of expected to fail tests: 703503,702808 

Failed tests (9)

Click to expand
  • Rerun failed tests

  • Class TestActivityMultipleDevicePR:

    1. test_navigation_jump_to, id: 702936

    Device 2: Find `Text` by `xpath`: `//android.view.ViewGroup[@content-desc='chat-item']//android.widget.TextView[contains(@text,'https://status.app/c/')]`
    Device 2: Wait for element `Button` for max 120s and click when it is available

    Test setup failed: activity_center/test_activity_center.py:270: in prepare_devices
        self.community_2.join_community()
    ../views/chat_view.py:435: in join_community
        self.join_button.wait_and_click(120)
    ../views/base_element.py:96: in wait_and_click
        self.wait_for_visibility_of_element(sec)
    ../views/base_element.py:139: in wait_for_visibility_of_element
        raise TimeoutException(
     Device 2: Button by accessibility id:`show-request-to-join-screen-button` is not found on the screen after wait_for_visibility_of_element
    



    Device sessions

    2. test_activity_center_reply_read_unread_delete_filter_swipe, id: 702947

    Test setup failed: activity_center/test_activity_center.py:270: in prepare_devices
        self.community_2.join_community()
    ../views/chat_view.py:435: in join_community
        self.join_button.wait_and_click(120)
    ../views/base_element.py:96: in wait_and_click
        self.wait_for_visibility_of_element(sec)
    ../views/base_element.py:139: in wait_for_visibility_of_element
        raise TimeoutException(
     Device 2: Button by accessibility id:`show-request-to-join-screen-button` is not found on the screen after wait_for_visibility_of_element
    



    Class TestOneToOneChatMultipleSharedDevicesNewUi:

    1. test_1_1_chat_text_message_delete_push_disappear, id: 702733

    Device 1: Find Button by accessibility id: jump-to

    critical/chats/test_1_1_public_chats.py:460: in test_1_1_chat_text_message_delete_push_disappear
        self.chat_1.jump_to_card_by_text(self.username_2)
    ../views/base_view.py:658: in jump_to_card_by_text
        self.click_on_floating_jump_to()
    ../views/base_view.py:647: in click_on_floating_jump_to
        self.jump_to_button.click()
    ../views/base_element.py:90: in click
        self.find_element().click()
    ../views/base_element.py:79: in find_element
        raise NoSuchElementException(
     Device 1: Button by accessibility id: `jump-to` is not found on the screen; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception
    



    Device sessions

    2. test_1_1_chat_send_image_save_and_share, id: 703391

    Device 1: Tap on found: Button
    Device 1: Find BaseElement by accessibility id: toast-content

    critical/chats/test_1_1_public_chats.py:435: in test_1_1_chat_send_image_save_and_share
        toast_element_text = toast_element.text
    ../views/base_element.py:229: in text
        return self.find_element().text
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webelement.py:90: in text
        return self._execute(Command.GET_ELEMENT_TEXT)["value"]
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webelement.py:395: in _execute
        return self._parent.execute(command, params)
    /home/jenkins/.local/lib/python3.10/site-packages/selenium/webdriver/remote/webdriver.py:345: in execute
        self.error_handler.check_response(response)
    /home/jenkins/.local/lib/python3.10/site-packages/appium/webdriver/errorhandler.py:122: in check_response
        raise exception_class(msg=message, stacktrace=format_stacktrace(stacktrace))
     The element 'By.accessibilityId: toast-content' does not exist in DOM anymore; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#stale-element-reference-exception
    E   Stacktrace:
    E   io.appium.uiautomator2.common.exceptions.StaleElementReferenceException: The element 'By.accessibilityId: toast-content' does not exist in DOM anymore
    E   	at io.appium.uiautomator2.model.ElementsCache.restore(ElementsCache.java:117)
    E   	at io.appium.uiautomator2.model.ElementsCache.get(ElementsCache.java:153)
    E   	at io.appium.uiautomator2.handler.GetText.safeHandle(GetText.java:20)
    E   	at io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:59)
    E   	at io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:277)
    E   	at io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:271)
    E   	at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:68)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435)
    E   	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
    E   	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)
    E   	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345)
    E   	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)
    E   	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352)
    E   	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911)
    E   	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
    E   	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:611)
    E   	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:552)
    E   	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:466)
    E   	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)
    E   	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:140)
    E   	at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
    E   	at java.lang.Thread.run(Thread.java:1012)
    



    Device sessions

    Class TestCommunityMultipleDeviceMergedTwo:

    1. test_community_markdown_support, id: 702809

    Test setup failed: critical/chats/test_public_chat_browsing.py:835: in prepare_devices
        self.community_2.join_community()
    ../views/chat_view.py:435: in join_community
        self.join_button.wait_and_click(120)
    ../views/base_element.py:96: in wait_and_click
        self.wait_for_visibility_of_element(sec)
    ../views/base_element.py:139: in wait_for_visibility_of_element
        raise TimeoutException(
     Device 2: Button by accessibility id:`show-request-to-join-screen-button` is not found on the screen after wait_for_visibility_of_element
    



    2. test_community_hashtag_links_to_community_channels, id: 702948

    Test setup failed: critical/chats/test_public_chat_browsing.py:835: in prepare_devices
        self.community_2.join_community()
    ../views/chat_view.py:435: in join_community
        self.join_button.wait_and_click(120)
    ../views/base_element.py:96: in wait_and_click
        self.wait_for_visibility_of_element(sec)
    ../views/base_element.py:139: in wait_for_visibility_of_element
        raise TimeoutException(
     Device 2: Button by accessibility id:`show-request-to-join-screen-button` is not found on the screen after wait_for_visibility_of_element
    



    3. test_community_mentions_push_notification, id: 702786

    Device 2: Find Text by xpath: //android.view.ViewGroup[@content-desc='chat-item']//android.widget.TextView[contains(@text,'https://status.app/c/')]
    Device 2: Wait for element Button for max 120s and click when it is available

    Test setup failed: critical/chats/test_public_chat_browsing.py:835: in prepare_devices
        self.community_2.join_community()
    ../views/chat_view.py:435: in join_community
        self.join_button.wait_and_click(120)
    ../views/base_element.py:96: in wait_and_click
        self.wait_for_visibility_of_element(sec)
    ../views/base_element.py:139: in wait_for_visibility_of_element
        raise TimeoutException(
     Device 2: Button by accessibility id:`show-request-to-join-screen-button` is not found on the screen after wait_for_visibility_of_element
    



    Device sessions

    4. test_community_leave, id: 702845

    Test setup failed: critical/chats/test_public_chat_browsing.py:835: in prepare_devices
        self.community_2.join_community()
    ../views/chat_view.py:435: in join_community
        self.join_button.wait_and_click(120)
    ../views/base_element.py:96: in wait_and_click
        self.wait_for_visibility_of_element(sec)
    ../views/base_element.py:139: in wait_for_visibility_of_element
        raise TimeoutException(
     Device 2: Button by accessibility id:`show-request-to-join-screen-button` is not found on the screen after wait_for_visibility_of_element
    



    5. test_community_join_when_node_owner_offline, id: 703629

    Test setup failed: critical/chats/test_public_chat_browsing.py:835: in prepare_devices
        self.community_2.join_community()
    ../views/chat_view.py:435: in join_community
        self.join_button.wait_and_click(120)
    ../views/base_element.py:96: in wait_and_click
        self.wait_for_visibility_of_element(sec)
    ../views/base_element.py:139: in wait_for_visibility_of_element
        raise TimeoutException(
     Device 2: Button by accessibility id:`show-request-to-join-screen-button` is not found on the screen after wait_for_visibility_of_element 
    

    [[Can't join a community if admin goes offline, https://github.com//issues/17678]]

    Expected to fail tests (2)

    Click to expand

    Class TestCommunityOneDeviceMerged:

    1. test_community_discovery, id: 703503

    Test is not run, e2e blocker  
    

    [[reason: [NOTRUN] Curated communities not loading, https://github.com//issues/17852]]

    Class TestGroupChatMultipleDeviceMergedNewUI:

    1. test_group_chat_offline_pn, id: 702808

    Device 3: Looking for a message by text: message from old member
    Device 3: Looking for a message by text: message from new member

    critical/chats/test_group_chat.py:324: in test_group_chat_offline_pn
        self.errors.verify_no_errors()
    base_test_case.py:191: in verify_no_errors
        pytest.fail('\n '.join([self.errors.pop(0) for _ in range(len(self.errors))]))
     Messages PN was not fetched from offline 
    

    [[Data delivery issue]]

    Device sessions

    Passed tests (37)

    Click to expand

    Class TestCommunityOneDeviceMerged:

    1. test_restore_multiaccount_with_waku_backup_remove_switch, id: 703133
    Device sessions

    2. test_community_copy_and_paste_message_in_chat_input, id: 702742
    Device sessions

    3. test_community_undo_delete_message, id: 702869
    Device sessions

    4. test_community_navigate_to_channel_when_relaunch, id: 702846
    Device sessions

    5. test_community_mute_community_and_channel, id: 703382
    Device sessions

    Class TestActivityMultipleDevicePRTwo:

    1. test_activity_center_mentions, id: 702957
    Device sessions

    2. test_activity_center_admin_notification_accept_swipe, id: 702958
    Device sessions

    Class TestDeepLinksOneDevice:

    1. test_links_open_universal_links_from_chat, id: 704613
    Device sessions

    2. test_links_deep_links, id: 702775
    Device sessions

    Class TestGroupChatMultipleDeviceMergedNewUI:

    1. test_group_chat_pin_messages, id: 702732
    Device sessions

    2. test_group_chat_mute_chat, id: 703495
    Device sessions

    3. test_group_chat_send_image_save_and_share, id: 703297
    Device sessions

    4. test_group_chat_reactions, id: 703202
    Device sessions

    5. test_group_chat_join_send_text_messages_push, id: 702807
    Device sessions

    Class TestActivityCenterContactRequestMultipleDevicePR:

    1. test_add_contact_field_validation, id: 702777
    Device sessions

    2. test_activity_center_contact_request_accept_swipe_mark_all_as_read, id: 702851
    Device sessions

    3. test_activity_center_contact_request_decline, id: 702850
    Device sessions

    Class TestOneToOneChatMultipleSharedDevicesNewUi:

    1. test_1_1_chat_emoji_send_reply_and_open_link, id: 702782
    Device sessions

    2. test_1_1_chat_push_emoji, id: 702813
    Device sessions

    3. test_1_1_chat_non_latin_messages_stack_update_profile_photo, id: 702745
    Device sessions

    4. test_1_1_chat_edit_message, id: 702855
    Device sessions

    5. test_1_1_chat_pin_messages, id: 702731
    Device sessions

    6. test_1_1_chat_message_reaction, id: 702730
    Device sessions

    Class TestCommunityMultipleDeviceMerged:

    1. test_community_several_images_send_reply, id: 703194
    Device sessions

    2. test_community_one_image_send_reply, id: 702859
    Device sessions

    3. test_community_emoji_send_copy_paste_reply, id: 702840
    Device sessions

    4. test_community_mark_all_messages_as_read, id: 703086
    Device sessions

    5. test_community_contact_block_unblock_offline, id: 702894
    Device sessions

    6. test_community_edit_delete_message_when_offline, id: 704615
    Device sessions

    7. test_community_message_delete, id: 702839
    Device sessions

    8. test_community_message_send_check_timestamps_sender_username, id: 702838
    Device sessions

    9. test_community_links_with_previews_github_youtube_twitter_gif_send_enable, id: 702844
    Device sessions

    10. test_community_message_edit, id: 702843
    Device sessions

    11. test_community_unread_messages_badge, id: 702841
    Device sessions

    Class TestOneToOneChatMultipleSharedDevicesNewUiTwo:

    1. test_1_1_chat_delete_via_long_press_relogin, id: 702784
    Device sessions

    2. test_1_1_chat_is_shown_message_sent_delivered_from_offline, id: 702783
    Device sessions

    3. test_1_1_chat_mute_chat, id: 703496
    Device sessions

    @pavloburykh
    Copy link
    Contributor

    @Pau1fitz thanx for the PR.

    So here we have the same issue on Android that was pointed out in Share wallet PR #18424 (comment)

    @J-Son89 do we want to fix it separately as well?

    ISSUE 1 Selected app is opened within Status app tap during sharing of community channel (Android)

    Tested on Android 12, Samsung Galaxy A 52

    Steps:

    1. Long tap on community channel
    2. Tap share button
    3. Select app for sharing
    4. See if app is opened in the new tab

    Actual result: selected app is opened within Status app. User needs to tap system back button to come back to Status app screens.

    photo_2024-01-10 17 07 25

    Expected result: selected app should be opened in separate tab.

    @pavloburykh
    Copy link
    Contributor

    So far ISSUE 1 - is the only issue in this PR.

    @pavloburykh
    Copy link
    Contributor

    @Pau1fitz thanx! ISSUE 1 is fixed now. PR is ready to be merged.

    @Pau1fitz
    Copy link
    Collaborator Author

    closed by #18516

    @Pau1fitz Pau1fitz closed this Jan 15, 2024
    @Pau1fitz Pau1fitz deleted the 17994-share-community branch January 15, 2024 21:32
    @J-Son89 J-Son89 changed the title Enable user to share community Enable user to share community channel Jan 26, 2024
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    Archived in project
    Archived in project
    Development

    Successfully merging this pull request may close these issues.

    Communities - Share Community Channel
    9 participants