Skip to content

Commit

Permalink
feat: add macOS support (#60)
Browse files Browse the repository at this point in the history
* Update ChatView.swift

* Update ChatUser.swift

* Update ImageCell.swift

* Update ContactCell.swift

* Update BasicInputView.swift

* Update PlayerView.swift

* Update AvatarModifier.swift

* Update ContactItem.swift

* Update ChatMessageKind.swift

* Update MockMessages.swift

* Update ImageCell.swift

* Update CustomPlayerView.swift

* Update ChatView.swift

* Update PIPVideoCell.swift

* Update CustomVideoPlayer.swift

* refactor: add swiftUI example app, remove old UIKit generated app

* refactor: remove some redundant code

* fix: correct macOS video player
  • Loading branch information
EnesKaraosman authored Apr 12, 2024
1 parent ec6300e commit 6c871e8
Show file tree
Hide file tree
Showing 41 changed files with 465 additions and 783 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/swift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,3 @@ jobs:

- name: Build
run: swift build -v

- name: Run tests
run: swift test -v

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ struct AdvancedExampleView: View {
@State private var message = ""

var body: some View {
NavigationView {
chatView
}
chatView
}

private var chatView: some View {
Expand Down Expand Up @@ -84,8 +82,9 @@ struct AdvancedExampleView: View {
})
// ▼ Required
.environmentObject(ChatMessageCellStyle())
.navigationBarHidden(true)
.navigationBarTitle("")
#if os(iOS)
.navigationBarTitle("Advanced")
#endif
.listStyle(PlainListStyle())
.onAppear {

Expand Down
13 changes: 13 additions & 0 deletions Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ struct BasicExampleView: View {

@State var messages: [MockMessages.ChatMessageItem] = MockMessages.generateMessage(kind: .Text, count: 20)

// MARK: - InputBarView variables
@State private var message = ""

var body: some View {
Expand All @@ -31,9 +30,7 @@ struct BasicExampleView: View {
)
}
)
.accentColor(.chatBlue)
.background(Color.primary.colorInvert())
.animation(.linear)
.embedInAnyView()

}
Expand All @@ -43,7 +40,13 @@ struct BasicExampleView: View {
case .text(let text):
return Button(action: {
print("Copy Context Menu tapped!!")
#if os(iOS)
UIPasteboard.general.string = text
#endif

#if os(macOS)
NSPasteboard.general.setString(text, forType: .string)
#endif
}) {
Text("Copy")
Image(systemName: "doc.on.doc")
Expand All @@ -56,7 +59,9 @@ struct BasicExampleView: View {
}
// ▼ Required
.environmentObject(ChatMessageCellStyle.basicStyle)
#if os(iOS)
.navigationBarTitle("Basic")
#endif
.listStyle(PlainListStyle())
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ struct ChatListView: View {
NavigationLink("Basic Example", destination: BasicExampleView())
NavigationLink("Advanced Example", destination: AdvancedExampleView())
}
.navigationBarTitle("SwiftyChats")
}
}
}
Expand Down
17 changes: 17 additions & 0 deletions Example/Example/ExampleApp.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// ExampleApp.swift
// Example
//
// Created by Enes Karaosman on 10.04.2024.
//

import SwiftUI

@main
struct ExampleApp: App {
var body: some Scene {
WindowGroup {
ChatListView()
}
}
}
File renamed without changes.
11 changes: 11 additions & 0 deletions Example/Example/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>
78 changes: 29 additions & 49 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,52 +1,32 @@
{
"object": {
"pins": [
{
"package": "GSPlayer",
"repositoryURL": "https://github.com/wxxsw/GSPlayer.git",
"state": {
"branch": null,
"revision": "706fc28fcc8e33607993903eca82d9f6c7c3f6d2",
"version": "0.2.27"
}
},
{
"package": "Kingfisher",
"repositoryURL": "https://github.com/onevcat/Kingfisher.git",
"state": {
"branch": null,
"revision": "add0a87ec4e31e2ca2a0b2085f0559201e4f5918",
"version": "7.10.1"
}
},
{
"package": "SwiftUIEKtensions",
"repositoryURL": "https://github.com/EnesKaraosman/SwiftUIEKtensions.git",
"state": {
"branch": null,
"revision": "21421df3266c99b83992face9e1523c8f1acb924",
"version": "0.2.0"
}
},
{
"package": "VideoPlayer",
"repositoryURL": "https://github.com/wxxsw/VideoPlayer.git",
"state": {
"branch": null,
"revision": "0a271928849292713daf471398a2a9185f28709c",
"version": "1.2.4"
}
},
{
"package": "WrappingHStack",
"repositoryURL": "https://github.com/dkk/WrappingHStack.git",
"state": {
"branch": null,
"revision": "425d9488ba55f58f0b34498c64c054c77fc2a44b",
"version": "2.2.11"
}
"pins" : [
{
"identity" : "kingfisher",
"kind" : "remoteSourceControl",
"location" : "https://github.com/onevcat/Kingfisher.git",
"state" : {
"revision" : "5b92f029fab2cce44386d28588098b5be0824ef5",
"version" : "7.11.0"
}
]
},
"version": 1
},
{
"identity" : "swiftuiektensions",
"kind" : "remoteSourceControl",
"location" : "https://github.com/EnesKaraosman/SwiftUIEKtensions.git",
"state" : {
"revision" : "bf96c0d841d2bc81dac0d7e28aa9ab71cd7d6c2a",
"version" : "0.4.0"
}
},
{
"identity" : "wrappinghstack",
"kind" : "remoteSourceControl",
"location" : "https://github.com/dkk/WrappingHStack.git",
"state" : {
"revision" : "425d9488ba55f58f0b34498c64c054c77fc2a44b",
"version" : "2.2.11"
}
}
],
"version" : 2
}
51 changes: 31 additions & 20 deletions Sources/SwiftyChat/ChatView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@ public struct ChatView<Message: ChatMessage, User: ChatUser>: View {

PIPVideoCell<Message>()
}
.iOSOnlyModifier { $0.keyboardAwarePadding() }
.keyboardAwarePadding() // iOS only
}
#if os(iOS)
.environmentObject(DeviceOrientationInfo())
#endif
.environmentObject(VideoManager<Message>())
.edgesIgnoringSafeArea(.bottom)
.iOSOnlyModifier { $0.dismissKeyboardOnTappingOutside() }
.dismissKeyboardOnTappingOutside() // iOS only
}

@ViewBuilder private func chatView(in geometry: GeometryProxy) -> some View {
Expand Down Expand Up @@ -107,23 +109,27 @@ public struct ChatView<Message: ChatMessage, User: ChatUser>: View {
scrollTo = nil
}
}
.iOSOnlyModifier {
// Auto Scroll with Keyboard Notification
$0.onReceive(
NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)
.debounce(for: .milliseconds(400), scheduler: RunLoop.main),
perform: { _ in
if !isKeyboardActive {
isKeyboardActive = true
scrollToBottom = true
}
#if os(iOS)
// Auto Scroll with Keyboard Notification
.onReceive(
NotificationCenter
.default
.publisher(for: UIResponder.keyboardWillShowNotification)
.debounce(for: .milliseconds(400), scheduler: RunLoop.main),
perform: { _ in
if !isKeyboardActive {
isKeyboardActive = true
scrollToBottom = true
}
)
.onReceive(
NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification),
perform: { _ in isKeyboardActive = false }
)
}
}
)
.onReceive(
NotificationCenter
.default
.publisher(for: UIResponder.keyboardWillHideNotification),
perform: { _ in isKeyboardActive = false }
)
#endif
}
}
.background(Color.clear)
Expand Down Expand Up @@ -186,10 +192,15 @@ public extension ChatView {
}

if let messageIndex = messages.firstIndex(where: { $0.id == thisMessage.id }) {
if messageIndex == 0 { return true }
if messageIndex == 0 {
return true
}

let prevMessageUserID = messages[messageIndex].user.id
let currMessageUserID = messages[messageIndex - 1].user.id
return !(prevMessageUserID == currMessageUserID)
let isDifferentUser = prevMessageUserID != currMessageUserID

return isDifferentUser
}

return false
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftyChat/Common/Modifiers/AvatarModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ internal struct AvatarModifier<Message: ChatMessage, User: ChatUser>: ViewModifi
} else if let imageURL = user.avatarURL, currentStyle.imageStyle.imageSize.width > 0 {
KFImage(imageURL).resizable()
} else if let avatar = user.avatar, currentStyle.imageStyle.imageSize.width > 0 {
Image(uiImage: avatar).resizable()
Image(image: avatar).resizable()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,58 +7,8 @@

import SwiftUI

// Use below approach, when handle pushing content up when keyboard appears.
// Investigate keyboardAwarePadding() modifier, it does actually its job
// But some how its broken with current as-is

#if os(iOS)
internal extension UIApplication {
func addTapGestureRecognizer() {
let scenes = UIApplication.shared.connectedScenes
let windowScene = scenes.first as? UIWindowScene
guard let window = windowScene?.windows.first else { return }
let tapGesture = AnyGestureRecognizer(target: window, action:#selector(UIView.endEditing))
tapGesture.requiresExclusiveTouchType = false
tapGesture.cancelsTouchesInView = false
tapGesture.delegate = self // I don't use window as delegate to minimize possible side effects
window.addGestureRecognizer(tapGesture)
}
}

extension UIApplication: UIGestureRecognizerDelegate {
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true // set to `false` if you don't want to detect tap during other gestures
}
}

internal final class AnyGestureRecognizer: UIGestureRecognizer {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
if let touchedView = touches.first?.view, touchedView is UIControl {
state = .cancelled

} else if let touchedView = touches.first?.view as? UITextView, touchedView.isEditable {
state = .cancelled
} else if let touchedView = touches.first?.view as? UIButton, touchedView.isSelected {
state = .cancelled
} else {
state = .began
}
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
state = .ended
}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
state = .cancelled
}
}
#endif

// -----

internal extension View {
dynamic func dismissKeyboardOnTappingOutside() -> some View {
func dismissKeyboardOnTappingOutside() -> some View {
return ModifiedContent(content: self, modifier: DismissKeyboardOnTappingOutside())
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@
// Copyright © 2020 All rights reserved.
//

#if os(iOS)
import Combine
import SwiftUI
import SwiftUIEKtensions

internal extension View {
/// iOS only modifier to add necessary padding according to keyboard height
func keyboardAwarePadding() -> some View {
#if os(iOS)
ModifiedContent(content: self, modifier: KeyboardAwareModifier())
#else
self
#endif
}
}

Expand All @@ -28,4 +32,3 @@ struct KeyboardAwareModifier: ViewModifier {
}
}
}
#endif
Loading

0 comments on commit 6c871e8

Please sign in to comment.