mirror of
https://github.com/yattee/yattee.git
synced 2026-05-13 19:05:03 +00:00
Make source add/edit forms feel native on macOS
Use grouped Form style with LabeledContent rows and move primary actions into the sheet toolbar for SMB, WebDAV, Local Folder, Remote Server and the Edit sheet. iOS and tvOS branches unchanged.
This commit is contained in:
@@ -34,6 +34,9 @@ struct AddLocalFolderView: View {
|
|||||||
// MARK: - Body
|
// MARK: - Body
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
#if os(macOS)
|
||||||
|
macOSBody
|
||||||
|
#else
|
||||||
Form {
|
Form {
|
||||||
nameSection
|
nameSection
|
||||||
folderSection
|
folderSection
|
||||||
@@ -53,8 +56,64 @@ struct AddLocalFolderView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
private var macOSBody: some View {
|
||||||
|
Form {
|
||||||
|
Section {
|
||||||
|
LabeledContent(String(localized: "sources.field.name")) {
|
||||||
|
TextField("", text: $name)
|
||||||
|
}
|
||||||
|
} footer: {
|
||||||
|
Text(String(localized: "sources.footer.displayName"))
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
Section {
|
||||||
|
LabeledContent(String(localized: "sources.header.folder")) {
|
||||||
|
HStack {
|
||||||
|
if let url = selectedFolderURL {
|
||||||
|
Text(url.path)
|
||||||
|
.lineLimit(1)
|
||||||
|
.truncationMode(.middle)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
.font(.system(.body, design: .monospaced))
|
||||||
|
} else {
|
||||||
|
Text(String(localized: "sources.selectFolder"))
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
Button(String(localized: "sources.selectFolder")) {
|
||||||
|
selectFolderMacOS()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} footer: {
|
||||||
|
Text(String(localized: "sources.footer.folder"))
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let result = testResult {
|
||||||
|
SourceTestResultSection(result: result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.formStyle(.grouped)
|
||||||
|
.navigationTitle(String(localized: "sources.addLocalFolder"))
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .confirmationAction) {
|
||||||
|
Button(String(localized: "sources.addSource")) {
|
||||||
|
addSource()
|
||||||
|
}
|
||||||
|
.disabled(!canAdd)
|
||||||
|
.keyboardShortcut(.defaultAction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// MARK: - Sections
|
// MARK: - Sections
|
||||||
|
|
||||||
private var nameSection: some View {
|
private var nameSection: some View {
|
||||||
|
|||||||
@@ -172,12 +172,38 @@ struct AddRemoteServerView: View {
|
|||||||
|
|
||||||
if isFieldsRevealed {
|
if isFieldsRevealed {
|
||||||
serverConfigurationFields
|
serverConfigurationFields
|
||||||
|
#if !os(macOS)
|
||||||
actionSection
|
actionSection
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
.scrollDismissesKeyboard(.interactively)
|
.scrollDismissesKeyboard(.interactively)
|
||||||
#endif
|
#endif
|
||||||
|
#if os(macOS)
|
||||||
|
.formStyle(.grouped)
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .confirmationAction) {
|
||||||
|
if isFieldsRevealed {
|
||||||
|
Button {
|
||||||
|
addSource()
|
||||||
|
} label: {
|
||||||
|
if isValidatingCredentials {
|
||||||
|
HStack(spacing: 6) {
|
||||||
|
ProgressView().controlSize(.small)
|
||||||
|
Text(String(localized: "sources.validatingCredentials"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text(String(localized: "sources.addSource"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disabled(!canAdd || isValidatingCredentials)
|
||||||
|
.keyboardShortcut(.defaultAction)
|
||||||
|
.accessibilityIdentifier("addRemoteServer.actionButton")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - URL Entry Section
|
// MARK: - URL Entry Section
|
||||||
@@ -207,6 +233,35 @@ struct AddRemoteServerView: View {
|
|||||||
.buttonStyle(TVSettingsButtonStyle())
|
.buttonStyle(TVSettingsButtonStyle())
|
||||||
.disabled(urlString.isEmpty || uiState == .detecting)
|
.disabled(urlString.isEmpty || uiState == .detecting)
|
||||||
}
|
}
|
||||||
|
#elseif os(macOS)
|
||||||
|
LabeledContent(String(localized: "sources.field.url")) {
|
||||||
|
TextField("", text: $urlString, prompt: Text(String(localized: "sources.placeholder.urlOrAddress")))
|
||||||
|
.textContentType(.URL)
|
||||||
|
.autocorrectionDisabled()
|
||||||
|
.accessibilityIdentifier("addRemoteServer.urlField")
|
||||||
|
.onChange(of: urlString) { _, _ in
|
||||||
|
handleURLChange()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isFieldsRevealed && !isAwaitingBasicAuth {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Button {
|
||||||
|
startDetection()
|
||||||
|
} label: {
|
||||||
|
HStack(spacing: 6) {
|
||||||
|
if case .detecting = uiState {
|
||||||
|
ProgressView()
|
||||||
|
.controlSize(.small)
|
||||||
|
}
|
||||||
|
Text(String(localized: "sources.detect"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disabled(urlString.isEmpty || uiState == .detecting)
|
||||||
|
.accessibilityIdentifier("addRemoteServer.detectButton")
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
TextField(String(localized: "sources.placeholder.urlOrAddress"), text: $urlString)
|
TextField(String(localized: "sources.placeholder.urlOrAddress"), text: $urlString)
|
||||||
.textContentType(.URL)
|
.textContentType(.URL)
|
||||||
@@ -277,6 +332,16 @@ struct AddRemoteServerView: View {
|
|||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
TVSettingsTextField(title: String(localized: "sources.field.username"), text: $basicAuthUsername)
|
TVSettingsTextField(title: String(localized: "sources.field.username"), text: $basicAuthUsername)
|
||||||
TVSettingsTextField(title: String(localized: "sources.field.password"), text: $basicAuthPassword, isSecure: true)
|
TVSettingsTextField(title: String(localized: "sources.field.password"), text: $basicAuthPassword, isSecure: true)
|
||||||
|
#elseif os(macOS)
|
||||||
|
LabeledContent(String(localized: "sources.field.username")) {
|
||||||
|
TextField("", text: $basicAuthUsername)
|
||||||
|
.textContentType(.username)
|
||||||
|
.autocorrectionDisabled()
|
||||||
|
}
|
||||||
|
LabeledContent(String(localized: "sources.field.password")) {
|
||||||
|
SecureField("", text: $basicAuthPassword)
|
||||||
|
.textContentType(.password)
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
TextField(String(localized: "sources.field.username"), text: $basicAuthUsername)
|
TextField(String(localized: "sources.field.username"), text: $basicAuthUsername)
|
||||||
.textContentType(.username)
|
.textContentType(.username)
|
||||||
@@ -328,6 +393,10 @@ struct AddRemoteServerView: View {
|
|||||||
Section {
|
Section {
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
TVSettingsTextField(title: String(localized: "sources.field.nameOptional"), text: $name)
|
TVSettingsTextField(title: String(localized: "sources.field.nameOptional"), text: $name)
|
||||||
|
#elseif os(macOS)
|
||||||
|
LabeledContent(String(localized: "sources.field.name")) {
|
||||||
|
TextField("", text: $name, prompt: Text(String(localized: "sources.field.nameOptional")))
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
TextField(String(localized: "sources.field.nameOptional"), text: $name)
|
TextField(String(localized: "sources.field.nameOptional"), text: $name)
|
||||||
#endif
|
#endif
|
||||||
@@ -381,6 +450,16 @@ struct AddRemoteServerView: View {
|
|||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
TVSettingsTextField(title: String(localized: "sources.field.username"), text: $basicAuthUsername)
|
TVSettingsTextField(title: String(localized: "sources.field.username"), text: $basicAuthUsername)
|
||||||
TVSettingsTextField(title: String(localized: "sources.field.password"), text: $basicAuthPassword, isSecure: true)
|
TVSettingsTextField(title: String(localized: "sources.field.password"), text: $basicAuthPassword, isSecure: true)
|
||||||
|
#elseif os(macOS)
|
||||||
|
LabeledContent(String(localized: "sources.field.username")) {
|
||||||
|
TextField("", text: $basicAuthUsername)
|
||||||
|
.textContentType(.username)
|
||||||
|
.autocorrectionDisabled()
|
||||||
|
}
|
||||||
|
LabeledContent(String(localized: "sources.field.password")) {
|
||||||
|
SecureField("", text: $basicAuthPassword)
|
||||||
|
.textContentType(.password)
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
TextField(String(localized: "sources.field.username"), text: $basicAuthUsername)
|
TextField(String(localized: "sources.field.username"), text: $basicAuthUsername)
|
||||||
.textContentType(.username)
|
.textContentType(.username)
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ struct AddSMBView: View {
|
|||||||
// MARK: - Body
|
// MARK: - Body
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
#if os(macOS)
|
||||||
|
macOSBody
|
||||||
|
#else
|
||||||
Form {
|
Form {
|
||||||
nameSection
|
nameSection
|
||||||
serverSection
|
serverSection
|
||||||
@@ -68,8 +71,100 @@ struct AddSMBView: View {
|
|||||||
name = prefillName
|
name = prefillName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
private var macOSBody: some View {
|
||||||
|
Form {
|
||||||
|
Section {
|
||||||
|
LabeledContent(String(localized: "sources.field.name")) {
|
||||||
|
TextField("", text: $name)
|
||||||
|
}
|
||||||
|
} footer: {
|
||||||
|
Text(String(localized: "sources.footer.displayName"))
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
Section {
|
||||||
|
LabeledContent(String(localized: "sources.placeholder.smbServer")) {
|
||||||
|
TextField("", text: $server)
|
||||||
|
.autocorrectionDisabled()
|
||||||
|
}
|
||||||
|
} footer: {
|
||||||
|
Text(String(localized: "sources.footer.smb"))
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
Section {
|
||||||
|
LabeledContent(String(localized: "sources.field.usernameOptional")) {
|
||||||
|
TextField("", text: $username)
|
||||||
|
.textContentType(.username)
|
||||||
|
.autocorrectionDisabled()
|
||||||
|
}
|
||||||
|
LabeledContent(String(localized: "sources.field.passwordOptional")) {
|
||||||
|
SecureField("", text: $password)
|
||||||
|
.textContentType(.password)
|
||||||
|
}
|
||||||
|
} header: {
|
||||||
|
Text(String(localized: "sources.header.auth"))
|
||||||
|
} footer: {
|
||||||
|
Text(String(localized: "sources.footer.auth"))
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
Section {
|
||||||
|
Picker(String(localized: "sources.field.smbProtocol"), selection: $protocolVersion) {
|
||||||
|
ForEach(SMBProtocol.allCases, id: \.self) { proto in
|
||||||
|
Text(proto.displayName).tag(proto)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} header: {
|
||||||
|
Text(String(localized: "sources.header.advanced"))
|
||||||
|
} footer: {
|
||||||
|
Text(String(localized: "sources.footer.smbProtocol"))
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let result = testResult {
|
||||||
|
SourceTestResultSection(result: result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.formStyle(.grouped)
|
||||||
|
.navigationTitle(String(localized: "sources.addSMB"))
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .confirmationAction) {
|
||||||
|
Button {
|
||||||
|
addSource()
|
||||||
|
} label: {
|
||||||
|
if isTesting {
|
||||||
|
HStack(spacing: 6) {
|
||||||
|
ProgressView().controlSize(.small)
|
||||||
|
Text(testProgress ?? String(localized: "sources.testing"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text(String(localized: "sources.addSource"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disabled(!canAdd || isTesting)
|
||||||
|
.keyboardShortcut(.defaultAction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
if let prefillServer {
|
||||||
|
server = prefillServer
|
||||||
|
}
|
||||||
|
if let prefillName, name.isEmpty {
|
||||||
|
name = prefillName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// MARK: - Sections
|
// MARK: - Sections
|
||||||
|
|
||||||
private var nameSection: some View {
|
private var nameSection: some View {
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ struct AddWebDAVView: View {
|
|||||||
// MARK: - Body
|
// MARK: - Body
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
#if os(macOS)
|
||||||
|
macOSBody
|
||||||
|
#else
|
||||||
Form {
|
Form {
|
||||||
nameSection
|
nameSection
|
||||||
serverSection
|
serverSection
|
||||||
@@ -72,8 +75,100 @@ struct AddWebDAVView: View {
|
|||||||
allowInvalidCertificates = true
|
allowInvalidCertificates = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
private var macOSBody: some View {
|
||||||
|
Form {
|
||||||
|
Section {
|
||||||
|
LabeledContent(String(localized: "sources.field.name")) {
|
||||||
|
TextField("", text: $name)
|
||||||
|
}
|
||||||
|
} footer: {
|
||||||
|
Text(String(localized: "sources.footer.displayName"))
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
Section {
|
||||||
|
LabeledContent(String(localized: "sources.placeholder.webdavUrl")) {
|
||||||
|
TextField("", text: $urlString)
|
||||||
|
.textContentType(.URL)
|
||||||
|
.autocorrectionDisabled()
|
||||||
|
}
|
||||||
|
} footer: {
|
||||||
|
Text(String(localized: "sources.footer.webdav"))
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
Section {
|
||||||
|
LabeledContent(String(localized: "sources.field.usernameOptional")) {
|
||||||
|
TextField("", text: $username)
|
||||||
|
.textContentType(.username)
|
||||||
|
.autocorrectionDisabled()
|
||||||
|
}
|
||||||
|
LabeledContent(String(localized: "sources.field.passwordOptional")) {
|
||||||
|
SecureField("", text: $password)
|
||||||
|
.textContentType(.password)
|
||||||
|
}
|
||||||
|
} header: {
|
||||||
|
Text(String(localized: "sources.header.auth"))
|
||||||
|
} footer: {
|
||||||
|
Text(String(localized: "sources.footer.auth"))
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
Section {
|
||||||
|
Toggle(String(localized: "sources.field.allowInvalidCertificates"), isOn: $allowInvalidCertificates)
|
||||||
|
} header: {
|
||||||
|
Text(String(localized: "sources.header.security"))
|
||||||
|
} footer: {
|
||||||
|
Text(String(localized: "sources.footer.allowInvalidCertificates"))
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let result = testResult {
|
||||||
|
SourceTestResultSection(result: result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.formStyle(.grouped)
|
||||||
|
.navigationTitle(String(localized: "sources.addWebDAV"))
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .confirmationAction) {
|
||||||
|
Button {
|
||||||
|
addSource()
|
||||||
|
} label: {
|
||||||
|
if isTesting {
|
||||||
|
HStack(spacing: 6) {
|
||||||
|
ProgressView().controlSize(.small)
|
||||||
|
Text(testProgress ?? String(localized: "sources.testing"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text(String(localized: "sources.addSource"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disabled(!canAdd || isTesting)
|
||||||
|
.keyboardShortcut(.defaultAction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
if let url = prefillURL {
|
||||||
|
urlString = url.absoluteString
|
||||||
|
}
|
||||||
|
if let prefillName, name.isEmpty {
|
||||||
|
name = prefillName
|
||||||
|
}
|
||||||
|
if prefillAllowInvalidCertificates {
|
||||||
|
allowInvalidCertificates = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// MARK: - Sections
|
// MARK: - Sections
|
||||||
|
|
||||||
private var nameSection: some View {
|
private var nameSection: some View {
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ struct AddSourceView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
.frame(minWidth: 500, minHeight: 450)
|
.frame(minWidth: 560, minHeight: 560)
|
||||||
#endif
|
#endif
|
||||||
.sheet(isPresented: $showingNetworkDiscovery) {
|
.sheet(isPresented: $showingNetworkDiscovery) {
|
||||||
NetworkShareDiscoverySheet(filterType: selectedShareType) { share in
|
NetworkShareDiscoverySheet(filterType: selectedShareType) { share in
|
||||||
|
|||||||
@@ -118,6 +118,11 @@ private struct EditRemoteServerContent: View {
|
|||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
TVSettingsTextField(title: String(localized: "sources.field.name"), text: $name)
|
TVSettingsTextField(title: String(localized: "sources.field.name"), text: $name)
|
||||||
TVSettingsToggle(title: String(localized: "sources.field.enabled"), isOn: $isEnabled)
|
TVSettingsToggle(title: String(localized: "sources.field.enabled"), isOn: $isEnabled)
|
||||||
|
#elseif os(macOS)
|
||||||
|
LabeledContent(String(localized: "sources.field.name")) {
|
||||||
|
TextField("", text: $name)
|
||||||
|
}
|
||||||
|
Toggle(String(localized: "sources.field.enabled"), isOn: $isEnabled)
|
||||||
#else
|
#else
|
||||||
TextField(String(localized: "sources.field.name"), text: $name)
|
TextField(String(localized: "sources.field.name"), text: $name)
|
||||||
Toggle(String(localized: "sources.field.enabled"), isOn: $isEnabled)
|
Toggle(String(localized: "sources.field.enabled"), isOn: $isEnabled)
|
||||||
@@ -128,6 +133,16 @@ private struct EditRemoteServerContent: View {
|
|||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
TVSettingsTextField(title: String(localized: "sources.field.username"), text: $basicAuthUsername)
|
TVSettingsTextField(title: String(localized: "sources.field.username"), text: $basicAuthUsername)
|
||||||
TVSettingsTextField(title: String(localized: "sources.field.password"), text: $basicAuthPassword, isSecure: true)
|
TVSettingsTextField(title: String(localized: "sources.field.password"), text: $basicAuthPassword, isSecure: true)
|
||||||
|
#elseif os(macOS)
|
||||||
|
LabeledContent(String(localized: "sources.field.username")) {
|
||||||
|
TextField("", text: $basicAuthUsername)
|
||||||
|
.textContentType(.username)
|
||||||
|
.autocorrectionDisabled()
|
||||||
|
}
|
||||||
|
LabeledContent(String(localized: "sources.field.password")) {
|
||||||
|
SecureField("", text: $basicAuthPassword)
|
||||||
|
.textContentType(.password)
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
TextField(String(localized: "sources.field.username"), text: $basicAuthUsername)
|
TextField(String(localized: "sources.field.username"), text: $basicAuthUsername)
|
||||||
.textContentType(.username)
|
.textContentType(.username)
|
||||||
@@ -321,6 +336,9 @@ private struct EditRemoteServerContent: View {
|
|||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
.scrollDismissesKeyboard(.interactively)
|
.scrollDismissesKeyboard(.interactively)
|
||||||
#endif
|
#endif
|
||||||
|
#if os(macOS)
|
||||||
|
.formStyle(.grouped)
|
||||||
|
#endif
|
||||||
.confirmationDialog(
|
.confirmationDialog(
|
||||||
String(localized: "sources.delete.confirmation.single \(instance.displayName)"),
|
String(localized: "sources.delete.confirmation.single \(instance.displayName)"),
|
||||||
isPresented: $showingDeleteConfirmation,
|
isPresented: $showingDeleteConfirmation,
|
||||||
@@ -564,6 +582,11 @@ private struct EditFileSourceContent: View {
|
|||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
TVSettingsTextField(title: String(localized: "sources.field.name"), text: $name)
|
TVSettingsTextField(title: String(localized: "sources.field.name"), text: $name)
|
||||||
TVSettingsToggle(title: String(localized: "sources.field.enabled"), isOn: $isEnabled)
|
TVSettingsToggle(title: String(localized: "sources.field.enabled"), isOn: $isEnabled)
|
||||||
|
#elseif os(macOS)
|
||||||
|
LabeledContent(String(localized: "sources.field.name")) {
|
||||||
|
TextField("", text: $name)
|
||||||
|
}
|
||||||
|
Toggle(String(localized: "sources.field.enabled"), isOn: $isEnabled)
|
||||||
#else
|
#else
|
||||||
TextField(String(localized: "sources.field.name"), text: $name)
|
TextField(String(localized: "sources.field.name"), text: $name)
|
||||||
Toggle(String(localized: "sources.field.enabled"), isOn: $isEnabled)
|
Toggle(String(localized: "sources.field.enabled"), isOn: $isEnabled)
|
||||||
@@ -615,6 +638,21 @@ private struct EditFileSourceContent: View {
|
|||||||
text: $password,
|
text: $password,
|
||||||
isSecure: true
|
isSecure: true
|
||||||
)
|
)
|
||||||
|
#elseif os(macOS)
|
||||||
|
LabeledContent(String(localized: "sources.field.username")) {
|
||||||
|
TextField("", text: $username)
|
||||||
|
.textContentType(.username)
|
||||||
|
.autocorrectionDisabled()
|
||||||
|
}
|
||||||
|
LabeledContent(String(localized: "sources.field.password")) {
|
||||||
|
SecureField(
|
||||||
|
hasExistingPassword
|
||||||
|
? String(localized: "sources.field.passwordKeep")
|
||||||
|
: String(localized: "sources.field.passwordRequired"),
|
||||||
|
text: $password
|
||||||
|
)
|
||||||
|
.textContentType(.password)
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
TextField(String(localized: "sources.field.username"), text: $username)
|
TextField(String(localized: "sources.field.username"), text: $username)
|
||||||
.textContentType(.username)
|
.textContentType(.username)
|
||||||
@@ -718,6 +756,9 @@ private struct EditFileSourceContent: View {
|
|||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
.scrollDismissesKeyboard(.interactively)
|
.scrollDismissesKeyboard(.interactively)
|
||||||
#endif
|
#endif
|
||||||
|
#if os(macOS)
|
||||||
|
.formStyle(.grouped)
|
||||||
|
#endif
|
||||||
.confirmationDialog(
|
.confirmationDialog(
|
||||||
String(localized: "sources.delete.confirmation.single \(source.name)"),
|
String(localized: "sources.delete.confirmation.single \(source.name)"),
|
||||||
isPresented: $showingDeleteConfirmation,
|
isPresented: $showingDeleteConfirmation,
|
||||||
|
|||||||
Reference in New Issue
Block a user