Fixes and optimisation

This commit is contained in:
Lumaa 2024-01-10 17:45:41 +01:00
parent 0e6e63ea23
commit b524188790
4 changed files with 112 additions and 152 deletions

View File

@ -20,23 +20,11 @@ struct CompactPostView: View {
var body: some View {
VStack {
VStack(alignment: .leading) {
if pinned {
pinnedNotice
.padding(.leading, 35)
statusPost(status)
.contentShape(Rectangle())
.onTapGesture {
navigator.navigate(to: .post(status: status))
}
if status.reblog != nil {
repostNotice
.padding(.leading, 30)
}
if detailed {
detailedStatusPost(status.reblog ?? status)
} else {
statusPost(status.reblog ?? status)
}
}
if !quoted {
Rectangle()
@ -133,13 +121,25 @@ struct CompactPostView: View {
VStack(alignment: .leading) {
// MARK: Status main content
VStack(alignment: .leading, spacing: 10) {
Text(status.account.username)
.font(quoted ? .callout : .body)
.multilineTextAlignment(.leading)
.bold()
.onTapGesture {
navigator.navigate(to: .account(acc: status.account))
VStack(alignment: .leading, spacing: 2) {
Text(status.account.username)
.font(quoted ? .callout : .body)
.multilineTextAlignment(.leading)
.bold()
.onTapGesture {
navigator.navigate(to: .account(acc: status.account))
}
if status.inReplyToAccountId != nil {
if let user = status.mentions.first(where: { $0.id == status.inReplyToAccountId }) {
Text("status.replied-to.\(user.username)")
.multilineTextAlignment(.leading)
.lineLimit(1)
.font(.caption)
.foregroundStyle(Color(uiColor: UIColor.label).opacity(0.3))
}
}
}
if !status.content.asRawText.isEmpty {
TextEmoji(status.content, emojis: status.emojis, language: status.language)
@ -184,21 +184,20 @@ struct CompactPostView: View {
HStack(spacing: 13) {
asyncActionButton(isLiked ? "heart.fill" : "heart") {
do {
try await likePost()
HapticManager.playHaptics(haptics: Haptic.tap)
try await likePost()
} catch {
HapticManager.playHaptics(haptics: Haptic.error)
print("Error: \(error.localizedDescription)")
}
}
actionButton("bubble.right") {
print("reply")
navigator.presentedSheet = .post()
navigator.presentedSheet = .post(content: "@\(status.account.acct)", replyId: status.id)
}
asyncActionButton(isReposted ? "bolt.horizontal.fill" : "bolt.horizontal") {
do {
try await repostPost()
HapticManager.playHaptics(haptics: Haptic.tap)
try await repostPost()
} catch {
HapticManager.playHaptics(haptics: Haptic.error)
print("Error: \(error.localizedDescription)")
@ -219,116 +218,38 @@ struct CompactPostView: View {
}
}
@ViewBuilder
func detailedStatusPost(_ status: AnyStatus) -> some View {
VStack {
HStack {
profilePicture
Text(status.account.username)
.multilineTextAlignment(.leading)
.bold()
}
.onTapGesture {
navigator.navigate(to: .account(acc: status.account))
}
.contentShape(Rectangle())
VStack(alignment: .leading) {
// MARK: Status main content
VStack(alignment: .leading, spacing: 10) {
if !status.content.asRawText.isEmpty {
TextEmoji(status.content, emojis: status.emojis, language: status.language)
.multilineTextAlignment(.leading)
.frame(width: 300, alignment: .topLeading)
.fixedSize(horizontal: false, vertical: true)
.font(.callout)
}
var notices: some View {
ZStack {
if pinned {
HStack (alignment:.center, spacing: 5) {
Image(systemName: "pin.fill")
if status.card != nil && status.mediaAttachments.isEmpty {
PostCardView(card: status.card!)
}
if !status.mediaAttachments.isEmpty {
ForEach(status.mediaAttachments) { attachment in
PostAttachment(attachment: attachment)
}
}
if hasQuote {
if quoteStatus != nil {
QuotePostView(status: quoteStatus!)
} else {
ProgressView()
.progressViewStyle(.circular)
}
}
Text("status.pinned")
}
//MARK: Action buttons
HStack(spacing: 13) {
asyncActionButton(isLiked ? "heart.fill" : "heart") {
do {
try await likePost()
HapticManager.playHaptics(haptics: Haptic.tap)
} catch {
HapticManager.playHaptics(haptics: Haptic.error)
print("Error: \(error.localizedDescription)")
}
}
actionButton("bubble.right") {
print("reply")
navigator.presentedSheet = .post()
}
asyncActionButton(isReposted ? "bolt.horizontal.fill" : "bolt.horizontal") {
do {
try await repostPost()
HapticManager.playHaptics(haptics: Haptic.tap)
} catch {
HapticManager.playHaptics(haptics: Haptic.error)
print("Error: \(error.localizedDescription)")
}
}
ShareLink(item: URL(string: status.url ?? "https://joinmastodon.org/")!) {
Image(systemName: "square.and.arrow.up")
.font(.title2)
}
.tint(Color(uiColor: UIColor.label))
.padding(.leading, 20)
.multilineTextAlignment(.leading)
.lineLimit(1)
.font(.caption)
.foregroundStyle(Color(uiColor: UIColor.label).opacity(0.3))
.padding(.leading, 35)
}
if status.reblog != nil {
HStack (alignment:.center, spacing: 5) {
Image(systemName: "bolt.horizontal")
Text("status.reposted-by.\(status.account.username)")
}
.padding(.top)
// MARK: Status stats
stats.padding(.top, 5)
.padding(.leading, 20)
.multilineTextAlignment(.leading)
.lineLimit(1)
.font(.caption)
.foregroundStyle(Color(uiColor: UIColor.label).opacity(0.3))
.padding(.leading, 30)
}
}
}
var pinnedNotice: some View {
HStack (alignment:.center, spacing: 5) {
Image(systemName: "pin.fill")
Text("status.pinned")
}
.padding(.leading, 20)
.multilineTextAlignment(.leading)
.lineLimit(1)
.font(.caption)
.foregroundStyle(Color(uiColor: UIColor.label).opacity(0.3))
}
var repostNotice: some View {
HStack (alignment:.center, spacing: 5) {
Image(systemName: "bolt.horizontal")
Text("status.reposted-by.\(status.account.username)")
}
.padding(.leading, 20)
.multilineTextAlignment(.leading)
.lineLimit(1)
.font(.caption)
.foregroundStyle(Color(uiColor: UIColor.label).opacity(0.3))
}
var profilePicture: some View {
if status.reblog != nil {
OnlineImage(url: status.reblog!.account.avatar, size: 50, useNuke: true)

View File

@ -38,7 +38,7 @@ public enum TabDestination: Identifiable {
public enum SheetDestination: Identifiable {
case welcome
case mastodonLogin(logged: Binding<Bool>)
case post(content: String = "")
case post(content: String = "", replyId: String? = nil)
public var id: String {
switch self {
@ -70,6 +70,7 @@ public enum RouterDestination: Hashable {
case privacy
case appearence
case account(acc: Account)
case post(status: Status)
case about
}
@ -85,6 +86,8 @@ extension View {
AppearenceView()
case .account(let acc):
AccountView(account: acc, navigator: navigator)
case .post(let status):
PostDetailsView(status: status)
case .about:
AboutView()
}
@ -114,9 +117,9 @@ extension View {
}
} else {
switch destination {
case .post(let content):
case .post(let content, let replyId):
NavigationStack {
PostingView(initialString: content)
PostingView(initialString: content, replyId: replyId)
.tint(Color(uiColor: UIColor.label))
}
case let .mastodonLogin(logged):

View File

@ -355,7 +355,14 @@
}
},
"setting.experimental.activate" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Show experimental features"
}
}
}
},
"setting.privacy" : {
"localizations" : {
@ -519,6 +526,16 @@
}
}
},
"status.replied-to.%@" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Replied to @%@"
}
}
}
},
"status.replies-%lld" : {
"localizations" : {
"en" : {
@ -588,4 +605,4 @@
}
},
"version" : "1.0"
}
}

View File

@ -10,6 +10,7 @@ struct PostingView: View {
@Environment(Navigator.self) private var navigator: Navigator
public var initialString: String = ""
public var replyId: String? = nil
@State private var viewModel: PostingView.ViewModel = PostingView.ViewModel()
@ -43,7 +44,7 @@ struct PostingView: View {
viewModel.textView = textView
})
.placeholder(String(localized: "status.posting.placeholder"))
.keyboardType(.twitter)
.setKeyboardType(.twitter)
.multilineTextAlignment(.leading)
.font(.callout)
.foregroundStyle(Color(uiColor: UIColor.label))
@ -91,12 +92,11 @@ struct PostingView: View {
Task {
if let client = accountManager.getClient() {
postingStatus = true
let postedStatus: Status = try await client.post(endpoint: Statuses.postStatus(json: .init(status: viewModel.postText.string, visibility: visibility)))
let newStatus: Status = try await client.post(endpoint: Statuses.postStatus(json: .init(status: viewModel.postText.string, visibility: visibility, inReplyToId: replyId)))
postingStatus = false
HapticManager.playHaptics(haptics: Haptic.success)
dismiss()
// navigate to account until PostDetailsView is fully finished
navigator.navigate(to: .account(acc: accountManager.forceAccount()))
navigator.navigate(to: .post(status: newStatus))
}
}
} label: {
@ -127,9 +127,7 @@ struct PostingView: View {
}
}
.onAppear {
let newTxt = NSMutableAttributedString(string: "abc")
viewModel.postText.append(newTxt)
viewModel.append(text: initialString)
}
}
@ -150,7 +148,7 @@ struct PostingView: View {
actionButton("number") {
DispatchQueue.main.async {
viewModel.postText.append(NSMutableAttributedString(string: "#"))
viewModel.append(text: "#")
}
}
}
@ -187,21 +185,42 @@ struct PostingView: View {
.clipShape(.circle)
}
public class ViewModel: NSObject, UITextPasteDelegate {
init(postText: NSMutableAttributedString = .init(string: ""), textView: UITextView? = nil) {
self.postText = postText
self.textView = textView
@Observable public class ViewModel: NSObject {
init(text: String = "") {
self.postText = NSMutableAttributedString(string: text)
}
@State var postText: NSMutableAttributedString {
didSet {
textView?.attributedText = postText
var selectedRange: NSRange {
get {
guard let textView else {
return .init(location: 0, length: 0)
}
return textView.selectedRange
}
set {
textView?.selectedRange = newValue
}
}
var textView: UITextView? {
var postText: NSMutableAttributedString {
didSet {
textView?.pasteDelegate = self
let range = selectedRange
formatText()
textView?.attributedText = postText
selectedRange = range
}
}
var textView: UITextView?
func append(text: String) {
let string = postText
string.mutableString.insert(text, at: selectedRange.location)
postText = string
selectedRange = NSRange(location: selectedRange.location + text.utf16.count, length: 0)
}
func formatText() {
postText.addAttributes([.foregroundColor : UIColor.label, .font: UIFont.preferredFont(forTextStyle: .callout), .backgroundColor: UIColor.clear, .underlineColor: UIColor.clear], range: NSMakeRange(0, postText.string.utf16.count))
}
}
}