mac版本支持右键删除消息

应用内打开网页使用 BetterSafariView
修复markdown中图片出现相对路径时, 界面会卡死的问题
This commit is contained in:
hext 2022-03-30 01:45:02 +08:00
parent 0ec3bbc7cc
commit 69ec4f3774
6 changed files with 174 additions and 73 deletions

View File

@ -15,6 +15,7 @@
52163EBB277741AC00594190 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52163EBA277741AC00594190 /* SettingsView.swift */; }; 52163EBB277741AC00594190 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52163EBA277741AC00594190 /* SettingsView.swift */; };
523150D9277875FB00941EDC /* DeletableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 523150D8277875FB00941EDC /* DeletableView.swift */; }; 523150D9277875FB00941EDC /* DeletableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 523150D8277875FB00941EDC /* DeletableView.swift */; };
523150DC2778762B00941EDC /* DeviceItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 523150DB2778762B00941EDC /* DeviceItemView.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 */; }; 5242C872278C8CBB00FDB27E /* EditableText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5242C871278C8CBB00FDB27E /* EditableText.swift */; };
5242C873278C8CBB00FDB27E /* 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 */; }; 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 */; }; 52B8CF85277E0C12004CB680 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52EB90B22778DA4E0048E0ED /* Line.swift */; };
52B8CF86277E0C12004CB680 /* BaseNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52EB90AD2778AFD60048E0ED /* BaseNavigationView.swift */; }; 52B8CF86277E0C12004CB680 /* BaseNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52EB90AD2778AFD60048E0ED /* BaseNavigationView.swift */; };
52B8CF87277E0C5C004CB680 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5292F4FC2776BC7A00B9A7BB /* Assets.xcassets */; }; 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 */; }; 52E317D9279305BB000B8BB1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 52E317D7279305BB000B8BB1 /* InfoPlist.strings */; };
52E317DC279305BB000B8BB1 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 52E317DA279305BB000B8BB1 /* Localizable.strings */; }; 52E317DC279305BB000B8BB1 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 52E317DA279305BB000B8BB1 /* Localizable.strings */; };
52E317DF279305BB000B8BB1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 52E317DD279305BB000B8BB1 /* InfoPlist.strings */; }; 52E317DF279305BB000B8BB1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 52E317DD279305BB000B8BB1 /* InfoPlist.strings */; };
@ -184,6 +186,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
64B0C15E70CCC382B480F76E /* Pods_PushDeer.framework in Frameworks */, 64B0C15E70CCC382B480F76E /* Pods_PushDeer.framework in Frameworks */,
52B8FB8727F36F9D00C29D13 /* BetterSafariView in Frameworks */,
5287FF52278ADC8C00249A0E /* MarkdownUI in Frameworks */, 5287FF52278ADC8C00249A0E /* MarkdownUI in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -193,6 +196,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
4812F19BB0BFEFE089BC253E /* Pods_PushDeerClip.framework in Frameworks */, 4812F19BB0BFEFE089BC253E /* Pods_PushDeerClip.framework in Frameworks */,
5240023427F371EF00C245CF /* BetterSafariView in Frameworks */,
5287FF54278AEA5B00249A0E /* MarkdownUI in Frameworks */, 5287FF54278AEA5B00249A0E /* MarkdownUI in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -385,6 +389,7 @@
name = PushDeer; name = PushDeer;
packageProductDependencies = ( packageProductDependencies = (
5287FF51278ADC8C00249A0E /* MarkdownUI */, 5287FF51278ADC8C00249A0E /* MarkdownUI */,
52B8FB8627F36F9D00C29D13 /* BetterSafariView */,
); );
productName = PushDeer; productName = PushDeer;
productReference = 5292F4F52776BC7900B9A7BB /* PushDeer.app */; productReference = 5292F4F52776BC7900B9A7BB /* PushDeer.app */;
@ -407,6 +412,7 @@
name = PushDeerClip; name = PushDeerClip;
packageProductDependencies = ( packageProductDependencies = (
5287FF53278AEA5B00249A0E /* MarkdownUI */, 5287FF53278AEA5B00249A0E /* MarkdownUI */,
5240023327F371EF00C245CF /* BetterSafariView */,
); );
productName = PushDeerClip; productName = PushDeerClip;
productReference = 52B8CF64277E0B44004CB680 /* PushDeerClip.app */; productReference = 52B8CF64277E0B44004CB680 /* PushDeerClip.app */;
@ -444,6 +450,7 @@
mainGroup = 5292F4EC2776BC7900B9A7BB; mainGroup = 5292F4EC2776BC7900B9A7BB;
packageReferences = ( packageReferences = (
5287FF50278ADC8C00249A0E /* XCRemoteSwiftPackageReference "MarkdownUI" */, 5287FF50278ADC8C00249A0E /* XCRemoteSwiftPackageReference "MarkdownUI" */,
52B8FB8527F36F9D00C29D13 /* XCRemoteSwiftPackageReference "BetterSafariView" */,
); );
productRefGroup = 5292F4F62776BC7900B9A7BB /* Products */; productRefGroup = 5292F4F62776BC7900B9A7BB /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -1306,9 +1313,22 @@
minimumVersion = 1.1.0; 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 */ /* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */ /* Begin XCSwiftPackageProductDependency section */
5240023327F371EF00C245CF /* BetterSafariView */ = {
isa = XCSwiftPackageProductDependency;
package = 52B8FB8527F36F9D00C29D13 /* XCRemoteSwiftPackageReference "BetterSafariView" */;
productName = BetterSafariView;
};
5287FF51278ADC8C00249A0E /* MarkdownUI */ = { 5287FF51278ADC8C00249A0E /* MarkdownUI */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = 5287FF50278ADC8C00249A0E /* XCRemoteSwiftPackageReference "MarkdownUI" */; package = 5287FF50278ADC8C00249A0E /* XCRemoteSwiftPackageReference "MarkdownUI" */;
@ -1319,6 +1339,11 @@
package = 5287FF50278ADC8C00249A0E /* XCRemoteSwiftPackageReference "MarkdownUI" */; package = 5287FF50278ADC8C00249A0E /* XCRemoteSwiftPackageReference "MarkdownUI" */;
productName = MarkdownUI; productName = MarkdownUI;
}; };
52B8FB8627F36F9D00C29D13 /* BetterSafariView */ = {
isa = XCSwiftPackageProductDependency;
package = 52B8FB8527F36F9D00C29D13 /* XCRemoteSwiftPackageReference "BetterSafariView" */;
productName = BetterSafariView;
};
/* End XCSwiftPackageProductDependency section */ /* End XCSwiftPackageProductDependency section */
/* Begin XCVersionGroup section */ /* Begin XCVersionGroup section */

View File

@ -1,61 +1,68 @@
{ {
"object": { "pins" : [
"pins": [ {
{ "identity" : "attributedtext",
"package": "AttributedText", "kind" : "remoteSourceControl",
"repositoryURL": "https://github.com/gonzalezreal/AttributedText", "location" : "https://github.com/gonzalezreal/AttributedText",
"state": { "state" : {
"branch": null, "revision" : "2dc2d7864e0fee4b524a5850d7d7cf9a7eeda0fc",
"revision": "2dc2d7864e0fee4b524a5850d7d7cf9a7eeda0fc", "version" : "1.0.0"
"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"
}
} }
] },
}, {
"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
} }

View File

@ -8,7 +8,7 @@
import SwiftUI import SwiftUI
import SafariServices import SafariServices
struct SafariView: UIViewControllerRepresentable { struct HSafariView: UIViewControllerRepresentable {
let url: URL let url: URL

View File

@ -43,6 +43,12 @@ class AppState: ObservableObject {
UserDefaults.standard.set(isUseBuiltInBrowser, forKey: "PushDeer_isUseBuiltInBrowser") UserDefaults.standard.set(isUseBuiltInBrowser, forKey: "PushDeer_isUseBuiltInBrowser")
} }
} }
/// MarkDown BaseURL
@Published var markDownBaseURL: String? {
didSet {
UserDefaults.standard.set(markDownBaseURL, forKey: "PushDeer_markDownBaseURL")
}
}
/// API endpoint /// API endpoint
@Published var api_endpoint : String { @Published var api_endpoint : String {
@ -66,11 +72,13 @@ class AppState: ObservableObject {
let _tabSelectedIndex = UserDefaults.standard.integer(forKey: "PushDeer_tabSelectedIndex") let _tabSelectedIndex = UserDefaults.standard.integer(forKey: "PushDeer_tabSelectedIndex")
let _isShowTestPush = UserDefaults.standard.object(forKey: "PushDeer_isShowTestPush") let _isShowTestPush = UserDefaults.standard.object(forKey: "PushDeer_isShowTestPush")
let _isUseBuiltInBrowser = UserDefaults.standard.object(forKey: "PushDeer_isUseBuiltInBrowser") 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") let _api_endpoint = UserDefaults.standard.string(forKey: "PushDeer_api_endpoint")
token = _token ?? "" token = _token ?? ""
tabSelectedIndex = _tabSelectedIndex tabSelectedIndex = _tabSelectedIndex
isShowTestPush = _isShowTestPush as? Bool ?? true isShowTestPush = _isShowTestPush as? Bool ?? true
isUseBuiltInBrowser = _isUseBuiltInBrowser as? Bool ?? true isUseBuiltInBrowser = _isUseBuiltInBrowser as? Bool ?? true
markDownBaseURL = _markDownBaseURL
api_endpoint = _api_endpoint ?? "" api_endpoint = _api_endpoint ?? ""
} }

View File

@ -9,6 +9,7 @@ import SwiftUI
import MarkdownUI import MarkdownUI
import SDWebImageSwiftUI import SDWebImageSwiftUI
import Photos import Photos
import BetterSafariView
struct MessageItemView: View { struct MessageItemView: View {
let messageItem: MessageModel let messageItem: MessageModel
@ -35,7 +36,7 @@ struct MessageItemView: View {
} }
DeletableView(contentView: { DeletableView(contentView: {
MessageContentView(messageItem: messageItem) MessageContentView(messageItem: messageItem, deleteAction: deleteAction)
}, deleteAction: deleteAction) }, deleteAction: deleteAction)
.padding(messageItem.type == "image" ? EdgeInsets.init() : EdgeInsets(top: 10, leading: 26, bottom: 0, trailing: 24)) .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 { //extension URL: Identifiable {
public var id: Self { self } // public var id: Self { self }
} //}
struct MessageContentView: View { struct MessageContentView: View {
let messageItem: MessageModel let messageItem: MessageModel
///
let deleteAction : () -> ()
@EnvironmentObject private var store: AppState @EnvironmentObject private var store: AppState
@State private var image: PlatformImage? = nil @State private var image: PlatformImage? = nil
@State private var showUrl: URL? @State private var showUrl: URL?
@State private var showActionSheet = false @State private var showActionSheet = false
func getMarkDownBaseURL() -> URL? {
let urlStr = store.markDownBaseURL ?? "https://example.com/"
return URL(string: urlStr)
}
var body: some View { var body: some View {
switch messageItem.type { switch messageItem.type {
case "markdown": case "markdown":
CardView { CardView {
VStack(alignment: .leading, spacing: 5) { VStack(alignment: .leading, spacing: 5) {
Markdown(messageItem.text ?? "") Markdown(messageItem.text ?? "", baseURL: getMarkDownBaseURL())
.markdownStyle( .markdownStyle(
MarkdownStyle( MarkdownStyle(
font: .system(size: 14), font: .system(size: 14),
@ -77,7 +85,7 @@ struct MessageContentView: View {
} }
#endif #endif
if !(messageItem.desp?.isEmpty ?? true) { if !(messageItem.desp?.isEmpty ?? true) {
Markdown(messageItem.desp ?? "") Markdown(messageItem.desp ?? "", baseURL: getMarkDownBaseURL())
.markdownStyle( .markdownStyle(
MarkdownStyle( MarkdownStyle(
font: .system(size: 14), font: .system(size: 14),
@ -104,6 +112,12 @@ struct MessageContentView: View {
} label: { } label: {
Label("复制",systemImage: "doc.on.doc") Label("复制",systemImage: "doc.on.doc")
} }
#if targetEnvironment(macCatalyst)
Divider()
Button(action: deleteAction) {
Label("删除",systemImage: "trash.slash")
}
#endif
} }
//#endif //#endif
//#if !targetEnvironment(macCatalyst) //#if !targetEnvironment(macCatalyst)
@ -122,11 +136,14 @@ struct MessageContentView: View {
// } // }
//#endif //#endif
} }
.fullScreenCover(item: $showUrl) { .safariView(item: $showUrl, content: { url in
} content: { url in
SafariView(url: url) SafariView(url: url)
} })
// .fullScreenCover(item: $showUrl) {
//
// } content: { url in
// HSafariView(url: url)
// }
case "image": case "image":
WebImage(url: URL(string: messageItem.text ?? "")) WebImage(url: URL(string: messageItem.text ?? ""))
@ -181,6 +198,12 @@ struct MessageContentView: View {
} label: { } label: {
Label("保存图片",systemImage: "square.and.arrow.down") Label("保存图片",systemImage: "square.and.arrow.down")
} }
#if targetEnvironment(macCatalyst)
Divider()
Button(action: deleteAction) {
Label("删除",systemImage: "trash.slash")
}
#endif
} }
default: default:
@ -206,6 +229,12 @@ struct MessageContentView: View {
} label: { } label: {
Label("复制",systemImage: "doc.on.doc") Label("复制",systemImage: "doc.on.doc")
} }
#if targetEnvironment(macCatalyst)
Divider()
Button(action: deleteAction) {
Label("删除",systemImage: "trash.slash")
}
#endif
} }
} }
} }

View File

@ -7,6 +7,7 @@
import SwiftUI import SwiftUI
import AuthenticationServices import AuthenticationServices
import BetterSafariView
//import StoreKit //import StoreKit
/// ///
@ -72,6 +73,34 @@ struct SettingsView: View {
.padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20)) .padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20))
#endif #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() Spacer()
} }
} }
@ -84,11 +113,14 @@ struct SettingsView: View {
store.userInfo = try await HttpRequest.getUserInfo() store.userInfo = try await HttpRequest.getUserInfo()
} }
} }
.fullScreenCover(item: $showUrl) { .safariView(item: $showUrl, content: { url in
} content: { url in
SafariView(url: url) SafariView(url: url)
} })
// .fullScreenCover(item: $showUrl) {
//
// } content: { url in
// HSafariView(url: url)
// }
} }
func userName() -> String { func userName() -> String {