Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New docs #126

Merged
merged 24 commits into from
Sep 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6530562
[skip ci] new-docs - Add video to readme - TT
Tyler-Keith-Thompson Sep 9, 2021
ef52524
[skip ci] new-docs - Use the HTML5 video tag instead - TT
Tyler-Keith-Thompson Sep 9, 2021
fe13f11
Update README.md
Tyler-Keith-Thompson Sep 9, 2021
055989e
[skip ci] new-docs - Get rid of old text - TT
Tyler-Keith-Thompson Sep 9, 2021
b960bab
[ci skip] wip - updated the README
Tyler-Keith-Thompson Sep 9, 2021
c4d8790
[ci skip] wip - Modified the quickstart
Tyler-Keith-Thompson Sep 9, 2021
2eef23e
[ci skip] wip - Call to action is more apparent and guides you to the…
Tyler-Keith-Thompson Sep 9, 2021
d1dc2d1
Merge branch 'main' into new-docs
Tyler-Keith-Thompson Sep 10, 2021
b22c74b
[new-docs] - Added a post processor for modifying jazzy docs as we mi…
Tyler-Keith-Thompson Sep 10, 2021
1047547
[new-docs] - Replace readme video with vimeo embed - TT
Tyler-Keith-Thompson Sep 10, 2021
979bf71
[new-docs] - Docs are absolutely beautiful! - TT
Tyler-Keith-Thompson Sep 10, 2021
eb860ff
[new-docs] - Added an abstract for creating workflows - TT
Tyler-Keith-Thompson Sep 10, 2021
e11f3da
[new-docs] - Added an abstract for how to use SwiftCurrent with UIKit…
Tyler-Keith-Thompson Sep 10, 2021
ebae754
[new-docs] - Added and udpated abstracts, mostly around Creating Work…
Tyler-Keith-Thompson Sep 10, 2021
d6612d6
[new-docs] - Added an abstract for controlling presentation - TT
Tyler-Keith-Thompson Sep 10, 2021
933d38a
[new-docs] - Added an abstract for type erasure - TT
Tyler-Keith-Thompson Sep 10, 2021
bc206c4
[new-docs] - Added an abstract for underlying types - TT
Tyler-Keith-Thompson Sep 10, 2021
6317178
[new-docs] - Fixed the abstracts that referred to lowercase workflow …
Tyler-Keith-Thompson Sep 10, 2021
f04b04f
[new-docs] - Fixed docs post processing so that it does not mangle li…
Tyler-Keith-Thompson Sep 10, 2021
574fa51
Update .github/DocsPostProcessor/Package.swift
Tyler-Keith-Thompson Sep 10, 2021
fad9c4f
[new-docs] - the problem was fileURLWithPath, despite the fact that t…
Tyler-Keith-Thompson Sep 10, 2021
cdf8752
Merge branch 'new-docs' of github.com:wwt/SwiftCurrent into new-docs
Tyler-Keith-Thompson Sep 10, 2021
bc26e26
[new-docs] - Cleaned up comment - TT
Tyler-Keith-Thompson Sep 10, 2021
d6321ed
[new-docs] - Added a line about tuples, just for Richard - TT RAG
Tyler-Keith-Thompson Sep 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/DocsPostProcessor/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
25 changes: 25 additions & 0 deletions .github/DocsPostProcessor/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// swift-tools-version:5.4
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "DocsPostProcessor",
products: [
.executable(
name: "DocsPostProcessor",
targets: ["DocsPostProcessor"]),
],
dependencies: [
.package(url: "https://github.com/scinfu/SwiftSoup.git", from: "1.7.4"),
.package(url: "https://github.com/apple/swift-argument-parser", from: "0.5.0"),
],
targets: [
.executableTarget(
name: "DocsPostProcessor",
dependencies: [
"SwiftSoup",
.product(name: "ArgumentParser", package: "swift-argument-parser"),
]),
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import Foundation
import ArgumentParser
import SwiftSoup

struct DocsPostProcessor: ParsableCommand {
enum Err: Error {
case noOverviewFound
}

@Flag(help: "Replaces overview in the left navigation with rendered README")
var replaceOverviewWithReadme = false

@Flag(help: "Replaces readme video link with an embedded vimeo player")
var replaceReadmeVideoWithVimeoEmbed = false

@Argument(help: "The file, or directory with the HTML to change")
var path: String

mutating func run() throws {
let url = URL(fileURLWithPath: FileManager.default.currentDirectoryPath).appendingPathComponent(path)
var files: [URL] = (url.pathExtension == "html") ? [url] : []
if url.pathExtension != "html", let enumerator = FileManager.default.enumerator(at: url, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles]) {
for case let fileURL as URL in enumerator {
let fileAttributes = try fileURL.resourceValues(forKeys:[.isRegularFileKey])
if fileAttributes.isRegularFile == true, fileURL.pathExtension == "html" {
files.append(fileURL)
}
}
}
for file in files {
let html = try String(contentsOf: file, encoding: .utf8)
let doc: Document = try SwiftSoup.parse(html)
if replaceOverviewWithReadme {
try replaceOverviewWithReadme(document: doc)
print("Replaced overview with README for: \(file.absoluteString)")
}
if replaceReadmeVideoWithVimeoEmbed, file.lastPathComponent == "index.html" {
Tyler-Keith-Thompson marked this conversation as resolved.
Show resolved Hide resolved
try replaceReadmeVideoWithVimeoEmbed(document: doc)
print("Replaced readme video with vimeo embed")
}
try doc.html().write(to: file, atomically: true, encoding: .utf8)
}
}

func replaceOverviewWithReadme(document: Document) throws {
if let nav = try? document.select("nav").first() {
if let firstNavLink = try nav.getElementsByClass("nav-group-name-link").first(),
let oldUrl = URL(string: try firstNavLink.attr("href")),
oldUrl.lastPathComponent == "Overview.html" {
try firstNavLink.attr("href", oldUrl.deletingLastPathComponent().appendingPathComponent("index.html").absoluteString)
} else {
throw Err.noOverviewFound
}
}
}

func replaceReadmeVideoWithVimeoEmbed(document: Document) throws {
if let article = try? document.select("article").first() {
let link = try article.getElementsByAttributeValue("href", "https://user-images.githubusercontent.com/33705774/132767762-7447753c-feba-4ef4-b54c-38bfe9d1ee82.mp4")
try link.wrap("""
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/600610695?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479&amp;h=fd3976b77a" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Introducing SwiftCurrent.mp4"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
""")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DocsPostProcessor.main()
12 changes: 12 additions & 0 deletions .github/abstract/Controlling Presentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
SwiftCurrent allows you to control how your workflow presents its `FlowRepresentable`s. This control over presentation is different for UIKit and SwiftUI. You can also control `FlowPersistence` which is a description for what should happen to an item in a `Workflow` if it's been skipped, or once the workflow has proceeded.

### UIKit
In UIKit you control presentation using `LaunchStyle.PresentationType`. The default is a contextual presentation mode. If it detects you are in a navigation view, it'll present by pushing onto the navigation stack. If it cannot detect a navigation view it presents modally. Alternatively you can explicitly state you'd like it to present modally or in a navigation stack when you define your `Workflow`.

### In SwiftUI
In SwiftUI you control presentation using `LaunchStyle.SwiftUI.PresentationType`. The default is simple view replacement. This is especially powerful because your workflows in SwiftUI do not need to be an entire screen, they can be just part of a view. Using the default presentation type you can also get fine grained control over animations. You can also explicitly state you'd like it to present modally (using a sheet, or fullScreenCover) or in a navigation stack when you define your `WorkflowLauncher`.

### Persistence
You can control what happens to items in your workflow using `FlowPersistence`. Using `FlowPersistence.persistWhenSkipped` means that when `FlowRepresentable.shouldLoad` returns false the item is still stored on the workflow. If for example, you're in a navigation stack this means the item *is* skipped, but you can back up to it.

Using `FlowPersistence.removedAfterProceeding` means once the `Workflow` has proceeded, the item is removed, references to it are cleaned up, and it is removed from any back stacks.
2 changes: 1 addition & 1 deletion .github/abstract/Creating Workflows in SwiftUI.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct FirstView: View, FlowRepresentable {

> Note: The `_workflowPointer` is needed as an anchor point for your `Workflow`. You do not have to worry about setting it, you merely need space for it on your structs. SwiftUI actually does the exact same thing with a `_location` variable, it's just that Apple has secret compiler magic to hide that. Unfortunately, that compiler magic is not shared.

> Note: `Workflow.proceedInWorkflow()` is what you call to have your view move forward to the next item in the `Workflow` it is part of.
> Note: `FlowRepresentable.proceedInWorkflow()` is what you call to have your view move forward to the next item in the `Workflow` it is part of.

### Step 2:
Define your `WorkflowLauncher`. This indicates whether the workflow is shown and describes what items are in it.
Expand Down
43 changes: 43 additions & 0 deletions .github/abstract/Creating Workflows in UIKit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
### Step 1:
To create workflows in UIKit you should start with a `UIViewController` that should be part of a `Workflow` and modify it to be `FlowRepresentable`

#### Example:
```swift
import UIKit
import SwiftCurrent
import SwiftCurrent_UIKit

// This screen shows an employee only screen
class FirstViewController: UIWorkflowItem<String, String>, FlowRepresentable { // SwiftCurrent
private let email: String
private let finishButton = UIButton()

required init(with email: String) { // SwiftCurrent
self.email = email
super.init(nibName: nil, bundle: nil)
// Configure your view programmatically or look at StoryboardLoadable to use storyboards.
}

required init?(coder: NSCoder) { nil }

@objc private func finishPressed() {
proceedInWorkflow(email) // SwiftCurrent
}
}
```

> Note: `FlowRepresentable.proceedInWorkflow()` is what you call to have your view move forward to the next item in the `Workflow` it is part of.

### Step 2:
Define your `Workflow` and launch it. This is what allows you to configure or re-order your workflow.

#### Example:
```swift
// From the ViewController you'd like to launch the workflow
@objc private func didTapLaunchWorkflow() {
let workflow = Workflow(FirstViewController.self) // SwiftCurrent
.thenPresent(SecondViewController.self) // SwiftCurrent

launchInto(workflow, args: "Some starting arguments")
}
```
8 changes: 8 additions & 0 deletions .github/abstract/Creating Workflows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
### What is a workflow?
A `Workflow` is a description for a sequence of `FlowRepresentable`. Those operations are normally displaying screens or views. There are different ways of [creating workflows in SwiftUI](Creating%20Workflows%20in%20SwiftUI.html) and [creating workflows in UIKit](Creating%20Workflows%20in%20UIKit.html).

### What is a `FlowRepresentable`?
A `FlowRepresentable` is a protocol that describes a type that can appear in a `Workflow`. It optionally declares `FlowRepresentable.WorkflowInput` and `FlowRepresentable.WorkflowOutput` indicating whether it requires data or whether it passes data forward. It also provides an initializer so that it can be created by the `Workflow`. Once an item conforms to `FlowRepresentable` it is capable of being injected into any `Workflow`.

### Valid workflow sequences
Workflows enforce (either at compile-time or run-time) that the sequence of `FlowRepresentables` are well-formed. For example if a particular `FlowRepresentable` has a `FlowRepresentable.WorkflowInput` of `String` but the previous item passes an `Int` forward, that workflow is malformed. It's possible for a `FlowRepresentable` to declare a `FlowRepresentable.WorkflowInput` of `Never` if it does not take in data, `Any` if it can intake multiple types, or `AnyWorkflow.PassedArgs` if it can handle being passed no data, or data of any kind. Lastly, if your `FlowRepresentable.WorkflowInput` needs to take in multiple values you can use a tuple.
1 change: 1 addition & 0 deletions .github/abstract/How to use SwiftCurrent with UIKit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SwiftCurrent works well with UIKit. To work correctly it does require `FlowRepresentable`s to be `UIViewController`s and not `UIView`s. It comes with [support for Storyboards](using-storyboards.html) with `StoryboardLoadable` and [programmatic views](using-programmatic-views.html).
4 changes: 4 additions & 0 deletions .github/abstract/Type Erasure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Sometimes it may be desireable to explicitly remove type information. Often times this is when you want to pass around types with complicated generic signatures. SwiftCurrent, much like many of Apple's standard libraries, ships with several type erasers for your convenience.

### `AnyWorkflow.PassedArgs`
The type `AnyWorkflow.PassedArgs` is worth calling out separately. It's very similar to Swift's standard `Optional` type, but with a crucial difference. Consumers of SwiftCurrent need to be able to clearly differentiate between `nil` being passed in a `workflow` that proceeded and no arguments at all being passed. So if a `FlowRepresentable.WorkflowInput` is `Any?` that means it can accept any kind of data, even if that data is optional, but data *must* be passed to it. If a `FlowRepresentable.WorkflowInput` is `AnyWorkflow.PassedArgs` it means that it can take any kind of data, including nil data, OR it can take no data at all.
1 change: 1 addition & 0 deletions .github/abstract/Underlying Types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
These types are required to make SwiftCurrent function. Most of these are public symbols because of the modular design of SwiftCurrent. Some of them are public in case you want to extend SwiftCurrent to do even more. Generally speaking, these types are not something you need to worry about.
4 changes: 3 additions & 1 deletion .github/document.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ jazzy --config .github/.jazzy.yaml --podspec SwiftCurrent.podspec --sourcekitten
rm swiftcurrent-docs.json
rm swiftcurrentuikit-docs.json
rm swiftcurrent-swiftui-docs.json
open docs/index.html
cd .github/DocsPostProcessor
swift run DocsPostProcessor ../../Docs --replace-overview-with-readme --replace-readme-video-with-vimeo-embed
open ../../docs/index.html
Loading