Skip to content

Commit e7459f9

Browse files
authored
Merge pull request #674 from scenee/iss-673
I set the minimum support version to v12.0 because this library can be built on iOS 12 as well using compilation conditions.
2 parents edcf3ea + 5222c05 commit e7459f9

8 files changed

Lines changed: 71 additions & 9 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
fail-fast: false
3838
matrix:
3939
include:
40-
- os: "26.0"
40+
- os: "26.0.1"
4141
xcode: "26.0.1"
4242
sim: "iPhone 16 Pro"
4343
parallel: NO # Stop random test job failures

Examples/SamplesSwiftUI/SamplesSwiftUI/UseCases/MainView.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import FloatingPanel
44
import SwiftUI
55
import UIKit
6+
import os.log
67

78
struct MainView: View {
89
@State private var panelLayout: FloatingPanelLayout? = MyFloatingPanelLayout()
@@ -20,6 +21,9 @@ struct MainView: View {
2021
.floatingPanelSurfaceAppearance(.transparent())
2122
.floatingPanelLayout(panelLayout)
2223
.floatingPanelState($panelState)
24+
.onChange(of: panelState) { newValue in
25+
Logger().debug("Panel state changed: \(newValue ?? .hidden)")
26+
}
2327

2428
VStack(spacing: 32) {
2529
Button("Move to full") {

FloatingPanel.podspec

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ The new interface displays the related contents and utilities in parallel as a u
1111
s.author = "Shin Yamamoto"
1212
s.social_media_url = "https://x.com/scenee"
1313

14-
s.platform = :ios, "13.0"
14+
s.platform = :ios, "12.0"
1515
s.source = { :git => "https://github.com/scenee/FloatingPanel.git", :tag => s.version.to_s }
1616
s.source_files = "Sources/**/*.swift"
1717
s.swift_version = '5.0'
@@ -20,3 +20,4 @@ The new interface displays the related contents and utilities in parallel as a u
2020

2121
s.license = { :type => "MIT", :file => "LICENSE" }
2222
end
23+

FloatingPanel.xcodeproj/project.pbxproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@
523523
ENABLE_USER_SCRIPT_SANDBOXING = YES;
524524
INFOPLIST_FILE = Sources/Info.plist;
525525
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
526-
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
526+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
527527
LD_RUNPATH_SEARCH_PATHS = (
528528
"$(inherited)",
529529
"@executable_path/Frameworks",
@@ -556,7 +556,7 @@
556556
ENABLE_USER_SCRIPT_SANDBOXING = YES;
557557
INFOPLIST_FILE = Sources/Info.plist;
558558
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
559-
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
559+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
560560
LD_RUNPATH_SEARCH_PATHS = (
561561
"$(inherited)",
562562
"@executable_path/Frameworks",
@@ -694,7 +694,7 @@
694694
ENABLE_USER_SCRIPT_SANDBOXING = YES;
695695
INFOPLIST_FILE = Sources/Info.plist;
696696
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
697-
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
697+
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
698698
LD_RUNPATH_SEARCH_PATHS = (
699699
"$(inherited)",
700700
"@executable_path/Frameworks",

Package.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import PackageDescription
66
let package = Package(
77
name: "FloatingPanel",
88
platforms: [
9-
.iOS(.v13)
9+
.iOS(.v12)
1010
],
1111
products: [
1212
// Products define the executables and libraries produced by a package, and make them visible to other packages.
@@ -25,3 +25,4 @@ let package = Package(
2525
],
2626
swiftLanguageVersions: [.version("5")]
2727
)
28+

Sources/Core.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright 2018-Present Shin Yamamoto. All rights reserved. MIT license.
22

3+
#if canImport(Combine)
34
import Combine
5+
#endif
46
import UIKit
57
import os.log
68

@@ -50,7 +52,13 @@ class Core: NSObject, UIGestureRecognizerDelegate {
5052
}
5153
}
5254
}
53-
private(set) var statePublisher: CurrentValueSubject<FloatingPanelState, Never> = .init(.hidden)
55+
56+
@available(iOS 13.0, *)
57+
private(set) var statePublisher: CurrentValueSubject<FloatingPanelState, Never>? {
58+
get { _statePublisher as? CurrentValueSubject<FloatingPanelState, Never> }
59+
set { _statePublisher = newValue }
60+
}
61+
private var _statePublisher: Any?
5462

5563
var panGestureRecognizer: FloatingPanelPanGestureRecognizer
5664
let panGestureDelegateRouter: FloatingPanelPanGestureRecognizer.DelegateRouter
@@ -100,6 +108,10 @@ class Core: NSObject, UIGestureRecognizerDelegate {
100108

101109
super.init()
102110

111+
if #available(iOS 13.0, *) {
112+
statePublisher = .init(.hidden)
113+
}
114+
103115
panGestureRecognizer.set(floatingPanel: self)
104116
surfaceView.addGestureRecognizer(panGestureRecognizer)
105117
panGestureRecognizer.addTarget(self, action: #selector(handle(panGesture:)))
@@ -262,7 +274,9 @@ class Core: NSObject, UIGestureRecognizerDelegate {
262274
layoutAdapter.activateLayout(for: target, forceLayout: true)
263275
backdropView.alpha = getBackdropAlpha(for: target)
264276
adjustScrollContentInsetIfNeeded()
265-
statePublisher.send(target)
277+
if #available(iOS 13.0, *) {
278+
statePublisher?.send(target)
279+
}
266280
}
267281

268282
private func getBackdropAlpha(for target: FloatingPanelState) -> CGFloat {

Sources/SwiftUI/FloatingPanelView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ extension FloatingPanelCoordinatorProxy {
235235

236236
/// Start observing ``FloatingPanelController/state`` through the `Core` object.
237237
func observeStateChanges() {
238-
controller.floatingPanel.statePublisher
238+
controller.floatingPanel.statePublisher?
239239
.sink { [weak self] state in
240240
guard let self = self else { return }
241241
// Needs to update the state binding value on the next run loop cycle to avoid this error.

Tests/CoreTests.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// Copyright 2018 the FloatingPanel authors. All rights reserved. MIT license.
22

33
import XCTest
4+
#if canImport(Combine)
5+
import Combine
6+
#endif
47
@testable import FloatingPanel
58

69
class CoreTests: XCTestCase {
@@ -1022,6 +1025,45 @@ class CoreTests: XCTestCase {
10221025
XCTAssertEqual(fpc.surfaceLocation(for: .full).y, fpc.surfaceLocation.y)
10231026
XCTAssertEqual(delegate.willAttract, false)
10241027
}
1028+
1029+
@available(iOS 13.0, *)
1030+
func test_statePublisher() throws {
1031+
let fpc = FloatingPanelController()
1032+
fpc.showForTest()
1033+
1034+
XCTAssertEqual(fpc.state, .half)
1035+
1036+
// Verify statePublisher is available on iOS 13+
1037+
XCTAssertNotNil(fpc.floatingPanel.statePublisher)
1038+
1039+
var receivedStates: [FloatingPanelState] = []
1040+
var cancellables = Set<AnyCancellable>()
1041+
1042+
// Subscribe to statePublisher
1043+
fpc.floatingPanel.statePublisher?
1044+
.sink { state in
1045+
receivedStates.append(state)
1046+
}
1047+
.store(in: &cancellables)
1048+
1049+
// The initial state should be emitted first
1050+
XCTAssertEqual(receivedStates, [.half])
1051+
1052+
// Move to .full
1053+
fpc.move(to: .full, animated: false)
1054+
XCTAssertEqual(fpc.state, .full)
1055+
XCTAssertEqual(receivedStates, [.half, .full])
1056+
1057+
// Move to .tip
1058+
fpc.move(to: .tip, animated: false)
1059+
XCTAssertEqual(fpc.state, .tip)
1060+
XCTAssertEqual(receivedStates, [.half, .full, .tip])
1061+
1062+
// Move back to .half
1063+
fpc.move(to: .half, animated: false)
1064+
XCTAssertEqual(fpc.state, .half)
1065+
XCTAssertEqual(receivedStates, [.half, .full, .tip, .half])
1066+
}
10251067
}
10261068

10271069
private class FloatingPanelLayout3Positions: FloatingPanelTestLayout {

0 commit comments

Comments
 (0)