Skip to content

Commit

Permalink
+ extras: DSL for navigating between activities xebia-functional#62
Browse files Browse the repository at this point in the history
remove Parcelable
add a case class to wrap array in Serializable
add method to startActivityForResult
use method overloading
  • Loading branch information
rickrickrickyyy authored Jul 28, 2017
1 parent d09ed7b commit ec159ab
Showing 1 changed file with 54 additions and 216 deletions.
270 changes: 54 additions & 216 deletions macroid-extras/src/main/scala/macroid/extras/UIActionsExtras.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import android.app.Activity
import android.content.{Context, Intent}
import android.os._
import android.widget.Toast
import macroid.{ContextWrapper, Ui}
import macroid.{ActivityContextWrapper, ContextWrapper, Ui}

object UIActionsExtras {

Expand Down Expand Up @@ -41,208 +41,12 @@ object UIActionsExtras {
}
}

private def readArray[A](source: Parcel, build: Int Array[A], read: Parcel A) = {
val N = source.readInt()
val array = build(N)
for {
i <- 0 until N
} array(i) = read(source)
array
}

class Ints(val get: Array[Int]) extends Parcelable {


override def describeContents() = 0

override def writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(get.length)
get.foreach(dest.writeInt)
}
}

object Ints {
def apply(array: Int*) {
new Ints(array.toArray)
}
val CREATOR: Parcelable.Creator[Ints] = new Parcelable.Creator[Ints] {

override def createFromParcel(source: Parcel): Ints = new Ints({
source.createIntArray()
})

override def newArray(size: Int): Array[Ints] = new Array[Ints](size)
}
}


class Bytes(val get: Array[Byte]) extends Parcelable {

override def describeContents() = 0

override def writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(get.length)
get.foreach(dest.writeByte)
}
}

object Bytes {
def apply(array: Byte*) {
new Bytes(array.toArray)
}
val CREATOR: Parcelable.Creator[Bytes] = new Parcelable.Creator[Bytes] {

override def createFromParcel(source: Parcel): Bytes = new Bytes({
readArray(source, N new Array[Byte](N), _.readByte())
})

override def newArray(size: Int): Array[Bytes] = new Array[Bytes](size)
}
}

class Doubles(val get: Array[Double]) extends Parcelable {

override def describeContents() = 0

override def writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(get.length)
get.foreach(dest.writeDouble)
}
}

object Doubles {
def apply(array: Double*) {
new Doubles(array.toArray)
}
val CREATOR: Parcelable.Creator[Doubles] = new Parcelable.Creator[Doubles] {

override def createFromParcel(source: Parcel): Doubles = new Doubles({
readArray(source, N new Array[Double](N), _.readDouble())
})

override def newArray(size: Int): Array[Doubles] = new Array[Doubles](size)
}
}

class Floats(val get: Array[Float]) extends Parcelable {
override def describeContents() = 0

override def writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(get.length)
get.foreach(dest.writeFloat)
}
}

object Floats {
def apply(array: Float*) {
new Floats(array.toArray)
}

val CREATOR: Parcelable.Creator[Floats] = new Parcelable.Creator[Floats] {

override def createFromParcel(source: Parcel): Floats = new Floats({
readArray(source, N new Array[Float](N), _.readFloat())
})

override def newArray(size: Int): Array[Floats] = new Array[Floats](size)
}
}

class Longs(val get: Array[Long]) extends Parcelable {

override def describeContents() = 0

override def writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(get.length)
get.foreach(dest.writeLong)
}
}

object Longs {
def apply(array: Long*) {
new Longs(array.toArray)
}

val CREATOR: Parcelable.Creator[Longs] = new Parcelable.Creator[Longs] {

override def createFromParcel(source: Parcel): Longs = new Longs({
readArray(source, N new Array[Long](N), _.readLong())
})

override def newArray(size: Int): Array[Longs] = new Array[Longs](size)
}
}

class Booleans(val get: Array[Boolean]) extends Parcelable {


override def describeContents() = 0

override def writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(get.length)
get.foreach(c dest.writeInt(if (c) 1 else 0))
}
}

object Booleans {
def apply(array: Boolean*) {
new Booleans(array.toArray)
}
val CREATOR: Parcelable.Creator[Booleans] = new Parcelable.Creator[Booleans] {

override def createFromParcel(source: Parcel): Booleans = new Booleans({
readArray(source, N new Array[Boolean](N), _.readInt() != 0)
})

override def newArray(size: Int): Array[Booleans] = new Array[Booleans](size)
}
}

class Chars(val get: Array[Char]) extends Parcelable {
// def this(array: Char*) {
// this(array.toArray)
// }

override def describeContents() = 0

override def writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(get.length)
get.foreach(c dest.writeInt(c))
}
}

object Chars {
val CREATOR: Parcelable.Creator[Chars] = new Parcelable.Creator[Chars] {

override def createFromParcel(source: Parcel): Chars = new Chars(
readArray(source, N new Array[Char](N), _.readInt.toChar)
)

override def newArray(size: Int): Array[Chars] = new Array[Chars](size)
}
}

class Strings(val get: Array[String]) extends Parcelable {
override def describeContents() = 0

override def writeToParcel(dest: Parcel, flags: Int) {
dest.writeInt(get.length)
get.foreach(dest.writeString)
}
}

object Strings {

def apply(array:String*) ={
new Strings(array.toArray)
}

val CREATOR: Parcelable.Creator[Strings] = new Parcelable.Creator[Strings] {
override def createFromParcel(source: Parcel): Strings =
new Strings(readArray(source, n new Array[String](n), _.readString))


override def newArray(size: Int): Array[Strings] = new Array[Strings](size)

case class ArrayExtras[T](array: Array[T])

implicit class ArrayMethod[T](array: Array[T]) {
def toArrayExtras: ArrayExtras[T] = {
ArrayExtras[T](array)
}
}

Expand All @@ -262,39 +66,73 @@ object UIActionsExtras {
case v: Serializable intent.putExtra(key, v)
case v: Bundle intent.putExtra(key, v)
case v: Parcelable intent.putExtra(key, v)
case v throw new IllegalArgumentException(s"Please don't put ${v.getClass} into the extra")
case _: Array[_] throw new IllegalArgumentException(s"Array is not supported,but you can wrap it in a case class : ArrayExtras(Array(1,2,3))")
case v throw new IllegalArgumentException(s"class: ${v.getClass} is not supported")
}
}
}

/**
* example: goto(classOf[TuningActivity], i ⇒ i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), "ID" -> 1)
/**
*
*
* @param cls class of the activity
* @param configFn extra config steps(add flags)
* @param extra the extra key value pair
* @param context context
* @return Ui action that can navigate to the class of the Activity
* @return intent that can navigate to the class of the Activity
*/
def goto(cls: Class[_ <: Activity], configFn: Intent Unit, extra: (String, Any)*)(implicit context: ContextWrapper): Ui[Unit] = {
def intentFor(cls: Class[_ <: Activity], extra: (String, Any)*)(implicit context: ContextWrapper): Intent = {
val intent = new Intent(context.getOriginal, cls)
extra.foreach(elem elem._2.putExtra(intent, elem._1))
configFn(intent)
extra.foreach({
case (key, value) value.pushInto(intent, key)
})
intent
}

/**
* example: goto(intentFor(classOf[TuningActivity], "ID" -> 1, Array("some","array").toArrayExtras))
*
* @param intent x
* @param context context
* @return Ui action that can navigate to the class of the Activity
*/
def goto(intent: Intent)(implicit context: ContextWrapper): Ui[Unit] = {
Ui(context.getOriginal.startActivity(intent))
}
/**
* example: goto(classOf[TuningActivity], "ID" -> 1, Array("some","array").toArrayExtras)
*
* @param cls class of the activity
* @param extra the extra key value pair
* @param context context
* @return Ui action that can navigate to the class of the Activity
*/
def goto(cls: Class[_ <: Activity], extra: (String, Any)*)(implicit context: ContextWrapper): Ui[Unit] = {
goto(intentFor(cls, extra: _*))
}

/**
* example: goto(classOf[TuningActivity], i ⇒ i.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), "ID" -> 1)
*
* @param cls class of the activity
* @param extra the extra key value pair
* @param modified a function that return a modified version of the intent
* @param context context
* @return Ui action that can navigate to the class of the Activity
*/
def goto(cls: Class[_ <: Activity], extra: (String, Any)*)(implicit context: ContextWrapper): Ui[Unit] = {
val intent = new Intent(context.getOriginal, cls)
extra.foreach(elem elem._2.putExtra(intent, elem._1))
Ui(context.getOriginal.startActivity(intent))
def goto(cls: Class[_ <: Activity], modified: Intent => Intent, extra: (String, Any)*)(implicit context: ContextWrapper): Ui[Unit] = {
goto(modified(intentFor(cls, extra: _*)))
}

def request(requestCode: Int, intent: Intent)(implicit context: ActivityContextWrapper): Ui[Unit] = {
Ui(context.getOriginal.startActivityForResult(intent, requestCode))
}

def request(requestCode: Int, cls: Class[_ <: Activity], extra: (String, Any)*)(implicit context: ActivityContextWrapper): Ui[Unit] = {
request(requestCode, intentFor(cls, extra: _*))
}

def request(requestCode: Int, modified: Intent => Intent, cls: Class[_ <: Activity], extra: (String, Any)*)(implicit context: ActivityContextWrapper): Ui[Unit] = {
request(requestCode, modified(intentFor(cls, extra: _*)))
}
}

Expand Down

0 comments on commit ec159ab

Please sign in to comment.