From 1170a4411688d3dcc21a05fdf7e8e77cc325f8b8 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 11 Jul 2025 18:18:17 +0200 Subject: [PATCH] refactor (start chat) : start splitting things (create room, invite people, start chat) --- .../android/appnav/LoggedInFlowNode.kt | 19 +- .../createroom/api/CreateRoomEntryPoint.kt | 21 +- features/createroom/impl/build.gradle.kts | 2 +- .../createroom/impl/CreateRoomFlowNode.kt | 64 +--- .../impl/DefaultCreateRoomEntryPoint.kt | 23 +- .../impl/addpeople/AddPeopleNode.kt | 38 +- .../impl/configureroom/ConfigureRoomEvents.kt | 1 - .../impl/configureroom/ConfigureRoomNode.kt | 10 +- .../configureroom/ConfigureRoomPresenter.kt | 7 +- .../impl/configureroom/ConfigureRoomState.kt | 1 - .../ConfigureRoomStateProvider.kt | 1 - .../impl/configureroom/ConfigureRoomView.kt | 12 - .../{ => configureroom}/CreateRoomConfig.kt | 3 +- .../configureroom/CreateRoomConfigStore.kt | 119 ++++++ .../impl/root/CreateRoomRootEvents.kt | 15 - .../features/home/api/HomeEntryPoint.kt | 2 +- .../features/home/impl/HomeFlowNode.kt | 6 +- .../android/features/home/impl/HomeView.kt | 12 +- .../home/impl/roomlist/RoomListViewTest.kt | 2 +- features/invitepeople/api/build.gradle.kts | 18 + .../invitepeople/api/InvitePeoplePresenter.kt | 15 + .../invitepeople/api/InvitePeopleRenderer.kt | 16 + .../invitepeople/api/InvitePeopleState.kt | 10 + features/invitepeople/impl/build.gradle.kts | 64 ++++ features/roomdetails/impl/build.gradle.kts | 4 +- features/startchat/api/build.gradle.kts | 18 + .../api/ConfirmingStartDmWithMatrixUser.kt | 2 +- .../startchat/api/StartChatEntryPoint.kt | 27 ++ .../features/startchat}/api/StartDMAction.kt | 2 +- features/startchat/impl/build.gradle.kts | 64 ++++ .../features/startchat/StartChatNavigator.kt} | 10 +- .../startchat/impl/CreateRoomConfig.kt | 22 ++ .../startchat}/impl/CreateRoomDataStore.kt | 18 +- .../startchat/impl/CreateRoomFlowNode.kt} | 24 +- .../impl/DefaultStartChatEntryPoint.kt | 35 ++ .../startchat}/impl/DefaultStartDMAction.kt | 6 +- .../startchat/impl/StartChatFlowNode.kt | 90 +++++ .../startchat/impl/addpeople/AddPeopleNode.kt | 45 +++ .../impl/addpeople/AddPeoplePresenter.kt | 14 +- .../AddPeopleUserListStateProvider.kt | 12 +- .../impl/addpeople/AddPeopleView.kt | 18 +- .../SearchMultipleUsersResultItem.kt | 2 +- .../components/SearchSingleUserResultItem.kt | 2 +- .../impl/components/SearchUserBar.kt | 2 +- .../impl/components/UserListView.kt | 10 +- .../impl/configureroom/ConfigureRoomEvents.kt | 23 ++ .../impl/configureroom/ConfigureRoomNode.kt | 55 +++ .../configureroom/ConfigureRoomPresenter.kt | 209 +++++++++++ .../ConfigureRoomPresenterArgs.kt | 14 + .../impl/configureroom/ConfigureRoomState.kt | 30 ++ .../ConfigureRoomStateProvider.kt | 102 ++++++ .../impl/configureroom/ConfigureRoomView.kt | 339 ++++++++++++++++++ .../impl/configureroom/RoomAccess.kt | 22 ++ .../impl/configureroom/RoomAccessItem.kt | 25 ++ .../impl/configureroom/RoomAddress.kt | 13 + .../impl/configureroom/RoomVisibilityItem.kt | 30 ++ .../impl/configureroom/RoomVisibilityState.kt | 26 ++ .../startchat}/impl/di/CreateRoomComponent.kt | 2 +- .../startchat}/impl/di/CreateRoomScope.kt | 2 +- .../joinbyaddress/JoinRoomByAddressEvents.kt | 2 +- .../joinbyaddress/JoinRoomByAddressNode.kt | 6 +- .../JoinRoomByAddressPresenter.kt | 8 +- .../joinbyaddress/JoinRoomByAddressState.kt | 2 +- .../JoinRoomByAddressStateProvider.kt | 2 +- .../joinbyaddress/JoinRoomByAddressView.kt | 4 +- .../startchat/impl/root/StartChatEvents.kt | 15 + .../startchat/impl/root/StartChatNode.kt} | 12 +- .../impl/root/StartChatPresenter.kt} | 28 +- .../startchat/impl/root/StartChatState.kt} | 10 +- .../impl/root/StartChatStateProvider.kt} | 20 +- .../startchat/impl/root/StartChatView.kt} | 28 +- .../impl/userlist/DefaultUserListPresenter.kt | 2 +- .../impl/userlist/UserListDataStore.kt | 2 +- .../impl/userlist/UserListEvents.kt | 2 +- .../impl/userlist/UserListPresenter.kt | 2 +- .../impl/userlist/UserListPresenterArgs.kt | 2 +- .../startchat}/impl/userlist/UserListState.kt | 2 +- .../impl/userlist/UserListStateProvider.kt | 2 +- .../src/main/res/values-be/translations.xml | 19 + .../src/main/res/values-bg/translations.xml | 23 ++ .../src/main/res/values-cs/translations.xml | 30 ++ .../src/main/res/values-cy/translations.xml | 30 ++ .../src/main/res/values-da/translations.xml | 30 ++ .../src/main/res/values-de/translations.xml | 30 ++ .../src/main/res/values-el/translations.xml | 30 ++ .../src/main/res/values-es/translations.xml | 30 ++ .../src/main/res/values-et/translations.xml | 30 ++ .../src/main/res/values-eu/translations.xml | 23 ++ .../src/main/res/values-fa/translations.xml | 28 ++ .../src/main/res/values-fi/translations.xml | 30 ++ .../src/main/res/values-fr/translations.xml | 30 ++ .../src/main/res/values-hu/translations.xml | 30 ++ .../src/main/res/values-in/translations.xml | 30 ++ .../src/main/res/values-it/translations.xml | 30 ++ .../src/main/res/values-ka/translations.xml | 15 + .../src/main/res/values-lt/translations.xml | 14 + .../src/main/res/values-nb/translations.xml | 30 ++ .../src/main/res/values-nl/translations.xml | 21 ++ .../src/main/res/values-pl/translations.xml | 30 ++ .../main/res/values-pt-rBR/translations.xml | 30 ++ .../src/main/res/values-pt/translations.xml | 30 ++ .../src/main/res/values-ro/translations.xml | 22 ++ .../src/main/res/values-ru/translations.xml | 30 ++ .../src/main/res/values-sk/translations.xml | 30 ++ .../src/main/res/values-sv/translations.xml | 30 ++ .../src/main/res/values-tr/translations.xml | 24 ++ .../src/main/res/values-uk/translations.xml | 30 ++ .../src/main/res/values-ur/translations.xml | 16 + .../src/main/res/values-uz/translations.xml | 13 + .../main/res/values-zh-rTW/translations.xml | 30 ++ .../src/main/res/values-zh/translations.xml | 24 ++ .../impl/src/main/res/values/localazy.xml | 30 ++ .../impl/DefaultStartDMActionTest.kt | 4 +- .../startchat/impl/FakeStartChatNavigator.kt} | 8 +- .../impl/addpeople/AddPeoplePresenterTest.kt | 10 +- .../impl/addpeople/AddPeopleViewTest.kt | 10 +- .../ConfigureBaseRoomPresenterTest.kt | 8 +- .../JoinBaseRoomByAddressPresenterTest.kt | 12 +- .../JoinBaseRoomByAddressViewTest.kt | 4 +- .../root/CreateBaseRoomRootPresenterTest.kt | 34 +- .../impl/root/CreateBaseRoomRootViewTest.kt | 25 +- .../userlist/DefaultUserListPresenterTest.kt | 2 +- .../impl/userlist/FakeUserListPresenter.kt | 2 +- .../userlist/FakeUserListPresenterFactory.kt | 2 +- .../test/build.gradle.kts | 4 +- .../invitepeople}/test/FakeStartDMAction.kt | 4 +- features/userprofile/impl/build.gradle.kts | 4 +- .../impl/root/UserProfilePresenter.kt | 2 +- .../impl/UserProfilePresenterTest.kt | 6 +- features/userprofile/shared/build.gradle.kts | 2 +- .../shared/UserProfileStateProvider.kt | 2 +- .../userprofile/shared/UserProfileView.kt | 2 +- tools/localazy/config.json | 10 + 133 files changed, 2613 insertions(+), 397 deletions(-) rename features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/{ => configureroom}/CreateRoomConfig.kt (82%) create mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfigStore.kt delete mode 100644 features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootEvents.kt create mode 100644 features/invitepeople/api/build.gradle.kts create mode 100644 features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeoplePresenter.kt create mode 100644 features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleRenderer.kt create mode 100644 features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt create mode 100644 features/invitepeople/impl/build.gradle.kts create mode 100644 features/startchat/api/build.gradle.kts rename features/{createroom/api/src/main/kotlin/io/element/android/features/createroom => startchat/api/src/main/kotlin/io/element/android/features/startchat}/api/ConfirmingStartDmWithMatrixUser.kt (89%) create mode 100644 features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/StartChatEntryPoint.kt rename features/{createroom/api/src/main/kotlin/io/element/android/features/createroom => startchat/api/src/main/kotlin/io/element/android/features/startchat}/api/StartDMAction.kt (95%) create mode 100644 features/startchat/impl/build.gradle.kts rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt => startchat/impl/src/main/kotlin/io/element/android/features/startchat/StartChatNavigator.kt} (86%) create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/CreateRoomConfig.kt rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/CreateRoomDataStore.kt (87%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/ConfigureRoomFlowNode.kt => startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/CreateRoomFlowNode.kt} (78%) create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPoint.kt rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/DefaultStartDMAction.kt (90%) create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/StartChatFlowNode.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleNode.kt rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/addpeople/AddPeoplePresenter.kt (65%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/addpeople/AddPeopleUserListStateProvider.kt (80%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/addpeople/AddPeopleView.kt (85%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/components/SearchMultipleUsersResultItem.kt (98%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/components/SearchSingleUserResultItem.kt (97%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/components/SearchUserBar.kt (98%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/components/UserListView.kt (94%) create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomEvents.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomNode.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomPresenter.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomPresenterArgs.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomState.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomStateProvider.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomView.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAccess.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAccessItem.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAddress.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomVisibilityItem.kt create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomVisibilityState.kt rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/di/CreateRoomComponent.kt (93%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/di/CreateRoomScope.kt (81%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/joinbyaddress/JoinRoomByAddressEvents.kt (86%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/joinbyaddress/JoinRoomByAddressNode.kt (85%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/joinbyaddress/JoinRoomByAddressPresenter.kt (95%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/joinbyaddress/JoinRoomByAddressState.kt (92%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/joinbyaddress/JoinRoomByAddressStateProvider.kt (95%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/joinbyaddress/JoinRoomByAddressView.kt (97%) create mode 100644 features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatEvents.kt rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootNode.kt => startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatNode.kt} (87%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt => startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt} (73%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootState.kt => startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt} (63%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootStateProvider.kt => startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt} (82%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt => startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt} (90%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/userlist/DefaultUserListPresenter.kt (98%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/userlist/UserListDataStore.kt (93%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/userlist/UserListEvents.kt (90%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/userlist/UserListPresenter.kt (90%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/userlist/UserListPresenterArgs.kt (84%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/userlist/UserListState.kt (94%) rename features/{createroom/impl/src/main/kotlin/io/element/android/features/createroom => startchat/impl/src/main/kotlin/io/element/android/features/startchat}/impl/userlist/UserListStateProvider.kt (98%) create mode 100644 features/startchat/impl/src/main/res/values-be/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-bg/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-cs/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-cy/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-da/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-de/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-el/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-es/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-et/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-eu/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-fa/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-fi/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-fr/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-hu/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-in/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-it/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-ka/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-lt/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-nb/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-nl/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-pl/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-pt-rBR/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-pt/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-ro/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-ru/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-sk/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-sv/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-tr/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-uk/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-ur/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-uz/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-zh-rTW/translations.xml create mode 100644 features/startchat/impl/src/main/res/values-zh/translations.xml create mode 100644 features/startchat/impl/src/main/res/values/localazy.xml rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom => startchat/impl/src/test/kotlin/io/element/android/features/startchat}/impl/DefaultStartDMActionTest.kt (97%) rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/FakeCreateRoomNavigator.kt => startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/FakeStartChatNavigator.kt} (86%) rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom => startchat/impl/src/test/kotlin/io/element/android/features/startchat}/impl/addpeople/AddPeoplePresenterTest.kt (79%) rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom => startchat/impl/src/test/kotlin/io/element/android/features/startchat}/impl/addpeople/AddPeopleViewTest.kt (89%) rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom => startchat/impl/src/test/kotlin/io/element/android/features/startchat}/impl/configureroom/ConfigureBaseRoomPresenterTest.kt (98%) rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom => startchat/impl/src/test/kotlin/io/element/android/features/startchat}/impl/joinbyaddress/JoinBaseRoomByAddressPresenterTest.kt (93%) rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom => startchat/impl/src/test/kotlin/io/element/android/features/startchat}/impl/joinbyaddress/JoinBaseRoomByAddressViewTest.kt (94%) rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom => startchat/impl/src/test/kotlin/io/element/android/features/startchat}/impl/root/CreateBaseRoomRootPresenterTest.kt (87%) rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom => startchat/impl/src/test/kotlin/io/element/android/features/startchat}/impl/root/CreateBaseRoomRootViewTest.kt (85%) rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom => startchat/impl/src/test/kotlin/io/element/android/features/startchat}/impl/userlist/DefaultUserListPresenterTest.kt (99%) rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom => startchat/impl/src/test/kotlin/io/element/android/features/startchat}/impl/userlist/FakeUserListPresenter.kt (89%) rename features/{createroom/impl/src/test/kotlin/io/element/android/features/createroom => startchat/impl/src/test/kotlin/io/element/android/features/startchat}/impl/userlist/FakeUserListPresenterFactory.kt (91%) rename features/{createroom => startchat}/test/build.gradle.kts (83%) rename features/{createroom/test/src/main/kotlin/io/element/android/features/createroom => startchat/test/src/main/kotlin/io/element/android/features/invitepeople}/test/FakeStartDMAction.kt (88%) diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt index fb9b38352c..ae22e5aa97 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -46,7 +46,6 @@ import io.element.android.appnav.loggedin.SendQueues import io.element.android.appnav.room.RoomFlowNode import io.element.android.appnav.room.RoomNavigationTarget import io.element.android.appnav.room.joined.JoinedRoomLoadedFlowNode -import io.element.android.features.createroom.api.CreateRoomEntryPoint import io.element.android.features.enterprise.api.SessionEnterpriseService import io.element.android.features.ftue.api.FtueEntryPoint import io.element.android.features.ftue.api.state.FtueService @@ -60,6 +59,7 @@ import io.element.android.features.roomdirectory.api.RoomDescription import io.element.android.features.roomdirectory.api.RoomDirectoryEntryPoint import io.element.android.features.securebackup.api.SecureBackupEntryPoint import io.element.android.features.share.api.ShareEntryPoint +import io.element.android.features.startchat.api.StartChatEntryPoint import io.element.android.features.userprofile.api.UserProfileEntryPoint import io.element.android.features.verifysession.api.IncomingVerificationEntryPoint import io.element.android.libraries.architecture.BackstackView @@ -94,15 +94,6 @@ import java.time.Duration import java.time.Instant import java.util.Optional import java.util.UUID -import kotlin.collections.List -import kotlin.collections.any -import kotlin.collections.emptyList -import kotlin.collections.first -import kotlin.collections.forEach -import kotlin.collections.listOf -import kotlin.collections.mapNotNull -import kotlin.collections.plus -import kotlin.collections.setOf import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds import kotlin.time.toKotlinDuration @@ -113,7 +104,7 @@ class LoggedInFlowNode @AssistedInject constructor( @Assisted plugins: List, private val homeEntryPoint: HomeEntryPoint, private val preferencesEntryPoint: PreferencesEntryPoint, - private val createRoomEntryPoint: CreateRoomEntryPoint, + private val startChatEntryPoint: StartChatEntryPoint, private val appNavigationStateService: AppNavigationStateService, private val secureBackupEntryPoint: SecureBackupEntryPoint, private val userProfileEntryPoint: UserProfileEntryPoint, @@ -304,7 +295,7 @@ class LoggedInFlowNode @AssistedInject constructor( backstack.push(NavTarget.Settings()) } - override fun onCreateRoomClick() { + override fun onStartChatClick() { backstack.push(NavTarget.CreateRoom) } @@ -422,7 +413,7 @@ class LoggedInFlowNode @AssistedInject constructor( .build() } NavTarget.CreateRoom -> { - val callback = object : CreateRoomEntryPoint.Callback { + val callback = object : StartChatEntryPoint.Callback { override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List) { backstack.replace(NavTarget.Room(roomIdOrAlias = roomIdOrAlias, serverNames = serverNames)) } @@ -432,7 +423,7 @@ class LoggedInFlowNode @AssistedInject constructor( } } - createRoomEntryPoint + startChatEntryPoint .nodeBuilder(this, buildContext) .callback(callback) .build() diff --git a/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/CreateRoomEntryPoint.kt b/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/CreateRoomEntryPoint.kt index 3b35d0a3e1..6b4f02c033 100644 --- a/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/CreateRoomEntryPoint.kt +++ b/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/CreateRoomEntryPoint.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. @@ -7,21 +7,6 @@ package io.element.android.features.createroom.api -import com.bumble.appyx.core.modality.BuildContext -import com.bumble.appyx.core.node.Node -import com.bumble.appyx.core.plugin.Plugin -import io.element.android.libraries.architecture.FeatureEntryPoint -import io.element.android.libraries.matrix.api.core.RoomIdOrAlias +import io.element.android.libraries.architecture.SimpleFeatureEntryPoint -interface CreateRoomEntryPoint : FeatureEntryPoint { - fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder - interface NodeBuilder { - fun callback(callback: Callback): NodeBuilder - fun build(): Node - } - - interface Callback : Plugin { - fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List) - fun onOpenRoomDirectory() - } -} +interface CreateRoomEntryPoint: SimpleFeatureEntryPoint diff --git a/features/createroom/impl/build.gradle.kts b/features/createroom/impl/build.gradle.kts index 769f7b5628..dfc503dfbf 100644 --- a/features/createroom/impl/build.gradle.kts +++ b/features/createroom/impl/build.gradle.kts @@ -56,7 +56,7 @@ dependencies { testImplementation(projects.libraries.mediaupload.test) testImplementation(projects.libraries.permissions.test) testImplementation(projects.libraries.usersearch.test) - testImplementation(projects.features.createroom.test) + testImplementation(projects.features.startchat.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.tests.testutils) testImplementation(libs.androidx.compose.ui.test.junit) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt index b8b755a0b3..f1628e754b 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomFlowNode.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. @@ -8,28 +8,19 @@ package io.element.android.features.createroom.impl import android.os.Parcelable -import androidx.compose.foundation.layout.Box -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier import com.bumble.appyx.core.modality.BuildContext -import com.bumble.appyx.core.navigation.transition.JumpToEndTransitionHandler import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin -import com.bumble.appyx.core.plugin.plugins import com.bumble.appyx.navmodel.backstack.BackStack import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode -import io.element.android.features.createroom.DefaultCreateRoomNavigator -import io.element.android.features.createroom.api.CreateRoomEntryPoint -import io.element.android.features.createroom.impl.joinbyaddress.JoinRoomByAddressNode -import io.element.android.features.createroom.impl.root.CreateRoomRootNode -import io.element.android.libraries.architecture.BackstackView +import io.element.android.features.createroom.impl.addpeople.AddPeopleNode +import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode import io.element.android.libraries.architecture.BaseFlowNode -import io.element.android.libraries.architecture.OverlayView import io.element.android.libraries.architecture.createNode import io.element.android.libraries.di.SessionScope +import io.element.android.libraries.matrix.api.core.RoomId import kotlinx.parcelize.Parcelize @ContributesNode(SessionScope::class) @@ -38,53 +29,24 @@ class CreateRoomFlowNode @AssistedInject constructor( @Assisted plugins: List, ) : BaseFlowNode( backstack = BackStack( - initialElement = NavTarget.Root, + initialElement = NavTarget.ConfigureRoom, savedStateMap = buildContext.savedStateMap, ), buildContext = buildContext, plugins = plugins ) { - sealed interface NavTarget : Parcelable { - @Parcelize - data object Root : NavTarget - - @Parcelize - data object NewRoom : NavTarget - - @Parcelize - data object JoinByAddress : NavTarget - } - - private val navigator = DefaultCreateRoomNavigator( - backstack = backstack, - overlay = overlay, - openRoom = { roomIdOrAlias, viaServers -> - plugins().forEach { it.onOpenRoom(roomIdOrAlias, viaServers) } - }, - openRoomDirectory = { - plugins().forEach { it.onOpenRoomDirectory() } - } - ) - override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { - NavTarget.Root -> { - createNode(buildContext = buildContext, plugins = listOf(navigator)) - } - NavTarget.NewRoom -> { - createNode(buildContext = buildContext, plugins = listOf(navigator)) - } - NavTarget.JoinByAddress -> { - createNode(buildContext = buildContext, plugins = listOf(navigator)) - } + NavTarget.ConfigureRoom -> createNode(buildContext) + is NavTarget.AddPeople -> createNode(buildContext) } } - @Composable - override fun View(modifier: Modifier) { - Box(modifier = modifier) { - BackstackView() - OverlayView(transitionHandler = remember { JumpToEndTransitionHandler() }) - } + sealed interface NavTarget : Parcelable { + @Parcelize + data object ConfigureRoom : NavTarget + + @Parcelize + data class AddPeople(val roomId: RoomId) : NavTarget } } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPoint.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPoint.kt index 161d67e817..33854be08e 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPoint.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPoint.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. @@ -9,27 +9,12 @@ package io.element.android.features.createroom.impl import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node -import com.bumble.appyx.core.plugin.Plugin -import com.squareup.anvil.annotations.ContributesBinding import io.element.android.features.createroom.api.CreateRoomEntryPoint import io.element.android.libraries.architecture.createNode -import io.element.android.libraries.di.AppScope import javax.inject.Inject -@ContributesBinding(AppScope::class) -class DefaultCreateRoomEntryPoint @Inject constructor() : CreateRoomEntryPoint { - override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): CreateRoomEntryPoint.NodeBuilder { - val plugins = ArrayList() - - return object : CreateRoomEntryPoint.NodeBuilder { - override fun callback(callback: CreateRoomEntryPoint.Callback): CreateRoomEntryPoint.NodeBuilder { - plugins += callback - return this - } - - override fun build(): Node { - return parentNode.createNode(buildContext, plugins) - } - } +class DefaultCreateRoomEntryPoint @Inject constructor(): CreateRoomEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext): Node { + return parentNode.createNode(buildContext) } } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleNode.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleNode.kt index ba9eb82073..df215c005e 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleNode.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleNode.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. @@ -7,39 +7,11 @@ package io.element.android.features.createroom.impl.addpeople -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin -import com.bumble.appyx.core.plugin.plugins -import dagger.assisted.Assisted -import dagger.assisted.AssistedInject -import io.element.android.anvilannotations.ContributesNode -import io.element.android.features.createroom.impl.di.CreateRoomScope -@ContributesNode(CreateRoomScope::class) -class AddPeopleNode @AssistedInject constructor( - @Assisted buildContext: BuildContext, - @Assisted plugins: List, - private val presenter: AddPeoplePresenter, -) : Node(buildContext, plugins = plugins) { - interface Callback : Plugin { - fun onContinue() - } - - private fun onContinue() { - plugins().forEach { it.onContinue() } - } - - @Composable - override fun View(modifier: Modifier) { - val state = presenter.present() - AddPeopleView( - state = state, - modifier = modifier, - onBackClick = this::navigateUp, - onNextClick = this::onContinue, - ) - } -} +class AddPeopleNode( + buildContext: BuildContext, + plugins: List, +) : Node(buildContext, plugins = plugins) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt index 6885123f63..ae23149fee 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomEvents.kt @@ -16,7 +16,6 @@ sealed interface ConfigureRoomEvents { data class RoomVisibilityChanged(val visibilityItem: RoomVisibilityItem) : ConfigureRoomEvents data class RoomAccessChanged(val roomAccess: RoomAccessItem) : ConfigureRoomEvents data class RoomAddressChanged(val roomAddress: String) : ConfigureRoomEvents - data class RemoveUserFromSelection(val matrixUser: MatrixUser) : ConfigureRoomEvents data object CreateRoom : ConfigureRoomEvents data class HandleAvatarAction(val action: AvatarAction) : ConfigureRoomEvents data object CancelCreateRoom : ConfigureRoomEvents diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomNode.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomNode.kt index e718825163..fcc85afcb7 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomNode.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomNode.kt @@ -13,24 +13,20 @@ import com.bumble.appyx.core.lifecycle.subscribe import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin -import com.bumble.appyx.core.plugin.plugins import dagger.assisted.Assisted import dagger.assisted.AssistedInject import im.vector.app.features.analytics.plan.MobileScreen import io.element.android.anvilannotations.ContributesNode -import io.element.android.features.createroom.CreateRoomNavigator -import io.element.android.features.createroom.impl.di.CreateRoomScope -import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias +import io.element.android.libraries.di.SessionScope import io.element.android.services.analytics.api.AnalyticsService -@ContributesNode(CreateRoomScope::class) +@ContributesNode(SessionScope::class) class ConfigureRoomNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, private val presenter: ConfigureRoomPresenter, private val analyticsService: AnalyticsService, ) : Node(buildContext, plugins = plugins) { - private val navigator = plugins().first() init { lifecycle.subscribe( @@ -48,7 +44,7 @@ class ConfigureRoomNode @AssistedInject constructor( modifier = modifier, onBackClick = this::navigateUp, onCreateRoomSuccess = { - navigator.onOpenRoom(roomIdOrAlias = it.toRoomIdOrAlias(), serverNames = emptyList()) + }, ) } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt index a3e8f67edf..397ae74186 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomPresenter.kt @@ -18,8 +18,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import im.vector.app.features.analytics.plan.CreatedRoom -import io.element.android.features.createroom.impl.CreateRoomConfig -import io.element.android.features.createroom.impl.CreateRoomDataStore import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runCatchingUpdatingState @@ -50,7 +48,7 @@ import javax.inject.Inject import kotlin.jvm.optionals.getOrDefault class ConfigureRoomPresenter @Inject constructor( - private val dataStore: CreateRoomDataStore, + private val dataStore: CreateRoomConfigStore, private val matrixClient: MatrixClient, private val mediaPickerProvider: PickerProvider, private val mediaPreProcessor: MediaPreProcessor, @@ -66,7 +64,7 @@ class ConfigureRoomPresenter @Inject constructor( @Composable override fun present(): ConfigureRoomState { val cameraPermissionState = cameraPermissionPresenter.present() - val createRoomConfig by dataStore.createRoomConfigWithInvites.collectAsState(CreateRoomConfig()) + val createRoomConfig by dataStore.getCreateRoomConfigFlow().collectAsState(CreateRoomConfig()) val homeserverName = remember { matrixClient.userIdServerName() } val isKnockFeatureEnabled by remember { featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock) @@ -121,7 +119,6 @@ class ConfigureRoomPresenter @Inject constructor( is ConfigureRoomEvents.RoomNameChanged -> dataStore.setRoomName(event.name) is ConfigureRoomEvents.TopicChanged -> dataStore.setTopic(event.topic) is ConfigureRoomEvents.RoomVisibilityChanged -> dataStore.setRoomVisibility(event.visibilityItem) - is ConfigureRoomEvents.RemoveUserFromSelection -> dataStore.selectedUserListDataStore.removeUserFromSelection(event.matrixUser) is ConfigureRoomEvents.RoomAccessChanged -> dataStore.setRoomAccess(event.roomAccess) is ConfigureRoomEvents.RoomAddressChanged -> dataStore.setRoomAddress(event.roomAddress) is ConfigureRoomEvents.CreateRoom -> createRoom(createRoomConfig) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt index 6651d16604..90022a9204 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomState.kt @@ -7,7 +7,6 @@ package io.element.android.features.createroom.impl.configureroom -import io.element.android.features.createroom.impl.CreateRoomConfig import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.ui.media.AvatarAction diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt index 71568dbbc7..7db8744408 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomStateProvider.kt @@ -8,7 +8,6 @@ package io.element.android.features.createroom.impl.configureroom import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.features.createroom.impl.CreateRoomConfig import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.ui.components.aMatrixUserList diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt index f639704890..8c56607a22 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt @@ -12,7 +12,6 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.consumeWindowInsets @@ -58,7 +57,6 @@ import io.element.android.libraries.designsystem.theme.components.TextField import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet -import io.element.android.libraries.matrix.ui.components.SelectedUsersRowList import io.element.android.libraries.matrix.ui.components.UnsavedAvatar import io.element.android.libraries.matrix.ui.room.address.RoomAddressField import io.element.android.libraries.permissions.api.PermissionsView @@ -112,16 +110,6 @@ fun ConfigureRoomView( topic = state.config.topic.orEmpty(), onTopicChange = { state.eventSink(ConfigureRoomEvents.TopicChanged(it)) }, ) - if (state.config.invites.isNotEmpty()) { - SelectedUsersRowList( - contentPadding = PaddingValues(horizontal = 24.dp), - selectedUsers = state.config.invites, - onUserRemove = { - focusManager.clearFocus() - state.eventSink(ConfigureRoomEvents.RemoveUserFromSelection(it)) - }, - ) - } RoomVisibilityOptions( selected = when (state.config.roomVisibility) { is RoomVisibilityState.Private -> RoomVisibilityItem.Private diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfig.kt similarity index 82% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt rename to features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfig.kt index 4cfa6158b8..9ec71f5b76 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomConfig.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfig.kt @@ -5,10 +5,9 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl +package io.element.android.features.createroom.impl.configureroom import android.net.Uri -import io.element.android.features.createroom.impl.configureroom.RoomVisibilityState import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfigStore.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfigStore.kt new file mode 100644 index 0000000000..ef5b632306 --- /dev/null +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/CreateRoomConfigStore.kt @@ -0,0 +1,119 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.createroom.impl.configureroom + +import android.net.Uri +import io.element.android.libraries.androidutils.file.safeDelete +import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.getAndUpdate +import java.io.File +import javax.inject.Inject + +class CreateRoomConfigStore @Inject constructor( + private val roomAliasHelper: RoomAliasHelper, +) { + private val createRoomConfigFlow: MutableStateFlow = MutableStateFlow(CreateRoomConfig()) + + private var cachedAvatarUri: Uri? = null + set(value) { + field?.path?.let { File(it) }?.safeDelete() + field = value + } + + fun getCreateRoomConfigFlow(): StateFlow = createRoomConfigFlow + + fun setRoomName(roomName: String) { + createRoomConfigFlow.getAndUpdate { config -> + val newVisibility = when (config.roomVisibility) { + is RoomVisibilityState.Public -> { + val roomAddress = config.roomVisibility.roomAddress + if (roomAddress is RoomAddress.AutoFilled || roomName.isEmpty()) { + val roomAliasName = roomAliasHelper.roomAliasNameFromRoomDisplayName(roomName) + config.roomVisibility.copy( + roomAddress = RoomAddress.AutoFilled(roomAliasName), + ) + } else { + config.roomVisibility + } + } + else -> config.roomVisibility + } + config.copy( + roomName = roomName.takeIf { it.isNotEmpty() }, + roomVisibility = newVisibility, + ) + } + } + + fun setTopic(topic: String) { + createRoomConfigFlow.getAndUpdate { config -> + config.copy(topic = topic.takeIf { it.isNotEmpty() }) + } + } + + fun setAvatarUri(uri: Uri?, cached: Boolean = false) { + cachedAvatarUri = uri.takeIf { cached } + createRoomConfigFlow.getAndUpdate { config -> + config.copy(avatarUri = uri) + } + } + + fun setRoomVisibility(visibility: RoomVisibilityItem) { + createRoomConfigFlow.getAndUpdate { config -> + config.copy( + roomVisibility = when (visibility) { + RoomVisibilityItem.Private -> RoomVisibilityState.Private + RoomVisibilityItem.Public -> { + val roomAliasName = roomAliasHelper.roomAliasNameFromRoomDisplayName(config.roomName.orEmpty()) + RoomVisibilityState.Public( + roomAddress = RoomAddress.AutoFilled(roomAliasName), + roomAccess = RoomAccess.Anyone, + ) + } + } + ) + } + } + + fun setRoomAddress(address: String) { + createRoomConfigFlow.getAndUpdate { config -> + config.copy( + roomVisibility = when (config.roomVisibility) { + is RoomVisibilityState.Public -> { + val sanitizedAddress = address.lowercase() + config.roomVisibility.copy(roomAddress = RoomAddress.Edited(sanitizedAddress)) + } + else -> config.roomVisibility + } + ) + } + } + + fun setRoomAccess(access: RoomAccessItem) { + createRoomConfigFlow.getAndUpdate { config -> + config.copy( + roomVisibility = when (config.roomVisibility) { + is RoomVisibilityState.Public -> { + when (access) { + RoomAccessItem.Anyone -> config.roomVisibility.copy(roomAccess = RoomAccess.Anyone) + RoomAccessItem.AskToJoin -> config.roomVisibility.copy(roomAccess = RoomAccess.Knocking) + } + } + else -> config.roomVisibility + } + ) + } + } + + fun clearCachedData() { + cachedAvatarUri = null + } +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootEvents.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootEvents.kt deleted file mode 100644 index bc3c4a39b9..0000000000 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootEvents.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2023, 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.createroom.impl.root - -import io.element.android.libraries.matrix.api.user.MatrixUser - -sealed interface CreateRoomRootEvents { - data class StartDM(val matrixUser: MatrixUser) : CreateRoomRootEvents - data object CancelStartDM : CreateRoomRootEvents -} diff --git a/features/home/api/src/main/kotlin/io/element/android/features/home/api/HomeEntryPoint.kt b/features/home/api/src/main/kotlin/io/element/android/features/home/api/HomeEntryPoint.kt index 0f6ee581bb..88b55d4e02 100644 --- a/features/home/api/src/main/kotlin/io/element/android/features/home/api/HomeEntryPoint.kt +++ b/features/home/api/src/main/kotlin/io/element/android/features/home/api/HomeEntryPoint.kt @@ -22,7 +22,7 @@ interface HomeEntryPoint : FeatureEntryPoint { interface Callback : Plugin { fun onRoomClick(roomId: RoomId) - fun onCreateRoomClick() + fun onStartChatClick() fun onSettingsClick() fun onSetUpRecoveryClick() fun onSessionConfirmRecoveryKeyClick() diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt index 54c58d7387..d08abb6891 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeFlowNode.kt @@ -120,8 +120,8 @@ class HomeFlowNode @AssistedInject constructor( plugins().forEach { it.onSettingsClick() } } - private fun onCreateRoomClick() { - plugins().forEach { it.onCreateRoomClick() } + private fun onStartChatClick() { + plugins().forEach { it.onStartChatClick() } } private fun onSetUpRecoveryClick() { @@ -171,7 +171,7 @@ class HomeFlowNode @AssistedInject constructor( homeState = state, onRoomClick = this::onRoomClick, onSettingsClick = this::onOpenSettings, - onCreateRoomClick = this::onCreateRoomClick, + onStartChatClick = this::onStartChatClick, onSetUpRecoveryClick = this::onSetUpRecoveryClick, onConfirmRecoveryKeyClick = this::onSessionConfirmRecoveryKeyClick, onRoomSettingsClick = this::onRoomSettingsClick, diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt index c2ef2e4bc5..c0e999e7f5 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/HomeView.kt @@ -72,7 +72,7 @@ fun HomeView( onSettingsClick: () -> Unit, onSetUpRecoveryClick: () -> Unit, onConfirmRecoveryKeyClick: () -> Unit, - onCreateRoomClick: () -> Unit, + onStartChatClick: () -> Unit, onRoomSettingsClick: (roomId: RoomId) -> Unit, onMenuActionClick: (RoomListMenuAction) -> Unit, onReportRoomClick: (roomId: RoomId) -> Unit, @@ -116,7 +116,7 @@ fun HomeView( onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, onRoomClick = { if (firstThrottler.canHandle()) onRoomClick(it) }, onOpenSettings = { if (firstThrottler.canHandle()) onSettingsClick() }, - onCreateRoomClick = { if (firstThrottler.canHandle()) onCreateRoomClick() }, + onStartChatClick = { if (firstThrottler.canHandle()) onStartChatClick() }, onMenuActionClick = onMenuActionClick, modifier = Modifier.padding(top = topPadding), ) @@ -145,7 +145,7 @@ private fun HomeScaffold( onConfirmRecoveryKeyClick: () -> Unit, onRoomClick: (RoomId) -> Unit, onOpenSettings: () -> Unit, - onCreateRoomClick: () -> Unit, + onStartChatClick: () -> Unit, onMenuActionClick: (RoomListMenuAction) -> Unit, modifier: Modifier = Modifier, ) { @@ -236,7 +236,7 @@ private fun HomeScaffold( onSetUpRecoveryClick = onSetUpRecoveryClick, onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, onRoomClick = ::onRoomClick, - onCreateRoomClick = onCreateRoomClick, + onCreateRoomClick = onStartChatClick, contentPadding = PaddingValues( // FAB height is 56dp, bottom padding is 16dp, we add 8dp as extra margin -> 56+16+8 = 80, // and include provided bottom padding @@ -280,7 +280,7 @@ private fun HomeScaffold( floatingActionButton = { if (state.displayActions) { FloatingActionButton( - onClick = onCreateRoomClick, + onClick = onStartChatClick, ) { Icon( imageVector = CompoundIcons.Plus(), @@ -304,7 +304,7 @@ internal fun HomeViewPreview(@PreviewParameter(HomeStateProvider::class) state: onSettingsClick = {}, onSetUpRecoveryClick = {}, onConfirmRecoveryKeyClick = {}, - onCreateRoomClick = {}, + onStartChatClick = {}, onRoomSettingsClick = {}, onReportRoomClick = {}, onMenuActionClick = {}, diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt index e29b2cf580..4fcbcd170b 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/roomlist/RoomListViewTest.kt @@ -284,7 +284,7 @@ private fun AndroidComposeTestRule.setRoomL onSettingsClick = onSettingsClick, onSetUpRecoveryClick = onSetUpRecoveryClick, onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, - onCreateRoomClick = onCreateRoomClick, + onStartChatClick = onCreateRoomClick, onRoomSettingsClick = onRoomSettingsClick, onMenuActionClick = onMenuActionClick, onDeclineInviteAndBlockUser = onDeclineInviteAndBlockUser, diff --git a/features/invitepeople/api/build.gradle.kts b/features/invitepeople/api/build.gradle.kts new file mode 100644 index 0000000000..85ce7164b9 --- /dev/null +++ b/features/invitepeople/api/build.gradle.kts @@ -0,0 +1,18 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.features.invitepeople.api" +} + +dependencies { + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) +} diff --git a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeoplePresenter.kt b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeoplePresenter.kt new file mode 100644 index 0000000000..d41b4db093 --- /dev/null +++ b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeoplePresenter.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.invitepeople.api + +import androidx.compose.runtime.Composable + +interface InvitePeoplePresenter { + @Composable + fun present(): InvitePeopleState +} diff --git a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleRenderer.kt b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleRenderer.kt new file mode 100644 index 0000000000..70523653ed --- /dev/null +++ b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleRenderer.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.invitepeople.api + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +interface InvitePeopleRenderer { + @Composable + fun Render(state: InvitePeopleState, modifier: Modifier) +} diff --git a/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt new file mode 100644 index 0000000000..059c360df6 --- /dev/null +++ b/features/invitepeople/api/src/main/kotlin/io/element/android/features/invitepeople/api/InvitePeopleState.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.invitepeople.api + +interface InvitePeopleState diff --git a/features/invitepeople/impl/build.gradle.kts b/features/invitepeople/impl/build.gradle.kts new file mode 100644 index 0000000000..42c96fee18 --- /dev/null +++ b/features/invitepeople/impl/build.gradle.kts @@ -0,0 +1,64 @@ +import extension.ComponentMergingStrategy +import extension.setupAnvil + +/* + * Copyright 2022-2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +plugins { + id("io.element.android-compose-library") + id("kotlin-parcelize") +} + +android { + namespace = "io.element.android.features.invitepeople.impl" + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + } +} + +setupAnvil(componentMergingStrategy = ComponentMergingStrategy.KSP) + +dependencies { + implementation(projects.libraries.core) + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) + implementation(projects.libraries.matrixui) + implementation(projects.libraries.designsystem) + implementation(projects.libraries.uiStrings) + implementation(projects.libraries.androidutils) + implementation(projects.libraries.deeplink) + implementation(projects.libraries.mediapickers.api) + implementation(projects.libraries.mediaupload.api) + implementation(projects.libraries.permissions.api) + implementation(projects.libraries.usersearch.impl) + implementation(projects.services.analytics.api) + implementation(libs.coil.compose) + implementation(projects.libraries.featureflag.api) + api(projects.features.invitepeople.api) + + testImplementation(libs.test.junit) + testImplementation(libs.test.mockk) + testImplementation(libs.coroutines.test) + testImplementation(libs.molecule.runtime) + testImplementation(libs.test.truth) + testImplementation(libs.test.turbine) + testImplementation(libs.test.robolectric) + testImplementation(projects.services.analytics.test) + testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.mediapickers.test) + testImplementation(projects.libraries.mediaupload.test) + testImplementation(projects.libraries.permissions.test) + testImplementation(projects.libraries.usersearch.test) + testImplementation(projects.features.startchat.test) + testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.tests.testutils) + testImplementation(libs.androidx.compose.ui.test.junit) + testReleaseImplementation(libs.androidx.compose.ui.test.manifest) +} diff --git a/features/roomdetails/impl/build.gradle.kts b/features/roomdetails/impl/build.gradle.kts index ad45eda8fc..91bb79c8b7 100644 --- a/features/roomdetails/impl/build.gradle.kts +++ b/features/roomdetails/impl/build.gradle.kts @@ -44,7 +44,7 @@ dependencies { api(projects.services.apperror.api) implementation(libs.coil.compose) implementation(projects.features.call.api) - implementation(projects.features.createroom.api) + implementation(projects.features.startchat.api) implementation(projects.features.leaveroom.api) implementation(projects.features.userprofile.shared) implementation(projects.services.analytics.compose) @@ -72,7 +72,7 @@ dependencies { testImplementation(projects.libraries.usersearch.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.tests.testutils) - testImplementation(projects.features.createroom.test) + testImplementation(projects.features.startchat.test) testImplementation(projects.services.analytics.test) testImplementation(libs.androidx.compose.ui.test.junit) testReleaseImplementation(libs.androidx.compose.ui.test.manifest) diff --git a/features/startchat/api/build.gradle.kts b/features/startchat/api/build.gradle.kts new file mode 100644 index 0000000000..77822f1a15 --- /dev/null +++ b/features/startchat/api/build.gradle.kts @@ -0,0 +1,18 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.features.startchat.api" +} + +dependencies { + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) +} diff --git a/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/ConfirmingStartDmWithMatrixUser.kt b/features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/ConfirmingStartDmWithMatrixUser.kt similarity index 89% rename from features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/ConfirmingStartDmWithMatrixUser.kt rename to features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/ConfirmingStartDmWithMatrixUser.kt index af19408324..192c32fee7 100644 --- a/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/ConfirmingStartDmWithMatrixUser.kt +++ b/features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/ConfirmingStartDmWithMatrixUser.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.api +package io.element.android.features.startchat.api import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.user.MatrixUser diff --git a/features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/StartChatEntryPoint.kt b/features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/StartChatEntryPoint.kt new file mode 100644 index 0000000000..17b9b902e2 --- /dev/null +++ b/features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/StartChatEntryPoint.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.api + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import io.element.android.libraries.architecture.FeatureEntryPoint +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias + +interface StartChatEntryPoint : FeatureEntryPoint { + fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder + interface NodeBuilder { + fun callback(callback: Callback): NodeBuilder + fun build(): Node + } + + interface Callback : Plugin { + fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List) + fun onOpenRoomDirectory() + } +} diff --git a/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/StartDMAction.kt b/features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/StartDMAction.kt similarity index 95% rename from features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/StartDMAction.kt rename to features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/StartDMAction.kt index e64be9f923..b49a9fbdfd 100644 --- a/features/createroom/api/src/main/kotlin/io/element/android/features/createroom/api/StartDMAction.kt +++ b/features/startchat/api/src/main/kotlin/io/element/android/features/startchat/api/StartDMAction.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.api +package io.element.android.features.startchat.api import androidx.compose.runtime.MutableState import io.element.android.libraries.architecture.AsyncAction diff --git a/features/startchat/impl/build.gradle.kts b/features/startchat/impl/build.gradle.kts new file mode 100644 index 0000000000..b53f3d8c89 --- /dev/null +++ b/features/startchat/impl/build.gradle.kts @@ -0,0 +1,64 @@ +import extension.ComponentMergingStrategy +import extension.setupAnvil + +/* + * Copyright 2022-2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +plugins { + id("io.element.android-compose-library") + id("kotlin-parcelize") +} + +android { + namespace = "io.element.android.features.startchat.impl" + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + } +} + +setupAnvil(componentMergingStrategy = ComponentMergingStrategy.KSP) + +dependencies { + implementation(projects.libraries.core) + implementation(projects.libraries.architecture) + implementation(projects.libraries.matrix.api) + implementation(projects.libraries.matrixui) + implementation(projects.libraries.designsystem) + implementation(projects.libraries.uiStrings) + implementation(projects.libraries.androidutils) + implementation(projects.libraries.deeplink) + implementation(projects.libraries.mediapickers.api) + implementation(projects.libraries.mediaupload.api) + implementation(projects.libraries.permissions.api) + implementation(projects.libraries.usersearch.impl) + implementation(projects.services.analytics.api) + implementation(libs.coil.compose) + implementation(projects.libraries.featureflag.api) + api(projects.features.startchat.api) + + testImplementation(libs.test.junit) + testImplementation(libs.test.mockk) + testImplementation(libs.coroutines.test) + testImplementation(libs.molecule.runtime) + testImplementation(libs.test.truth) + testImplementation(libs.test.turbine) + testImplementation(libs.test.robolectric) + testImplementation(projects.services.analytics.test) + testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.mediapickers.test) + testImplementation(projects.libraries.mediaupload.test) + testImplementation(projects.libraries.permissions.test) + testImplementation(projects.libraries.usersearch.test) + testImplementation(projects.features.startchat.test) + testImplementation(projects.libraries.featureflag.test) + testImplementation(projects.tests.testutils) + testImplementation(libs.androidx.compose.ui.test.junit) + testReleaseImplementation(libs.androidx.compose.ui.test.manifest) +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/StartChatNavigator.kt similarity index 86% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/StartChatNavigator.kt index 69eac7d369..a45b4dddab 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/CreateRoomNavigator.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/StartChatNavigator.kt @@ -5,18 +5,18 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom +package io.element.android.features.startchat import com.bumble.appyx.core.plugin.Plugin import com.bumble.appyx.navmodel.backstack.BackStack import com.bumble.appyx.navmodel.backstack.operation.push -import io.element.android.features.createroom.impl.CreateRoomFlowNode.NavTarget +import io.element.android.features.startchat.impl.StartChatFlowNode.NavTarget import io.element.android.libraries.architecture.overlay.Overlay import io.element.android.libraries.architecture.overlay.operation.hide import io.element.android.libraries.architecture.overlay.operation.show import io.element.android.libraries.matrix.api.core.RoomIdOrAlias -interface CreateRoomNavigator : Plugin { +interface StartChatNavigator : Plugin { fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List) fun onCreateNewRoom() fun onShowJoinRoomByAddress() @@ -24,12 +24,12 @@ interface CreateRoomNavigator : Plugin { fun onOpenRoomDirectory() } -class DefaultCreateRoomNavigator( +class DefaultStartChatNavigator( private val backstack: BackStack, private val overlay: Overlay, private val openRoom: (RoomIdOrAlias, List) -> Unit, private val openRoomDirectory: () -> Unit, -) : CreateRoomNavigator { +) : StartChatNavigator { override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List) = openRoom(roomIdOrAlias, serverNames) override fun onOpenRoomDirectory() = openRoomDirectory() diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/CreateRoomConfig.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/CreateRoomConfig.kt new file mode 100644 index 0000000000..2cbd961dad --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/CreateRoomConfig.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl + +import android.net.Uri +import io.element.android.features.startchat.impl.configureroom.RoomVisibilityState +import io.element.android.libraries.matrix.api.user.MatrixUser +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf + +data class CreateRoomConfig( + val roomName: String? = null, + val topic: String? = null, + val avatarUri: Uri? = null, + val invites: ImmutableList = persistentListOf(), + val roomVisibility: RoomVisibilityState = RoomVisibilityState.Private, +) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/CreateRoomDataStore.kt similarity index 87% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/CreateRoomDataStore.kt index 29b1525f51..ff0746c1b3 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/CreateRoomDataStore.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/CreateRoomDataStore.kt @@ -1,20 +1,20 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl +package io.element.android.features.startchat.impl import android.net.Uri -import io.element.android.features.createroom.impl.configureroom.RoomAccess -import io.element.android.features.createroom.impl.configureroom.RoomAccessItem -import io.element.android.features.createroom.impl.configureroom.RoomAddress -import io.element.android.features.createroom.impl.configureroom.RoomVisibilityItem -import io.element.android.features.createroom.impl.configureroom.RoomVisibilityState -import io.element.android.features.createroom.impl.di.CreateRoomScope -import io.element.android.features.createroom.impl.userlist.UserListDataStore +import io.element.android.features.startchat.impl.configureroom.RoomAccess +import io.element.android.features.startchat.impl.configureroom.RoomAccessItem +import io.element.android.features.startchat.impl.configureroom.RoomAddress +import io.element.android.features.startchat.impl.configureroom.RoomVisibilityItem +import io.element.android.features.startchat.impl.configureroom.RoomVisibilityState +import io.element.android.features.startchat.impl.di.CreateRoomScope +import io.element.android.features.startchat.impl.userlist.UserListDataStore import io.element.android.libraries.androidutils.file.safeDelete import io.element.android.libraries.di.SingleIn import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/ConfigureRoomFlowNode.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/CreateRoomFlowNode.kt similarity index 78% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/ConfigureRoomFlowNode.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/CreateRoomFlowNode.kt index a7678f130f..1124314250 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/ConfigureRoomFlowNode.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/CreateRoomFlowNode.kt @@ -1,11 +1,11 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl +package io.element.android.features.startchat.impl import android.os.Parcelable import androidx.compose.runtime.Composable @@ -19,10 +19,10 @@ import com.bumble.appyx.navmodel.backstack.operation.push import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode -import io.element.android.features.createroom.CreateRoomNavigator -import io.element.android.features.createroom.impl.addpeople.AddPeopleNode -import io.element.android.features.createroom.impl.configureroom.ConfigureRoomNode -import io.element.android.features.createroom.impl.di.CreateRoomComponent +import io.element.android.features.startchat.StartChatNavigator +import io.element.android.features.startchat.impl.addpeople.AddPeopleNode +import io.element.android.features.startchat.impl.configureroom.ConfigureRoomNode +import io.element.android.features.startchat.impl.di.CreateRoomComponent import io.element.android.libraries.architecture.BackstackView import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.bindings @@ -32,13 +32,13 @@ import io.element.android.libraries.di.SessionScope import kotlinx.parcelize.Parcelize @ContributesNode(SessionScope::class) -class ConfigureRoomFlowNode @AssistedInject constructor( +class CreateRoomFlowNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, ) : DaggerComponentOwner, - BaseFlowNode( + BaseFlowNode( backstack = BackStack( - initialElement = NavTarget.Root, + initialElement = NavTarget.ConfigureRoom, savedStateMap = buildContext.savedStateMap, ), buildContext = buildContext, @@ -47,14 +47,14 @@ class ConfigureRoomFlowNode @AssistedInject constructor( private val component by lazy { parent!!.bindings().createRoomComponentBuilder().build() } - private val navigator = plugins().first() + private val navigator = plugins().first() override val daggerComponent: Any get() = component sealed interface NavTarget : Parcelable { @Parcelize - data object Root : NavTarget + data object AddPeople : NavTarget @Parcelize data object ConfigureRoom : NavTarget @@ -62,7 +62,7 @@ class ConfigureRoomFlowNode @AssistedInject constructor( override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { - NavTarget.Root -> { + NavTarget.AddPeople -> { val callback = object : AddPeopleNode.Callback { override fun onContinue() { backstack.push(NavTarget.ConfigureRoom) diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPoint.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPoint.kt new file mode 100644 index 0000000000..9f9073f1d7 --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPoint.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.startchat.api.StartChatEntryPoint +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.AppScope +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class DefaultStartChatEntryPoint @Inject constructor() : StartChatEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): StartChatEntryPoint.NodeBuilder { + val plugins = ArrayList() + + return object : StartChatEntryPoint.NodeBuilder { + override fun callback(callback: StartChatEntryPoint.Callback): StartChatEntryPoint.NodeBuilder { + plugins += callback + return this + } + + override fun build(): Node { + return parentNode.createNode(buildContext, plugins) + } + } + } +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultStartDMAction.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartDMAction.kt similarity index 90% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultStartDMAction.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartDMAction.kt index c9b60786bd..b09c5ea174 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/DefaultStartDMAction.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/DefaultStartDMAction.kt @@ -5,13 +5,13 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl +package io.element.android.features.startchat.impl import androidx.compose.runtime.MutableState import com.squareup.anvil.annotations.ContributesBinding import im.vector.app.features.analytics.plan.CreatedRoom -import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUser -import io.element.android.features.createroom.api.StartDMAction +import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser +import io.element.android.features.startchat.api.StartDMAction import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/StartChatFlowNode.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/StartChatFlowNode.kt new file mode 100644 index 0000000000..c635023df3 --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/StartChatFlowNode.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl + +import android.os.Parcelable +import androidx.compose.foundation.layout.Box +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.navigation.transition.JumpToEndTransitionHandler +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.bumble.appyx.core.plugin.plugins +import com.bumble.appyx.navmodel.backstack.BackStack +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.startchat.DefaultStartChatNavigator +import io.element.android.features.startchat.api.StartChatEntryPoint +import io.element.android.features.startchat.impl.joinbyaddress.JoinRoomByAddressNode +import io.element.android.features.startchat.impl.root.StartChatNode +import io.element.android.libraries.architecture.BackstackView +import io.element.android.libraries.architecture.BaseFlowNode +import io.element.android.libraries.architecture.OverlayView +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.SessionScope +import kotlinx.parcelize.Parcelize + +@ContributesNode(SessionScope::class) +class StartChatFlowNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, +) : BaseFlowNode( + backstack = BackStack( + initialElement = NavTarget.Root, + savedStateMap = buildContext.savedStateMap, + ), + buildContext = buildContext, + plugins = plugins +) { + sealed interface NavTarget : Parcelable { + @Parcelize + data object Root : NavTarget + + @Parcelize + data object NewRoom : NavTarget + + @Parcelize + data object JoinByAddress : NavTarget + } + + private val navigator = DefaultStartChatNavigator( + backstack = backstack, + overlay = overlay, + openRoom = { roomIdOrAlias, viaServers -> + plugins().forEach { it.onOpenRoom(roomIdOrAlias, viaServers) } + }, + openRoomDirectory = { + plugins().forEach { it.onOpenRoomDirectory() } + } + ) + + override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { + return when (navTarget) { + NavTarget.Root -> { + createNode(buildContext = buildContext, plugins = listOf(navigator)) + } + NavTarget.NewRoom -> { + createNode(buildContext = buildContext, plugins = listOf(navigator)) + } + NavTarget.JoinByAddress -> { + createNode(buildContext = buildContext, plugins = listOf(navigator)) + } + } + } + + @Composable + override fun View(modifier: Modifier) { + Box(modifier = modifier) { + BackstackView() + OverlayView(transitionHandler = remember { JumpToEndTransitionHandler() }) + } + } +} diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleNode.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleNode.kt new file mode 100644 index 0000000000..441ba8cc76 --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleNode.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.addpeople + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.bumble.appyx.core.plugin.plugins +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.startchat.impl.di.CreateRoomScope + +@ContributesNode(CreateRoomScope::class) +class AddPeopleNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: AddPeoplePresenter, +) : Node(buildContext, plugins = plugins) { + interface Callback : Plugin { + fun onContinue() + } + + private fun onContinue() { + plugins().forEach { it.onContinue() } + } + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + AddPeopleView( + state = state, + modifier = modifier, + onBackClick = this::navigateUp, + onSkipClick = this::onContinue, + ) + } +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenter.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeoplePresenter.kt similarity index 65% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenter.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeoplePresenter.kt index e050a0738e..aacd80fca3 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenter.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeoplePresenter.kt @@ -1,18 +1,18 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.addpeople +package io.element.android.features.startchat.impl.addpeople import androidx.compose.runtime.Composable -import io.element.android.features.createroom.impl.CreateRoomDataStore -import io.element.android.features.createroom.impl.userlist.SelectionMode -import io.element.android.features.createroom.impl.userlist.UserListPresenter -import io.element.android.features.createroom.impl.userlist.UserListPresenterArgs -import io.element.android.features.createroom.impl.userlist.UserListState +import io.element.android.features.startchat.impl.CreateRoomDataStore +import io.element.android.features.startchat.impl.userlist.SelectionMode +import io.element.android.features.startchat.impl.userlist.UserListPresenter +import io.element.android.features.startchat.impl.userlist.UserListPresenterArgs +import io.element.android.features.startchat.impl.userlist.UserListState import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.usersearch.api.UserRepository import javax.inject.Inject diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleUserListStateProvider.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleUserListStateProvider.kt similarity index 80% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleUserListStateProvider.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleUserListStateProvider.kt index 9e0ddd04c8..57b3a93d57 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleUserListStateProvider.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleUserListStateProvider.kt @@ -1,17 +1,17 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.addpeople +package io.element.android.features.startchat.impl.addpeople import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.features.createroom.impl.userlist.SelectionMode -import io.element.android.features.createroom.impl.userlist.UserListState -import io.element.android.features.createroom.impl.userlist.aRecentDirectRoomList -import io.element.android.features.createroom.impl.userlist.aUserListState +import io.element.android.features.startchat.impl.userlist.SelectionMode +import io.element.android.features.startchat.impl.userlist.UserListState +import io.element.android.features.startchat.impl.userlist.aRecentDirectRoomList +import io.element.android.features.startchat.impl.userlist.aUserListState import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.ui.components.aMatrixUserList import io.element.android.libraries.usersearch.api.UserSearchResult diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleView.kt similarity index 85% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleView.kt index d39ac4d250..ac457955d5 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleView.kt @@ -1,11 +1,11 @@ /* - * Copyright 2022-2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.addpeople +package io.element.android.features.startchat.impl.addpeople import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.fillMaxSize @@ -15,10 +15,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter -import io.element.android.features.createroom.impl.R -import io.element.android.features.createroom.impl.components.UserListView -import io.element.android.features.createroom.impl.userlist.UserListEvents -import io.element.android.features.createroom.impl.userlist.UserListState +import io.element.android.features.startchat.impl.R +import io.element.android.features.startchat.impl.components.UserListView +import io.element.android.features.startchat.impl.userlist.UserListEvents +import io.element.android.features.startchat.impl.userlist.UserListState import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -31,7 +31,7 @@ import io.element.android.libraries.ui.strings.CommonStrings fun AddPeopleView( state: UserListState, onBackClick: () -> Unit, - onNextClick: () -> Unit, + onSkipClick: () -> Unit, modifier: Modifier = Modifier, ) { Scaffold( @@ -46,7 +46,7 @@ fun AddPeopleView( onBackClick() } }, - onNextClick = onNextClick, + onNextClick = onSkipClick, ) } ) { padding -> @@ -89,6 +89,6 @@ internal fun AddPeopleViewPreview(@PreviewParameter(AddPeopleUserListStateProvid AddPeopleView( state = state, onBackClick = {}, - onNextClick = {}, + onSkipClick = {}, ) } diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/SearchMultipleUsersResultItem.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/SearchMultipleUsersResultItem.kt similarity index 98% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/SearchMultipleUsersResultItem.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/SearchMultipleUsersResultItem.kt index af12895fff..867ac9d918 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/SearchMultipleUsersResultItem.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/SearchMultipleUsersResultItem.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.components +package io.element.android.features.startchat.impl.components import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/SearchSingleUserResultItem.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/SearchSingleUserResultItem.kt similarity index 97% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/SearchSingleUserResultItem.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/SearchSingleUserResultItem.kt index eb922f1ae3..bd94d136af 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/SearchSingleUserResultItem.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/SearchSingleUserResultItem.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.components +package io.element.android.features.startchat.impl.components import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/SearchUserBar.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/SearchUserBar.kt similarity index 98% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/SearchUserBar.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/SearchUserBar.kt index 290c1aff0c..3d42c40067 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/SearchUserBar.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/SearchUserBar.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.components +package io.element.android.features.startchat.impl.components import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.Spring diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/UserListView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/UserListView.kt similarity index 94% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/UserListView.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/UserListView.kt index a660480258..753bebec83 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/components/UserListView.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/components/UserListView.kt @@ -1,11 +1,11 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.components +package io.element.android.features.startchat.impl.components import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues @@ -16,9 +16,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp -import io.element.android.features.createroom.impl.userlist.UserListEvents -import io.element.android.features.createroom.impl.userlist.UserListState -import io.element.android.features.createroom.impl.userlist.UserListStateProvider +import io.element.android.features.startchat.impl.userlist.UserListEvents +import io.element.android.features.startchat.impl.userlist.UserListState +import io.element.android.features.startchat.impl.userlist.UserListStateProvider import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomEvents.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomEvents.kt new file mode 100644 index 0000000000..13ce502559 --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomEvents.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.ui.media.AvatarAction + +sealed interface ConfigureRoomEvents { + data class RoomNameChanged(val name: String) : ConfigureRoomEvents + data class TopicChanged(val topic: String) : ConfigureRoomEvents + data class RoomVisibilityChanged(val visibilityItem: RoomVisibilityItem) : ConfigureRoomEvents + data class RoomAccessChanged(val roomAccess: RoomAccessItem) : ConfigureRoomEvents + data class RoomAddressChanged(val roomAddress: String) : ConfigureRoomEvents + data class RemoveUserFromSelection(val matrixUser: MatrixUser) : ConfigureRoomEvents + data object CreateRoom : ConfigureRoomEvents + data class HandleAvatarAction(val action: AvatarAction) : ConfigureRoomEvents + data object CancelCreateRoom : ConfigureRoomEvents +} diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomNode.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomNode.kt new file mode 100644 index 0000000000..3251fbff8d --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomNode.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.lifecycle.subscribe +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.bumble.appyx.core.plugin.plugins +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import im.vector.app.features.analytics.plan.MobileScreen +import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.startchat.StartChatNavigator +import io.element.android.features.startchat.impl.di.CreateRoomScope +import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias +import io.element.android.services.analytics.api.AnalyticsService + +@ContributesNode(CreateRoomScope::class) +class ConfigureRoomNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + private val presenter: ConfigureRoomPresenter, + private val analyticsService: AnalyticsService, +) : Node(buildContext, plugins = plugins) { + private val navigator = plugins().first() + + init { + lifecycle.subscribe( + onResume = { + analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.CreateRoom)) + } + ) + } + + @Composable + override fun View(modifier: Modifier) { + val state = presenter.present() + ConfigureRoomView( + state = state, + modifier = modifier, + onBackClick = this::navigateUp, + onCreateRoomSuccess = { + navigator.onOpenRoom(roomIdOrAlias = it.toRoomIdOrAlias(), serverNames = emptyList()) + }, + ) + } +} diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomPresenter.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomPresenter.kt new file mode 100644 index 0000000000..a715bf568d --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomPresenter.kt @@ -0,0 +1,209 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +import android.net.Uri +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import im.vector.app.features.analytics.plan.CreatedRoom +import io.element.android.features.startchat.impl.CreateRoomConfig +import io.element.android.features.startchat.impl.CreateRoomDataStore +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.architecture.runCatchingUpdatingState +import io.element.android.libraries.core.mimetype.MimeTypes +import io.element.android.libraries.featureflag.api.FeatureFlagService +import io.element.android.libraries.featureflag.api.FeatureFlags +import io.element.android.libraries.matrix.api.MatrixClient +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters +import io.element.android.libraries.matrix.api.createroom.RoomPreset +import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper +import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility +import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility +import io.element.android.libraries.matrix.ui.media.AvatarAction +import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity +import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidityEffect +import io.element.android.libraries.mediapickers.api.PickerProvider +import io.element.android.libraries.mediaupload.api.MediaPreProcessor +import io.element.android.libraries.permissions.api.PermissionsEvents +import io.element.android.libraries.permissions.api.PermissionsPresenter +import io.element.android.services.analytics.api.AnalyticsService +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import timber.log.Timber +import javax.inject.Inject +import kotlin.jvm.optionals.getOrDefault + +class ConfigureRoomPresenter @Inject constructor( + private val dataStore: CreateRoomDataStore, + private val matrixClient: MatrixClient, + private val mediaPickerProvider: PickerProvider, + private val mediaPreProcessor: MediaPreProcessor, + private val analyticsService: AnalyticsService, + permissionsPresenterFactory: PermissionsPresenter.Factory, + private val featureFlagService: FeatureFlagService, + private val roomAliasHelper: RoomAliasHelper, +) : Presenter { + private val cameraPermissionPresenter: PermissionsPresenter = permissionsPresenterFactory.create(android.Manifest.permission.CAMERA) + private var pendingPermissionRequest = false + + @Composable + override fun present(): ConfigureRoomState { + val cameraPermissionState = cameraPermissionPresenter.present() + val createRoomConfig by dataStore.createRoomConfigWithInvites.collectAsState(CreateRoomConfig()) + val homeserverName = remember { matrixClient.userIdServerName() } + val isKnockFeatureEnabled by remember { + featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock) + }.collectAsState(initial = false) + val roomAddressValidity = remember { + mutableStateOf(RoomAddressValidity.Unknown) + } + + val cameraPhotoPicker = mediaPickerProvider.registerCameraPhotoPicker( + onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri, cached = true) }, + ) + val galleryImagePicker = mediaPickerProvider.registerGalleryImagePicker( + onResult = { uri -> if (uri != null) dataStore.setAvatarUri(uri = uri) } + ) + + val avatarActions by remember(createRoomConfig.avatarUri) { + derivedStateOf { + listOfNotNull( + AvatarAction.TakePhoto, + AvatarAction.ChoosePhoto, + AvatarAction.Remove.takeIf { createRoomConfig.avatarUri != null }, + ).toImmutableList() + } + } + + LaunchedEffect(cameraPermissionState.permissionGranted) { + if (cameraPermissionState.permissionGranted && pendingPermissionRequest) { + pendingPermissionRequest = false + cameraPhotoPicker.launch() + } + } + + RoomAddressValidityEffect( + client = matrixClient, + roomAliasHelper = roomAliasHelper, + newRoomAddress = createRoomConfig.roomVisibility.roomAddress().getOrDefault(""), + knownRoomAddress = null, + ) { newRoomAddressValidity -> + roomAddressValidity.value = newRoomAddressValidity + } + + val localCoroutineScope = rememberCoroutineScope() + val createRoomAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } + + fun createRoom(config: CreateRoomConfig) { + createRoomAction.value = AsyncAction.Uninitialized + localCoroutineScope.createRoom(config, createRoomAction) + } + + fun handleEvents(event: ConfigureRoomEvents) { + when (event) { + is ConfigureRoomEvents.RoomNameChanged -> dataStore.setRoomName(event.name) + is ConfigureRoomEvents.TopicChanged -> dataStore.setTopic(event.topic) + is ConfigureRoomEvents.RoomVisibilityChanged -> dataStore.setRoomVisibility(event.visibilityItem) + is ConfigureRoomEvents.RemoveUserFromSelection -> dataStore.selectedUserListDataStore.removeUserFromSelection(event.matrixUser) + is ConfigureRoomEvents.RoomAccessChanged -> dataStore.setRoomAccess(event.roomAccess) + is ConfigureRoomEvents.RoomAddressChanged -> dataStore.setRoomAddress(event.roomAddress) + is ConfigureRoomEvents.CreateRoom -> createRoom(createRoomConfig) + is ConfigureRoomEvents.HandleAvatarAction -> { + when (event.action) { + AvatarAction.ChoosePhoto -> galleryImagePicker.launch() + AvatarAction.TakePhoto -> if (cameraPermissionState.permissionGranted) { + cameraPhotoPicker.launch() + } else { + pendingPermissionRequest = true + cameraPermissionState.eventSink(PermissionsEvents.RequestPermissions) + } + AvatarAction.Remove -> dataStore.setAvatarUri(uri = null) + } + } + + ConfigureRoomEvents.CancelCreateRoom -> createRoomAction.value = AsyncAction.Uninitialized + } + } + + return ConfigureRoomState( + isKnockFeatureEnabled = isKnockFeatureEnabled, + config = createRoomConfig, + avatarActions = avatarActions, + createRoomAction = createRoomAction.value, + cameraPermissionState = cameraPermissionState, + homeserverName = homeserverName, + roomAddressValidity = roomAddressValidity.value, + eventSink = ::handleEvents, + ) + } + + private fun CoroutineScope.createRoom( + config: CreateRoomConfig, + createRoomAction: MutableState> + ) = launch { + suspend { + val avatarUrl = config.avatarUri?.let { uploadAvatar(it) } + val params = if (config.roomVisibility is RoomVisibilityState.Public) { + CreateRoomParameters( + name = config.roomName, + topic = config.topic, + isEncrypted = false, + isDirect = false, + visibility = RoomVisibility.Public, + joinRuleOverride = config.roomVisibility.roomAccess.toJoinRule(), + preset = RoomPreset.PUBLIC_CHAT, + invite = config.invites.map { it.userId }, + avatar = avatarUrl, + roomAliasName = config.roomVisibility.roomAddress() + ) + } else { + CreateRoomParameters( + name = config.roomName, + topic = config.topic, + isEncrypted = config.roomVisibility is RoomVisibilityState.Private, + isDirect = false, + visibility = RoomVisibility.Private, + historyVisibilityOverride = RoomHistoryVisibility.Invited, + preset = RoomPreset.PRIVATE_CHAT, + invite = config.invites.map { it.userId }, + avatar = avatarUrl, + ) + } + matrixClient.createRoom(params) + .onFailure { failure -> + Timber.e(failure, "Failed to create room") + } + .onSuccess { + dataStore.clearCachedData() + analyticsService.capture(CreatedRoom(isDM = false)) + } + .getOrThrow() + }.runCatchingUpdatingState(createRoomAction) + } + + private suspend fun uploadAvatar(avatarUri: Uri): String { + val preprocessed = mediaPreProcessor.process( + uri = avatarUri, + mimeType = MimeTypes.Jpeg, + deleteOriginal = false, + compressIfPossible = false, + ).getOrThrow() + val byteArray = preprocessed.file.readBytes() + return matrixClient.uploadMedia(MimeTypes.Jpeg, byteArray, null).getOrThrow() + } +} diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomPresenterArgs.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomPresenterArgs.kt new file mode 100644 index 0000000000..2ee98b2a35 --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomPresenterArgs.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +import io.element.android.libraries.matrix.api.user.MatrixUser + +data class ConfigureRoomPresenterArgs( + val selectedUsers: List, +) diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomState.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomState.kt new file mode 100644 index 0000000000..e94066caed --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomState.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +import io.element.android.features.startchat.impl.CreateRoomConfig +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.ui.media.AvatarAction +import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity +import io.element.android.libraries.permissions.api.PermissionsState +import kotlinx.collections.immutable.ImmutableList + +data class ConfigureRoomState( + val isKnockFeatureEnabled: Boolean, + val config: CreateRoomConfig, + val avatarActions: ImmutableList, + val createRoomAction: AsyncAction, + val cameraPermissionState: PermissionsState, + val roomAddressValidity: RoomAddressValidity, + val homeserverName: String, + val eventSink: (ConfigureRoomEvents) -> Unit +) { + val isValid: Boolean = config.roomName?.isNotEmpty() == true && + (config.roomVisibility is RoomVisibilityState.Private || roomAddressValidity == RoomAddressValidity.Valid) +} diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomStateProvider.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomStateProvider.kt new file mode 100644 index 0000000000..09d801440b --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomStateProvider.kt @@ -0,0 +1,102 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.features.startchat.impl.CreateRoomConfig +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.ui.components.aMatrixUserList +import io.element.android.libraries.matrix.ui.media.AvatarAction +import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity +import io.element.android.libraries.permissions.api.PermissionsState +import io.element.android.libraries.permissions.api.aPermissionsState +import kotlinx.collections.immutable.toImmutableList + +open class ConfigureRoomStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + aConfigureRoomState(), + aConfigureRoomState( + isKnockFeatureEnabled = false, + config = CreateRoomConfig( + roomName = "Room 101", + topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines", + invites = aMatrixUserList().toImmutableList(), + roomVisibility = RoomVisibilityState.Public( + roomAddress = RoomAddress.AutoFilled("Room-101"), + roomAccess = RoomAccess.Knocking, + ), + ), + ), + aConfigureRoomState( + config = CreateRoomConfig( + roomName = "Room 101", + topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines", + invites = aMatrixUserList().toImmutableList(), + roomVisibility = RoomVisibilityState.Public( + roomAddress = RoomAddress.AutoFilled("Room-101"), + roomAccess = RoomAccess.Knocking, + ), + ), + ), + aConfigureRoomState( + config = CreateRoomConfig( + roomName = "Room 101", + topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines", + roomVisibility = RoomVisibilityState.Public( + roomAddress = RoomAddress.AutoFilled("Room-101"), + roomAccess = RoomAccess.Knocking, + ), + ), + roomAddressValidity = RoomAddressValidity.NotAvailable, + ), + aConfigureRoomState( + config = CreateRoomConfig( + roomName = "Room 101", + topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines", + roomVisibility = RoomVisibilityState.Public( + roomAddress = RoomAddress.AutoFilled("Room-101"), + roomAccess = RoomAccess.Knocking, + ), + ), + roomAddressValidity = RoomAddressValidity.InvalidSymbols, + ), + aConfigureRoomState( + config = CreateRoomConfig( + roomName = "Room 101", + topic = "Room topic for this room when the text goes onto multiple lines and is really long, there shouldn’t be more than 3 lines", + roomVisibility = RoomVisibilityState.Public( + roomAddress = RoomAddress.AutoFilled("Room-101"), + roomAccess = RoomAccess.Knocking, + ), + ), + roomAddressValidity = RoomAddressValidity.Valid, + ), + ) +} + +fun aConfigureRoomState( + config: CreateRoomConfig = CreateRoomConfig(), + isKnockFeatureEnabled: Boolean = true, + avatarActions: List = emptyList(), + createRoomAction: AsyncAction = AsyncAction.Uninitialized, + cameraPermissionState: PermissionsState = aPermissionsState(showDialog = false), + homeserverName: String = "matrix.org", + roomAddressValidity: RoomAddressValidity = RoomAddressValidity.Valid, + eventSink: (ConfigureRoomEvents) -> Unit = { }, +) = ConfigureRoomState( + config = config, + isKnockFeatureEnabled = isKnockFeatureEnabled, + avatarActions = avatarActions.toImmutableList(), + createRoomAction = createRoomAction, + cameraPermissionState = cameraPermissionState, + homeserverName = homeserverName, + roomAddressValidity = roomAddressValidity, + eventSink = eventSink, +) diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomView.kt new file mode 100644 index 0000000000..c056570913 --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureRoomView.kt @@ -0,0 +1,339 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +import android.net.Uri +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.selection.selectableGroup +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardCapitalization +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import io.element.android.compound.theme.ElementTheme +import io.element.android.features.startchat.impl.R +import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage +import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtom +import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtomSize +import io.element.android.libraries.designsystem.components.async.AsyncActionView +import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.AvatarType +import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.components.list.ListItemContent +import io.element.android.libraries.designsystem.modifiers.clearFocusOnTap +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight +import io.element.android.libraries.designsystem.theme.components.ListItem +import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TextButton +import io.element.android.libraries.designsystem.theme.components.TextField +import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet +import io.element.android.libraries.matrix.ui.components.SelectedUsersRowList +import io.element.android.libraries.matrix.ui.components.UnsavedAvatar +import io.element.android.libraries.matrix.ui.room.address.RoomAddressField +import io.element.android.libraries.permissions.api.PermissionsView +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun ConfigureRoomView( + state: ConfigureRoomState, + onBackClick: () -> Unit, + onCreateRoomSuccess: (RoomId) -> Unit, + modifier: Modifier = Modifier, +) { + val focusManager = LocalFocusManager.current + val isAvatarActionsSheetVisible = remember { mutableStateOf(false) } + + fun onAvatarClick() { + focusManager.clearFocus() + isAvatarActionsSheetVisible.value = true + } + + Scaffold( + modifier = modifier.clearFocusOnTap(focusManager), + topBar = { + ConfigureRoomToolbar( + isNextActionEnabled = state.isValid, + onBackClick = onBackClick, + onNextClick = { + focusManager.clearFocus() + state.eventSink(ConfigureRoomEvents.CreateRoom) + }, + ) + } + ) { padding -> + Column( + modifier = Modifier + .padding(padding) + .imePadding() + .verticalScroll(rememberScrollState()) + .consumeWindowInsets(padding), + verticalArrangement = Arrangement.spacedBy(24.dp), + ) { + RoomNameWithAvatar( + modifier = Modifier.padding(horizontal = 16.dp), + avatarUri = state.config.avatarUri, + roomName = state.config.roomName.orEmpty(), + onAvatarClick = ::onAvatarClick, + onChangeRoomName = { state.eventSink(ConfigureRoomEvents.RoomNameChanged(it)) }, + ) + RoomTopic( + modifier = Modifier.padding(horizontal = 16.dp), + topic = state.config.topic.orEmpty(), + onTopicChange = { state.eventSink(ConfigureRoomEvents.TopicChanged(it)) }, + ) + if (state.config.invites.isNotEmpty()) { + SelectedUsersRowList( + contentPadding = PaddingValues(horizontal = 24.dp), + selectedUsers = state.config.invites, + onUserRemove = { + focusManager.clearFocus() + state.eventSink(ConfigureRoomEvents.RemoveUserFromSelection(it)) + }, + ) + } + RoomVisibilityOptions( + selected = when (state.config.roomVisibility) { + is RoomVisibilityState.Private -> RoomVisibilityItem.Private + is RoomVisibilityState.Public -> RoomVisibilityItem.Public + }, + onOptionClick = { + focusManager.clearFocus() + state.eventSink(ConfigureRoomEvents.RoomVisibilityChanged(it)) + }, + ) + if (state.config.roomVisibility is RoomVisibilityState.Public && state.isKnockFeatureEnabled) { + RoomAccessOptions( + selected = when (state.config.roomVisibility.roomAccess) { + RoomAccess.Anyone -> RoomAccessItem.Anyone + RoomAccess.Knocking -> RoomAccessItem.AskToJoin + }, + onOptionClick = { + focusManager.clearFocus() + state.eventSink(ConfigureRoomEvents.RoomAccessChanged(it)) + }, + ) + RoomAddressField( + modifier = Modifier.padding(horizontal = 16.dp), + address = state.config.roomVisibility.roomAddress.value, + homeserverName = state.homeserverName, + addressValidity = state.roomAddressValidity, + onAddressChange = { state.eventSink(ConfigureRoomEvents.RoomAddressChanged(it)) }, + label = stringResource(R.string.screen_create_room_room_address_section_title), + supportingText = stringResource(R.string.screen_create_room_room_address_section_footer), + ) + Spacer(Modifier) + } + } + } + + AvatarActionBottomSheet( + actions = state.avatarActions, + isVisible = isAvatarActionsSheetVisible.value, + onDismiss = { isAvatarActionsSheetVisible.value = false }, + onSelectAction = { state.eventSink(ConfigureRoomEvents.HandleAvatarAction(it)) } + ) + + AsyncActionView( + async = state.createRoomAction, + progressDialog = { + AsyncActionViewDefaults.ProgressDialog( + progressText = stringResource(CommonStrings.common_creating_room), + ) + }, + onSuccess = { onCreateRoomSuccess(it) }, + errorMessage = { stringResource(R.string.screen_create_room_error_creating_room) }, + onRetry = { state.eventSink(ConfigureRoomEvents.CreateRoom) }, + onErrorDismiss = { state.eventSink(ConfigureRoomEvents.CancelCreateRoom) }, + ) + + PermissionsView( + state = state.cameraPermissionState, + ) +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun ConfigureRoomToolbar( + isNextActionEnabled: Boolean, + onBackClick: () -> Unit, + onNextClick: () -> Unit, +) { + TopAppBar( + titleStr = stringResource(R.string.screen_create_room_title), + navigationIcon = { BackButton(onClick = onBackClick) }, + actions = { + TextButton( + text = stringResource(CommonStrings.action_create), + enabled = isNextActionEnabled, + onClick = onNextClick, + ) + } + ) +} + +@Composable +private fun RoomNameWithAvatar( + avatarUri: Uri?, + roomName: String, + onAvatarClick: () -> Unit, + onChangeRoomName: (String) -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + UnsavedAvatar( + avatarUri = avatarUri, + avatarSize = AvatarSize.EditRoomDetails, + avatarType = AvatarType.Room(), + modifier = Modifier.clickable(onClick = onAvatarClick), + ) + + TextField( + label = stringResource(R.string.screen_create_room_room_name_label), + value = roomName, + placeholder = stringResource(CommonStrings.common_room_name_placeholder), + singleLine = true, + onValueChange = onChangeRoomName, + ) + } +} + +@Composable +private fun RoomTopic( + topic: String, + onTopicChange: (String) -> Unit, + modifier: Modifier = Modifier, +) { + TextField( + modifier = modifier, + label = stringResource(R.string.screen_create_room_topic_label), + value = topic, + onValueChange = onTopicChange, + maxLines = 3, + supportingText = stringResource(CommonStrings.common_topic_placeholder), + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.Sentences, + ), + ) +} + +@Composable +private fun ConfigureRoomOptions( + title: String, + modifier: Modifier = Modifier, + content: @Composable ColumnScope.() -> Unit, +) { + Column( + modifier = modifier.selectableGroup() + ) { + Text( + text = title, + style = ElementTheme.typography.fontBodyLgMedium, + color = ElementTheme.colors.textPrimary, + modifier = Modifier.padding(horizontal = 16.dp), + ) + content() + } +} + +@Composable +private fun RoomVisibilityOptions( + selected: RoomVisibilityItem, + onOptionClick: (RoomVisibilityItem) -> Unit, + modifier: Modifier = Modifier, +) { + ConfigureRoomOptions( + title = stringResource(R.string.screen_create_room_room_visibility_section_title), + modifier = modifier, + ) { + RoomVisibilityItem.entries.forEach { item -> + val isSelected = item == selected + ListItem( + leadingContent = ListItemContent.Custom { + RoundedIconAtom( + size = RoundedIconAtomSize.Big, + resourceId = item.icon, + tint = if (isSelected) ElementTheme.colors.iconPrimary else ElementTheme.colors.iconSecondary, + ) + }, + headlineContent = { Text(text = stringResource(item.title)) }, + supportingContent = { Text(text = stringResource(item.description)) }, + trailingContent = ListItemContent.RadioButton(selected = isSelected), + onClick = { onOptionClick(item) }, + ) + } + } +} + +@Composable +private fun RoomAccessOptions( + selected: RoomAccessItem, + onOptionClick: (RoomAccessItem) -> Unit, + modifier: Modifier = Modifier, +) { + ConfigureRoomOptions( + title = stringResource(R.string.screen_create_room_room_access_section_header), + modifier = modifier, + ) { + RoomAccessItem.entries.forEach { item -> + ListItem( + headlineContent = { Text(text = stringResource(item.title)) }, + supportingContent = { Text(text = stringResource(item.description)) }, + trailingContent = ListItemContent.RadioButton(selected = item == selected), + onClick = { onOptionClick(item) }, + ) + } + } +} + +@PreviewWithLargeHeight +@Composable +internal fun ConfigureRoomViewLightPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) = + ElementPreviewLight { ContentToPreview(state) } + +@PreviewWithLargeHeight +@Composable +internal fun ConfigureRoomViewDarkPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) = + ElementPreviewDark { ContentToPreview(state) } + +@ExcludeFromCoverage +@Composable +private fun ContentToPreview(state: ConfigureRoomState) { + ConfigureRoomView( + state = state, + onBackClick = {}, + onCreateRoomSuccess = {}, + ) +} diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAccess.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAccess.kt new file mode 100644 index 0000000000..bf75d9605e --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAccess.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +import io.element.android.libraries.matrix.api.room.join.JoinRule + +enum class RoomAccess { + Anyone, + Knocking +} + +fun RoomAccess.toJoinRule(): JoinRule? { + return when (this) { + RoomAccess.Anyone -> null + RoomAccess.Knocking -> JoinRule.Knock + } +} diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAccessItem.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAccessItem.kt new file mode 100644 index 0000000000..0a48afe849 --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAccessItem.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +import androidx.annotation.StringRes +import io.element.android.features.startchat.impl.R + +enum class RoomAccessItem( + @StringRes val title: Int, + @StringRes val description: Int +) { + Anyone( + title = R.string.screen_create_room_room_access_section_anyone_option_title, + description = R.string.screen_create_room_room_access_section_anyone_option_description, + ), + AskToJoin( + title = R.string.screen_create_room_room_access_section_knocking_option_title, + description = R.string.screen_create_room_room_access_section_knocking_option_description, + ), +} diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAddress.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAddress.kt new file mode 100644 index 0000000000..51e02d881a --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomAddress.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +sealed class RoomAddress(open val value: String) { + data class AutoFilled(override val value: String) : RoomAddress(value) + data class Edited(override val value: String) : RoomAddress(value) +} diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomVisibilityItem.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomVisibilityItem.kt new file mode 100644 index 0000000000..4ca8b51601 --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomVisibilityItem.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import io.element.android.features.startchat.impl.R +import io.element.android.libraries.designsystem.icons.CompoundDrawables + +enum class RoomVisibilityItem( + @DrawableRes val icon: Int, + @StringRes val title: Int, + @StringRes val description: Int +) { + Private( + icon = CompoundDrawables.ic_compound_lock, + title = R.string.screen_create_room_private_option_title, + description = R.string.screen_create_room_private_option_description, + ), + Public( + icon = CompoundDrawables.ic_compound_public, + title = R.string.screen_create_room_public_option_title, + description = R.string.screen_create_room_public_option_description, + ) +} diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomVisibilityState.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomVisibilityState.kt new file mode 100644 index 0000000000..5a9a3126f6 --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/configureroom/RoomVisibilityState.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2023, 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.configureroom + +import java.util.Optional + +sealed interface RoomVisibilityState { + data object Private : RoomVisibilityState + + data class Public( + val roomAddress: RoomAddress, + val roomAccess: RoomAccess, + ) : RoomVisibilityState + + fun roomAddress(): Optional { + return when (this) { + is Private -> Optional.empty() + is Public -> Optional.of(roomAddress.value) + } + } +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/di/CreateRoomComponent.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/di/CreateRoomComponent.kt similarity index 93% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/di/CreateRoomComponent.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/di/CreateRoomComponent.kt index b47b8c30e5..6f6569bcb3 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/di/CreateRoomComponent.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/di/CreateRoomComponent.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.di +package io.element.android.features.startchat.impl.di import com.squareup.anvil.annotations.ContributesTo import com.squareup.anvil.annotations.MergeSubcomponent diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/di/CreateRoomScope.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/di/CreateRoomScope.kt similarity index 81% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/di/CreateRoomScope.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/di/CreateRoomScope.kt index b0a011424a..a164ba50b8 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/di/CreateRoomScope.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/di/CreateRoomScope.kt @@ -5,6 +5,6 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.di +package io.element.android.features.startchat.impl.di abstract class CreateRoomScope private constructor() diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressEvents.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressEvents.kt similarity index 86% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressEvents.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressEvents.kt index dbbcef56fa..648146fbd7 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressEvents.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressEvents.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.joinbyaddress +package io.element.android.features.startchat.impl.joinbyaddress sealed interface JoinRoomByAddressEvents { data object Dismiss : JoinRoomByAddressEvents diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressNode.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressNode.kt similarity index 85% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressNode.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressNode.kt index d6338ab43c..67dba8b46e 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressNode.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressNode.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.joinbyaddress +package io.element.android.features.startchat.impl.joinbyaddress import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -16,7 +16,7 @@ import com.bumble.appyx.core.plugin.plugins import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode -import io.element.android.features.createroom.CreateRoomNavigator +import io.element.android.features.startchat.StartChatNavigator import io.element.android.libraries.di.SessionScope @ContributesNode(SessionScope::class) @@ -25,7 +25,7 @@ class JoinRoomByAddressNode @AssistedInject constructor( @Assisted plugins: List, presenterFactory: JoinRoomByAddressPresenter.Factory, ) : Node(buildContext, plugins = plugins) { - private val navigator = plugins().first() + private val navigator = plugins().first() private val presenter = presenterFactory.create(navigator) @Composable diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressPresenter.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressPresenter.kt similarity index 95% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressPresenter.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressPresenter.kt index cf4788cbbf..4e1f9f9ab0 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressPresenter.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressPresenter.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.joinbyaddress +package io.element.android.features.startchat.impl.joinbyaddress import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -18,7 +18,7 @@ import androidx.compose.runtime.setValue import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import io.element.android.features.createroom.CreateRoomNavigator +import io.element.android.features.startchat.StartChatNavigator import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.data.tryOrNull import io.element.android.libraries.matrix.api.MatrixClient @@ -32,13 +32,13 @@ import kotlin.time.Duration.Companion.seconds private const val ADDRESS_RESOLVE_TIMEOUT_IN_SECONDS = 10 class JoinRoomByAddressPresenter @AssistedInject constructor( - @Assisted private val navigator: CreateRoomNavigator, + @Assisted private val navigator: StartChatNavigator, private val client: MatrixClient, private val roomAliasHelper: RoomAliasHelper, ) : Presenter { @AssistedFactory interface Factory { - fun create(navigator: CreateRoomNavigator): JoinRoomByAddressPresenter + fun create(navigator: StartChatNavigator): JoinRoomByAddressPresenter } @Composable diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressState.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressState.kt similarity index 92% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressState.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressState.kt index 11791181e1..84b01ac263 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressState.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressState.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.joinbyaddress +package io.element.android.features.startchat.impl.joinbyaddress import androidx.compose.runtime.Immutable import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressStateProvider.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressStateProvider.kt similarity index 95% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressStateProvider.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressStateProvider.kt index 6281a8e8e3..847ca78837 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressStateProvider.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressStateProvider.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.joinbyaddress +package io.element.android.features.startchat.impl.joinbyaddress import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.matrix.api.core.RoomId diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressView.kt similarity index 97% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressView.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressView.kt index c256f5140c..2d34dcc1cf 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinRoomByAddressView.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinRoomByAddressView.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.joinbyaddress +package io.element.android.features.startchat.impl.joinbyaddress import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -29,7 +29,7 @@ import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp -import io.element.android.features.createroom.impl.R +import io.element.android.features.startchat.impl.R import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.theme.components.Button diff --git a/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatEvents.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatEvents.kt new file mode 100644 index 0000000000..6ea72d8b05 --- /dev/null +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatEvents.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl.root + +import io.element.android.libraries.matrix.api.user.MatrixUser + +sealed interface StartChatEvents { + data class StartDM(val matrixUser: MatrixUser) : StartChatEvents + data object CancelStartDM : StartChatEvents +} diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootNode.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatNode.kt similarity index 87% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootNode.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatNode.kt index f76a5d5c61..29a13d2fa4 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootNode.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatNode.kt @@ -1,11 +1,11 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.root +package io.element.android.features.startchat.impl.root import android.app.Activity import androidx.activity.compose.LocalActivity @@ -20,21 +20,21 @@ import dagger.assisted.Assisted import dagger.assisted.AssistedInject import im.vector.app.features.analytics.plan.MobileScreen import io.element.android.anvilannotations.ContributesNode -import io.element.android.features.createroom.CreateRoomNavigator +import io.element.android.features.startchat.StartChatNavigator import io.element.android.libraries.deeplink.usecase.InviteFriendsUseCase import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias import io.element.android.services.analytics.api.AnalyticsService @ContributesNode(SessionScope::class) -class CreateRoomRootNode @AssistedInject constructor( +class StartChatNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, - private val presenter: CreateRoomRootPresenter, + private val presenter: StartChatPresenter, private val analyticsService: AnalyticsService, private val inviteFriendsUseCase: InviteFriendsUseCase, ) : Node(buildContext, plugins = plugins) { - private val navigator = plugins().first() + private val navigator = plugins().first() init { lifecycle.subscribe( diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt similarity index 73% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt index ea8be45e6b..9f7bea5c68 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootPresenter.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenter.kt @@ -1,11 +1,11 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.root +package io.element.android.features.startchat.impl.root import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState @@ -14,11 +14,11 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope -import io.element.android.features.createroom.api.StartDMAction -import io.element.android.features.createroom.impl.userlist.SelectionMode -import io.element.android.features.createroom.impl.userlist.UserListDataStore -import io.element.android.features.createroom.impl.userlist.UserListPresenter -import io.element.android.features.createroom.impl.userlist.UserListPresenterArgs +import io.element.android.features.startchat.api.StartDMAction +import io.element.android.features.startchat.impl.userlist.SelectionMode +import io.element.android.features.startchat.impl.userlist.UserListDataStore +import io.element.android.features.startchat.impl.userlist.UserListPresenter +import io.element.android.features.startchat.impl.userlist.UserListPresenterArgs import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildMeta @@ -29,14 +29,14 @@ import io.element.android.libraries.usersearch.api.UserRepository import kotlinx.coroutines.launch import javax.inject.Inject -class CreateRoomRootPresenter @Inject constructor( +class StartChatPresenter @Inject constructor( presenterFactory: UserListPresenter.Factory, userRepository: UserRepository, userListDataStore: UserListDataStore, private val startDMAction: StartDMAction, private val buildMeta: BuildMeta, private val featureFlagService: FeatureFlagService, -) : Presenter { +) : Presenter { private val presenter = presenterFactory.create( UserListPresenterArgs( selectionMode = SelectionMode.Single, @@ -46,7 +46,7 @@ class CreateRoomRootPresenter @Inject constructor( ) @Composable - override fun present(): CreateRoomRootState { + override fun present(): StartChatState { val userListState = presenter.present() val localCoroutineScope = rememberCoroutineScope() @@ -56,20 +56,20 @@ class CreateRoomRootPresenter @Inject constructor( featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomDirectorySearch) }.collectAsState(initial = false) - fun handleEvents(event: CreateRoomRootEvents) { + fun handleEvents(event: StartChatEvents) { when (event) { - is CreateRoomRootEvents.StartDM -> localCoroutineScope.launch { + is StartChatEvents.StartDM -> localCoroutineScope.launch { startDMAction.execute( matrixUser = event.matrixUser, createIfDmDoesNotExist = startDmActionState.value is AsyncAction.Confirming, actionState = startDmActionState, ) } - CreateRoomRootEvents.CancelStartDM -> startDmActionState.value = AsyncAction.Uninitialized + StartChatEvents.CancelStartDM -> startDmActionState.value = AsyncAction.Uninitialized } } - return CreateRoomRootState( + return StartChatState( applicationName = buildMeta.applicationName, userListState = userListState, startDmAction = startDmActionState.value, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootState.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt similarity index 63% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootState.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt index 7a6d651db3..724d6e5e88 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootState.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatState.kt @@ -1,20 +1,20 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.root +package io.element.android.features.startchat.impl.root -import io.element.android.features.createroom.impl.userlist.UserListState +import io.element.android.features.startchat.impl.userlist.UserListState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.RoomId -data class CreateRoomRootState( +data class StartChatState( val applicationName: String, val userListState: UserListState, val startDmAction: AsyncAction, val isRoomDirectorySearchEnabled: Boolean, - val eventSink: (CreateRoomRootEvents) -> Unit, + val eventSink: (StartChatEvents) -> Unit, ) diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootStateProvider.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt similarity index 82% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootStateProvider.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt index 9f2d59e3b6..1173425aa1 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootStateProvider.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatStateProvider.kt @@ -1,17 +1,17 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.root +package io.element.android.features.startchat.impl.root import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUser -import io.element.android.features.createroom.impl.userlist.UserListState -import io.element.android.features.createroom.impl.userlist.aRecentDirectRoomList -import io.element.android.features.createroom.impl.userlist.aUserListState +import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser +import io.element.android.features.startchat.impl.userlist.UserListState +import io.element.android.features.startchat.impl.userlist.aRecentDirectRoomList +import io.element.android.features.startchat.impl.userlist.aUserListState import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.api.core.RoomId @@ -19,8 +19,8 @@ import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.usersearch.api.UserSearchResult import kotlinx.collections.immutable.persistentListOf -open class CreateRoomRootStateProvider : PreviewParameterProvider { - override val values: Sequence +open class CreateRoomRootStateProvider : PreviewParameterProvider { + override val values: Sequence get() = sequenceOf( aCreateRoomRootState(), aCreateRoomRootState( @@ -64,8 +64,8 @@ fun aCreateRoomRootState( userListState: UserListState = aUserListState(), startDmAction: AsyncAction = AsyncAction.Uninitialized, isRoomDirectorySearchEnabled: Boolean = false, - eventSink: (CreateRoomRootEvents) -> Unit = {}, -) = CreateRoomRootState( + eventSink: (StartChatEvents) -> Unit = {}, +) = StartChatState( applicationName = applicationName, userListState = userListState, startDmAction = startDmAction, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt similarity index 90% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt index 248d331985..340e6a9134 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/root/StartChatView.kt @@ -1,11 +1,11 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.root +package io.element.android.features.startchat.impl.root import androidx.annotation.DrawableRes import androidx.compose.foundation.clickable @@ -27,9 +27,9 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUser -import io.element.android.features.createroom.impl.R -import io.element.android.features.createroom.impl.components.UserListView +import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser +import io.element.android.features.startchat.impl.R +import io.element.android.features.startchat.impl.components.UserListView import io.element.android.libraries.designsystem.components.async.AsyncActionView import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults import io.element.android.libraries.designsystem.components.button.BackButton @@ -49,7 +49,7 @@ import kotlinx.collections.immutable.persistentListOf @Composable fun CreateRoomRootView( - state: CreateRoomRootState, + state: StartChatState, onCloseClick: () -> Unit, onNewRoomClick: () -> Unit, onOpenDM: (RoomId) -> Unit, @@ -80,7 +80,7 @@ fun CreateRoomRootView( recentDirectRooms = persistentListOf(), ), onSelectUser = { - state.eventSink(CreateRoomRootEvents.StartDM(it)) + state.eventSink(StartChatEvents.StartDM(it)) }, onDeselectUser = { }, ) @@ -109,20 +109,20 @@ fun CreateRoomRootView( errorMessage = { stringResource(R.string.screen_start_chat_error_starting_chat) }, onRetry = { state.userListState.selectedUsers.firstOrNull() - ?.let { state.eventSink(CreateRoomRootEvents.StartDM(it)) } + ?.let { state.eventSink(StartChatEvents.StartDM(it)) } // Cancel start DM if there is no more selected user (should not happen) - ?: state.eventSink(CreateRoomRootEvents.CancelStartDM) + ?: state.eventSink(StartChatEvents.CancelStartDM) }, - onErrorDismiss = { state.eventSink(CreateRoomRootEvents.CancelStartDM) }, + onErrorDismiss = { state.eventSink(StartChatEvents.CancelStartDM) }, confirmationDialog = { data -> if (data is ConfirmingStartDmWithMatrixUser) { CreateDmConfirmationBottomSheet( matrixUser = data.matrixUser, onSendInvite = { - state.eventSink(CreateRoomRootEvents.StartDM(data.matrixUser)) + state.eventSink(StartChatEvents.StartDM(data.matrixUser)) }, onDismiss = { - state.eventSink(CreateRoomRootEvents.CancelStartDM) + state.eventSink(StartChatEvents.CancelStartDM) }, ) } @@ -148,7 +148,7 @@ private fun CreateRoomRootViewTopBar( @Composable private fun CreateRoomActionButtonsList( - state: CreateRoomRootState, + state: StartChatState, onNewRoomClick: () -> Unit, onInvitePeopleClick: () -> Unit, onJoinByAddressClick: () -> Unit, @@ -239,7 +239,7 @@ private fun CreateRoomActionButton( @PreviewsDayNight @Composable -internal fun CreateRoomRootViewPreview(@PreviewParameter(CreateRoomRootStateProvider::class) state: CreateRoomRootState) = +internal fun CreateRoomRootViewPreview(@PreviewParameter(CreateRoomRootStateProvider::class) state: StartChatState) = ElementPreview { CreateRoomRootView( state = state, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenter.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenter.kt similarity index 98% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenter.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenter.kt index 32d5767cc6..c964b18441 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenter.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenter.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.userlist +package io.element.android.features.startchat.impl.userlist import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListDataStore.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListDataStore.kt similarity index 93% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListDataStore.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListDataStore.kt index a500e3a05f..64048d7e86 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListDataStore.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListDataStore.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.userlist +package io.element.android.features.startchat.impl.userlist import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.coroutines.flow.MutableStateFlow diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListEvents.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListEvents.kt similarity index 90% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListEvents.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListEvents.kt index 45b40597da..794b2c18af 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListEvents.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListEvents.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.userlist +package io.element.android.features.startchat.impl.userlist import io.element.android.libraries.matrix.api.user.MatrixUser diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListPresenter.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListPresenter.kt similarity index 90% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListPresenter.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListPresenter.kt index 38f45d202f..a07b39a1e7 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListPresenter.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListPresenter.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.userlist +package io.element.android.features.startchat.impl.userlist import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.usersearch.api.UserRepository diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListPresenterArgs.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListPresenterArgs.kt similarity index 84% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListPresenterArgs.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListPresenterArgs.kt index 85cc58e995..d7e6a727f8 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListPresenterArgs.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListPresenterArgs.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.userlist +package io.element.android.features.startchat.impl.userlist data class UserListPresenterArgs( val selectionMode: SelectionMode, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListState.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListState.kt similarity index 94% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListState.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListState.kt index bed3ac7f63..2186bcb57a 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListState.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListState.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.userlist +package io.element.android.features.startchat.impl.userlist import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.api.room.recent.RecentDirectRoom diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListStateProvider.kt b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListStateProvider.kt similarity index 98% rename from features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListStateProvider.kt rename to features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListStateProvider.kt index 3b5918abc5..65b4efdadb 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/userlist/UserListStateProvider.kt +++ b/features/startchat/impl/src/main/kotlin/io/element/android/features/startchat/impl/userlist/UserListStateProvider.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.userlist +package io.element.android.features.startchat.impl.userlist import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.designsystem.theme.components.SearchBarResultState diff --git a/features/startchat/impl/src/main/res/values-be/translations.xml b/features/startchat/impl/src/main/res/values-be/translations.xml new file mode 100644 index 0000000000..8acb990b02 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-be/translations.xml @@ -0,0 +1,19 @@ + + + "Новы пакой" + "Запрасіць карыстальнікаў" + "Пры стварэнні пакоя адбылася памылка" + "Толькі запрошаныя людзі могуць атрымаць доступ да гэтага пакоя. Усе паведамленні абаронены end-to-end шыфраваннем." + "Прыватны пакой" + "Любы можа знайсці гэты пакой. +Вы можаце змяніць гэта ў любы час у наладах пакоя." + "Публічны пакой" + "Хто заўгодна" + "Доступ у пакой" + "Папрасіце далучыцца" + "Назва пакоя" + "Стварыце пакой" + "Тэма (неабавязкова)" + "Каталог пакояў" + "Пры спробе пачаць чат адбылася памылка" + diff --git a/features/startchat/impl/src/main/res/values-bg/translations.xml b/features/startchat/impl/src/main/res/values-bg/translations.xml new file mode 100644 index 0000000000..fa6dae371c --- /dev/null +++ b/features/startchat/impl/src/main/res/values-bg/translations.xml @@ -0,0 +1,23 @@ + + + "Нова стая" + "Поканване на хора" + "Възникна грешка при създаването на стаята" + "Само поканени хора имат достъп до тази стая. Всички съобщения са шифровани от край до край." + "Частна стая" + "Всеки може да намери тази стая. +Можете да промените това по всяко време в настройките на стаята." + "Общодостъпна стая" + "Всеки може да се присъедини към тази стая" + "Всеки" + "За да бъде тази стая видима в директорията на общодостъпните стаи, ще ви е необходим адрес на стаята." + "Име на стаята" + "Видимост на стаята" + "Създаване на стая" + "Тема за разговор (незадължително)" + "Присъединяване към стая по адрес" + "Не е валиден адрес" + "Въведете…" + "Стаята не е намерена" + "напр. #room-name:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-cs/translations.xml b/features/startchat/impl/src/main/res/values-cs/translations.xml new file mode 100644 index 0000000000..53592e0db0 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-cs/translations.xml @@ -0,0 +1,30 @@ + + + "Nová místnost" + "Pozvat přátele" + "Při vytváření místnosti došlo k chybě" + "Do této místnosti mají přístup pouze pozvaní lidé. Všechny zprávy jsou koncově šifrovány." + "Soukromá místnost" + "Tuto místnost může najít kdokoli. +To můžete kdykoli změnit v nastavení místnosti." + "Veřejná místnost" + "Do této místnosti může vstoupit kdokoli" + "Kdokoliv" + "Přístup do místnosti" + "Kdokoli může požádat o vstup do místnosti, ale správce nebo moderátor bude muset žádost přijmout" + "Požádat o připojení" + "Aby byla tato místnost viditelná v adresáři veřejných místností, budete potřebovat adresu místnosti." + "Adresa místnosti" + "Název místnosti" + "Viditelnost místnosti" + "Vytvořit místnost" + "Téma (nepovinné)" + "Adresář místností" + "Při pokusu o zahájení chatu došlo k chybě" + "Vstoupit do místnosti pomocí adresy" + "Neplatná adresa" + "Zadejte…" + "Odpovídající místnost nalezena" + "Místnost nebyla nalezena" + "např. #room-name:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-cy/translations.xml b/features/startchat/impl/src/main/res/values-cy/translations.xml new file mode 100644 index 0000000000..a3a9e30e35 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-cy/translations.xml @@ -0,0 +1,30 @@ + + + "Ystafell newydd" + "Gwahodd pobl" + "Bu gwall wrth greu\'r ystafell" + "Dim ond pobl wahoddwyd all gael mynediad i\'r ystafell hon. Mae pob neges wedi\'i hamgryptio o\'r dechrau i\'r diwedd." + "Ystafell breifat" + "Gall unrhyw un ddod o hyd i\'r ystafell hon. +Gallwch newid hyn unrhyw bryd yng ngosodiadau ystafell." + "Ystafell gyhoeddus" + "Gall unrhyw un ymuno â\'r ystafell hon" + "Unrhyw un" + "Mynediad i\'r Ystafell" + "Gall unrhyw un ofyn am gael ymuno â\'r ystafell ond bydd rhaid i weinyddwr neu gymedrolwr dderbyn y cais" + "Gofyn i gael ymuno" + "Er mwyn i\'r ystafell hon fod yn weladwy yn y cyfeiriadur ystafelloedd cyhoeddus, bydd angen cyfeiriad ystafell arnoch." + "Cyfeiriad yr ystafell" + "Enw\'r ystafell" + "Gwelededd yr ystafell" + "Creu ystafell" + "Pwnc (dewisol)" + "Cyfeiriadur ystafelloedd" + "Digwyddodd gwall wrth geisio cychwyn sgwrs" + "Ymuno â\'r ystafell yn ôl cyfeiriad" + "Ddim yn gyfeiriad dilys" + "Ewch i mewn…" + "Cafwyd hyd i ystafell gyfatebol" + "Heb ganfod yr ystafell" + "e.e. #enw-ystafell:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-da/translations.xml b/features/startchat/impl/src/main/res/values-da/translations.xml new file mode 100644 index 0000000000..c9c182b474 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-da/translations.xml @@ -0,0 +1,30 @@ + + + "Nyt rum" + "Invitér folk" + "Der opstod en fejl ved oprettelsen af rummet" + "Kun inviterede personer kan få adgang til dette rum. Alle meddelelser er ende-til-ende krypteret." + "Privat rum" + "Alle kan finde dette rum. +Du kan ændre dette når som helst i rummets indstillinger." + "Offentligt rum" + "Alle kan deltage i dette rum" + "Enhver" + "Adgang til rummet" + "Alle kan bede om at deltage i rummet, men en administrator eller en moderator skal acceptere anmodningen" + "Spørg om at deltage" + "Hvis dette rum skal være synligt i det offentlige register, skal du bruge en rum-adresse." + "Rummets adresse" + "Navn på rum" + "Rummets synlighed" + "Opret et rum" + "Emne (valgfrit)" + "Register over rum" + "Der opstod en fejl under forsøget på at starte en samtale" + "Tilslut dig rummet med adressen" + "Ikke en gyldig adresse" + "Indtast…" + "Matchende rum fundet" + "Rum ikke fundet" + "f.eks. #rummets-navn:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-de/translations.xml b/features/startchat/impl/src/main/res/values-de/translations.xml new file mode 100644 index 0000000000..90438aa38c --- /dev/null +++ b/features/startchat/impl/src/main/res/values-de/translations.xml @@ -0,0 +1,30 @@ + + + "Neuer Raum" + "Nutzer einladen" + "Beim Erstellen des Chats ist ein Fehler aufgetreten" + "Nur eingeladene Personen haben Zutritt zu diesem Chatroom. Alle Nachrichten sind Ende-zu-Ende verschlüsselt." + "Privater Chatroom" + "Alle können diesen Chatroom finden. +Sie können dies aber jederzeit in den Chatroomeinstellungen ändern." + "Öffentlicher Raum" + "Jeder darf diesen Raum betreten" + "Jeder" + "Chatroomzugang" + "Jeder kann den Zutritt zum Raum beantragen, aber ein Moderator muss die Anfrage akzeptieren." + "Beitritt beantragen" + "Damit dieser Chatroom im öffentlichen Chatroomverzeichnis sichtbar ist, benötigen Sie eine Chatroomadresse." + "Chatroomadresse" + "Raumname" + " Sichtbarkeit des Chatrooms" + "Raum erstellen" + "Thema (optional)" + "Raum-Verzeichnis" + "Beim Versuch, einen Chat zu starten, ist ein Fehler aufgetreten" + "Raum per Adresse betreten" + "Keine gültige Adresse" + "Eintreten…" + "Passender Raum gefunden" + "Raum nicht gefunden" + "z. B. #room -name:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-el/translations.xml b/features/startchat/impl/src/main/res/values-el/translations.xml new file mode 100644 index 0000000000..c036b43a05 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-el/translations.xml @@ -0,0 +1,30 @@ + + + "Νέα αίθουσα" + "Πρόσκληση ατόμων" + "Προέκυψε σφάλμα κατά τη δημιουργία της αίθουσας" + "Μόνο τα άτομα που έχουν προσκληθεί μπορούν να έχουν πρόσβαση σε αυτή την αίθουσα. Όλα τα μηνύματα είναι κρυπτογραφημένα από άκρο σε άκρο." + "Ιδιωτική αίθουσα" + "Ο καθένας μπορεί να βρει αυτή την αίθουσα. +Αυτό μπορείτε να το αλλάξετε ανά πάσα στιγμή στις ρυθμίσεις της αίθουσας." + "Δημόσια αίθουσα" + "Οποιοσδήποτε μπορεί να συμμετάσχει σε αυτή την αίθουσα" + "Οποιοσδήποτε" + "Πρόσβαση στην Αίθουσα" + "Οποιοσδήποτε μπορεί να ζητήσει να συμμετάσχει στην αίθουσα, αλλά ένας διαχειριστής ή ένας συντονιστής θα πρέπει να αποδεχτεί το αίτημα" + "Αίτημα συμμετοχής" + "Για να είναι ορατή αυτή η αίθουσα στον δημόσιο κατάλογο αιθουσών, θα χρειαστείτε μια διεύθυνση αίθουσας." + "Διεύθυνση αίθουσας" + "Όνομα αίθουσας" + "Ορατότητα αίθουσας" + "Δημιουργία αίθουσας" + "Θέμα (προαιρετικό)" + "Κατάλογος αιθουσών" + "Παρουσιάστηκε σφάλμα κατά την προσπάθεια έναρξης μιας συνομιλίας" + "Συμμετοχή σε αίθουσα μέσω διεύθυνσης" + "Μη έγκυρη διεύθυνση" + "Εισάγετε…" + "Βρέθηκε η αντίστοιχη αίθουσα" + "Η αίθουσα δεν βρέθηκε" + "π.χ. #όνομα-αίθουσας:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-es/translations.xml b/features/startchat/impl/src/main/res/values-es/translations.xml new file mode 100644 index 0000000000..c11f08fc14 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-es/translations.xml @@ -0,0 +1,30 @@ + + + "Nueva sala" + "Invitar personas" + "Se ha producido un error al crear la sala" + "Solo las personas invitadas pueden acceder a esta sala. Todos los mensajes están cifrados de extremo a extremo." + "Sala privada" + "Cualquiera puede encontrar esta sala. +Puedes cambiar esto en cualquier momento en los ajustes de la sala." + "Sala pública" + "Cualquiera puede unirse a esta sala" + "Cualquiera" + "Acceso a la sala" + "Cualquiera puede solicitar unirse a la sala, pero un administrador o un moderador tendrá que aceptar la solicitud" + "Solicitud para unirse" + "Para que esta sala sea visible en el directorio de salas públicas, necesitarás una dirección de sala." + "Dirección de la sala" + "Nombre de la sala" + "Visibilidad de la sala" + "Crear una sala" + "Tema (opcional)" + "Directorio de salas" + "Se ha producido un error al intentar iniciar un chat" + "Unirse a una sala por su dirección" + "Dirección no válida" + "Introducir…" + "Sala encontrada" + "No se encontró la sala" + "p. ej., #nombre-de-la-sala:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-et/translations.xml b/features/startchat/impl/src/main/res/values-et/translations.xml new file mode 100644 index 0000000000..57a26106b3 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-et/translations.xml @@ -0,0 +1,30 @@ + + + "Uus jututuba" + "Kutsu osalejaid" + "Jututoa loomisel tekkis viga" + "Ligipääs siia jututuppa on vaid kutse alusel. Kõik sõnumid siin jututoas on läbivalt krüptitud." + "Privaatne jututuba" + "Kõik saavad seda jututuba leida. +Sa võid seda jututoa seadistustest alati muuta." + "Avalik jututuba" + "Kõik võivad selle jututoaga liituda" + "Kõik" + "Ligipääs jututoale" + "Kõik võivad paluda selle jututoaga liitumist, kuid peakasutaja või moderaator peavad selle kinnitama" + "Küsi võimalust liitumiseks" + "Selleks, et see jututuba oleks nähtav jututubade avalikus kataloogis, sa vajad jututoa aadressi." + "Jututoa aadress" + "Jututoa nimi" + "Jututoa nähtavus" + "Loo jututuba" + "Teema (kui soovid lisada)" + "Jututubade kataloog" + "Vestluse alustamisel tekkis viga" + "Liitu jututoaga aadressi alusel" + "See pole kehtiv aadress" + "Sisene…" + "Leidsime vastava jututoa" + "Jututuba ei leidu" + "nt. #jututoa-nimi:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-eu/translations.xml b/features/startchat/impl/src/main/res/values-eu/translations.xml new file mode 100644 index 0000000000..43f67e429c --- /dev/null +++ b/features/startchat/impl/src/main/res/values-eu/translations.xml @@ -0,0 +1,23 @@ + + + "Gela berria" + "Gonbidatu jendea" + "Errorea gertatu da gela sortzean" + "Gonbidatutako jendea soilik sar daiteke gelara. Mezu guztiak daude ertzetik ertzera zifratuta." + "Gela pribatua" + "Edonork aurki dezake gela hau. +Gelaren ezarpenetan aldatu dezakezu hobespena." + "Gela publikoa" + "Edonor sar daiteke gela honetara" + "Edonork" + "Gelarako sarbidea" + "Gelaren helbidea" + "Gelaren izena" + "Gelaren ikusgarritasuna" + "Sortu gela" + "Mintzagaia (aukerakoa)" + "Gelen direktorioa" + "Errorea gertatu da txata hasten saiatzean" + "Sartu…" + "Ez da gela aurkitu" + diff --git a/features/startchat/impl/src/main/res/values-fa/translations.xml b/features/startchat/impl/src/main/res/values-fa/translations.xml new file mode 100644 index 0000000000..03bc5c3f58 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-fa/translations.xml @@ -0,0 +1,28 @@ + + + "اتاق جدید" + "دعوت افراد" + "هنگام ایجاد اتاق خطایی رخ داد" + "تنها افراد دعوت شده می‌توانند به این اتاق دسترسی داشته باشند. همهٔ پیام‌ها رمزنگاری سرتاسری شده‌اند." + "اتاق خصوصی" + "هرکسی می‌تواند اتاق را بیابد. +می‌توانید بعداً در تظیمات اتاق عوضش کنید." + "اتاق عمومی" + "هرکسی می‌تواند به این اتاق بپیوندد" + "هرکسی" + "دسترسی اتاق" + "درخواست دعوت" + "نشانی اتاق" + "نام اتاق" + "نمایانی اتاق" + "ایجاد اتاق" + "موضوع (اختیاری)" + "فهرست اتاق‌ها" + "هنگام تلاش برای شروع چت خطایی روی داد" + "پیوستن به اتاق با نشانی" + "نشانی معتبری نیست" + "ورود…" + "اتاق مطابق پیدا شد" + "اتاق پیدا نشد" + "نمونه: ‪#room-name:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-fi/translations.xml b/features/startchat/impl/src/main/res/values-fi/translations.xml new file mode 100644 index 0000000000..cdb6d04d59 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-fi/translations.xml @@ -0,0 +1,30 @@ + + + "Uusi huone" + "Kutsu ihmisiä" + "Huoneen luomisessa tapahtui virhe" + "Vain kutsutut henkilöt pääsevät tähän huoneeseen. Kaikki viestit ovat päästä päähän salattuja." + "Yksityinen huone" + "Kuka tahansa voi löytää tämän huoneen. +Voit muuttaa tämän milloin tahansa huoneen asetuksista." + "Julkinen huone" + "Kuka tahansa voi liittyä tähän huoneeseen" + "Kuka tahansa" + "Huoneeseen Pääsy" + "Kuka tahansa voi pyytää saada liittyä huoneeseen, mutta ylläpitäjän tai valvojan on hyväksyttävä pyyntö" + "Pyydä liittymistä" + "Jotta tämä huone näkyisi julkisessa huonehakemistossa, tarvitset huoneen osoitteen." + "Huoneen osoite" + "Huoneen nimi" + "Huoneen näkyvyys" + "Luo huone" + "Aihe (valinnainen)" + "Huoneluettelo" + "Keskustelun aloituksessa tapahtui virhe" + "Liity huoneeseen osoitteella" + "Osoite ei ole kelvollinen" + "Syötä…" + "Täsmäävä huone löytyi" + "Huonetta ei löytynyt" + "esim. #huoneen-nimi:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-fr/translations.xml b/features/startchat/impl/src/main/res/values-fr/translations.xml new file mode 100644 index 0000000000..3f9e01dc85 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-fr/translations.xml @@ -0,0 +1,30 @@ + + + "Nouveau salon" + "Inviter des amis" + "Une erreur s’est produite lors de la création du salon" + "Seules les personnes invitées peuvent accéder à ce salon. Tous les messages sont chiffrés de bout en bout." + "Salon privé" + "N’importe qui peut trouver ce salon. +Vous pouvez modifier cela à tout moment dans les paramètres du salon." + "Salon public" + "Tout le monde peut rejoindre ce salon" + "Tout le monde" + "Accès au salon" + "Tout le monde peut demander à rejoindre le salon, mais un administrateur ou un modérateur devra accepter la demande" + "Demander à rejoindre" + "Pour que ce salon soit visible dans le répertoire des salons publics, vous aurez besoin d’une adresse de salon." + "Adresse du salon" + "Nom du salon" + "Visibilité du salon" + "Créer un salon" + "Sujet (facultatif)" + "Annuaire des salons" + "Une erreur s’est produite lors de la tentative de création de la discussion" + "Saisir une adresse de salon" + "Ce n’est pas une adresse valide" + "Saisir…" + "Ce salon existe" + "Salon non trouvé" + "ex: #nom-du-salon:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-hu/translations.xml b/features/startchat/impl/src/main/res/values-hu/translations.xml new file mode 100644 index 0000000000..1e4a721279 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-hu/translations.xml @@ -0,0 +1,30 @@ + + + "Új szoba" + "Ismerősök meghívása" + "Hiba történt a szoba létrehozásakor" + "Csak a meghívottak léphetnek be ebbe a szobába. Az összes üzenet végpontok közti titkosítással van védve." + "Privát szoba" + "Bárki megtalálhatja ezt a szobát. +Ezt bármikor módosíthatja a szobabeállításokban." + "Nyilvános szoba" + "Bárki csatlakozhat ehhez a szobához" + "Bárki" + "Szobahozzáférés" + "Bárki kérheti, hogy csatlakozzon a szobához, de egy adminisztrátornak vagy moderátornak el kell fogadnia a kérést" + "Csatlakozás kérése" + "Ahhoz, hogy ez a szoba látható legyen a nyilvános szobák címtárában, meg kell adnia a szoba címét." + "A szoba címe" + "Szoba neve" + "Szoba láthatósága" + "Szoba létrehozása" + "Téma (nem kötelező)" + "Szobakatalógus" + "Hiba történt a csevegés indításakor" + "Csatlakozás a szobához cím szerint" + "Nem érvényes cím" + "Írja be…" + "Megfelelő szoba található" + "Szoba nem található" + "pl. #szoba-neve:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-in/translations.xml b/features/startchat/impl/src/main/res/values-in/translations.xml new file mode 100644 index 0000000000..65f135e617 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-in/translations.xml @@ -0,0 +1,30 @@ + + + "Ruangan baru" + "Undang orang-orang" + "Terjadi kesalahan saat membuat ruangan" + "Hanya orang-orang yang diundang dapat mengakses ruangan ini. Semua pesan terenkripsi secara ujung ke ujung." + "Ruangan pribadi" + "Siapa pun dapat mencari ruangan ini. +Anda dapat mengubah ini kapan pun dalam pengaturan ruangan." + "Ruangan publik" + "Siapa pun dapat bergabung dengan ruangan ini" + "Siapa pun" + "Akses Ruangan" + "Siapa pun dapat meminta untuk bergabung dengan ruangan tetapi administrator atau moderator harus menerima permintaan tersebut" + "Minta untuk bergabung" + "Supaya ruangan ini terlihat di direktori ruangan publik, Anda memerlukan alamat ruangan." + "Alamat ruangan" + "Nama ruangan" + "Keterlihatan ruangan" + "Buat ruangan" + "Topik (opsional)" + "Direktori ruangan" + "Terjadi kesalahan saat mencoba memulai obrolan" + "Bergabung dalam ruangan berdasarkan alamat" + "Bukan alamat yang valid" + "Masuk…" + "Ruangan yang cocok ditemukan" + "Ruangan tidak ditemukan" + "mis. #nama-ruangan:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-it/translations.xml b/features/startchat/impl/src/main/res/values-it/translations.xml new file mode 100644 index 0000000000..701ebc967f --- /dev/null +++ b/features/startchat/impl/src/main/res/values-it/translations.xml @@ -0,0 +1,30 @@ + + + "Nuova stanza" + "Invita persone" + "Si è verificato un errore durante la creazione della stanza" + "Solo le persone invitate possono accedere a questa stanza. Tutti i messaggi sono cifrati end-to-end." + "Stanza privata" + "Chiunque può trovare questa stanza. +Puoi modificarlo in qualsiasi momento nelle impostazioni della stanza." + "Stanza pubblica" + "Chiunque può entrare in questa stanza" + "Chiunque" + "Accesso alla stanza" + "Chiunque può chiedere di entrare nella stanza, ma un amministratore o un moderatore dovrà accettare la richiesta" + "Chiedi di entrare" + "Affinché questa stanza sia visibile nell\'elenco delle stanze pubbliche, è necessario un indirizzo della stanza." + "Indirizzo della stanza" + "Nome stanza" + "Visibilità della stanza" + "Crea una stanza" + "Argomento (facoltativo)" + "Elenco delle stanze" + "Si è verificato un errore durante il tentativo di avviare una chat" + "Accedi alla stanza tramite indirizzo" + "Indirizzo non valido" + "Inserisci…" + "Stanza trovata" + "Stanza non trovata" + "ad esempio #room -name:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-ka/translations.xml b/features/startchat/impl/src/main/res/values-ka/translations.xml new file mode 100644 index 0000000000..bb4a430320 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-ka/translations.xml @@ -0,0 +1,15 @@ + + + "ახალი ოთახი" + "ხალხის მოწვევა" + "ოთახის შექმნისას შეცდომა მოხდა" + "ამ ოთახში შეტყობინებები დაშიფრულია. შემდგომ დაშიფვრის გამორთვა შეუძლებელია." + "კერძო ოთახი" + "ყველას ამ ოთახის მოძებნა შეუძლია. +თქვენ ნებისმიერ დროს შეგიძლიათ ამის შეცვლა ოთახის პარამეტრებში." + "ოთახის სახელი" + "ოთახის შექმნა" + "თემა (სურვილისამებრ)" + "ოთახის კატალოგი" + "ჩატის დაწყების მცდელობისას შეცდომა მოხდა" + diff --git a/features/startchat/impl/src/main/res/values-lt/translations.xml b/features/startchat/impl/src/main/res/values-lt/translations.xml new file mode 100644 index 0000000000..2f7a4438ea --- /dev/null +++ b/features/startchat/impl/src/main/res/values-lt/translations.xml @@ -0,0 +1,14 @@ + + + "Naujas kambarys" + "Pakviesti žmonių" + "Kuriant kambarį įvyko klaida" + "Į šį kambarį gali patekti tik pakviesti žmonės. Visi pranešimai yra užšifruoti nuo pradžios iki galo." + "Privatus kambarys" + "Bet kas gali rasti šį kambarį. +Tai galite bet kada pakeisti kambario nustatymuose." + "Kambario pavadinimas" + "Kurti kambarį" + "Tema (nebūtina)" + "Bandant pradėti pokalbį įvyko klaida" + diff --git a/features/startchat/impl/src/main/res/values-nb/translations.xml b/features/startchat/impl/src/main/res/values-nb/translations.xml new file mode 100644 index 0000000000..9266993fd4 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-nb/translations.xml @@ -0,0 +1,30 @@ + + + "Nytt rom" + "Inviter folk" + "Det oppsto en feil under opprettelsen av rommet" + "Bare inviterte personer har tilgang til dette rommet. Alle meldinger er ende-til-ende-kryptert." + "Privat rom" + "Alle kan finne dette rommet. +Du kan endre dette når som helst i rominnstillingene." + "Offentlig rom" + "Alle kan bli med i dette rommet" + "Alle" + "Tilgang til rom" + "Alle kan be om å få bli med i rommet, men en administrator eller moderator må godta forespørselen" + "Be om å bli med" + "For at dette rommet skal være synlig i den offentlige romkatalogen, trenger du en romadresse." + "Romadresse" + "Romnavn" + "Romsynlighet" + "Opprett et rom" + "Emne (valgfritt)" + "Romkatalog" + "Det oppstod en feil når du prøvde å starte en chat" + "Bli med i rommet med adresse" + "Ikke en gyldig adresse" + "Gå inn…" + "Matchende rom funnet" + "Rom ikke funnet" + "f.eks. #rom-navn:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-nl/translations.xml b/features/startchat/impl/src/main/res/values-nl/translations.xml new file mode 100644 index 0000000000..29d070a263 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-nl/translations.xml @@ -0,0 +1,21 @@ + + + "Nieuwe kamer" + "Mensen uitnodigen" + "Er is een fout opgetreden bij het aanmaken van de kamer" + "Alleen uitgenodigde personen hebben toegang tot deze kamer. Alle berichten zijn end-to-end versleuteld." + "Privé kamer" + "Iedereen kan deze kamer vinden. +Je kunt dit op elk gewenst moment wijzigen in de kamerinstellingen." + "Openbare kamer" + "Iedereen kan toetreden tot deze kamer" + "Iedereen" + "Toegang tot de kamer" + "Iedereen kan vragen om toe te treden tot de kamer, maar een beheerder of moderator moet het verzoek accepteren" + "Vraag om toe te treden" + "Naam van de kamer" + "Creëer een kamer" + "Onderwerp (optioneel)" + "Kamergids" + "Er is een fout opgetreden bij het starten van een chat" + diff --git a/features/startchat/impl/src/main/res/values-pl/translations.xml b/features/startchat/impl/src/main/res/values-pl/translations.xml new file mode 100644 index 0000000000..3ed917b7bb --- /dev/null +++ b/features/startchat/impl/src/main/res/values-pl/translations.xml @@ -0,0 +1,30 @@ + + + "Nowy pokój" + "Zaproś znajomych" + "Wystąpił błąd w trakcie tworzenia pokoju" + "Tylko zaproszone osoby mogą dołączyć do tego pokoju. Wszystkie wiadomości są szyfrowane end-to-end." + "Pokój prywatny" + "Każdy może znaleźć ten pokój. +Możesz to zmienić w ustawieniach pokoju." + "Pokój publiczny" + "Każdy może dołączyć do tego pokoju" + "Wszyscy" + "Dostęp do pokoju" + "Każdy może poprosić o dołączenie do pokoju, ale administrator lub moderator będzie musiał zatwierdzić prośbę" + "Poproś o dołączenie" + "Aby ten pokój był widoczny w katalogu pomieszczeń publicznych, będziesz potrzebował adres pokoju." + "Adres pokoju" + "Nazwa pokoju" + "Widoczność pomieszczenia" + "Utwórz pokój" + "Temat (opcjonalnie)" + "Katalog pokoi" + "Wystąpił błąd podczas próby rozpoczęcia czatu" + "Dołącz do pokoju za pomocą adresu" + "Nieprawidłowy adres" + "Wprowadź…" + "Znaleziono pasujący pokój" + "Nie znaleziono pokoju" + "np. #room-name:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-pt-rBR/translations.xml b/features/startchat/impl/src/main/res/values-pt-rBR/translations.xml new file mode 100644 index 0000000000..52c9f569af --- /dev/null +++ b/features/startchat/impl/src/main/res/values-pt-rBR/translations.xml @@ -0,0 +1,30 @@ + + + "Nova sala" + "Convidar pessoas" + "Ocorreu um erro ao criar a sala" + "Apenas as pessoas convidadas podem aceder a esta sala. Todas as mensagens são criptografadas de ponta a ponta." + "Sala privada" + "Qualquer um pode encontrar esta sala. +Você pode mudar isso a qualquer momento nas configurações da sala." + "Sala pública" + "Qualquer pessoa pode entrar nesta sala" + "Qualquer pessoa" + "Acesso à sala" + "Qualquer pessoa pode pedir para entrar na sala, mas um administrador ou moderador terá de aceitar a solicitação" + "Pedir para entrar" + "Para que esta sala fique visível no diretório público de salas, você precisará de um endereço de sala." + "Endereço da sala" + "Nome da sala" + "Visibilidade da sala" + "Criar uma sala" + "Tópico (opcional)" + "Diretório de salas" + "Ocorreu um erro ao tentar iniciar um chat" + "Entrar na sala pelo endereço" + "Não é um endereço válido" + "Entrar…" + "Foi encontrada uma sala correspondente" + "Sala não encontrada" + "Por exemplo, #nome-da-sala:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-pt/translations.xml b/features/startchat/impl/src/main/res/values-pt/translations.xml new file mode 100644 index 0000000000..5e5f5fc9c3 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-pt/translations.xml @@ -0,0 +1,30 @@ + + + "Nova sala" + "Convidar pessoas" + "Ocorreu um erro ao criar a sala" + "Apenas as pessoas convidadas podem aceder a esta sala. Todas as mensagens são cifradas ponta-a-ponta." + "Sala privada" + "Qualquer um pode encontrar esta sala. +Pode alterar esta opção nas definições da sala." + "Sala pública" + "Qualquer pessoa pode entrar nesta sala" + "Qualquer pessoa" + "Acesso à sala" + "Qualquer pessoa pode pedir para entrar na sala, mas um administrador ou um moderador terá de aceitar o pedido" + "Pedir para participar" + "Para que esta sala seja visível no diretório público de salas, precisas de um endereço de sala." + "Endereço da sala" + "Nome da sala" + "Visibilidade da sala" + "Criar uma sala" + "Descrição (opcional)" + "Diretório de salas" + "Ocorreu um erro ao tentar iniciar uma conversa" + "Entrar na sala pelo endereço" + "Não é um endereço válido" + "Entrar…" + "Sala correspondente encontrado" + "Sala não encontrada" + "por exemplo, #sala:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-ro/translations.xml b/features/startchat/impl/src/main/res/values-ro/translations.xml new file mode 100644 index 0000000000..8d9e74b530 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-ro/translations.xml @@ -0,0 +1,22 @@ + + + "Cameră nouă" + "Invitați prieteni" + "A apărut o eroare la crearea camerei" + "Doar persoanele invitate pot accesa această cameră. Toate mesajele sunt criptate end-to-end." + "Cameră privată" + "Oricine poate găsi această cameră. +Puteți modifica acest lucru oricând în setări." + "Cameră publică" + "Oricine se poate alătura acestei camere" + "Oricine" + "Acces la cameră" + "Oricine poate cere să se alăture camerei, dar un administrator sau un moderator va trebui să accepte solicitarea" + "Cereți să vă alăturați" + "Pentru ca această cameră să fie vizibilă în directorul de camere publice, veți avea nevoie de o adresă de cameră." + "Numele camerei" + "Creați o cameră" + "Subiect (opțional)" + "Director de camere" + "A apărut o eroare la încercarea începerii conversației" + diff --git a/features/startchat/impl/src/main/res/values-ru/translations.xml b/features/startchat/impl/src/main/res/values-ru/translations.xml new file mode 100644 index 0000000000..6344491248 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-ru/translations.xml @@ -0,0 +1,30 @@ + + + "Создать новую комнату" + "Пригласить в комнату" + "Произошла ошибка при создании комнаты" + "Доступ в эту комнату имеют только приглашенные пользователи. Все сообщения защищены сквозным шифрованием." + "Частная комната" + "Любой желающий может найти эту комнату. +Вы можете изменить это в любое время в настройках комнаты." + "Общедоступная комната" + "Любой желающий может присоединиться к этой комнате" + "Любой" + "Доступ в комнату" + "Любой желающий может подать заявку на присоединение к комнате, но администратор или модератор должен будет принять запрос." + "Попросить присоединиться" + "Чтобы эта комната была видна в каталоге общедоступных, вам необходим ее адрес" + "Адрес комнаты" + "Название комнаты" + "Видимость комнаты" + "Создать комнату" + "Тема (необязательно)" + "Каталог комнат" + "Произошла ошибка при запуске чата" + "Присоединиться к комнате по адресу" + "Недействительный адрес" + "Ввести…" + "Соответствующая комната найдена" + "Комната не найдена" + "прим. #room-name:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-sk/translations.xml b/features/startchat/impl/src/main/res/values-sk/translations.xml new file mode 100644 index 0000000000..eaf6c2f19c --- /dev/null +++ b/features/startchat/impl/src/main/res/values-sk/translations.xml @@ -0,0 +1,30 @@ + + + "Nová miestnosť" + "Pozvať ľudí" + "Pri vytváraní miestnosti došlo k chybe" + "Do tejto miestnosti majú prístup iba pozvaní ľudia. Všetky správy sú end-to-end šifrované." + "Súkromná miestnosť" + "Túto miestnosť môže nájsť ktokoľvek. +Môžete to kedykoľvek zmeniť v nastaveniach miestnosti." + "Verejná miestnosť" + "Do tejto miestnosti sa môže pripojiť ktokoľvek" + "Ktokoľvek" + "Prístup do miestnosti" + "Ktokoľvek môže požiadať o pripojenie sa k miestnosti, ale administrátor alebo moderátor bude musieť žiadosť schváliť" + "Požiadať o pripojenie" + "Aby bola táto miestnosť viditeľná v adresári verejných miestností, budete potrebovať adresu miestnosti." + "Adresa miestnosti" + "Názov miestnosti" + "Viditeľnosť miestnosti" + "Vytvoriť miestnosť" + "Téma (voliteľné)" + "Adresár miestností" + "Pri pokuse o spustenie konverzácie sa vyskytla chyba" + "Pripojte sa do miestnosti podľa adresy" + "Neplatná adresa" + "Zadajte…" + "Nájdená zodpovedajúca miestnosť" + "Miestnosť sa nenašla" + "napr. #nazov-miestnosti:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-sv/translations.xml b/features/startchat/impl/src/main/res/values-sv/translations.xml new file mode 100644 index 0000000000..316c9cc32e --- /dev/null +++ b/features/startchat/impl/src/main/res/values-sv/translations.xml @@ -0,0 +1,30 @@ + + + "Nytt rum" + "Bjud in personer" + "Ett fel uppstod när rummet skapades" + "Endast inbjudna personer har tillgång till detta rum. Alla meddelanden är totalsträckskrypterade." + "Privat rum" + "Vem som helst kan hitta det här rummet. +Du kan ändra detta när som helst i rumsinställningarna." + "Offentligt rum" + "Vem som helst kan gå med i det här rummet" + "Vem som helst" + "Rumsåtkomst" + "Vem som helst kan be om att gå med i rummet men en administratör eller en moderator måste acceptera begäran" + "Be om att gå med" + "För att detta rum ska vara synligt i den allmänna rumskatalogen behöver du en rumsadress." + "Rumsadress" + "Rumsnamn" + "Rumssynlighet" + "Skapa ett rum" + "Ämne (valfritt)" + "Rumskatalog" + "Ett fel uppstod när du försökte starta en chatt" + "Gå med i rum med adress" + "Inte en giltig adress" + "Ange …" + "Matchande rum hittades" + "Rummet hittades inte" + "t.ex. #rumsnamn:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-tr/translations.xml b/features/startchat/impl/src/main/res/values-tr/translations.xml new file mode 100644 index 0000000000..c8e3136517 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-tr/translations.xml @@ -0,0 +1,24 @@ + + + "Yeni oda" + "İnsanları davet et" + "Oda oluşturulurken bir hata oluştu" + "Bu odaya yalnızca davet edilen kişiler erişebilir. Tüm mesajlar uçtan uca şifrelenir." + "Özel oda" + "Bu odayı herkes bulabilir. +Bunu istediğiniz zaman oda ayarlarından değiştirebilirsiniz." + "Herkese açık oda" + "Bu odaya herkes katılabilir" + "Herkes" + "Oda Erişimi" + "Herkes odaya katılmayı isteyebilir ancak bir yönetici veya moderatörün isteği kabul etmesi gerekecektir" + "Katılmak için sor" + "Bu odanın genel oda dizininde görünür olması için bir oda adresine ihtiyacınız olacaktır." + "Oda adresi" + "Oda adı" + "Oda görünürlüğü" + "Bir oda oluştur" + "Konu (isteğe bağlı)" + "Oda dizini" + "Sohbet başlatmaya çalışırken bir hata oluştu" + diff --git a/features/startchat/impl/src/main/res/values-uk/translations.xml b/features/startchat/impl/src/main/res/values-uk/translations.xml new file mode 100644 index 0000000000..a43172fb8b --- /dev/null +++ b/features/startchat/impl/src/main/res/values-uk/translations.xml @@ -0,0 +1,30 @@ + + + "Нова кімната" + "Запросити людей" + "Під час створення кімнати сталася помилка" + "Лише запрошені люди мають доступ до цієї кімнати. Усі повідомлення захищені наскрізним шифруванням." + "Приватна кімната (тільки за запрошенням)" + "Будь-хто може знайти цю кімнату. +Ви можете змінити це в будь-який час у налаштуваннях кімнати." + "Загальнодоступна кімната" + "Будь-хто може приєднатися до цієї кімнати" + "Кожний" + "Доступ до кімнати" + "Будь-хто може попросити приєднатися до кімнати, але адміністратор або модератор повинен буде прийняти запит" + "Запросити приєднатися" + "Щоб цю кімнату було видно в каталозі загальнодоступних кімнат, вам знадобиться її адреса." + "Адреса кімнати" + "Назва кімнати" + "Видимість кімнати" + "Створити кімнату" + "Тема (необов\'язково)" + "Каталог кімнат" + "Під час спроби почати бесіду сталася помилка" + "Приєднатися до кімнати за адресою" + "Недійсна адреса" + "Введіть…" + "Знайдено відповідну кімнату" + "Кімната не знайдена" + "наприклад, #room-name:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-ur/translations.xml b/features/startchat/impl/src/main/res/values-ur/translations.xml new file mode 100644 index 0000000000..6fe476462e --- /dev/null +++ b/features/startchat/impl/src/main/res/values-ur/translations.xml @@ -0,0 +1,16 @@ + + + "نیا کمرہ" + "لوگوں کو مدعو کریں" + "کمرہ تخلیق کرتے ہوئے ایک نقص واقع ہوا" + "صرف مدعو لوگ ہی اس کمرے تک رسائی حاصل کر سکتے ہیں۔ تمام پیغامات آخر تا آخر مرموز کردہ ہیں۔" + "نجی کمرہ" + "کوئی بھی یہ کمرہ ڈھونڈ سکتا ہے۔ +آپ اسے کمرے کی ترتیبات میں کسی بھی وقت تبدیل کرسکتے ہیں۔" + "عوامی کمرہ" + "کمرے کا نام" + "ایک کمرہ بنائیں" + "موضوع (اختیاری)" + "کمرے کا راہنامچہ" + "گفتگو شروع کرنے کی کوشش کرتے وقت ایک خرابی واقع ہوگئی" + diff --git a/features/startchat/impl/src/main/res/values-uz/translations.xml b/features/startchat/impl/src/main/res/values-uz/translations.xml new file mode 100644 index 0000000000..e3bc9de528 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-uz/translations.xml @@ -0,0 +1,13 @@ + + + "Yangi xona" + "Odamlarni taklif qiling" + "Xonani yaratishda xatolik yuz berdi" + "Bu xonadagi xabarlar shifrlangan. Keyinchalik shifrlashni o‘chirib bo‘lmaydi." + "Shaxsiy xona (faqat taklif)" + "Xabarlar shifrlanmagan va har kim ularni o\'qiy oladi. Keyinchalik shifrlashni yoqishingiz mumkin." + "Xona nomi" + "Xonani yaratish" + "Mavzu (ixtiyoriy)" + "Suhbatni boshlashda xatolik yuz berdi" + diff --git a/features/startchat/impl/src/main/res/values-zh-rTW/translations.xml b/features/startchat/impl/src/main/res/values-zh-rTW/translations.xml new file mode 100644 index 0000000000..0d67c883c7 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-zh-rTW/translations.xml @@ -0,0 +1,30 @@ + + + "建立聊天室" + "邀請夥伴" + "建立聊天室時發生錯誤" + "僅被邀請的人才能存取此聊天室。所有訊息均會端到端加密。" + "私密聊天室" + "任何人都可以找到此聊天室。 +您隨時都可以在聊天室設定中變更此設定。" + "公開的聊天室" + "任何人都可以加入此聊天室" + "任何人" + "聊天室存取權" + "任何人都可以要求加入聊天室,但管理員或版主必須接受該請求" + "要求加入" + "為了讓此聊天室在公開聊天室目錄中可見,您需要聊天室地址。" + "聊天室地址" + "聊天室名稱" + "聊天室能見度" + "建立聊天室" + "主題(非必填)" + "聊天室目錄" + "嘗試開始聊天時發生錯誤" + "按地址加入聊天室" + "不是有效的位址" + "輸入……" + "找到相符的聊天室" + "找不到聊天室" + "例如 #room-name:matrix.org" + diff --git a/features/startchat/impl/src/main/res/values-zh/translations.xml b/features/startchat/impl/src/main/res/values-zh/translations.xml new file mode 100644 index 0000000000..24d7df7f35 --- /dev/null +++ b/features/startchat/impl/src/main/res/values-zh/translations.xml @@ -0,0 +1,24 @@ + + + "新聊天室" + "邀请朋友" + "创建聊天室时出错" + "只有受邀用户才能访问此聊天室。所有消息均经过端到端加密。" + "私有聊天室" + "任何人都能找到此聊天室。 +你可以随时在聊天室设置中更改。" + "公共聊天室" + "任何人都可以加入此房间" + "任何人" + "房间访问权限" + "任何人都可以请求加入房间,但必须由管理员或审核人接受" + "请求加入" + "要使该房间在公开房间目录中可见,您需要一个房间地址。" + "房间地址" + "聊天室名称" + "房间可见性" + "创建聊天室" + "主题(可选)" + "聊天室目录" + "在开始聊天时发生了错误" + diff --git a/features/startchat/impl/src/main/res/values/localazy.xml b/features/startchat/impl/src/main/res/values/localazy.xml new file mode 100644 index 0000000000..d011a1d87b --- /dev/null +++ b/features/startchat/impl/src/main/res/values/localazy.xml @@ -0,0 +1,30 @@ + + + "New room" + "Invite people" + "An error occurred when creating the room" + "Only people invited can access this room. All messages are end-to-end encrypted." + "Private room" + "Anyone can find this room. +You can change this anytime in room settings." + "Public room" + "Anyone can join this room" + "Anyone" + "Room Access" + "Anyone can ask to join the room but an administrator or a moderator will have to accept the request" + "Ask to join" + "In order for this room to be visible in the public room directory, you will need a room address." + "Room address" + "Room name" + "Room visibility" + "Create a room" + "Topic (optional)" + "Room directory" + "An error occurred when trying to start a chat" + "Join room by address" + "Not a valid address" + "Enter…" + "Matching room found" + "Room not found" + "e.g. #room-name:matrix.org" + diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultStartDMActionTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartDMActionTest.kt similarity index 97% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultStartDMActionTest.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartDMActionTest.kt index ef6b3b9517..fa6e140c3a 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultStartDMActionTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartDMActionTest.kt @@ -5,12 +5,12 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl +package io.element.android.features.startchat.impl import androidx.compose.runtime.mutableStateOf import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.CreatedRoom -import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUser +import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/FakeCreateRoomNavigator.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/FakeStartChatNavigator.kt similarity index 86% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/FakeCreateRoomNavigator.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/FakeStartChatNavigator.kt index 28dcdd409d..2cc0f08ea9 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/FakeCreateRoomNavigator.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/FakeStartChatNavigator.kt @@ -5,18 +5,18 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl +package io.element.android.features.startchat.impl -import io.element.android.features.createroom.CreateRoomNavigator +import io.element.android.features.invitepeople.StartChatNavigator import io.element.android.libraries.matrix.api.core.RoomIdOrAlias -class FakeCreateRoomNavigator( +class FakeStartChatNavigator( private val openRoomLambda: (roomIdOrAlias: RoomIdOrAlias, serverNames: List) -> Unit = { _, _ -> }, private val createNewRoomLambda: () -> Unit = {}, private val showJoinRoomByAddressLambda: () -> Unit = {}, private val dismissJoinRoomByAddressLambda: () -> Unit = {}, private val openRoomDirectoryLambda: () -> Unit = {}, -) : CreateRoomNavigator { +) : StartChatNavigator { override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List) { openRoomLambda(roomIdOrAlias, serverNames) } diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeoplePresenterTest.kt similarity index 79% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTest.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeoplePresenterTest.kt index acb381dadc..d5742b2a26 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeoplePresenterTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeoplePresenterTest.kt @@ -1,19 +1,19 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.addpeople +package io.element.android.features.startchat.impl.addpeople import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.features.createroom.impl.CreateRoomDataStore -import io.element.android.features.createroom.impl.userlist.FakeUserListPresenterFactory -import io.element.android.features.createroom.impl.userlist.UserListDataStore +import io.element.android.features.invitepeople.impl.CreateRoomDataStore +import io.element.android.features.startchat.impl.userlist.FakeUserListPresenterFactory +import io.element.android.features.invitepeople.impl.userlist.UserListDataStore import io.element.android.libraries.matrix.test.room.alias.FakeRoomAliasHelper import io.element.android.libraries.usersearch.test.FakeUserRepository import io.element.android.tests.testutils.WarmUpRule diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleViewTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleViewTest.kt similarity index 89% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleViewTest.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleViewTest.kt index c18abf0daa..9d8af8d61d 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleViewTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/addpeople/AddPeopleViewTest.kt @@ -5,15 +5,15 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.addpeople +package io.element.android.features.startchat.impl.addpeople import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.element.android.features.createroom.impl.userlist.UserListEvents -import io.element.android.features.createroom.impl.userlist.UserListState -import io.element.android.features.createroom.impl.userlist.aUserListState +import io.element.android.features.invitepeople.impl.userlist.UserListEvents +import io.element.android.features.invitepeople.impl.userlist.UserListState +import io.element.android.features.invitepeople.impl.userlist.aUserListState import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EventsRecorder @@ -83,7 +83,7 @@ private fun AndroidComposeTestRule.setAddPe AddPeopleView( state = state, onBackClick = onBackClick, - onNextClick = onNextClick, + onSkipClick = onNextClick, ) } } diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureBaseRoomPresenterTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureBaseRoomPresenterTest.kt similarity index 98% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureBaseRoomPresenterTest.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureBaseRoomPresenterTest.kt index 8c8ba7ca58..8eab477f1a 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureBaseRoomPresenterTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/configureroom/ConfigureBaseRoomPresenterTest.kt @@ -5,15 +5,15 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.configureroom +package io.element.android.features.startchat.impl.configureroom import android.net.Uri import app.cash.turbine.TurbineTestContext import com.google.common.truth.Truth.assertThat import im.vector.app.features.analytics.plan.CreatedRoom -import io.element.android.features.createroom.impl.CreateRoomConfig -import io.element.android.features.createroom.impl.CreateRoomDataStore -import io.element.android.features.createroom.impl.userlist.UserListDataStore +import io.element.android.features.invitepeople.impl.CreateRoomConfig +import io.element.android.features.invitepeople.impl.CreateRoomDataStore +import io.element.android.features.invitepeople.impl.userlist.UserListDataStore import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinBaseRoomByAddressPresenterTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinBaseRoomByAddressPresenterTest.kt similarity index 93% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinBaseRoomByAddressPresenterTest.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinBaseRoomByAddressPresenterTest.kt index 10cca20fa3..e477c07f60 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinBaseRoomByAddressPresenterTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinBaseRoomByAddressPresenterTest.kt @@ -5,11 +5,11 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.joinbyaddress +package io.element.android.features.startchat.impl.joinbyaddress import com.google.common.truth.Truth.assertThat -import io.element.android.features.createroom.CreateRoomNavigator -import io.element.android.features.createroom.impl.FakeCreateRoomNavigator +import io.element.android.features.invitepeople.StartChatNavigator +import io.element.android.features.startchat.impl.FakeStartChatNavigator import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper @@ -61,7 +61,7 @@ class JoinBaseRoomByAddressPresenterTest { fun `present - room found`() = runTest { val openRoomLambda = lambdaRecorder, Unit> { _, _ -> } val dismissJoinRoomByAddressLambda = lambdaRecorder { } - val navigator = FakeCreateRoomNavigator( + val navigator = FakeStartChatNavigator( openRoomLambda = openRoomLambda, dismissJoinRoomByAddressLambda = dismissJoinRoomByAddressLambda ) @@ -114,7 +114,7 @@ class JoinBaseRoomByAddressPresenterTest { @Test fun `present - dismiss`() = runTest { val dismissJoinRoomByAddressLambda = lambdaRecorder { } - val navigator = FakeCreateRoomNavigator( + val navigator = FakeStartChatNavigator( dismissJoinRoomByAddressLambda = dismissJoinRoomByAddressLambda ) val presenter = createJoinRoomByAddressPresenter(navigator = navigator) @@ -127,7 +127,7 @@ class JoinBaseRoomByAddressPresenterTest { } private fun createJoinRoomByAddressPresenter( - navigator: CreateRoomNavigator = FakeCreateRoomNavigator(), + navigator: StartChatNavigator = FakeStartChatNavigator(), matrixClient: MatrixClient = FakeMatrixClient(), roomAliasHelper: RoomAliasHelper = FakeRoomAliasHelper(), ): JoinRoomByAddressPresenter { diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinBaseRoomByAddressViewTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinBaseRoomByAddressViewTest.kt similarity index 94% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinBaseRoomByAddressViewTest.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinBaseRoomByAddressViewTest.kt index b2e75c9f5a..195ca55081 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/joinbyaddress/JoinBaseRoomByAddressViewTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/joinbyaddress/JoinBaseRoomByAddressViewTest.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.joinbyaddress +package io.element.android.features.startchat.impl.joinbyaddress import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.AndroidComposeTestRule @@ -13,7 +13,7 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performTextInput import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.element.android.features.createroom.impl.R +import io.element.android.features.invitepeople.impl.R import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateBaseRoomRootPresenterTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/CreateBaseRoomRootPresenterTest.kt similarity index 87% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateBaseRoomRootPresenterTest.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/CreateBaseRoomRootPresenterTest.kt index d2d9959e2a..9c2d2ac1ef 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateBaseRoomRootPresenterTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/CreateBaseRoomRootPresenterTest.kt @@ -1,23 +1,23 @@ /* - * Copyright 2023, 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.root +package io.element.android.features.startchat.impl.root import androidx.compose.runtime.MutableState import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUser -import io.element.android.features.createroom.api.StartDMAction -import io.element.android.features.createroom.impl.userlist.FakeUserListPresenter -import io.element.android.features.createroom.impl.userlist.FakeUserListPresenterFactory -import io.element.android.features.createroom.impl.userlist.UserListDataStore -import io.element.android.features.createroom.test.FakeStartDMAction +import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser +import io.element.android.features.startchat.api.StartDMAction +import io.element.android.features.startchat.impl.userlist.FakeUserListPresenter +import io.element.android.features.startchat.impl.userlist.FakeUserListPresenterFactory +import io.element.android.features.invitepeople.impl.userlist.UserListDataStore +import io.element.android.features.invitepeople.test.FakeStartDMAction import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService @@ -58,7 +58,7 @@ class CreateBaseRoomRootPresenterTest { assertThat(initialState.userListState.isSearchActive).isFalse() assertThat(initialState.userListState.isMultiSelectionEnabled).isFalse() val matrixUser = MatrixUser(UserId("@name:domain")) - initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser)) + initialState.eventSink(StartChatEvents.StartDM(matrixUser)) awaitItem().also { state -> assertThat(state.startDmAction).isEqualTo(startDMFailureResult) executeResult.assertions().isCalledOnce().with( @@ -66,7 +66,7 @@ class CreateBaseRoomRootPresenterTest { value(false), any(), ) - state.eventSink(CreateRoomRootEvents.CancelStartDM) + state.eventSink(StartChatEvents.CancelStartDM) } awaitItem().also { state -> assertThat(state.startDmAction.isUninitialized()).isTrue() @@ -92,7 +92,7 @@ class CreateBaseRoomRootPresenterTest { assertThat(initialState.userListState.isSearchActive).isFalse() assertThat(initialState.userListState.isMultiSelectionEnabled).isFalse() val matrixUser = MatrixUser(UserId("@name:domain")) - initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser)) + initialState.eventSink(StartChatEvents.StartDM(matrixUser)) awaitItem().also { state -> assertThat(state.startDmAction).isEqualTo(startDMSuccessResult) executeResult.assertions().isCalledOnce().with( @@ -118,7 +118,7 @@ class CreateBaseRoomRootPresenterTest { }.test { val initialState = awaitItem() assertThat(initialState.startDmAction).isInstanceOf(AsyncAction.Uninitialized::class.java) - initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser)) + initialState.eventSink(StartChatEvents.StartDM(matrixUser)) val confirmingState = awaitItem() assertThat(confirmingState.startDmAction).isEqualTo(startDMConfirmationResult) executeResult.assertions().isCalledOnce().with( @@ -127,7 +127,7 @@ class CreateBaseRoomRootPresenterTest { any(), ) // Cancelling should not create the DM - confirmingState.eventSink(CreateRoomRootEvents.CancelStartDM) + confirmingState.eventSink(StartChatEvents.CancelStartDM) val finalState = awaitItem() assertThat(finalState.startDmAction.isUninitialized()).isTrue() executeResult.assertions().isCalledExactly(1) @@ -148,7 +148,7 @@ class CreateBaseRoomRootPresenterTest { }.test { val initialState = awaitItem() assertThat(initialState.startDmAction).isInstanceOf(AsyncAction.Uninitialized::class.java) - initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser)) + initialState.eventSink(StartChatEvents.StartDM(matrixUser)) val confirmingState = awaitItem() assertThat(confirmingState.startDmAction).isEqualTo(startDMConfirmationResult) executeResult.assertions().isCalledOnce().with( @@ -157,7 +157,7 @@ class CreateBaseRoomRootPresenterTest { any(), ) // Start DM again should invoke the action with createIfDmDoesNotExist = true - confirmingState.eventSink(CreateRoomRootEvents.StartDM(matrixUser)) + confirmingState.eventSink(StartChatEvents.StartDM(matrixUser)) executeResult.assertions().isCalledExactly(2).withSequence( listOf(value(matrixUser), value(false), any()), listOf(value(matrixUser), value(true), any()), @@ -181,13 +181,13 @@ class CreateBaseRoomRootPresenterTest { private fun createCreateRoomRootPresenter( startDMAction: StartDMAction = FakeStartDMAction(), isRoomDirectorySearchEnabled: Boolean = false, - ): CreateRoomRootPresenter { + ): StartChatPresenter { val featureFlagService = FakeFeatureFlagService( initialState = mapOf( FeatureFlags.RoomDirectorySearch.key to isRoomDirectorySearchEnabled, ), ) - return CreateRoomRootPresenter( + return StartChatPresenter( presenterFactory = FakeUserListPresenterFactory(FakeUserListPresenter()), userRepository = FakeUserRepository(), userListDataStore = UserListDataStore(), diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateBaseRoomRootViewTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/CreateBaseRoomRootViewTest.kt similarity index 85% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateBaseRoomRootViewTest.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/CreateBaseRoomRootViewTest.kt index 9104b2dfb2..81f764dd59 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/root/CreateBaseRoomRootViewTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/CreateBaseRoomRootViewTest.kt @@ -1,11 +1,11 @@ /* - * Copyright 2024 New Vector Ltd. + * Copyright 2025 New Vector Ltd. * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.root +package io.element.android.features.startchat.impl.root import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.AndroidComposeTestRule @@ -13,9 +13,9 @@ import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.test.ext.junit.runners.AndroidJUnit4 -import io.element.android.features.createroom.impl.R -import io.element.android.features.createroom.impl.userlist.aRecentDirectRoomList -import io.element.android.features.createroom.impl.userlist.aUserListState +import io.element.android.features.invitepeople.impl.R +import io.element.android.features.invitepeople.impl.userlist.aRecentDirectRoomList +import io.element.android.features.invitepeople.impl.userlist.aUserListState import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.ui.model.getBestName import io.element.android.libraries.ui.strings.CommonStrings @@ -31,6 +31,7 @@ import org.junit.Test import org.junit.rules.TestRule import org.junit.runner.RunWith import org.robolectric.annotation.Config +import kotlin.collections.get @RunWith(AndroidJUnit4::class) class CreateBaseRoomRootViewTest { @@ -39,7 +40,7 @@ class CreateBaseRoomRootViewTest { @Test fun `clicking on back invokes the expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { rule.setCreateRoomRootView( aCreateRoomRootState( @@ -53,7 +54,7 @@ class CreateBaseRoomRootViewTest { @Test fun `clicking on New room invokes the expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { rule.setCreateRoomRootView( aCreateRoomRootState( @@ -68,7 +69,7 @@ class CreateBaseRoomRootViewTest { @Config(qualifiers = "h1024dp") @Test fun `clicking on Invite people invokes the expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { rule.setCreateRoomRootView( aCreateRoomRootState( @@ -87,7 +88,7 @@ class CreateBaseRoomRootViewTest { fun `clicking on a user suggestion invokes the expected callback`() { val recentDirectRoomList = aRecentDirectRoomList() val firstRoom = recentDirectRoomList[0] - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnceWithParam(firstRoom.roomId) { rule.setCreateRoomRootView( aCreateRoomRootState( @@ -105,7 +106,7 @@ class CreateBaseRoomRootViewTest { @Config(qualifiers = "h1024dp") @Test fun `clicking on Join room by address invokes the expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { rule.setCreateRoomRootView( aCreateRoomRootState( @@ -119,7 +120,7 @@ class CreateBaseRoomRootViewTest { @Test fun `clicking on room directory invokes the expected callback`() { - val eventsRecorder = EventsRecorder(expectEvents = false) + val eventsRecorder = EventsRecorder(expectEvents = false) ensureCalledOnce { rule.setCreateRoomRootView( aCreateRoomRootState( @@ -134,7 +135,7 @@ class CreateBaseRoomRootViewTest { } private fun AndroidComposeTestRule.setCreateRoomRootView( - state: CreateRoomRootState, + state: StartChatState, onCloseClick: () -> Unit = EnsureNeverCalled(), onNewRoomClick: () -> Unit = EnsureNeverCalled(), onOpenDM: (RoomId) -> Unit = EnsureNeverCalledWithParam(), diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenterTest.kt similarity index 99% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTest.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenterTest.kt index ac793a247f..50bbc425c2 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/DefaultUserListPresenterTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/DefaultUserListPresenterTest.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.userlist +package io.element.android.features.startchat.impl.userlist import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/FakeUserListPresenter.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/FakeUserListPresenter.kt similarity index 89% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/FakeUserListPresenter.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/FakeUserListPresenter.kt index a0768ffda8..84c4fd9d67 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/FakeUserListPresenter.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/FakeUserListPresenter.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.userlist +package io.element.android.features.startchat.impl.userlist import androidx.compose.runtime.Composable diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/FakeUserListPresenterFactory.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/FakeUserListPresenterFactory.kt similarity index 91% rename from features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/FakeUserListPresenterFactory.kt rename to features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/FakeUserListPresenterFactory.kt index 123a013670..8e80626e86 100644 --- a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/userlist/FakeUserListPresenterFactory.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/userlist/FakeUserListPresenterFactory.kt @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.impl.userlist +package io.element.android.features.startchat.impl.userlist import io.element.android.libraries.usersearch.api.UserRepository diff --git a/features/createroom/test/build.gradle.kts b/features/startchat/test/build.gradle.kts similarity index 83% rename from features/createroom/test/build.gradle.kts rename to features/startchat/test/build.gradle.kts index b7df0caab6..96b05a80fa 100644 --- a/features/createroom/test/build.gradle.kts +++ b/features/startchat/test/build.gradle.kts @@ -10,7 +10,7 @@ plugins { } android { - namespace = "io.element.android.features.createroom.test" + namespace = "io.element.android.features.invitepeople.test" } dependencies { @@ -19,5 +19,5 @@ dependencies { implementation(projects.libraries.matrix.test) implementation(projects.libraries.architecture) implementation(projects.tests.testutils) - api(projects.features.createroom.api) + api(projects.features.startchat.api) } diff --git a/features/createroom/test/src/main/kotlin/io/element/android/features/createroom/test/FakeStartDMAction.kt b/features/startchat/test/src/main/kotlin/io/element/android/features/invitepeople/test/FakeStartDMAction.kt similarity index 88% rename from features/createroom/test/src/main/kotlin/io/element/android/features/createroom/test/FakeStartDMAction.kt rename to features/startchat/test/src/main/kotlin/io/element/android/features/invitepeople/test/FakeStartDMAction.kt index 90e2ecf1c1..d7ab63d0e3 100644 --- a/features/createroom/test/src/main/kotlin/io/element/android/features/createroom/test/FakeStartDMAction.kt +++ b/features/startchat/test/src/main/kotlin/io/element/android/features/invitepeople/test/FakeStartDMAction.kt @@ -5,10 +5,10 @@ * Please see LICENSE files in the repository root for full details. */ -package io.element.android.features.createroom.test +package io.element.android.features.invitepeople.test import androidx.compose.runtime.MutableState -import io.element.android.features.createroom.api.StartDMAction +import io.element.android.features.startchat.api.StartDMAction import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.user.MatrixUser diff --git a/features/userprofile/impl/build.gradle.kts b/features/userprofile/impl/build.gradle.kts index 4242efcb98..7bcebae565 100644 --- a/features/userprofile/impl/build.gradle.kts +++ b/features/userprofile/impl/build.gradle.kts @@ -38,7 +38,7 @@ dependencies { api(projects.features.userprofile.api) api(projects.features.userprofile.shared) implementation(libs.coil.compose) - implementation(projects.features.createroom.api) + implementation(projects.features.startchat.api) implementation(projects.services.analytics.api) testImplementation(libs.test.junit) @@ -49,7 +49,7 @@ dependencies { testImplementation(libs.test.mockk) testImplementation(libs.test.robolectric) testImplementation(projects.libraries.matrix.test) - testImplementation(projects.features.createroom.test) + testImplementation(projects.features.startchat.test) testImplementation(projects.features.enterprise.test) testImplementation(projects.tests.testutils) testImplementation(libs.androidx.compose.ui.test.junit) diff --git a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt index 4de79b8375..6f696d9cdf 100644 --- a/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt +++ b/features/userprofile/impl/src/main/kotlin/io/element/android/features/userprofile/impl/root/UserProfilePresenter.kt @@ -20,7 +20,7 @@ import androidx.compose.runtime.setValue import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject -import io.element.android.features.createroom.api.StartDMAction +import io.element.android.features.startchat.api.StartDMAction import io.element.android.features.enterprise.api.SessionEnterpriseService import io.element.android.features.userprofile.api.UserProfileEvents import io.element.android.features.userprofile.api.UserProfileState diff --git a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt index 2ce7f99c2c..e86c66bc4f 100644 --- a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt +++ b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/UserProfilePresenterTest.kt @@ -13,9 +13,9 @@ import app.cash.molecule.moleculeFlow import app.cash.turbine.ReceiveTurbine import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUser -import io.element.android.features.createroom.api.StartDMAction -import io.element.android.features.createroom.test.FakeStartDMAction +import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser +import io.element.android.features.startchat.api.StartDMAction +import io.element.android.features.invitepeople.test.FakeStartDMAction import io.element.android.features.enterprise.test.FakeSessionEnterpriseService import io.element.android.features.userprofile.api.UserProfileEvents import io.element.android.features.userprofile.api.UserProfileState diff --git a/features/userprofile/shared/build.gradle.kts b/features/userprofile/shared/build.gradle.kts index 0b14ce63f2..53e8e9dee2 100644 --- a/features/userprofile/shared/build.gradle.kts +++ b/features/userprofile/shared/build.gradle.kts @@ -39,7 +39,7 @@ dependencies { api(projects.features.userprofile.api) api(projects.services.apperror.api) implementation(libs.coil.compose) - implementation(projects.features.createroom.api) + implementation(projects.features.startchat.api) implementation(projects.services.analytics.api) testImplementation(libs.test.junit) diff --git a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt index 7a5cc53239..25cb8a5df6 100644 --- a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt +++ b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileStateProvider.kt @@ -8,7 +8,7 @@ package io.element.android.features.userprofile.shared import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUser +import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser import io.element.android.features.userprofile.api.UserProfileEvents import io.element.android.features.userprofile.api.UserProfileState import io.element.android.features.userprofile.api.UserProfileVerificationState diff --git a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt index a43478e466..f39cbfaf73 100644 --- a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt +++ b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/UserProfileView.kt @@ -21,7 +21,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.tokens.generated.CompoundIcons -import io.element.android.features.createroom.api.ConfirmingStartDmWithMatrixUser +import io.element.android.features.startchat.api.ConfirmingStartDmWithMatrixUser import io.element.android.features.userprofile.api.UserProfileEvents import io.element.android.features.userprofile.api.UserProfileState import io.element.android.features.userprofile.api.UserProfileVerificationState diff --git a/tools/localazy/config.json b/tools/localazy/config.json index 1f0d291d0b..923113cd39 100644 --- a/tools/localazy/config.json +++ b/tools/localazy/config.json @@ -65,6 +65,16 @@ "screen_room_directory_search_title*" ] }, + { + "name" : ":features:startchat:impl", + "includeRegex" : [ + "screen_create_room_.*", + "screen\\.create_room\\..*", + "screen_start_chat_.*", + "screen\\.start_chat\\..*", + "screen_room_directory_search_title*" + ] + }, { "name" : ":features:verifysession:impl", "includeRegex" : [