Very basic status post
This commit is contained in:
parent
e569bb1d74
commit
8df70043cb
|
@ -42,7 +42,7 @@
|
|||
"location" : "https://github.com/Dimillian/TextView",
|
||||
"state" : {
|
||||
"branch" : "main",
|
||||
"revision" : "0316b7df487f5e6f1b199d326e903310b9044c0d"
|
||||
"revision" : "002a062d6275a2b5352f0ea6ff6c22aaadd19b55"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -32,8 +32,8 @@ extension View {
|
|||
func withSheetDestinations(sheetDestinations: Binding<SheetDestinations?>) -> some View {
|
||||
self.sheet(item: sheetDestinations) { destination in
|
||||
switch destination {
|
||||
case .statusEditor:
|
||||
StatusEditorView()
|
||||
case let .statusEditor(replyToStatus):
|
||||
StatusEditorView(inReplyTo: replyToStatus)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ public enum RouteurDestinations: Hashable {
|
|||
}
|
||||
|
||||
public enum SheetDestinations: Identifiable {
|
||||
case statusEditor(replyToStatus: String?)
|
||||
case statusEditor(replyToStatus: Status?)
|
||||
|
||||
public var id: String {
|
||||
switch self {
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import Foundation
|
||||
|
||||
public enum Statuses: Endpoint {
|
||||
case postStatus(status: String,
|
||||
inReplyTo: String?,
|
||||
mediaIds: [String]?,
|
||||
spoilerText: String?)
|
||||
case status(id: String)
|
||||
case context(id: String)
|
||||
case favourite(id: String)
|
||||
|
@ -12,6 +16,8 @@ public enum Statuses: Endpoint {
|
|||
|
||||
public func path() -> String {
|
||||
switch self {
|
||||
case .postStatus:
|
||||
return "statuses"
|
||||
case .status(let id):
|
||||
return "statuses/\(id)"
|
||||
case .context(let id):
|
||||
|
@ -33,6 +39,20 @@ public enum Statuses: Endpoint {
|
|||
|
||||
public func queryItems() -> [URLQueryItem]? {
|
||||
switch self {
|
||||
case let .postStatus(status, inReplyTo, mediaIds, spoilerText):
|
||||
var params: [URLQueryItem] = [.init(name: "status", value: status)]
|
||||
if let inReplyTo {
|
||||
params.append(.init(name: "in_reply_to_id", value: inReplyTo))
|
||||
}
|
||||
if let mediaIds {
|
||||
for mediaId in mediaIds {
|
||||
params.append(.init(name: "media_ids[]", value: mediaId))
|
||||
}
|
||||
}
|
||||
if let spoilerText {
|
||||
params.append(.init(name: "spoiler_text", value: spoilerText))
|
||||
}
|
||||
return params
|
||||
case let .rebloggedBy(_, maxId):
|
||||
return makePaginationParam(sinceId: nil, maxId: maxId)
|
||||
case let .favouritedBy(_, maxId):
|
||||
|
|
|
@ -3,25 +3,36 @@ import Accounts
|
|||
import Env
|
||||
import DesignSystem
|
||||
import TextView
|
||||
import Models
|
||||
import Network
|
||||
|
||||
public struct StatusEditorView: View {
|
||||
@EnvironmentObject private var client: Client
|
||||
@EnvironmentObject private var currentAccount: CurrentAccount
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
@StateObject private var viewModel = StatusEditorViewModel()
|
||||
@StateObject private var viewModel: StatusEditorViewModel
|
||||
|
||||
public init() {
|
||||
|
||||
public init(inReplyTo: Status?) {
|
||||
_viewModel = StateObject(wrappedValue: .init(inReplyTo: inReplyTo))
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
NavigationStack {
|
||||
VStack {
|
||||
accountHeaderView
|
||||
TextView($viewModel.statusText)
|
||||
.placeholder("What's on your mind")
|
||||
.foregroundColor(.clear)
|
||||
Spacer()
|
||||
ZStack(alignment: .bottom) {
|
||||
VStack {
|
||||
accountHeaderView
|
||||
TextView($viewModel.statusText)
|
||||
.placeholder("What's on your mind")
|
||||
.foregroundColor(.clear)
|
||||
Spacer()
|
||||
}
|
||||
accessoryView
|
||||
.padding(.bottom, 12)
|
||||
}
|
||||
.onAppear {
|
||||
viewModel.client = client
|
||||
viewModel.insertReplyTo()
|
||||
}
|
||||
.padding(.horizontal, DS.Constants.layoutPadding)
|
||||
.navigationTitle("New post")
|
||||
|
@ -29,7 +40,10 @@ public struct StatusEditorView: View {
|
|||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
Button {
|
||||
dismiss()
|
||||
Task {
|
||||
_ = await viewModel.postStatus()
|
||||
dismiss()
|
||||
}
|
||||
} label: {
|
||||
Text("Post")
|
||||
}
|
||||
|
@ -61,5 +75,16 @@ public struct StatusEditorView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var accessoryView: some View {
|
||||
HStack {
|
||||
Button {
|
||||
|
||||
} label: {
|
||||
Image(systemName: "photo.fill.on.rectangle.fill")
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import SwiftUI
|
||||
import DesignSystem
|
||||
import Models
|
||||
import Network
|
||||
|
||||
@MainActor
|
||||
class StatusEditorViewModel: ObservableObject {
|
||||
|
@ -10,12 +12,37 @@ class StatusEditorViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
var client: Client?
|
||||
private var internalUpdate: Bool = false
|
||||
private var inReplyTo: Status?
|
||||
|
||||
init(inReplyTo: Status?) {
|
||||
self.inReplyTo = inReplyTo
|
||||
}
|
||||
|
||||
func postStatus() async -> Status? {
|
||||
guard let client else { return nil }
|
||||
do {
|
||||
let status: Status = try await client.post(endpoint: Statuses.postStatus(status: statusText.string,
|
||||
inReplyTo: inReplyTo?.id,
|
||||
mediaIds: nil,
|
||||
spoilerText: nil))
|
||||
return status
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func insertReplyTo() {
|
||||
if let inReplyTo {
|
||||
statusText = .init(string: "@\(inReplyTo.account.acct) ")
|
||||
}
|
||||
}
|
||||
|
||||
func highlightMeta() {
|
||||
let mutableString = NSMutableAttributedString(attributedString: statusText)
|
||||
let hashtagPattern = "(#+[a-zA-Z0-9(_)]{1,})"
|
||||
let mentionPattern = "(@+[a-zA-Z0-9(_)]{1,})"
|
||||
let mentionPattern = "(@+[a-zA-Z0-9(_).]{1,})"
|
||||
var ranges: [NSRange] = [NSRange]()
|
||||
|
||||
let hashtagRegex = try! NSRegularExpression(pattern: hashtagPattern, options: [])
|
||||
|
|
|
@ -128,7 +128,7 @@ struct StatusActionsView: View {
|
|||
generator.notificationOccurred(.success)
|
||||
switch action {
|
||||
case .respond:
|
||||
routeurPath.navigate(to: .statusDetail(id: viewModel.status.reblog?.id ?? viewModel.status.id))
|
||||
routeurPath.presentedSheet = .statusEditor(replyToStatus: viewModel.status)
|
||||
case .favourite:
|
||||
if viewModel.isFavourited {
|
||||
await viewModel.unFavourite()
|
||||
|
|
|
@ -12,15 +12,13 @@ class TimelineViewModel: ObservableObject, StatusesFetcher {
|
|||
@Published var statusesState: StatusesState = .loading
|
||||
@Published var timeline: TimelineFilter = .pub {
|
||||
didSet {
|
||||
if oldValue != timeline || statuses.isEmpty {
|
||||
Task {
|
||||
await fetchStatuses()
|
||||
switch timeline {
|
||||
case let .hashtag(tag, _):
|
||||
await fetchTag(id: tag)
|
||||
default:
|
||||
break
|
||||
}
|
||||
Task {
|
||||
await fetchStatuses()
|
||||
switch timeline {
|
||||
case let .hashtag(tag, _):
|
||||
await fetchTag(id: tag)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue