Skip to content

Commit

Permalink
Add Link implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyle-Ye committed Nov 27, 2023
1 parent 7466ac4 commit dd516ee
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 1 deletion.
15 changes: 15 additions & 0 deletions Sources/OpenSwiftUI/OpenSwiftUI.docc/Views/Controls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Controls and indicators

Display values and get user selections.

## Overview

OpenSwiftUI provides controls that enable user interaction specific to each platform and context. For example, people can initiate events with buttons and links, or choose among a set of discrete values with different kinds of pickers. You can also display information to the user with indicators like progress views and gauges.

Use these built-in controls and indicators when composing custom views, and style them to match the needs of your app’s user interface. For design guidance, see [All components](https://developer.apple.com/design/human-interface-guidelines/components) in the Human Interface Guidelines.

## Topics

### Linking to other content

- ``Link``
8 changes: 7 additions & 1 deletion Sources/OpenSwiftUI/UIElements/Button/TODO/Button.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@
// Lastest Version: iOS 15.5
// Status: Empty

public struct Button {}
public struct Button<Label>: View where Label: View {
public init(action: @escaping () -> Void, @ViewBuilder label: () -> Label) {

}

public var body: some View { EmptyView() }
}
83 changes: 83 additions & 0 deletions Sources/OpenSwiftUI/Views/Controls/Link/Link.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//
// Link.swift
// OpenSwiftUI
//
// Created by Kyle on 2023/11/28.
// Lastest Version: iOS 15.0
// Status: Blocked by Text

import Foundation

/// A control for navigating to a URL.
///
/// Create a link by providing a destination URL and a title. The title
/// tells the user the purpose of the link, and can be a string, a title
/// key that produces a localized string, or a view that acts as a label.
/// The example below creates a link to `example.com` and displays the
/// title string as a link-styled view:
///
/// Link("View Our Terms of Service",
/// destination: URL(string: "https://www.example.com/TOS.html")!)
///
/// When a user taps or clicks a `Link`, the default behavior depends on the
/// contents of the URL. For example, OpenSwiftUI opens a Universal Link in the
/// associated app if possible, or in the user's default web browser if not.
/// Alternatively, you can override the default behavior by setting the
/// ``EnvironmentValues/openURL`` environment value with a custom
/// ``OpenURLAction``:
///
/// Link("Visit Our Site", destination: URL(string: "https://www.example.com")!)
/// .environment(\.openURL, OpenURLAction { url in
/// print("Open \(url)")
/// return .handled
/// })
///
/// As with other views, you can style links using standard view modifiers
/// depending on the view type of the link's label. For example, a ``Text``
/// label could be modified with a custom ``View/font(_:)`` or
/// ``View/foregroundColor(_:)`` to customize the appearance of the link in
/// your app's UI.
public struct Link<Label>: View where Label: View {
/// Creates a control, consisting of a URL and a label, used to navigate
/// to the given URL.
///
/// - Parameters:
/// - destination: The URL for the link.
/// - label: A view that describes the destination of URL.
public init(destination: URL, @ViewBuilder label: () -> Label) {
self.label = label()
self.destination = LinkDestination(configuration: .init(url: destination, isSensitive: false))
}

init(sensitiveUrl: URL, @ViewBuilder label: () -> Label) {
self.label = label()
self.destination = LinkDestination(configuration: .init(url: sensitiveUrl, isSensitive: true))
}

init(configuration: LinkDestination.Configuration, label: Label) {
self.label = label
self.destination = LinkDestination(configuration: configuration)
}

public var body: some View {
Button {
destination.open()
} label: {
label
}
}

var label: Label
var destination: LinkDestination
}

// extension Link where Label == Text {
// public init(_ titleKey: LocalizedStringKey, destination: URL) {
//
// }
//
// @_disfavoredOverload
// public init<S>(_ title: S, destination: URL) where S : StringProtocol {
//
// }
// }
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// LinkDestination.swift
// OpenSwiftUI
//
// Created by Kyle on 2023/11/28.
// Lastest Version: iOS 15.0
// Status: Complete
// ID: 85AAA54365DC4DDF1DC8F2FECEF4501A

import Foundation

struct LinkDestination {
var configuration: Configuration

@Environment(\.openURL)
private var openURL: OpenURLAction

@Environment(\._openSensitiveURL)
private var openSensitiveURL: OpenURLAction

func open() {
let openURLAction = configuration.isSensitive ? openSensitiveURL : openURL
openURLAction(configuration.url)
}
}

extension LinkDestination {
struct Configuration: Codable {
var url: URL
var isSensitive: Bool

init(url: URL, isSensitive: Bool) {
self.url = url
self.isSensitive = isSensitive
}

private enum CodingKeys: CodingKey {
case url
case isSensitive
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
url = try container.decode(URL.self, forKey: .url)
isSensitive = try container.decode(Bool.self, forKey: .isSensitive)
}

func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(url, forKey: .url)
try container.encode(isSensitive, forKey: .isSensitive)
}
}
}

0 comments on commit dd516ee

Please sign in to comment.