-
Notifications
You must be signed in to change notification settings - Fork 191
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #315 from WalletConnect/feature/chat-samplle-app-#298
[Showcase] Chat sample app template
- Loading branch information
Showing
64 changed files
with
1,906 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
20 changes: 20 additions & 0 deletions
20
Example/Showcase/Classes/ApplicationLayer/AppDelegate.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import UIKit | ||
|
||
@main | ||
class AppDelegate: UIResponder, UIApplicationDelegate { | ||
|
||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { | ||
// Override point for customization after application launch. | ||
return true | ||
} | ||
|
||
// MARK: UISceneSession Lifecycle | ||
|
||
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { | ||
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) | ||
} | ||
|
||
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) { | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import Foundation | ||
|
||
final class Application { | ||
|
||
let chatService: ChatService = { | ||
return ChatService() | ||
}() | ||
} |
8 changes: 8 additions & 0 deletions
8
Example/Showcase/Classes/ApplicationLayer/Configurator/AppearanceConfigurator.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import UIKit | ||
|
||
struct AppearanceConfigurator: Configurator { | ||
|
||
func configure() { | ||
|
||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
Example/Showcase/Classes/ApplicationLayer/Configurator/ApplicationConfigurator.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
struct ApplicationConfigurator: Configurator { | ||
|
||
private let app: Application | ||
|
||
init(app: Application) { | ||
self.app = app | ||
} | ||
|
||
func configure() { | ||
ChatListModule.create(app: app) | ||
.wrapToNavigationController() | ||
.present() | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
Example/Showcase/Classes/ApplicationLayer/Configurator/Configurator.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
protocol Configurator { | ||
func configure() | ||
} | ||
|
||
extension Array where Element == Configurator { | ||
func configure() { | ||
forEach { $0.configure() } | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
Example/Showcase/Classes/ApplicationLayer/Configurator/MigrationConfigurator.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
struct MigrationConfigurator: Configurator { | ||
|
||
let app: Application | ||
|
||
init(app: Application) { | ||
self.app = app | ||
} | ||
|
||
func configure() { | ||
|
||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
Example/Showcase/Classes/ApplicationLayer/Configurator/ThirdPartyConfigurator.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
struct ThirdPartyConfigurator: Configurator { | ||
|
||
func configure() { | ||
|
||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
Example/Showcase/Classes/ApplicationLayer/SceneDelegate.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import UIKit | ||
|
||
class SceneDelegate: UIResponder, UIWindowSceneDelegate { | ||
|
||
var window: UIWindow? | ||
|
||
private let app = Application() | ||
|
||
private var configurators: [Configurator] { | ||
return [ | ||
MigrationConfigurator(app: app), | ||
ApplicationConfigurator(app: app), | ||
AppearanceConfigurator(), | ||
ThirdPartyConfigurator() | ||
] | ||
} | ||
|
||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { | ||
guard let windowScene = (scene as? UIWindowScene) else { return } | ||
|
||
window = UIWindow(windowScene: windowScene) | ||
window?.makeKeyAndVisible() | ||
|
||
configurators.configure() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import Foundation | ||
import Combine | ||
|
||
typealias MessageStream = AsyncPublisher<AnyPublisher<[Message], Never>> | ||
|
||
final class ChatService { | ||
|
||
private let messagesSubject: CurrentValueSubject<[Message], Never> = { | ||
return CurrentValueSubject([ | ||
Message(message: "✨gm", authorAccount: "2", timestamp: 0), | ||
Message(message: "how r u man?", authorAccount: "1", timestamp: 0), | ||
Message(message: "good", authorAccount: "2", timestamp: 0), | ||
Message(message: "u?", authorAccount: "2", timestamp: 0), | ||
Message(message: "I’m so happy I have you as my best friend, and I love Lisa so much", authorAccount: "1", timestamp: 0), | ||
Message(message: "Why, Lisa, why, WHY?!", authorAccount: "2", timestamp: 0), | ||
Message(message: "It’s bullshit, I did not hit her. I did nooot. Oh hi, Mark!", authorAccount: "1", timestamp: 0), | ||
Message(message: "Johnny’s my best friend!", authorAccount: "2", timestamp: 0), | ||
Message(message: "Anyway, how’s your sex life?", authorAccount: "1", timestamp: 0) | ||
]) | ||
}() | ||
|
||
func getMessages(topic: String) -> MessageStream { | ||
return messagesSubject.eraseToAnyPublisher().values | ||
} | ||
|
||
func getAuthorAccount() async -> String { | ||
return "1" | ||
} | ||
|
||
func sendMessage(text: String) async throws { | ||
let authorAccount = await getAuthorAccount() | ||
let message = Message( | ||
message: text, | ||
authorAccount: authorAccount, | ||
timestamp: Int64(Date().timeIntervalSince1970) | ||
) | ||
messagesSubject.send(messagesSubject.value + [message]) | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
Example/Showcase/Classes/PresentationLayer/Chat/ChatInteractor.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
final class ChatInteractor { | ||
|
||
private let chatService: ChatService | ||
|
||
init(chatService: ChatService) { | ||
self.chatService = chatService | ||
} | ||
|
||
func getCurrentAccount() async -> String { | ||
return await chatService.getAuthorAccount() | ||
} | ||
|
||
func getMessages(topic: String) -> MessageStream { | ||
return chatService.getMessages(topic: topic) | ||
} | ||
|
||
func sendMessage(text: String) async throws { | ||
try await chatService.sendMessage(text: text) | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
Example/Showcase/Classes/PresentationLayer/Chat/ChatModule.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import SwiftUI | ||
|
||
final class ChatModule { | ||
|
||
@discardableResult | ||
static func create(app: Application) -> UIViewController { | ||
let router = ChatRouter(app: app) | ||
let interactor = ChatInteractor(chatService: app.chatService) | ||
let presenter = ChatPresenter(topic: "", interactor: interactor, router: router) | ||
let view = ChatView().environmentObject(presenter) | ||
let viewController = SceneViewController(viewModel: presenter, content: view) | ||
|
||
router.viewController = viewController | ||
|
||
return viewController | ||
} | ||
|
||
} |
55 changes: 55 additions & 0 deletions
55
Example/Showcase/Classes/PresentationLayer/Chat/ChatPresenter.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import UIKit | ||
import Combine | ||
|
||
final class ChatPresenter: ObservableObject { | ||
|
||
private let topic: String | ||
private let interactor: ChatInteractor | ||
private let router: ChatRouter | ||
private var disposeBag = Set<AnyCancellable>() | ||
|
||
@Published var messages: [MessageViewModel] = [] | ||
@Published var input: String = .empty | ||
|
||
init(topic: String, interactor: ChatInteractor, router: ChatRouter) { | ||
self.topic = topic | ||
self.interactor = interactor | ||
self.router = router | ||
} | ||
|
||
@MainActor | ||
func setupInitialState() async { | ||
let account = await interactor.getCurrentAccount() | ||
|
||
for await messages in interactor.getMessages(topic: topic) { | ||
self.messages = messages | ||
.sorted(by: { $0.timestamp < $1.timestamp }) | ||
.map { MessageViewModel(message: $0, currentAccount: account) } | ||
} | ||
} | ||
|
||
func didPressSend() { | ||
sendMessage() | ||
} | ||
} | ||
|
||
// MARK: SceneViewModel | ||
|
||
extension ChatPresenter: SceneViewModel { | ||
|
||
var sceneTitle: String? { | ||
return "Chat" | ||
} | ||
} | ||
|
||
// MARK: Privates | ||
|
||
private extension ChatPresenter { | ||
|
||
func sendMessage() { | ||
Task { | ||
try! await interactor.sendMessage(text: input) | ||
input = .empty | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
Example/Showcase/Classes/PresentationLayer/Chat/ChatRouter.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import UIKit | ||
|
||
final class ChatRouter { | ||
|
||
weak var viewController: UIViewController! | ||
|
||
private let app: Application | ||
|
||
init(app: Application) { | ||
self.app = app | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
Example/Showcase/Classes/PresentationLayer/Chat/ChatView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import SwiftUI | ||
|
||
struct ChatView: View { | ||
|
||
@EnvironmentObject var presenter: ChatPresenter | ||
|
||
var body: some View { | ||
ZStack { | ||
ChatScrollView { | ||
// TODO: Replace id | ||
ForEach(presenter.messages, id: \.text) { message in | ||
MessageView(message: message) | ||
} | ||
|
||
Spacer().frame(height: 72) | ||
} | ||
|
||
VStack { | ||
Spacer() | ||
|
||
HStack { | ||
InputView(title: "Message...", text: $presenter.input) { | ||
presenter.didPressSend() | ||
} | ||
.padding(16.0) | ||
} | ||
} | ||
} | ||
.task { | ||
await presenter.setupInitialState() | ||
} | ||
} | ||
} | ||
|
||
#if DEBUG | ||
struct ChatView_Previews: PreviewProvider { | ||
static var previews: some View { | ||
ChatView() | ||
} | ||
} | ||
#endif |
30 changes: 30 additions & 0 deletions
30
Example/Showcase/Classes/PresentationLayer/Chat/Models/MessageViewModel.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import Foundation | ||
|
||
// TODO: After Chat SDK integration | ||
struct Message: Codable, Equatable { | ||
let message: String | ||
let authorAccount: String | ||
let timestamp: Int64 | ||
} | ||
|
||
struct MessageViewModel { | ||
private let message: Message | ||
private let currentAccount: String | ||
|
||
init(message: Message, currentAccount: String) { | ||
self.message = message | ||
self.currentAccount = currentAccount | ||
} | ||
|
||
var isCurrentUser: Bool { | ||
return currentAccount == message.authorAccount | ||
} | ||
|
||
var text: String { | ||
return message.message | ||
} | ||
|
||
var showAvatar: Bool { | ||
return !isCurrentUser | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
Example/Showcase/Classes/PresentationLayer/Chat/Views/ChatScrollView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import SwiftUI | ||
|
||
struct ChatScrollView<Content>: View where Content: View { | ||
|
||
@ViewBuilder let content: () -> Content | ||
|
||
var body: some View { | ||
ScrollView(showsIndicators: false) { | ||
VStack(alignment: .leading, spacing: 12) { | ||
Spacer() | ||
.frame( | ||
minWidth: 0, | ||
maxWidth: .infinity, | ||
minHeight: 0, | ||
maxHeight: .infinity, | ||
alignment: .topLeading | ||
) | ||
|
||
content() | ||
} | ||
.rotationEffect(Angle(degrees: 180)) | ||
} | ||
.rotationEffect(Angle(degrees: 180)) | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
Example/Showcase/Classes/PresentationLayer/Chat/Views/ContentMessageView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import SwiftUI | ||
|
||
struct ContentMessageView: View { | ||
|
||
let text: String | ||
let isCurrentUser: Bool | ||
|
||
var body: some View { | ||
Text(text) | ||
.font(.body) | ||
.padding(.horizontal, 16.0) | ||
.padding(.vertical, 10.0) | ||
.foregroundColor(.white) | ||
.background( | ||
// TODO: Add border | ||
overlayView | ||
.foregroundColor(backgroundColor) | ||
) | ||
} | ||
|
||
private var overlayView: some View { | ||
return Rectangle() | ||
.cornerRadius(22, corners: [.topLeft, .topRight]) | ||
.cornerRadius(22, corners: isCurrentUser ? .bottomLeft : .bottomRight) | ||
.cornerRadius(4, corners: isCurrentUser ? .bottomRight : .bottomLeft) | ||
} | ||
|
||
private var backgroundColor: Color { | ||
return isCurrentUser ? .w_secondaryBackground : .w_purpleBackground | ||
} | ||
|
||
private var borderColor: Color { | ||
return isCurrentUser ? .w_tertiaryBackground : .w_purpleForeground | ||
} | ||
} |
Oops, something went wrong.