Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Epic: create and join rooms - Start Chat #680

Merged
merged 14 commits into from
Mar 14, 2023
1 change: 1 addition & 0 deletions Dangerfile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ let allowList = ["stefanceriu",
"gileluard",
"phlniji",
"aringenbach",
"flescio",
"Velin92"]

let requiresSignOff = !allowList.contains(where: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@
"all_chats" = "All Chats";
"start_chat" = "Start Chat";
"create_room" = "Create Room";
"create_a_room" = "Create a room";
"change_space" = "Change Space";
"explore_rooms" = "Explore Rooms";
"a11y_expand_space_children" = "Expand %@ children";
Expand Down Expand Up @@ -1865,6 +1866,7 @@
"inviting_users_to_room" = "Inviting users…";
"invite_users_to_room_title" = "Invite Users";
"invite_friends" = "Invite friends";
"invite_friends_to_element" = "Invite friends to Element";
"invite_friends_text" = "Hey, talk to me on %@: %@";
"invite_friends_rich_title" = "🔐️ Join me on %@";
"invitation_sent_to_one_user" = "Invitation sent to %1$@";
Expand Down Expand Up @@ -2355,3 +2357,4 @@
"emoji_picker_objects_category" = "Objects";
"emoji_picker_symbols_category" = "Symbols";
"emoji_picker_flags_category" = "Flags";
"search_for_someone" = "Search for someone";
9 changes: 8 additions & 1 deletion ElementX/Sources/Application/AppSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ final class AppSettings: ObservableObject {
case enableInAppNotifications
case pusherProfileTag
case shouldCollapseRoomStateEvents
case showStartChatFlow
}

private static var suiteName: String = InfoPlistReader.main.appGroupIdentifier
Expand Down Expand Up @@ -140,7 +141,6 @@ final class AppSettings: ObservableObject {

@UserSetting(key: UserDefaultsKeys.shouldCollapseRoomStateEvents.rawValue, defaultValue: true, persistIn: nil)
var shouldCollapseRoomStateEvents

// MARK: - Notifications

@UserSetting(key: UserDefaultsKeys.timelineStyle.rawValue, defaultValue: true, persistIn: store)
Expand All @@ -153,4 +153,11 @@ final class AppSettings: ObservableObject {
// MARK: - Other

let permalinkBaseURL = URL(staticString: "https://matrix.to")

// MARK: - Feature Flags
flescio marked this conversation as resolved.
Show resolved Hide resolved

// MARK: Start Chat

@UserSetting(key: UserDefaultsKeys.showStartChatFlow.rawValue, defaultValue: false, persistIn: store)
var startChatFlowFeatureFlag
}
6 changes: 6 additions & 0 deletions ElementX/Sources/Generated/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,8 @@ public enum ElementL10n {
public static var copiedToClipboard: String { return ElementL10n.tr("Localizable", "copied_to_clipboard") }
/// Create
public static var create: String { return ElementL10n.tr("Localizable", "create") }
/// Create a room
public static var createARoom: String { return ElementL10n.tr("Localizable", "create_a_room") }
/// Create New Room
public static var createNewRoom: String { return ElementL10n.tr("Localizable", "create_new_room") }
/// Create New Space
Expand Down Expand Up @@ -1858,6 +1860,8 @@ public enum ElementL10n {
public static func inviteFriendsText(_ p1: Any, _ p2: Any) -> String {
return ElementL10n.tr("Localizable", "invite_friends_text", String(describing: p1), String(describing: p2))
}
/// Invite friends to Element
public static var inviteFriendsToElement: String { return ElementL10n.tr("Localizable", "invite_friends_to_element") }
/// Just to this room
public static var inviteJustToThisRoom: String { return ElementL10n.tr("Localizable", "invite_just_to_this_room") }
/// They won’t be a part of %@
Expand Down Expand Up @@ -4177,6 +4181,8 @@ public enum ElementL10n {
public static var search: String { return ElementL10n.tr("Localizable", "search") }
/// Filter banned users
public static var searchBannedUserHint: String { return ElementL10n.tr("Localizable", "search_banned_user_hint") }
/// Search for someone
public static var searchForSomeone: String { return ElementL10n.tr("Localizable", "search_for_someone") }
/// Search
public static var searchHint: String { return ElementL10n.tr("Localizable", "search_hint") }
/// Search Name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ struct DeveloperOptionsScreenViewState: BindableState {

struct DeveloperOptionsScreenViewStateBindings {
var shouldCollapseRoomStateEvents: Bool
var showStartChatFlow: Bool
}

enum DeveloperOptionsScreenViewAction {
case changedShouldCollapseRoomStateEvents
case changedShowStartChatFlow
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class DeveloperOptionsScreenViewModel: DeveloperOptionsScreenViewModelType, Deve
var callback: ((DeveloperOptionsScreenViewModelAction) -> Void)?

init() {
super.init(initialViewState: DeveloperOptionsScreenViewState(bindings: DeveloperOptionsScreenViewStateBindings(shouldCollapseRoomStateEvents: ServiceLocator.shared.settings.shouldCollapseRoomStateEvents)))
super.init(initialViewState: DeveloperOptionsScreenViewState(bindings: DeveloperOptionsScreenViewStateBindings(shouldCollapseRoomStateEvents: ServiceLocator.shared.settings.shouldCollapseRoomStateEvents, showStartChatFlow: ServiceLocator.shared.settings.startChatFlowFeatureFlag)))

ServiceLocator.shared.settings.$shouldCollapseRoomStateEvents
.weakAssign(to: \.state.bindings.shouldCollapseRoomStateEvents, on: self)
Expand All @@ -33,6 +33,8 @@ class DeveloperOptionsScreenViewModel: DeveloperOptionsScreenViewModelType, Deve
switch viewAction {
case .changedShouldCollapseRoomStateEvents:
ServiceLocator.shared.settings.shouldCollapseRoomStateEvents = state.bindings.shouldCollapseRoomStateEvents
case .changedShowStartChatFlow:
ServiceLocator.shared.settings.startChatFlowFeatureFlag = state.bindings.showStartChatFlow
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ struct DeveloperOptionsScreenScreen: View {
.onChange(of: context.shouldCollapseRoomStateEvents) { _ in
context.send(viewAction: .changedShouldCollapseRoomStateEvents)
}
Toggle(isOn: $context.showStartChatFlow) {
Text("Show Start Chat flow")
}
.onChange(of: context.showStartChatFlow) { _ in
context.send(viewAction: .changedShowStartChatFlow)
}
}

Section {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ enum HomeScreenCoordinatorAction {
case presentSettingsScreen
case presentFeedbackScreen
case presentSessionVerificationScreen
case presentStartChatScreen
case signOut
}

Expand Down Expand Up @@ -62,6 +63,8 @@ final class HomeScreenCoordinator: CoordinatorProtocol {
self.callback?(.presentSessionVerificationScreen)
case .signOut:
self.callback?(.signOut)
case .presentStartChatScreen:
self.callback?(.presentStartChatScreen)
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions ElementX/Sources/Screens/HomeScreen/HomeScreenModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum HomeScreenViewModelAction {
case presentSettingsScreen
case presentInviteFriendsScreen
case presentFeedbackScreen
case presentStartChatScreen
case signOut
}

Expand All @@ -37,6 +38,7 @@ enum HomeScreenViewUserMenuAction {
enum HomeScreenViewAction {
case selectRoom(roomIdentifier: String)
case userMenu(action: HomeScreenViewUserMenuAction)
case startChat
case verifySession
case skipSessionVerification
case updateVisibleItemRange(range: Range<Int>, isScrolling: Bool)
Expand Down Expand Up @@ -67,6 +69,10 @@ struct HomeScreenViewState: BindableState {

var roomListMode: HomeScreenRoomListMode = .skeletons

var showStartChatFlowEnabled: Bool {
ServiceLocator.shared.settings.startChatFlowFeatureFlag
}

var visibleRooms: [HomeScreenRoom] {
if roomListMode == .skeletons {
return placeholderRooms
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
state.showSessionVerificationBanner = false
case .updateVisibleItemRange(let range, let isScrolling):
visibleItemRangePublisher.send((range, isScrolling))
case .startChat:
callback?(.presentStartChatScreen)
}
}

Expand Down
16 changes: 16 additions & 0 deletions ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ struct HomeScreen: View {
ToolbarItem(placement: .navigationBarLeading) {
userMenuButton
}
if context.viewState.showStartChatFlowEnabled {
ToolbarItemGroup(placement: .bottomBar) {
Spacer()
newRoomButton
}
}
}
.background(Color.element.background.ignoresSafeArea())
}
Expand Down Expand Up @@ -148,6 +154,12 @@ struct HomeScreen: View {
.accessibilityLabel(ElementL10n.a11yAllChatsUserAvatarMenu)
}

private var newRoomButton: some View {
Button(action: startChat) {
Image(systemName: "square.and.pencil")
}
}

private var sessionVerificationBanner: some View {
VStack(alignment: .leading, spacing: 16) {
VStack(alignment: .leading, spacing: 4) {
Expand Down Expand Up @@ -191,6 +203,10 @@ struct HomeScreen: View {
context.send(viewAction: .userMenu(action: .inviteFriends))
}

private func startChat() {
context.send(viewAction: .startChat)
}

private func feedback() {
context.send(viewAction: .userMenu(action: .feedback))
}
Expand Down
55 changes: 55 additions & 0 deletions ElementX/Sources/Screens/StartChat/StartChatCoordinator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import SwiftUI

struct StartChatCoordinatorParameters {
let userSession: UserSessionProtocol
}

enum StartChatCoordinatorAction {
case close
}

final class StartChatCoordinator: CoordinatorProtocol {
private let parameters: StartChatCoordinatorParameters
private var viewModel: StartChatViewModelProtocol

var callback: ((StartChatCoordinatorAction) -> Void)?

init(parameters: StartChatCoordinatorParameters) {
self.parameters = parameters

viewModel = StartChatViewModel(userSession: parameters.userSession)
}

func start() {
viewModel.callback = { [weak self] action in
guard let self else { return }
switch action {
case .close:
self.callback?(.close)
case .createRoom:
// TODO: start create room flow
flescio marked this conversation as resolved.
Show resolved Hide resolved
break
}
}
}

func toPresentable() -> AnyView {
AnyView(StartChatScreen(context: viewModel.context))
}
}
39 changes: 39 additions & 0 deletions ElementX/Sources/Screens/StartChat/StartChatModels.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation

enum StartChatViewModelAction {
case close
case createRoom
}

struct StartChatViewState: BindableState {
var bindings = StartChatScreenViewStateBindings()

// TODO: bind with real service, and mock data only in preview
flescio marked this conversation as resolved.
Show resolved Hide resolved
var suggestedUsers: [RoomMemberProxy] = [.mockAlice, .mockBob, .mockCharlie]
}

struct StartChatScreenViewStateBindings {
var searchQuery = ""
}

enum StartChatViewAction {
case close
case createRoom
case inviteFriends
}
44 changes: 44 additions & 0 deletions ElementX/Sources/Screens/StartChat/StartChatViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import SwiftUI

typealias StartChatViewModelType = StateStoreViewModel<StartChatViewState, StartChatViewAction>

class StartChatViewModel: StartChatViewModelType, StartChatViewModelProtocol {
private let userSession: UserSessionProtocol

var callback: ((StartChatViewModelAction) -> Void)?

init(userSession: UserSessionProtocol) {
self.userSession = userSession
super.init(initialViewState: StartChatViewState(), imageProvider: userSession.mediaProvider)
}

// MARK: - Public

override func process(viewAction: StartChatViewAction) async {
switch viewAction {
case .close:
callback?(.close)
case .createRoom:
callback?(.createRoom)
case .inviteFriends:
// TODO: start invite people flow
flescio marked this conversation as resolved.
Show resolved Hide resolved
break
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation

@MainActor
protocol StartChatViewModelProtocol {
var callback: ((StartChatViewModelAction) -> Void)? { get set }
var context: StartChatViewModelType.Context { get }
}
Loading