# UI Components

Your app's user interface and everything that users can see and interact with.

## VGSLabel

A user interface element that displays any revealed text to the user.

## VGSLabel configuration

Set `contentPath` for `VGSLabel` view as identifier for Reveal operations on Inbound routes. Check more details how to show revealed data [here](https://docs.verygoodsecurity.com/vault/developer-tools/vgs-show/ios-sdk/reveal-data).

### Code example

```swift
cardNumberLabel.contentPath = "<CONTENT_PATH_NAME_1>"
expDateLabel.contentPath = "<CONTENT_PATH_NAME_2>"
```

Set UI configurations for `VGSLabel` view.

### Code example

```swift
private func configureUI() {
    let paddings = UIEdgeInsets.init(top: 8, left: 8, bottom: 8, right: 8)
    let textColor = UIColor.white
    let borderColor = UIColor.clear
    let font = UIFont.systemFont(ofSize: 20)
    let backgroundColor = UIColor.systemBlue
    let cornerRadius: CGFloat = 0
    let textAlignment = NSTextAlignment.left
    let characterSpacing: CGFloat = 0.83

    // Text color.
    cardNumberLabel.textColor = textColor

    // Paddings - should be non-negative!.
    cardNumberLabel.paddings = paddings

    // Border color.
    cardNumberLabel.borderColor = borderColor

    // Font.
    cardNumberLabel.font = font

    // Background color.
    cardNumberLabel.backgroundColor = backgroundColor

    // Corner radius.
    cardNumberLabel.layer.cornerRadius = cornerRadius

    // Text alignment.
    cardNumberLabel.textAlignment = textAlignment

    // Character spacing.
    cardNumberLabel.characterSpacing = characterSpacing
}
```

### Placeholder

You can setup placeholder for `VGSLabel`. Placeholder is displayed in label when there is no revealed text to show. Placeholder style can be customized with `placeholderStyle` property.

By default `VGSLabel` placeholder has paddings from `VGSLabel` text `paddings` property. Custom placeholder paddings can be specified with `placeholderPaddings`. Paddings should contain non-negative values. Negative paddings will be ignored.

```swift
private func configurePlaceholderUI() {
    let paddings = UIEdgeInsets.init(top: 8, left: 8, bottom: 8, right: 8)
    let color = UIColor.white.withAlphaComponent(0.6)
    let font = UIFont.systemFont(ofSize: 16)
    let textAlignment = NSTextAlignment.left
    let characterSpacing: CGFloat = 0.83

    // Placeholder text.
    cardNumberLabel.placeholder = "Card number"

    // Placeholder paddings. Should be non-negative!.
    cardNumberLabel.placeholderPaddings = paddings

    // Placeholder color.
	  cardNumberLabel.placeholderStyle.color = color

    // Placeholder font.
    cardNumberLabel.placeholderStyle.font = font

    // Placehplder text alignment.
    cardNumberLabel.placeholderStyle.textAlignment = textAlignment

    // Placehplder character spacing.
    cardNumberLabel.placeholderStyle.characterSpacing = characterSpacing
}
```

## Data formatting

You have ability to format received data or value in `VGSLabel` view. Use `addTransformationRegex(_:)` to setup custom transformation `NSRegularExpression` object and replacement `template` for text formatting. Use `try/catch` to validate your custom regular expression.

> You can apply multiple `NSRegularExpression` objects for formatting. Final text will be a result of the subsequent transformations.\\

## Handle changes in VGSLabel

You can handle changes in `VGSLabel` view setting its `delegate` property to object implementing `VGSLabelDelegate` protocol.

```swift
@objc
public protocol VGSLabelDelegate: class {

  /// Tells the delegate when text changes in the specified label.
  /// - Parameter label: `VGSLabel` view in which text was changed.
  @objc optional func labelTextDidChange(_ label: VGSLabel)

	/// Tells the delegate when raw text is copied in the specified label.
	/// - Parameters:
	///   - label: `VGSLabel` view in which raw text was copied.
	///   - format: `VGSLabelCopyTextFormat` object, copied text format.
	@objc optional func labelCopyTextDidFinish(_ label: VGSLabel, format: VGSLabel.CopyTextFormat)

    /// Tells the delegate when reveal data operation was failed for the subscribed `VGSLabel` view.
	/// - Parameter label: `VGSLabel` view in which reveal data operation was failed.
	/// - Parameter error: `VGSShowError` object.
	@objc optional func labelRevealDataDidFail(_ label: VGSLabel, error: VGSShowError)
}
```

### Code example

```swift
extension ViewController: VGSLabelDelegate {
	func labelTextDidChange(_ label: VGSLabel) {
		/// Handle changes in label.
        label.borderColor = UIColor.red
	}

	func labelCopyTextDidFinish(_ label: VGSLabel, format: VGSLabel.CopyTextFormat) {
		/// Handle copy event.
        print("Text was copied from label \(label) with format: \(format)")
	}

    func labelRevealDataDidFail(_ label: VGSLabel, error: VGSShowError) {
         // Set label border to red color on error.
         label.borderColor = .red
    }
}
```

## Secure text

VGS Show SDK provides you an option to secure text in VGSLabel. By secure we mean that you can optionally replace all or only some characters in revealed string by secure symbol. This works similar to "password mode" that you could see in UITextFields.

```swift
/// Enable/disable secure text mode in `VGSLabel`. Default is `false`.
public var isSecureText: Bool

/// Text symbol that replace visible label text character when securing String. Should be one charcter only. Default symbol - *.
public var secureTextSymbol: String

/// Set boundaries for secured text in  `VGSLabel`.  Boundaries always applied to visiblt text in `VGSLabel`.
/// - Parameters:
///   - start: `Int?` first boundaries index. If not set, will be replaced to 0.
///   - end: `Int?`  last included  boundaries index. If not set, will be replaced max index in visible text.
public func setSecureText(start: Int? = nil, end: Int? = nil)

/// Set range of boundaries for secured text in  `VGSLabel`.  Boundaries always applied to visiblt text in `VGSLabel`.
/// - Parameters:
///   - ranges: `[VGSTextRange]` an array of ranges where visible `VGSLabel` text should be secured.
public func setSecureText(ranges: [VGSTextRange])
```

> • Secure text is applied to visible text in VGSLabel. You should take it into consideration you apply `tranformationRegex` to revealed data, ranges should be valid for modified string.\
> • At the moment, `secureTextSymbol` can be only one character symbol.\
> • Inappropriate text ranges will be ignored. Inappropriate text ranges are range where `start` > `end` or `start` < `0`.\\

## Copy text to clipboard

You can provide an option for your end-users to copy revealed text to the clipboard after the request. Use `copyTextToClipboard(_:)` for VGSLabel to copy revealed text. The default option is `.raw` to copy raw revealed text without applying any custom formatting. You can also use `.transformed` the option to copy formatted text.

```swift
/// Copy text to pasteboard with format.
/// - Parameter format: `VGSLabel.CopyTextFormat` object, text format to copy. Default is `.raw`.
cardNumberLabel.copyTextToClipboard(format: .transformed)
```

## Clear text

You have an option to clear text from `VGSLabel` with `clearText(_:)` function. Placeholder will be displayed in the label after clear text (if `placeholder` is configured).

```swift
func resetScreenUI() {
    cardNumberLabel.clearText()
}
```

> After `clearText(_:)` new `VGSShow` request will required to populate label with revealed data. Please use this method carefully.

### VGSLabel Accessibility attributes

| **Attribute**             | **Description**                                                                                       |
| ------------------------- | ----------------------------------------------------------------------------------------------------- |
| vgsAccessibilityLabel     | `String` instance, localized string to identify the accessibility label                               |
| vgsAccessibilityHint      | `String` instance, brief description of the result of performing an action on the accessibility label |
| vgsIsAccessibilityElement | `Boolean` value, determinates if the label should be exposed as an accesibility element               |

## VGSPDFView

A user interface element that displays a revealed PDF document to the user.

> `VGSPDFView` is available only from iOS 11 since it is built upon [Apple PDFKit](https://developer.apple.com/documentation/pdfkit)\\

## VGSPDFView configuration

Set `contentPath` for `VGSPDFView` view as an identifier for Reveal operations on Inbound routes. Check more details on how to show revealed data [here](https://docs.verygoodsecurity.com/vault/developer-tools/vgs-show/ios-sdk/reveal-data).

### Code example

```swift
pdfView.contentPath = "<CONTENT_PATH_NAME>"
```

Set UI configurations for `VGSPDFView` instance.

```swift
private func configureUI() {
    // Background color.
    pdfView.backgroundColor = UIColor.gray

    // Set display direction.
    pdfView.pdfDisplayDirection = .horizontal

    // Set page shadows.
    pdfView.pageShadowsEnabled = true
}
```

## Reveal PDF with VGSShowSDK

Revealing PDF files might take more time than for text data. Consider your PDF file size and specify an additional request timeout  `VGSShowRequestOptions` if needed. The maximum file size that can be sent to VGS [is 24Mb](https://www.verygoodsecurity.com/docs/guides/managing-your-routes#redact-a-file-through-vgs-http-proxy).

```swift
@IBAction fileprivate func revealPdf(_ sender: UIButton) {
    let payload: [String: Any] = ["customKey" : "customData"]

	var options = VGSShowRequestOptions()
	options.requestTimeoutInterval = 360

	vgsShow.request(path: "/post", method: .post, payload: payload, requestOptions: options) {[weak self] result in
	switch result {
		case .success(let code):
            print("success")
		case .failure(let code, let error):
			print("vgsshow failed, code: \(code), error: \(error)")
		}
	}
}
```

> `Revealing invalid base64 data or invalid pdf data will produce an error.`>

## Handle changes in VGSPDFView

You can handle changes in `VGSPDFView` view setting its `delegate` property to the object implementing `VGSPDFViewDelegate` protocol.

```swift
@available(iOS 11.0, *)
@objc
public protocol VGSPDFViewDelegate: class {

	/// Tells the delegate the document was displayed in view.
	/// - Parameter pdfView: `VGSPDFView` view in which document was changed.
	/// Discussion.
	/// A pdf view sends this message to its delegate just after it updated the document.
	@objc optional func documentDidChange(in pdfView: VGSPDFView)

	/// Tells the delegate when pdf view encounters an error.
	/// - Parameter pdfView: `VGSPDFView` view in which error was occurred.
	/// - Parameter error: `VGSShowError` object, contains error information.
	@objc optional func pdfView(_ pdfView: VGSPDFView, didFailWithError error: VGSShowError)
}
```

### Code example

```swift
extension ShowDemoPDFViewController: VGSPDFViewDelegate {
	func documentDidChange(in pdfView: VGSPDFView) {
		innerTitleLabel.text = "REVEALED"
	}

    func pdfView(_ pdfView: VGSPDFView, didFailWithError error: VGSShowError) {
		print(error.localizedDescription ?? "uknown error")
	}
}
```

## VGSImageView

A user interface element that displays revealed images to the user.

### Declaration

```swift
class VGSImageView: UIView, VGSImageViewProtocol
```

### VGSImageView Functional attributes

| **Attribute**    | **Description**                                                                                                    |
| ---------------- | ------------------------------------------------------------------------------------------------------------------ |
| imageContentMode | `UIView.ContentMode` value, specifies how the image is rendered. Default to `.scaleToFill`                         |
| hasImage         | read-only `Boolean` value, determines if an image is being revealed or it is empty                                 |
| contentPath      | read-only `String` instance, name associated with `VGSImageView` to decode image data from your organization vault |
| delegate         | `VGSImageViewDelegate` object that will handle image reveal process                                                |

### VGSImageView Functional functions

| **Function** | **Description**                  |
| ------------ | -------------------------------- |
| clear        | Remove previously revealed image |

## VGSImageView configuration

Set `contentPath` for `VGSImageView` view as an identifier for Reveal operations on Inbound routes. Check more details on how to show revealed data [here](https://docs.verygoodsecurity.com/vault/developer-tools/vgs-show/ios-sdk/reveal-data).

## Handle changes in VGSImageView

You can handle changes in `VGSImageView` view setting its `delegate` property to the object implementing `VGSImageViewDelegate` protocol.

```swift
@objc
public protocol VGSImageViewDelegate {

    /// Tells the delegate the image was displayed in view.
    /// - Parameter imageView: `VGSImageView` view in which image was changed.
    @objc optional func imageDidChange(in imageView: VGSImageView)

    /// Tells the delegate when image view encounters an error.
    /// - Parameters:
    ///     - imageView: `VGSImageView` view in which error was occurred.
    ///     - error: `VGSShowError` object, contains error information.
    @objc optional func imageView(_ imageView: VGSImageView, didFailWithError error: VGSShowError)
}
```

### Code example

```swift
class ViewController {

  // Create instances
  var imageView = VGSImageView()

  // ...

  private func configureUI() {

    // Subscribe to show SDK
    vgsShow.subscribe(imageView)

    // Configure content path
    imageView.contentPath = "<CONTENT_PATH_NAME>"

    // Set image display content mode
    imageView.imageContentMode = .scaleAspectFit

    // Set VGSImageViewDelegate to handle reveal events
    imageView.delegate = self

    // Background color.
    imageView.backgroundColor = UIColor.gray
  }

  // ...

  // Clear image content
  imageView.clear()

  // ...
}

/// Handle VGSImageViewDelegate methods
extension ViewController: VGSImageViewDelegate {
  
  func imageDidChange(in imageView: VGSImageView) {
    /// VGSImageView change image content
  }
  
  func imageView(_ imageView: VGSImageView, didFailWithError error: VGSShowError) {
    /// Handle reveal image errors
  }
}
```

## Reveal image with VGSShowSDK

Revealing image files might take more time than for text data. Consider your image file size and specify additional request timeout with `VGSShowRequestOptions` if needed. Max file size that can be sent to VGS [is 24Mb](https://docs.verygoodsecurity.com/vault/http-proxy/operations/redacting-files-via-the-https-proxy).

```swift
@IBAction fileprivate func revealImage(_ sender: UIButton) {
    let payload: [String: Any] = ["customKey": "customData"]
    
    var options = VGSShowRequestOptions()
    options.requestTimeoutInterval = 360
    
    vgsShow.request(path: "/post", method: .post, payload: payload, requestOptions: options) {[weak self] result in
    switch result {
        case .success(let code):
            print("success")
        case .failure(let code, let error):
            print("vgsshow failed, code: \(code), error: \(error)")
        }
    }
}
```

> `Revealing invalid base64 data or invalid image data will produce an error.`
