Skip to content

Commit ce23420

Browse files
graycreateclaude
andcommitted
fix: use SafariView for all links instead of jumping out of app
Changed link opening behavior to match the "Open in Browser" button: - All links (internal V2EX and external) now open in SafariView - Stays within the app instead of jumping to Safari - Provides consistent user experience across the app Changes: - NewsContentView: Added SafariView sheet presentation - ReplyItemView: Added SafariView sheet presentation - Both views now use openInSafari() method - Removed UIApplication.shared.open() calls This matches the UX pattern used in FeedDetailPage's toolbar. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 279bfc4 commit ce23420

File tree

2 files changed

+41
-19
lines changed

2 files changed

+41
-19
lines changed

V2er/View/FeedDetail/NewsContentView.swift

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ struct NewsContentView: View {
1313
@Binding var rendered: Bool
1414
@EnvironmentObject var store: Store
1515
@Environment(\.colorScheme) var colorScheme
16-
@State private var navigationPath = NavigationPath()
16+
@State private var showingSafari = false
17+
@State private var safariURL: URL?
1718

1819
init(_ contentInfo: FeedDetailInfo.ContentInfo?, rendered: Binding<Bool>) {
1920
self.contentInfo = contentInfo
@@ -42,11 +43,15 @@ struct NewsContentView: View {
4243

4344
Divider()
4445
}
46+
.sheet(isPresented: $showingSafari) {
47+
if let url = safariURL {
48+
SafariView(url: url)
49+
}
50+
}
4551
}
4652

4753
private func handleLinkTap(_ url: URL) {
4854
// Smart URL routing - parse V2EX URLs and route accordingly
49-
let urlString = url.absoluteString
5055
let path = url.path
5156

5257
// Check if it's a V2EX internal link
@@ -55,37 +60,42 @@ struct NewsContentView: View {
5560
if path.contains("/t/"), let topicId = extractTopicId(from: path) {
5661
print("Navigate to topic: \(topicId)")
5762
// TODO: Use proper navigation to FeedDetailPage(id: topicId)
58-
// For now, open in Safari
59-
UIApplication.shared.open(url)
63+
// For now, open in SafariView
64+
openInSafari(url)
6065
return
6166
}
6267

6368
// Member: /member/username
6469
if path.contains("/member/"), let username = extractUsername(from: path) {
6570
print("Navigate to user: \(username)")
6671
// TODO: Use proper navigation to UserDetailPage(userId: username)
67-
// For now, open in Safari
68-
UIApplication.shared.open(url)
72+
// For now, open in SafariView
73+
openInSafari(url)
6974
return
7075
}
7176

7277
// Node: /go/nodename
7378
if path.contains("/go/"), let nodeName = extractNodeName(from: path) {
7479
print("Navigate to node: \(nodeName)")
7580
// TODO: Use proper navigation to TagDetailPage
76-
// For now, open in Safari
77-
UIApplication.shared.open(url)
81+
// For now, open in SafariView
82+
openInSafari(url)
7883
return
7984
}
8085

81-
// Other V2EX pages - open in Safari
82-
UIApplication.shared.open(url)
86+
// Other V2EX pages - open in SafariView
87+
openInSafari(url)
8388
} else {
84-
// External link - open in Safari
85-
UIApplication.shared.open(url)
89+
// External link - open in SafariView (stays in app)
90+
openInSafari(url)
8691
}
8792
}
8893

94+
private func openInSafari(_ url: URL) {
95+
safariURL = url
96+
showingSafari = true
97+
}
98+
8999
private func extractTopicId(from path: String) -> String? {
90100
let pattern = "/t/(\\d+)"
91101
guard let regex = try? NSRegularExpression(pattern: pattern),

V2er/View/FeedDetail/ReplyItemView.swift

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ struct ReplyItemView: View {
1414
var info: FeedDetailInfo.ReplyInfo.Item
1515
@EnvironmentObject var store: Store
1616
@Environment(\.colorScheme) var colorScheme
17+
@State private var showingSafari = false
18+
@State private var safariURL: URL?
1719

1820
var body: some View {
1921
HStack(alignment: .top) {
@@ -66,6 +68,11 @@ struct ReplyItemView: View {
6668
}
6769
}
6870
.padding(.horizontal, 12)
71+
.sheet(isPresented: $showingSafari) {
72+
if let url = safariURL {
73+
SafariView(url: url)
74+
}
75+
}
6976
}
7077

7178
private func handleLinkTap(_ url: URL) {
@@ -78,34 +85,39 @@ struct ReplyItemView: View {
7885
if path.contains("/t/"), let topicId = extractTopicId(from: path) {
7986
print("Navigate to topic: \(topicId)")
8087
// TODO: Use proper navigation to FeedDetailPage(id: topicId)
81-
UIApplication.shared.open(url)
88+
openInSafari(url)
8289
return
8390
}
8491

8592
// Member: /member/username
8693
if path.contains("/member/"), let username = extractUsername(from: path) {
8794
print("Navigate to user: \(username)")
8895
// TODO: Use proper navigation to UserDetailPage(userId: username)
89-
UIApplication.shared.open(url)
96+
openInSafari(url)
9097
return
9198
}
9299

93100
// Node: /go/nodename
94101
if path.contains("/go/"), let nodeName = extractNodeName(from: path) {
95102
print("Navigate to node: \(nodeName)")
96103
// TODO: Use proper navigation to TagDetailPage
97-
UIApplication.shared.open(url)
104+
openInSafari(url)
98105
return
99106
}
100107

101-
// Other V2EX pages - open in Safari
102-
UIApplication.shared.open(url)
108+
// Other V2EX pages - open in SafariView
109+
openInSafari(url)
103110
} else {
104-
// External link - open in Safari
105-
UIApplication.shared.open(url)
111+
// External link - open in SafariView (stays in app)
112+
openInSafari(url)
106113
}
107114
}
108115

116+
private func openInSafari(_ url: URL) {
117+
safariURL = url
118+
showingSafari = true
119+
}
120+
109121
private func extractTopicId(from path: String) -> String? {
110122
let pattern = "/t/(\\d+)"
111123
guard let regex = try? NSRegularExpression(pattern: pattern),

0 commit comments

Comments
 (0)