All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.com.slack.circuit.runtime.CircuitContext.kt Maven / Gradle / Ivy

The newest version!
// Copyright (C) 2022 Slack Technologies, LLC
// SPDX-License-Identifier: Apache-2.0
package com.slack.circuit.runtime

import androidx.compose.runtime.Stable
import com.slack.circuit.runtime.internal.NoOpMap
import kotlin.reflect.KClass

/**
 * A [CircuitContext] is used in `Presenter.Factory` and `Ui.Factory` to inform creation of their
 * respective `Presenter` and `Ui` instances.
 *
 * Available information includes:
 * - [parent] – the parent [CircuitContext] or null if this is the root context.
 * - [tag] – a tag API to plumb arbitrary metadata through the [CircuitContext].
 */
@Stable
public class CircuitContext
@InternalCircuitApi
public constructor(
  public val parent: CircuitContext?,
  // Don't expose the raw map.
  private val tags: MutableMap, Any> = mutableMapOf(),
) {

  /** Returns the tag attached with [type] as a key, or null if no tag is attached with that key. */
  public fun  tag(type: KClass): T? {
    @Suppress("UNCHECKED_CAST")
    return tags[type] as T?
  }

  /** Returns the tag attached with [T] as a key, or null if no tag is attached with that key. */
  public inline fun  tag(): T? = tag(T::class)

  /**
   * Attaches [tag] to the request using [T] as a key. Tags can be read from a request using
   * [CircuitContext.tag]. Use `null` to remove any existing tag assigned for [T].
   *
   * Use this API to attach metadata, debugging, or other application data to a spec so that you may
   * read it in other APIs or callbacks.
   */
  public inline fun  putTag(tag: T?): Unit = putTag(T::class, tag)

  /**
   * Attaches [tag] to the request using [type] as a key. Tags can be read from a request using
   * [CircuitContext.tag]. Use `null` to remove any existing tag assigned for [type].
   *
   * Use this API to attach metadata, debugging, or other application data to a spec so that you may
   * read it in other APIs or callbacks.
   */
  public fun  putTag(type: KClass, tag: T?): Unit {
    if (tag == null) {
      this.tags.remove(type)
    } else {
      this.tags[type] = tag
    }
  }

  /** Clears all the current tags. */
  public fun clearTags() {
    tags.clear()
  }

  public companion object {
    /** An empty context */
    @Suppress("UNCHECKED_CAST")
    @OptIn(InternalCircuitApi::class)
    public val EMPTY: CircuitContext = CircuitContext(null, NoOpMap as MutableMap, Any>)
  }
}