Allow authoring local-only posts on Akkoma

Closes #332
This commit is contained in:
Shadowfacts 2023-09-25 21:23:28 -04:00
parent 6821f1b9a0
commit bf1ed57180
5 changed files with 33 additions and 7 deletions

View File

@ -72,12 +72,12 @@ class PostService: ObservableObject {
mediaIDs: uploadedAttachments, mediaIDs: uploadedAttachments,
sensitive: sensitive, sensitive: sensitive,
spoilerText: contentWarning, spoilerText: contentWarning,
visibility: draft.visibility, visibility: draft.localOnly && mastodonController.instanceFeatures.localOnlyPostsVisibility ? Status.localPostVisibility : draft.visibility.rawValue,
language: mastodonController.instanceFeatures.createStatusWithLanguage ? draft.language : nil, language: mastodonController.instanceFeatures.createStatusWithLanguage ? draft.language : nil,
pollOptions: draft.poll?.pollOptions.map(\.text), pollOptions: draft.poll?.pollOptions.map(\.text),
pollExpiresIn: draft.poll == nil ? nil : Int(draft.poll!.duration), pollExpiresIn: draft.poll == nil ? nil : Int(draft.poll!.duration),
pollMultiple: draft.poll?.multiple, pollMultiple: draft.poll?.multiple,
localOnly: mastodonController.instanceFeatures.localOnlyPosts ? draft.localOnly : nil, localOnly: mastodonController.instanceFeatures.localOnlyPosts && !mastodonController.instanceFeatures.localOnlyPostsVisibility ? draft.localOnly : nil,
idempotencyKey: draft.id.uuidString idempotencyKey: draft.id.uuidString
) )
} }

View File

@ -53,10 +53,11 @@ class ToolbarController: ViewController {
HStack(spacing: 0) { HStack(spacing: 0) {
cwButton cwButton
MenuPicker(selection: $draft.visibility, options: visibilityOptions, buttonStyle: .iconOnly) MenuPicker(selection: visibilityBinding, options: visibilityOptions, buttonStyle: .iconOnly)
// the button has a bunch of extra space by default, but combined with what we add it's too much // the button has a bunch of extra space by default, but combined with what we add it's too much
.padding(.horizontal, -8) .padding(.horizontal, -8)
.disabled(draft.editedStatusID != nil) .disabled(draft.editedStatusID != nil)
.disabled(composeController.mastodonController.instanceFeatures.localOnlyPostsVisibility && draft.localOnly)
if composeController.mastodonController.instanceFeatures.localOnlyPosts { if composeController.mastodonController.instanceFeatures.localOnlyPosts {
localOnlyPicker localOnlyPicker
@ -118,9 +119,20 @@ class ToolbarController: ViewController {
.hoverEffect() .hoverEffect()
} }
private var visibilityBinding: Binding<Pachyderm.Visibility> {
// On instances that conflate visibliity and local only, we still show two separate controls but don't allow
// changing the visibility when local-only.
if draft.localOnly,
composeController.mastodonController.instanceFeatures.localOnlyPostsVisibility {
return .constant(.public)
} else {
return $draft.visibility
}
}
private var visibilityOptions: [MenuPicker<Pachyderm.Visibility>.Option] { private var visibilityOptions: [MenuPicker<Pachyderm.Visibility>.Option] {
let visibilities: [Pachyderm.Visibility] let visibilities: [Pachyderm.Visibility]
if !controller.parent.mastodonController.instanceFeatures.composeDirectStatuses { if !composeController.mastodonController.instanceFeatures.composeDirectStatuses {
visibilities = [.public, .unlisted, .private] visibilities = [.public, .unlisted, .private]
} else { } else {
visibilities = Pachyderm.Visibility.allCases visibilities = Pachyderm.Visibility.allCases

View File

@ -27,11 +27,22 @@ public class InstanceFeatures: ObservableObject {
switch instanceType { switch instanceType {
case .mastodon(.hometown(_), _), .mastodon(.glitch, _): case .mastodon(.hometown(_), _), .mastodon(.glitch, _):
return true return true
case .pleroma(.akkoma(_)):
return true
default: default:
return false return false
} }
} }
/// Instance types that use a separate visibility to indicate local-only posts.
public var localOnlyPostsVisibility: Bool {
if case .pleroma(.akkoma(_)) = instanceType {
return true
} else {
return false
}
}
public var mastodonAttachmentRestrictions: Bool { public var mastodonAttachmentRestrictions: Bool {
instanceType.isMastodon instanceType.isMastodon
} }

View File

@ -396,7 +396,7 @@ public class Client {
mediaIDs: [String]? = nil, mediaIDs: [String]? = nil,
sensitive: Bool? = nil, sensitive: Bool? = nil,
spoilerText: String? = nil, spoilerText: String? = nil,
visibility: Visibility? = nil, visibility: String? = nil,
language: String? = nil, // language supported by mastodon and akkoma language: String? = nil, // language supported by mastodon and akkoma
pollOptions: [String]? = nil, pollOptions: [String]? = nil,
pollExpiresIn: Int? = nil, pollExpiresIn: Int? = nil,
@ -409,7 +409,7 @@ public class Client {
"in_reply_to_id" => inReplyTo, "in_reply_to_id" => inReplyTo,
"sensitive" => sensitive, "sensitive" => sensitive,
"spoiler_text" => spoilerText, "spoiler_text" => spoilerText,
"visibility" => visibility?.rawValue, "visibility" => visibility,
"language" => language, "language" => language,
"poll[expires_in]" => pollExpiresIn, "poll[expires_in]" => pollExpiresIn,
"poll[multiple]" => pollMultiple, "poll[multiple]" => pollMultiple,

View File

@ -10,6 +10,9 @@ import Foundation
import WebURL import WebURL
public final class Status: StatusProtocol, Decodable, Sendable { public final class Status: StatusProtocol, Decodable, Sendable {
/// The pseudo-visibility used by instance types (Akkoma) that overload the visibility for local-only posts.
public static let localPostVisibility: String = "local"
public let id: String public let id: String
public let uri: String public let uri: String
public let url: WebURL? public let url: WebURL?
@ -77,7 +80,7 @@ public final class Status: StatusProtocol, Decodable, Sendable {
self.visibility = visibility self.visibility = visibility
self.localOnly = try container.decodeIfPresent(Bool.self, forKey: .localOnly) self.localOnly = try container.decodeIfPresent(Bool.self, forKey: .localOnly)
} else if let s = try? container.decode(String.self, forKey: .visibility), } else if let s = try? container.decode(String.self, forKey: .visibility),
s == "local" { s == Status.localPostVisibility {
// hacky workaround for #332, akkoma describes local posts with a separate visibility // hacky workaround for #332, akkoma describes local posts with a separate visibility
self.visibility = .public self.visibility = .public
self.localOnly = true self.localOnly = true