diff --git a/ios/PushDeer-iOS/PushDeer.xcodeproj/project.pbxproj b/ios/PushDeer-iOS/PushDeer.xcodeproj/project.pbxproj index 51cf733..f5eda93 100644 --- a/ios/PushDeer-iOS/PushDeer.xcodeproj/project.pbxproj +++ b/ios/PushDeer-iOS/PushDeer.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 52163EBB277741AC00594190 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52163EBA277741AC00594190 /* SettingsView.swift */; }; 523150D9277875FB00941EDC /* DeletableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 523150D8277875FB00941EDC /* DeletableView.swift */; }; 523150DC2778762B00941EDC /* DeviceItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 523150DB2778762B00941EDC /* DeviceItemView.swift */; }; + 5240023427F371EF00C245CF /* BetterSafariView in Frameworks */ = {isa = PBXBuildFile; productRef = 5240023327F371EF00C245CF /* BetterSafariView */; }; 5242C872278C8CBB00FDB27E /* EditableText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5242C871278C8CBB00FDB27E /* EditableText.swift */; }; 5242C873278C8CBB00FDB27E /* EditableText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5242C871278C8CBB00FDB27E /* EditableText.swift */; }; 5243372727A6D86200190D00 /* Env.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5243372627A6D86200190D00 /* Env.swift */; }; @@ -69,6 +70,7 @@ 52B8CF85277E0C12004CB680 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52EB90B22778DA4E0048E0ED /* Line.swift */; }; 52B8CF86277E0C12004CB680 /* BaseNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52EB90AD2778AFD60048E0ED /* BaseNavigationView.swift */; }; 52B8CF87277E0C5C004CB680 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5292F4FC2776BC7A00B9A7BB /* Assets.xcassets */; }; + 52B8FB8727F36F9D00C29D13 /* BetterSafariView in Frameworks */ = {isa = PBXBuildFile; productRef = 52B8FB8627F36F9D00C29D13 /* BetterSafariView */; }; 52E317D9279305BB000B8BB1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 52E317D7279305BB000B8BB1 /* InfoPlist.strings */; }; 52E317DC279305BB000B8BB1 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 52E317DA279305BB000B8BB1 /* Localizable.strings */; }; 52E317DF279305BB000B8BB1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 52E317DD279305BB000B8BB1 /* InfoPlist.strings */; }; @@ -184,6 +186,7 @@ buildActionMask = 2147483647; files = ( 64B0C15E70CCC382B480F76E /* Pods_PushDeer.framework in Frameworks */, + 52B8FB8727F36F9D00C29D13 /* BetterSafariView in Frameworks */, 5287FF52278ADC8C00249A0E /* MarkdownUI in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -193,6 +196,7 @@ buildActionMask = 2147483647; files = ( 4812F19BB0BFEFE089BC253E /* Pods_PushDeerClip.framework in Frameworks */, + 5240023427F371EF00C245CF /* BetterSafariView in Frameworks */, 5287FF54278AEA5B00249A0E /* MarkdownUI in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -385,6 +389,7 @@ name = PushDeer; packageProductDependencies = ( 5287FF51278ADC8C00249A0E /* MarkdownUI */, + 52B8FB8627F36F9D00C29D13 /* BetterSafariView */, ); productName = PushDeer; productReference = 5292F4F52776BC7900B9A7BB /* PushDeer.app */; @@ -407,6 +412,7 @@ name = PushDeerClip; packageProductDependencies = ( 5287FF53278AEA5B00249A0E /* MarkdownUI */, + 5240023327F371EF00C245CF /* BetterSafariView */, ); productName = PushDeerClip; productReference = 52B8CF64277E0B44004CB680 /* PushDeerClip.app */; @@ -444,6 +450,7 @@ mainGroup = 5292F4EC2776BC7900B9A7BB; packageReferences = ( 5287FF50278ADC8C00249A0E /* XCRemoteSwiftPackageReference "MarkdownUI" */, + 52B8FB8527F36F9D00C29D13 /* XCRemoteSwiftPackageReference "BetterSafariView" */, ); productRefGroup = 5292F4F62776BC7900B9A7BB /* Products */; projectDirPath = ""; @@ -1306,9 +1313,22 @@ minimumVersion = 1.1.0; }; }; + 52B8FB8527F36F9D00C29D13 /* XCRemoteSwiftPackageReference "BetterSafariView" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/stleamist/BetterSafariView.git"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 2.4.0; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 5240023327F371EF00C245CF /* BetterSafariView */ = { + isa = XCSwiftPackageProductDependency; + package = 52B8FB8527F36F9D00C29D13 /* XCRemoteSwiftPackageReference "BetterSafariView" */; + productName = BetterSafariView; + }; 5287FF51278ADC8C00249A0E /* MarkdownUI */ = { isa = XCSwiftPackageProductDependency; package = 5287FF50278ADC8C00249A0E /* XCRemoteSwiftPackageReference "MarkdownUI" */; @@ -1319,6 +1339,11 @@ package = 5287FF50278ADC8C00249A0E /* XCRemoteSwiftPackageReference "MarkdownUI" */; productName = MarkdownUI; }; + 52B8FB8627F36F9D00C29D13 /* BetterSafariView */ = { + isa = XCSwiftPackageProductDependency; + package = 52B8FB8527F36F9D00C29D13 /* XCRemoteSwiftPackageReference "BetterSafariView" */; + productName = BetterSafariView; + }; /* End XCSwiftPackageProductDependency section */ /* Begin XCVersionGroup section */ diff --git a/ios/PushDeer-iOS/PushDeer.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/PushDeer-iOS/PushDeer.xcworkspace/xcshareddata/swiftpm/Package.resolved index 770fc5a..4f21823 100644 --- a/ios/PushDeer-iOS/PushDeer.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ios/PushDeer-iOS/PushDeer.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,61 +1,68 @@ { - "object": { - "pins": [ - { - "package": "AttributedText", - "repositoryURL": "https://github.com/gonzalezreal/AttributedText", - "state": { - "branch": null, - "revision": "2dc2d7864e0fee4b524a5850d7d7cf9a7eeda0fc", - "version": "1.0.0" - } - }, - { - "package": "combine-schedulers", - "repositoryURL": "https://github.com/pointfreeco/combine-schedulers", - "state": { - "branch": null, - "revision": "4cf088c29a20f52be0f2ca54992b492c54e0076b", - "version": "0.5.3" - } - }, - { - "package": "MarkdownUI", - "repositoryURL": "https://github.com/gonzalezreal/MarkdownUI", - "state": { - "branch": null, - "revision": "4c164300337a35d002188a83a878346819b203c0", - "version": "1.1.0" - } - }, - { - "package": "NetworkImage", - "repositoryURL": "https://github.com/gonzalezreal/NetworkImage", - "state": { - "branch": null, - "revision": "f8b8ed0be39d2f4aa00a6e8d3b18a62a94eff8d8", - "version": "4.0.0" - } - }, - { - "package": "SwiftCommonMark", - "repositoryURL": "https://github.com/gonzalezreal/SwiftCommonMark", - "state": { - "branch": null, - "revision": "ed252beaddecce28ea6363f800c773d6169011b8", - "version": "1.0.0" - } - }, - { - "package": "xctest-dynamic-overlay", - "repositoryURL": "https://github.com/pointfreeco/xctest-dynamic-overlay", - "state": { - "branch": null, - "revision": "50a70a9d3583fe228ce672e8923010c8df2deddd", - "version": "0.2.1" - } + "pins" : [ + { + "identity" : "attributedtext", + "kind" : "remoteSourceControl", + "location" : "https://github.com/gonzalezreal/AttributedText", + "state" : { + "revision" : "2dc2d7864e0fee4b524a5850d7d7cf9a7eeda0fc", + "version" : "1.0.0" } - ] - }, - "version": 1 + }, + { + "identity" : "bettersafariview", + "kind" : "remoteSourceControl", + "location" : "https://github.com/stleamist/BetterSafariView.git", + "state" : { + "revision" : "be7248720af18c57c7a1348b20f6212379b28c6b", + "version" : "2.4.0" + } + }, + { + "identity" : "combine-schedulers", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/combine-schedulers", + "state" : { + "revision" : "4cf088c29a20f52be0f2ca54992b492c54e0076b", + "version" : "0.5.3" + } + }, + { + "identity" : "markdownui", + "kind" : "remoteSourceControl", + "location" : "https://github.com/gonzalezreal/MarkdownUI", + "state" : { + "revision" : "4c164300337a35d002188a83a878346819b203c0", + "version" : "1.1.0" + } + }, + { + "identity" : "networkimage", + "kind" : "remoteSourceControl", + "location" : "https://github.com/gonzalezreal/NetworkImage", + "state" : { + "revision" : "f8b8ed0be39d2f4aa00a6e8d3b18a62a94eff8d8", + "version" : "4.0.0" + } + }, + { + "identity" : "swiftcommonmark", + "kind" : "remoteSourceControl", + "location" : "https://github.com/gonzalezreal/SwiftCommonMark", + "state" : { + "revision" : "ed252beaddecce28ea6363f800c773d6169011b8", + "version" : "1.0.0" + } + }, + { + "identity" : "xctest-dynamic-overlay", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "state" : { + "revision" : "50a70a9d3583fe228ce672e8923010c8df2deddd", + "version" : "0.2.1" + } + } + ], + "version" : 2 } diff --git a/ios/PushDeer-iOS/PushDeer/Common/SafariView.swift b/ios/PushDeer-iOS/PushDeer/Common/SafariView.swift index 3757ed2..710dbc7 100644 --- a/ios/PushDeer-iOS/PushDeer/Common/SafariView.swift +++ b/ios/PushDeer-iOS/PushDeer/Common/SafariView.swift @@ -8,7 +8,7 @@ import SwiftUI import SafariServices -struct SafariView: UIViewControllerRepresentable { +struct HSafariView: UIViewControllerRepresentable { let url: URL diff --git a/ios/PushDeer-iOS/PushDeer/Service/AppState.swift b/ios/PushDeer-iOS/PushDeer/Service/AppState.swift index bcfe920..5d33992 100644 --- a/ios/PushDeer-iOS/PushDeer/Service/AppState.swift +++ b/ios/PushDeer-iOS/PushDeer/Service/AppState.swift @@ -43,6 +43,12 @@ class AppState: ObservableObject { UserDefaults.standard.set(isUseBuiltInBrowser, forKey: "PushDeer_isUseBuiltInBrowser") } } + /// MarkDown BaseURL + @Published var markDownBaseURL: String? { + didSet { + UserDefaults.standard.set(markDownBaseURL, forKey: "PushDeer_markDownBaseURL") + } + } /// API endpoint @Published var api_endpoint : String { @@ -66,11 +72,13 @@ class AppState: ObservableObject { let _tabSelectedIndex = UserDefaults.standard.integer(forKey: "PushDeer_tabSelectedIndex") let _isShowTestPush = UserDefaults.standard.object(forKey: "PushDeer_isShowTestPush") let _isUseBuiltInBrowser = UserDefaults.standard.object(forKey: "PushDeer_isUseBuiltInBrowser") + let _markDownBaseURL = UserDefaults.standard.string(forKey: "PushDeer_markDownBaseURL") let _api_endpoint = UserDefaults.standard.string(forKey: "PushDeer_api_endpoint") token = _token ?? "" tabSelectedIndex = _tabSelectedIndex isShowTestPush = _isShowTestPush as? Bool ?? true isUseBuiltInBrowser = _isUseBuiltInBrowser as? Bool ?? true + markDownBaseURL = _markDownBaseURL api_endpoint = _api_endpoint ?? "" } diff --git a/ios/PushDeer-iOS/PushDeer/View/MessageItemView.swift b/ios/PushDeer-iOS/PushDeer/View/MessageItemView.swift index 99ceed9..682811e 100644 --- a/ios/PushDeer-iOS/PushDeer/View/MessageItemView.swift +++ b/ios/PushDeer-iOS/PushDeer/View/MessageItemView.swift @@ -9,6 +9,7 @@ import SwiftUI import MarkdownUI import SDWebImageSwiftUI import Photos +import BetterSafariView struct MessageItemView: View { let messageItem: MessageModel @@ -35,7 +36,7 @@ struct MessageItemView: View { } DeletableView(contentView: { - MessageContentView(messageItem: messageItem) + MessageContentView(messageItem: messageItem, deleteAction: deleteAction) }, deleteAction: deleteAction) .padding(messageItem.type == "image" ? EdgeInsets.init() : EdgeInsets(top: 10, leading: 26, bottom: 0, trailing: 24)) @@ -44,23 +45,30 @@ struct MessageItemView: View { } } -extension URL: Identifiable { - public var id: Self { self } -} +//extension URL: Identifiable { +// public var id: Self { self } +//} struct MessageContentView: View { let messageItem: MessageModel + /// 删除按钮点击的回调 + let deleteAction : () -> () @EnvironmentObject private var store: AppState @State private var image: PlatformImage? = nil @State private var showUrl: URL? @State private var showActionSheet = false + func getMarkDownBaseURL() -> URL? { + let urlStr = store.markDownBaseURL ?? "https://example.com/" + return URL(string: urlStr) + } + var body: some View { switch messageItem.type { case "markdown": CardView { VStack(alignment: .leading, spacing: 5) { - Markdown(messageItem.text ?? "") + Markdown(messageItem.text ?? "", baseURL: getMarkDownBaseURL()) .markdownStyle( MarkdownStyle( font: .system(size: 14), @@ -77,7 +85,7 @@ struct MessageContentView: View { } #endif if !(messageItem.desp?.isEmpty ?? true) { - Markdown(messageItem.desp ?? "") + Markdown(messageItem.desp ?? "", baseURL: getMarkDownBaseURL()) .markdownStyle( MarkdownStyle( font: .system(size: 14), @@ -104,6 +112,12 @@ struct MessageContentView: View { } label: { Label("复制",systemImage: "doc.on.doc") } +#if targetEnvironment(macCatalyst) + Divider() + Button(action: deleteAction) { + Label("删除",systemImage: "trash.slash") + } +#endif } //#endif //#if !targetEnvironment(macCatalyst) @@ -122,11 +136,14 @@ struct MessageContentView: View { // } //#endif } - .fullScreenCover(item: $showUrl) { - - } content: { url in + .safariView(item: $showUrl, content: { url in SafariView(url: url) - } + }) +// .fullScreenCover(item: $showUrl) { +// +// } content: { url in +// HSafariView(url: url) +// } case "image": WebImage(url: URL(string: messageItem.text ?? "")) @@ -181,6 +198,12 @@ struct MessageContentView: View { } label: { Label("保存图片",systemImage: "square.and.arrow.down") } +#if targetEnvironment(macCatalyst) + Divider() + Button(action: deleteAction) { + Label("删除",systemImage: "trash.slash") + } +#endif } default: @@ -206,6 +229,12 @@ struct MessageContentView: View { } label: { Label("复制",systemImage: "doc.on.doc") } +#if targetEnvironment(macCatalyst) + Divider() + Button(action: deleteAction) { + Label("删除",systemImage: "trash.slash") + } +#endif } } } diff --git a/ios/PushDeer-iOS/PushDeer/View/SettingsView.swift b/ios/PushDeer-iOS/PushDeer/View/SettingsView.swift index 8883f06..e18730e 100644 --- a/ios/PushDeer-iOS/PushDeer/View/SettingsView.swift +++ b/ios/PushDeer-iOS/PushDeer/View/SettingsView.swift @@ -7,6 +7,7 @@ import SwiftUI import AuthenticationServices +import BetterSafariView //import StoreKit /// 设置界面 @@ -72,6 +73,34 @@ struct SettingsView: View { .padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20)) #endif + CardView { + VStack(alignment: .leading, spacing: 5){ + Text("MarkDown BaseURL: (Image/Link)") + .font(.system(size: 18)) + .foregroundColor(Color("textColor")) + EditableText(placeholder: "https://example.com/", value: store.markDownBaseURL ?? "") { value in + if value.isEmpty { + store.markDownBaseURL = nil; + HToast.showSuccess(NSLocalizedString("保存成功", comment: "")) + return + } + if URL(string: value) == nil { + HToast.showError(NSLocalizedString("URL 格式不正确", comment: "")) + return + } + if !value.lowercased().hasPrefix("http") { + HToast.showError(NSLocalizedString("请输入协议前缀: http:// 或 https://", comment: "")) + return + } + store.markDownBaseURL = value + HToast.showSuccess(NSLocalizedString("保存成功", comment: "")) + } + } + .padding(16) + .frame(height: 74) + } + .padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20)) + Spacer() } } @@ -84,11 +113,14 @@ struct SettingsView: View { store.userInfo = try await HttpRequest.getUserInfo() } } - .fullScreenCover(item: $showUrl) { - - } content: { url in + .safariView(item: $showUrl, content: { url in SafariView(url: url) - } + }) +// .fullScreenCover(item: $showUrl) { +// +// } content: { url in +// HSafariView(url: url) +// } } func userName() -> String {