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

korolev.ApplicationContext.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017-2018 Aleksey Fomkin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package korolev

import levsha.Document
import levsha.events.EventPhase
import Async._
import korolev.state.{StateDeserializer, StateSerializer}

import scala.concurrent.duration.FiniteDuration
import scala.reflect.ClassTag

/**
  * Legacy (version < 0.6.0) API layer.
  * @see [[Context]]
  * @deprecated
  */
final class ApplicationContext[F[_]: Async, S: StateSerializer: StateDeserializer, M] {

  import Context._
  import ApplicationContext._
  import EventPhase._

  type Effect = Context.Effect[F, S, M]
  type Event = Context.Event[F, S, M]
  type EventFactory[T] = T => Event
  type Transition = korolev.Transition[S]
  type Render = PartialFunction[S, Document.Node[Effect]]
  type ElementId = Context.ElementId[F, S, M]
  type Access = ApplicationContext.LegacyAccess[F, S, M]

  val symbolDsl = new KorolevTemplateDsl[F, S, M]()
  val modern = new Context[F, S, M]()

  def elementId(name: Option[String] = None) = new Context.ElementId[F, S, M](name)

  def delay(duration: FiniteDuration)(f: Transition): Delay[F, S, M] =
    Delay(duration, access => access.transition(f))

  private def provideEventResult(ler: LegacyEventResult[F, S], access: Context.Access[F, S, M]) = {
    for {
      _ <- ler.immediate.fold(Async[F].unit)(access.transition)
      _ <- ler.deferred.map(_.flatMap(access.transition)).getOrElse(Async[F].unit)
    } yield ()
  }

  def eventWithAccess(name: Symbol, phase: EventPhase = Bubbling)(f: Access => LegacyEventResult[F, S]): Event = {
    Event(name, phase, access => provideEventResult(f(new LegacyAccess[F, S, M](access)), access))
  }

  def event(name: Symbol, phase: EventPhase = Bubbling)(ler: => LegacyEventResult[F, S]): Event = {
    Event(name, phase, access => provideEventResult(ler, access))
  }

  def immediateTransition(transition: Transition): LegacyEventResult[F, S] =
    LegacyEventResult(immediate = Some(transition))

  def deferredTransition(transition: F[Transition]): LegacyEventResult[F, S] =
    LegacyEventResult(deferred = Some(transition))

  /**
    * This is an immediateTransition return same state
    */
  def noTransition: LegacyEventResult[F, S] = immediateTransition(identity)

  val emptyTransition: PartialFunction[S, S] = { case x => x }

  def transition(t: Transition): Transition = t
}

object ApplicationContext {

  @deprecated("This is compatibility layer for old fashioned API. Use Context instead.", "0.6.0")
  def apply[F[_]: Async, S: StateSerializer: StateDeserializer, M] =
    new ApplicationContext[F, S, M]()

  case class LegacyEventResult[F[_]: Async, S](
      immediate: Option[Transition[S]] = None,
      deferred: Option[F[Transition[S]]] = None,
      shouldStopPropagation: Boolean = false
  ) {
    def immediateTransition(t: Transition[S]): LegacyEventResult[F, S] =
      copy(immediate = Some(t))

    def deferredTransition(t: F[Transition[S]]): LegacyEventResult[F, S] =
      copy(deferred = Some(t))

    def stopPropagation: LegacyEventResult[F, S] =
      copy(shouldStopPropagation = true)
  }

  import Context._

  class LegacyPropertyHandler[F[_]: Async, T: ClassTag](propertyHandler: PropertyHandler[F]) {

    import reflect.classTag

    def get(propName: Symbol): F[T] = propertyHandler.get(propName) map { value =>
      val valueToCast = classTag[T] match {
        case t if t == classTag[String] => value
        case t if t == classTag[Int] => value.toInt
        case t if t == classTag[Double] => value.toDouble
        case t if t == classTag[Long] => value.toLong
        case t if t == classTag[Float] => value.toFloat
        case t if t == classTag[Boolean] => value.toBoolean
      }
      valueToCast.asInstanceOf[T]
    }

    def set(propName: Symbol, value: T): F[Unit] = {
      propertyHandler.set(propName, value)
    }
  }

  final class LegacyAccess[F[_]: Async, S, M](access: Access[F, S, M]) {

    def property[T: ClassTag](id: ElementId[F, S, M]): LegacyPropertyHandler[F, T] =
      new LegacyPropertyHandler(access.property(id))

    def property[T: ClassTag](id: ElementId[F, S, M], propName: Symbol): F[T] =
      property[T](id).get(propName)

    def focus(id: ElementId[F, S, M]): F[Unit] =
      access.focus(id)

    def publish(message: M): F[Unit] =
      access.publish(message)

    def downloadFormData(id: ElementId[F, S, M]): FormDataDownloader[F, S] =
      access.downloadFormData(id)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy