Skip to content

Commit

Permalink
docs: split documentation per Examples (#172)
Browse files Browse the repository at this point in the history
* docs: split documentation per Examples

* chore: apply Xcode update suggestions

* Apply suggestions from code review

---------

Co-authored-by: e271828- <[email protected]>
  • Loading branch information
CAMOBAP and e271828- authored Dec 16, 2024
1 parent 0d2da07 commit 304c13f
Show file tree
Hide file tree
Showing 13 changed files with 330 additions and 238 deletions.
82 changes: 43 additions & 39 deletions Example/HCaptcha.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1320"
LastUpgradeVersion = "1600"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E6A23A382CEA6D480071D531"
BuildableName = "HCaptacha_PassiveExample.app"
BlueprintName = "HCaptacha_PassiveExample"
BuildableName = "HCaptcha_PassiveExample.app"
BlueprintName = "HCaptcha_PassiveExample"
ReferencedContainer = "container:HCaptcha.xcodeproj">
</BuildableReference>
</BuildActionEntry>
Expand Down Expand Up @@ -45,8 +45,8 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E6A23A382CEA6D480071D531"
BuildableName = "HCaptacha_PassiveExample.app"
BlueprintName = "HCaptacha_PassiveExample"
BuildableName = "HCaptcha_PassiveExample.app"
BlueprintName = "HCaptcha_PassiveExample"
ReferencedContainer = "container:HCaptcha.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
Expand All @@ -62,8 +62,8 @@
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E6A23A382CEA6D480071D531"
BuildableName = "HCaptacha_PassiveExample.app"
BlueprintName = "HCaptacha_PassiveExample"
BuildableName = "HCaptcha_PassiveExample.app"
BlueprintName = "HCaptcha_PassiveExample"
ReferencedContainer = "container:HCaptcha.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1340"
LastUpgradeVersion = "1600"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:HCaptcha_Tests/HCaptcha_Tests.xctestplan">
reference = "container:HCaptcha_Tests/HCaptcha_Tests.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
<Testables>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1150"
LastUpgradeVersion = "1600"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
17 changes: 17 additions & 0 deletions Example/ObjC-Example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## Objective-C Example

Make sure [installation is complete](../../README.md#installation) and [pre-requisites are met](../../README.md#installation)

`HCaptcha` exposes its API to real native code, so it can be used from `Objective-C`.

Because `HCaptcha` is a pure Swift library, it exposes its API through the `@objc` attribute.

The `@objc` attribute makes Swift methods, properties, and classes available to Objective-C code. By marking a Swift method or class with `@objc`, it is automatically bridged to Objective-C, allowing for interoperability between Swift and Objective-C.

Also because `Objective-C` doesn't support optional arguments, the most popular constructors of `HCaptcha` are available in `Objective-C`

The full code is in [ViewController.m](./ViewController.m).

----

[Back to the main README](../../README.md)
13 changes: 13 additions & 0 deletions Example/Passive-Example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Passive ApiKey Example

Make sure [installation is complete](../../README.md#installation) and [pre-requisites are met](../../README.md#installation)

HCaptcha Enterprise supports verification with no interaction from the user: [Passive Site Keys](https://docs.hcaptcha.com/faq#what-are-the-difficulty-levels-for-the-challenges-and-how-are-they-selected).

Using the `passiveApiKey` option with Passive sitekeys provides performance improvements in SDK token generation time, at the cost of less flexibility if you want to change the sitekey mode in the future without a code update.

The full code is in [Example](./ContentView.swift).

----

[Back to the main README](../../README.md)
63 changes: 63 additions & 0 deletions Example/RxSwift-Example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
## RxSwift Example

Once [installation is complete](../../README.md#installation) and [pre-requisites are met](../../README.md#installation), we are ready to proceed with the actual implementation:

``` swift
var hcaptcha: HCaptcha!

// ...

hcaptcha.rx.validate(on: view)
.subscribe(onNext: { (token: String) in
// Do something
})
```

Note: caller code is responsible for hiding the `WebView` after challenge processing. This is illustrated in the Example app, and can be achieved with:

```swift
...
hcaptcha?.configureWebView { [weak self] webview in
webview.tag = "hCaptchaViewTag"
}
...

let disposeBag = DisposeBag()
let validate = hcaptcha.rx.validate(on: view)
...

validate
.map { [weak self] _ in
self?.view.viewWithTag("hCaptchaViewTag")
}
.subscribe(onNext: { webview in
webview?.removeFromSuperview()
})
.disposed(by: disposeBag)
```

The full code is in [`ViewController.swift`](./ViewController.swift)

### SDK Events

This SDK allows you to receive [interaction events](../../README.md#sdk-events). This is how it can be implemented:

For `RxSwift`:

```swift
let hcaptcha = try? HCaptcha(...)
...
hcaptcha.rx.events()
.subscribe { [weak self] rxevent in
let event = rxevent.element?.0

if event == .open {
...
}
}
...
```

----

[Back to the main README](../../README.md)
10 changes: 10 additions & 0 deletions Example/SwiftUI-Example/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>HCaptchaDomain</key>
<string>http://localhost</string>
<key>HCaptchaKey</key>
<string>a5f74b19-9e45-40e0-b45d-47ff91b7a6c2</string>
</dict>
</plist>
13 changes: 13 additions & 0 deletions Example/SwiftUI-Example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
### SwiftUI Example

Once [installation is complete](../../README.md#installation) and [pre-requisites are met](../../README.md#installation), we are ready to proceed with the actual implementation:

While `HCaptcha` was originally designed for UIKit, you can easily use it with `SwiftUI` as well. Check out the [SwiftUI Example](./ContentView.swift).

To integrate `UIKit` components into a `SwiftUI` project, you can use `UIViewRepresentable`. This protocol allows you to wrap a `UIKit` view and make it compatible with `SwiftUI`.

For example, to use a `HCaptcha` component (originally designed to show over `UIKit` views) in `SwiftUI`, you would create a `UIViewRepresentable` that provides a "placeholder" view for the `HCaptcha` to be used as host view to add `WKWebView`.

----

[Back to the main README](../../README.md)
116 changes: 116 additions & 0 deletions Example/UIKit-Example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
## UIKit Example

Once [installation is complete](../../README.md#installation) and [pre-requisites are met](../../README.md#installation), we are ready to proceed with the actual implementation:

``` swift
let hcaptcha = try? HCaptcha()

override func viewDidLoad() {
super.viewDidLoad()

hcaptcha?.configureWebView { [weak self] webview in
webview.frame = self?.view.bounds ?? CGRect.zero
}
}

// ...

func validate() {
hcaptcha?.validate(on: view) { [weak self] (result: HCaptchaResult) in
print(try? result.dematerialize())
}
}
```

**Note**: caller code is responsible for hiding the `WebView` after challenge processing. This is illustrated in the Example app, and can be achieved with:

```swift
...
var captchaWebView: WKWebView?
...

hcaptcha?.configureWebView { [weak self] webview in
self?.captchaWebView = webview
}
...

hcaptcha.validate(on: view) { result in
...

captchaWebView?.removeFromSuperview()
}

```

The full code is in [`ViewContoller.swift`](./ViewContoller.swift)

## Show `hCaptcha` above `UIVisualEffectView`

In case you need to show hCaptcha above `UIVisualEffectView` make sure to pass `visualEffectView.contentView` instead `visualEffectView`. Per Apple's documentation:

> After you add the visual effect view to the view hierarchy, add any subviews to the contentView property of the visual effect view. Do not add subviews directly to the visual effect view itself.
More details [here](https://github.com/hCaptcha/HCaptcha-ios-sdk/issues/50).

## Change hCaptcha frame

If you are customizing display beyond the defaults and need to resize or change the hCaptcha layout, for example after a visual challenge appears, you can use the following approach to trigger a redraw of the view:

``` swift
let hcaptcha = try? HCaptcha(...)
var visualChallengeShown = false
...
hcaptcha?.configureWebView { [weak self] webview in
webview.tag = "hCaptchaViewTag"
if visualChallengeShown {
let padding = 10
webview.frame = CGRect(
x: padding,
y: padding,
width: view.frame.size.width - 2 * padding,
height: targetHeight - 2 * padding
)
} else {
webview.frame = self?.view.bounds ?? CGRect.zero
}
}
...
hcaptcha.onEvent { (event, data) in
if event == .open {
visualChallengeShown = true
hcaptcha.redrawView()
} else if event == .error {
let error = data as? HCaptchaError
print("onEvent error: \(String(describing: error))")
...
}
}
...
hcaptcha.validate(on: view, resetOnError: false) { result in
visualChallengeShown = false
}
```

## SDK Events

This SDK allows you to receive [interaction events](../../README.md#sdk-events). This is how it can be implemented:

``` swift
let hcaptcha = try? HCaptcha(...)

// ...

hcaptcha.onEvent { (event, data) in
if event == .open {
...
} else if event == .error {
let error = data as? HCaptchaError
print("onEvent error: \(String(describing: error))")
...
}
}
```

----

[Back to the main README](../../README.md)
Loading

0 comments on commit 304c13f

Please sign in to comment.