Skip to content

Commit f891e0e

Browse files
committed
fix: restore precise iOS stream navigation gestures
1 parent 1e33e89 commit f891e0e

5 files changed

Lines changed: 282 additions & 185 deletions

File tree

client/src/styles/components.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2377,6 +2377,7 @@
23772377
.device-screen-backing {
23782378
position: absolute;
23792379
background: #000000;
2380+
box-shadow: 0 0 0 2px #000000;
23802381
pointer-events: none;
23812382
z-index: 0;
23822383
}

ios/SimDeckStudio.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@
449449
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
450450
CODE_SIGN_ENTITLEMENTS = SimDeckStudio/SimDeckStudio.entitlements;
451451
CODE_SIGN_STYLE = Automatic;
452-
CURRENT_PROJECT_VERSION = 20260520002805;
452+
CURRENT_PROJECT_VERSION = 20260520015532;
453453
DEVELOPMENT_ASSET_PATHS = "";
454454
DEVELOPMENT_TEAM = CS838V553Y;
455455
ENABLE_PREVIEWS = YES;
@@ -478,7 +478,7 @@
478478
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
479479
CODE_SIGN_ENTITLEMENTS = SimDeckStudio/SimDeckStudio.entitlements;
480480
CODE_SIGN_STYLE = Automatic;
481-
CURRENT_PROJECT_VERSION = 20260520002805;
481+
CURRENT_PROJECT_VERSION = 20260520015532;
482482
DEVELOPMENT_ASSET_PATHS = "";
483483
DEVELOPMENT_TEAM = CS838V553Y;
484484
ENABLE_PREVIEWS = YES;

ios/SimDeckStudio/Views/ContentView.swift

Lines changed: 82 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,21 @@ struct ContentView: View {
1919
private func navigationContent(usesSearchAccessory: Bool) -> some View {
2020
if usesCompactRootNavigation {
2121
NavigationStack {
22-
if showsStreamDetail {
23-
SimulatorStreamView(model: model)
24-
} else {
25-
SidebarView(
26-
model: model,
27-
searchText: $searchText,
28-
searchExpanded: $searchExpanded,
29-
usesSearchAccessory: usesSearchAccessory
30-
)
22+
SidebarView(
23+
model: model,
24+
searchText: $searchText,
25+
searchExpanded: $searchExpanded,
26+
usesSearchAccessory: usesSearchAccessory,
27+
onSelectSimulator: { udid in
28+
model.selectSimulator(udid)
29+
}
30+
)
31+
.navigationDestination(isPresented: compactStreamPresented) {
32+
if showsStreamDetail {
33+
SimulatorStreamView(model: model)
34+
} else {
35+
Color.clear
36+
}
3137
}
3238
}
3339
} else {
@@ -45,6 +51,16 @@ struct ContentView: View {
4551
&& model.selectedSimulator != nil
4652
}
4753

54+
private var compactStreamPresented: Binding<Bool> {
55+
Binding {
56+
showsStreamDetail
57+
} set: { isPresented in
58+
if !isPresented {
59+
model.selectSimulator(nil)
60+
}
61+
}
62+
}
63+
4864
private func splitNavigationContent(usesSearchAccessory: Bool) -> some View {
4965
NavigationSplitView {
5066
SidebarView(
@@ -68,6 +84,7 @@ private struct SidebarView: View {
6884
@Binding var searchText: String
6985
@Binding var searchExpanded: Bool
7086
let usesSearchAccessory: Bool
87+
var onSelectSimulator: ((String) -> Void)?
7188
@State private var presentedSheet: SidebarSheet?
7289
@State private var isScanningPairingQR = false
7390
@State private var selectedSimulatorTypeFilter: SimulatorTypeFilter?
@@ -243,34 +260,72 @@ private struct SidebarView: View {
243260
.modifier(SidebarNavigationBarBackgroundModifier(hidden: usesIPadSidebarLayout))
244261
}
245262

263+
@ViewBuilder
246264
private var simulatorList: some View {
247-
List(selection: simulatorSelection) {
248-
simulatorRows
249-
}
250-
.refreshable {
251-
await model.refreshSimulators()
252-
}
253-
.contentMargins(
254-
.top,
255-
showsSimulatorTypeFilters ? simulatorFilterHeaderHeight : 0,
256-
for: .scrollContent
257-
)
258-
.background {
259-
RefreshControlOffsetProbe(offset: showsSimulatorTypeFilters ? simulatorFilterHeaderHeight : 0)
265+
if onSelectSimulator != nil {
266+
List {
267+
simulatorRows
268+
}
269+
.refreshable {
270+
await model.refreshSimulators()
271+
}
272+
.contentMargins(
273+
.top,
274+
showsSimulatorTypeFilters ? simulatorFilterHeaderHeight : 0,
275+
for: .scrollContent
276+
)
277+
.background {
278+
RefreshControlOffsetProbe(offset: showsSimulatorTypeFilters ? simulatorFilterHeaderHeight : 0)
279+
}
280+
} else {
281+
List(selection: simulatorSelection) {
282+
simulatorRows
283+
}
284+
.refreshable {
285+
await model.refreshSimulators()
286+
}
287+
.contentMargins(
288+
.top,
289+
showsSimulatorTypeFilters ? simulatorFilterHeaderHeight : 0,
290+
for: .scrollContent
291+
)
292+
.background {
293+
RefreshControlOffsetProbe(offset: showsSimulatorTypeFilters ? simulatorFilterHeaderHeight : 0)
294+
}
260295
}
261296
}
262297

263298
@ViewBuilder
264299
private var simulatorRows: some View {
265300
ForEach(filteredSimulators) { simulator in
266-
SimulatorRow(
267-
simulator: simulator,
268-
isBusy: model.isSimulatorLifecycleBusy(simulator)
269-
)
270-
.tag(simulator.udid)
301+
if let onSelectSimulator {
302+
Button {
303+
model.hapticSelection()
304+
onSelectSimulator(simulator.udid)
305+
} label: {
306+
SimulatorRow(
307+
simulator: simulator,
308+
isBusy: model.isSimulatorLifecycleBusy(simulator)
309+
)
310+
.frame(maxWidth: .infinity, alignment: .leading)
311+
.contentShape(Rectangle())
312+
}
313+
.buttonStyle(.plain)
271314
.contextMenu {
272315
SimulatorLifecycleMenuItems(model: model, simulator: simulator)
273316
}
317+
} else {
318+
SimulatorRow(
319+
simulator: simulator,
320+
isBusy: model.isSimulatorLifecycleBusy(simulator)
321+
)
322+
.frame(maxWidth: .infinity, alignment: .leading)
323+
.contentShape(Rectangle())
324+
.tag(simulator.udid)
325+
.contextMenu {
326+
SimulatorLifecycleMenuItems(model: model, simulator: simulator)
327+
}
328+
}
274329
}
275330
}
276331

0 commit comments

Comments
 (0)