Commit 4397ceb4 authored by maxiaoliang's avatar maxiaoliang

提交代码

parent 254dad2d
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
......
package com.ym.game
import android.os.Bundle
import android.util.Log
import com.game.luckyfarm.UnityPlayerActivity
import com.tencent.ep.commonbase.api.AppContext.context
import com.ym.game.module.HomeInfoEntity
import com.ym.game.module.LandListEntity
import com.ym.game.module.OrderListEntity
import com.ym.game.module.StatusEntity
import com.ym.game.net.GameApiClient
import com.ym.game.view.SiginDropsPopupwindow
import com.ym.game.view.TurntableDialog
import com.ym.library.net.BaseObserver
import com.ym.library.net.RxSchedulers
import com.ym.library.rxbus.RxBusConstant
import com.ym.library.rxbus.RxBusUtil
import com.ym.library.utils.Utils
/**
......@@ -17,11 +23,22 @@ import com.ym.library.utils.Utils
* @detail :
*/
class GameActivity : UnityPlayerActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
TurntableDialog.initTurntableAnim()
// TurntableDialog.showTurntable(this)
// RxBusUtil.getDefault().send(RxBusConstant.RX_MAIN_TURNTABLE_LOTTERYED)
if (Utils.isFastClick()) {
}
}
/**
* 跳转提现页
*/
fun gotoWithdrawPage() {
Log.d("wxw", "跳转提现页")
}
/**
......@@ -36,6 +53,14 @@ class GameActivity : UnityPlayerActivity() {
*/
fun oneveryDayWelfareClick() {
Log.d("wxw", "每日福利")
this.runOnUiThread(object : Runnable {
override fun run() {
SiginDropsPopupwindow().init(this@GameActivity)
}
})
}
/**
......@@ -53,7 +78,7 @@ class GameActivity : UnityPlayerActivity() {
GameApiClient.gameApi.getGameHomeInfo().compose(RxSchedulers.observableIO2Main())
.subscribe(object : BaseObserver<HomeInfoEntity>() {
override fun onSuccess(result: HomeInfoEntity?) {
Log.d("wxw", "获取首页信息" +Utils.obj2Str(result))
Log.d("wxw", "获取首页信息" + Utils.obj2Str(result))
callback?.onHomeSuccess(true, Utils.obj2Str(result))
}
......
package com.ym.game.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.ym.game.module.SinginEntity
import com.ym.library.base.BaseRecyclerAdapter
import com.ym.quwei.guessing.R
/**
*Craeted by ${junqi.li}
*Craeted by 2020/9/12
*/
class SigninDropsAdapter :
BaseRecyclerAdapter<SinginEntity.SignInfoListEntity, SigninDropsAdapter.SigninDropsHolder> {
private var mContext: Context? = null
constructor(content: Context?) : super() {
mContext = content
}
override fun getItemCount(): Int {
return mList.size
}
override fun onBindViewHolder(holder: SigninDropsHolder, position: Int) {
if (mList.size > 0) {
val data = mList[position]
holder.tvDay.text = "第${data.id}天"
if(data.status == 1) {
holder.tvStatus.text = "已领取"
holder.ivStatus.setImageResource(R.mipmap.icon_main_popup_singnin_received)
} else {
holder.tvStatus.text = "+${data.awardNum}"
holder.ivStatus.setImageResource(R.mipmap.icon_main_popup_singnin_receiv)
}
if (data.id == 7) {
holder.ivStatus.setImageResource(R.mipmap.icon_main_popup_singnin_receiv_treasure_chest)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SigninDropsHolder {
return SigninDropsHolder(
LayoutInflater.from(mContext).inflate(R.layout.item_signin_drops, parent, false)
)
}
inner class SigninDropsHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val ivStatus: ImageView = itemView.findViewById(R.id.iv_item_signin_status)
val tvDay: TextView = itemView.findViewById(R.id.tv_item_signin_day)
val tvStatus: TextView = itemView.findViewById(R.id.tv_item_signin_status)
}
}
\ No newline at end of file
package com.ym.game.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.ym.game.module.WateringTaskEntity
import com.ym.game.view.MainDialog
import com.ym.library.base.BaseRecyclerAdapter
import com.ym.library.net.BaseObserver
import com.ym.library.net.RxSchedulers
import com.ym.library.rxbus.RxBusConstant
import com.ym.library.rxbus.RxBusUtil
import com.ym.library.utils.LogUtils
import com.ym.library.utils.Utils
import com.ym.module.guesssong.listener.OnRecycleItemClickListener
import com.ym.quwei.guessing.R
/**
*Craeted by ${junqi.li}
*Craeted by 2020/9/12
*/
class WateringTaskAdpater :
BaseRecyclerAdapter<WateringTaskEntity, WateringTaskAdpater.WateringTaskHolder> {
private var type: Int = -1
private var mContext: Context? = null
private val listener: OnRecycleItemClickListener<WateringTaskEntity>
constructor(
content: Context?,
type: Int,
listener: OnRecycleItemClickListener<WateringTaskEntity>
) : super() {
this.listener = listener
mContext = content
this.type = type
}
override fun getItemCount(): Int {
return mList.size
}
override fun onBindViewHolder(holder: WateringTaskHolder, position: Int) {
if (mList.size > 0) {
val data = mList[position]
holder.tvTitle.text = data.title
holder.tvCount.text = "+${data.awardNum}"
if (data.subTitle != null) {
holder.btnProgess.visibility = View.GONE
holder.tvProgess.text = data.subTitle
} else {
holder.btnProgess.visibility = View.VISIBLE
holder.btnProgess.max = data.targetNum
holder.btnProgess.setProgress(data.completedNum)
holder.tvProgess.text = "${data.completedNum}/${data.targetNum}"
}
holder.ivStatus.setOnClickListener {
if (Utils.isFastClick()) {
when (data.status) {
0 -> listener.onItemClick(it, position, mList[position])
1 -> Utils.showToast(mContext, "您已经领过了哦~")
//领取
2 -> getDripTaskReceive(type, data)
}
}
}
// 0未完成 1已领取 2可领取
when (data.status) {
0 -> holder.ivStatus.setImageResource(R.drawable.icon_mian_popup_complete)
1 -> holder.ivStatus.setImageResource(R.drawable.icon_main_popup_receiveed)
2 -> holder.ivStatus.setImageResource(R.drawable.icon_main_popup_receive)
}
val layoutParams = RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT
)
if (position == mList.size - 1) {
layoutParams.setMargins(0, 0, 0, Utils.dip2px(20f))
} else {
layoutParams.setMargins(0, 0, 0, Utils.dip2px(8f))
}
holder.layoutRoot.layoutParams = layoutParams
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WateringTaskHolder {
return WateringTaskHolder(
LayoutInflater.from(mContext).inflate(R.layout.item_watering_task, parent, false)
)
}
inner class WateringTaskHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvTitle: TextView = itemView.findViewById(R.id.tv_watering_item_title)
// val btnProgess: ProgressButton = itemView.findViewById(R.id.progess_watering_item)
val btnProgess: ProgressBar = itemView.findViewById(R.id.progess_watering_item)
val tvProgess: TextView = itemView.findViewById(R.id.tv_watering_item_progess)
val tvCount: TextView = itemView.findViewById(R.id.tv_watering_item_count)
val ivStatus: ImageView = itemView.findViewById(R.id.tv_watering_item_status)
val layoutRoot: RelativeLayout = itemView.findViewById(R.id.layout_watering_root)
}
// 领取水滴 type:1每日领水 2高额领水
private fun getDripTaskReceive(type: Int, data: WateringTaskEntity) {
// OrchardApiClient.orchard.getDripTaskReceive(data.id, type).compose(
// RxSchedulers.observableIO2Main()
// ).subscribe(object : BaseObserver<Any>() {
// override fun onSuccess(result: Any?) {
// if (result != null) {
// LogUtils.i("WateringTaskAdpater", "水滴领取" + result)
// var adType = ""
//// if (type == 1) {
//// RxBusUtil.getDefault()
//// .send(RxBusConstant.RX_MAIN_WATER_DROP_UPDATE)
//// adType = "每日"
//// } else if (type == 2) {
//// RxBusUtil.getDefault()
//// .send(RxBusConstant.RX_MAIN_HIGH_WATER_DROP_UPDATE)
//// adType = "高额"
//// }
// // MainDialog.showgetWaterDrop(mContext, 1,adType, data.awardNum)
// RxBusUtil.getDefault().send(RxBusConstant.RX_MAIN_UPDATE_HOME_INFO)
// }
// }
//
// override fun onFailure(e: Throwable?, code: String?, errorMsg: String?) {}
// })
}
}
\ No newline at end of file
package com.ym.game.contract
import com.ym.game.module.TurntableEntity
/**
*Craeted by ${junqi.li}
*Craeted by 2020/9/11
*/
class TurntableContract {
interface View {
fun turntableListResult(data: TurntableEntity)
fun turntableLotteryResult(data: TurntableEntity.Turntable)
}
interface Presenter {
fun getTurntableList()
fun getTurntableLotteryResult()
}
}
\ No newline at end of file
package com.ym.game.contract
import com.ym.game.module.SinginEntity
import com.ym.game.module.WateringTaskEntity
/**
*Craeted by ${junqi.li}
*Craeted by 2020/9/12
*/
class WateringRewardContract {
interface View {
fun rchardDailyTaskResult(datas: List<WateringTaskEntity>)
fun rchardSignTaskResult(datas: SinginEntity)
}
interface Presenter {
fun getRrchardDailyTask()
fun getOrchardSignTask()
}
}
\ No newline at end of file
package com.ym.game.module
/**
*Craeted by ${junqi.li}
*Craeted by 2020/9/12
*/
class SinginEntity {
var isPop: Int = 0 // 1弹领取水滴弹窗
var totalNum: Int = 0 //连续签到水滴数量
var awardNum: Int = 0 //每日首次签到水滴数量
var signInfoList: MutableList<SignInfoListEntity> = ArrayList()
class SignInfoListEntity {
var id = 0
var awardNum: Int = 0 // 奖励数量
var awardType: Int = 0 //("奖励类型 1 金币 2 红包 3 水滴")
var isToday: Int = -1
var status: Int = -1
}
}
\ No newline at end of file
package com.ym.game.module
/**
*Craeted by ${junqi.li}
*Craeted by 2020/9/10
*/
class TurntableEntity {
var turntables: MutableList<Turntable> = ArrayList()
var lotteryNum: Int? = 0
var countDownSecond: Int? = 0
var showVideo: Int? = 0
class Turntable {
var id = 0
var name: String? = ""
var awardNum: Int? = 0
var awardType: Int? = 0
var lotteryNum: Int? = 0
var countDownSecond: Int? = 0
var showVideo: Int? = 0
}
}
\ No newline at end of file
package com.ym.game.module
/**
*Craeted by ${junqi.li}
*Craeted by 2020/9/12
*/
class WateringTaskEntity {
var id = 0
var title: String = ""
var subTitle: String = ""
var targetNum: Int = 0 // 目标数量
var completedNum: Int = 0 // 已完成数量
var awardType: Int = 0 //("奖励类型 1 金币 2 红包 3 水滴")
var awardNum: Int = 0 // 奖励数量
var status: Int = 0 // "完成状态 0未完成 1已完成 2可领取" 领取后 --> 明日再来
var cashStr: String = "" //提现机会
var reference: Int = -1 //跳转页面 1转盘 2高额水滴任务 3首页 4激励视频 直客任务链接"
var url: String = "" //直客任务链接"
var ad: String = "" //直客任务链接"
var description: String = "" //高额任务副标题
var coins: Int = 0 //高额任务奖励数量
}
\ No newline at end of file
package com.ym.game.net
import com.ym.game.module.HomeInfoEntity
import com.ym.game.module.LandListEntity
import com.ym.game.module.OrderListEntity
import com.ym.game.module.StatusEntity
import com.ym.game.module.*
import com.ym.library.net.NetConfig
import com.ym.library.net.Response
import io.reactivex.Observable
......@@ -52,7 +49,10 @@ interface IGameApi {
* @return
*/
@POST(NetConfig.Game.URL_GAME_UNLOCK_LAND)
fun getUnlockLand(@Query("id") id: Int, @Query("type") type: Int): Observable<Response<StatusEntity>>
fun getUnlockLand(
@Query("id") id: Int,
@Query("type") type: Int
): Observable<Response<StatusEntity>>
/**
* 加速剂
......@@ -62,6 +62,7 @@ interface IGameApi {
*/
@POST(NetConfig.Game.URL_GAME_USE_ACCELERATORS)
fun getUseAccelerators(@Query("id") id: Int): Observable<Response<StatusEntity>>
/**
* 金币购买种子
* @param
......@@ -70,6 +71,7 @@ interface IGameApi {
*/
@POST(NetConfig.Game.URL_GAME_BUY_SEED)
fun getBuySeed(@Query("id") id: Int): Observable<Response<StatusEntity>>
/**
* 仓库
* @param id 仓库列表id
......@@ -88,5 +90,20 @@ interface IGameApi {
@GET(NetConfig.Game.URL_GAME_ORDER_DATA)
fun getOrderData(): Observable<Response<OrderListEntity>>
/*
转盘列表
*/
@GET(NetConfig.Game.URL_GAME_TURNTABLE_LIST)
fun getTurntableList(): Observable<Response<TurntableEntity>>
//抽奖结果
@POST(NetConfig.Game.URL_GAME_FARM_LOTTERY)
fun getLotteryResult(): Observable<Response<TurntableEntity.Turntable>>
//签到列表
@GET(NetConfig.Game.URL_GAME_FARM_LIST)
fun getOrchardSignTask(): Observable<Response<SinginEntity>>
//
@GET(NetConfig.Game.URL_GAME_FARM_DAILY_TASK)
fun getOrchardDailyTask(): Observable<Response<List<WateringTaskEntity>>>
}
\ No newline at end of file
package com.ym.game.presenter
import com.ym.game.contract.TurntableContract
import com.ym.game.module.TurntableEntity
import com.ym.game.net.GameApiClient
import com.ym.library.net.BaseObserver
import com.ym.library.net.RxSchedulers
/**
*Craeted by ${junqi.li}
*Craeted by 2020/9/11
*/
class TurntablePresenter : TurntableContract.Presenter {
var mView: TurntableContract.View
constructor(mView: TurntableContract.View) {
this.mView = mView
}
/**
* 转盘列表
*/
override fun getTurntableList() {
GameApiClient.gameApi.getTurntableList().compose(
RxSchedulers.observableIO2Main()
).subscribe(object : BaseObserver<TurntableEntity>() {
override fun onSuccess(result: TurntableEntity?) {
if (result != null) {
mView?.turntableListResult(result)
}
}
override fun onFailure(e: Throwable?, code: String?, errorMsg: String?) {}
})
}
/**
* 转盘抽奖结果
*/
override fun getTurntableLotteryResult() {
GameApiClient.gameApi.getLotteryResult().compose(
RxSchedulers.observableIO2Main()
).subscribe(object : BaseObserver<TurntableEntity.Turntable>() {
override fun onSuccess(result: TurntableEntity.Turntable?) {
if (result != null) {
mView?.turntableLotteryResult(result)
}
}
override fun onFailure(e: Throwable?, code: String?, errorMsg: String?) {}
})
}
}
\ No newline at end of file
package com.ym.game.presenter
import com.ym.game.contract.WateringRewardContract
import com.ym.game.module.SinginEntity
import com.ym.game.module.WateringTaskEntity
import com.ym.game.net.GameApiClient
import com.ym.library.net.BaseObserver
import com.ym.library.net.RxSchedulers
import com.ym.library.utils.LogUtils
/**
*Craeted by ${junqi.li}
*Craeted by 2020/9/12
*/
class WateringRewardPresenter : WateringRewardContract.Presenter {
var mView: WateringRewardContract.View
constructor(mView: WateringRewardContract.View) {
this.mView = mView
}
//每日水滴任务
override fun getRrchardDailyTask() {
GameApiClient.gameApi.getOrchardDailyTask().compose(
RxSchedulers.observableIO2Main()
).subscribe(object : BaseObserver<List<WateringTaskEntity>>() {
override fun onSuccess(result: List<WateringTaskEntity>?) {
if (result != null) {
mView?.rchardDailyTaskResult(result)
}
}
override fun onFailure(e: Throwable?, code: String?, errorMsg: String?) {}
})
}
//签到
override fun getOrchardSignTask() {
GameApiClient.gameApi.getOrchardSignTask().compose(
RxSchedulers.observableIO2Main()
).subscribe(object : BaseObserver<SinginEntity>() {
override fun onSuccess(result: SinginEntity?) {
if (result != null) {
mView?.rchardSignTaskResult(result)
}
}
override fun onFailure(e: Throwable?, code: String?, errorMsg: String?) {
LogUtils.i("Popupwindow",errorMsg)
}
})
}
}
\ No newline at end of file
package com.ym.game.view
import android.app.Dialog
import android.content.Context
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import com.ym.library.AppliContext
import com.ym.library.utils.PhoneUtils
object MainDialog {
fun showBottomDialog(
layout: Int,
activity: Context,
setHeadDialog: Dialog,
animation: Int,
gravity: Int
): View {
val mDialogView = View.inflate(activity, layout, null)
setHeadDialog.setContentView(mDialogView)
val window = setHeadDialog.window
window?.setGravity(gravity)
val lp = window?.attributes
window?.decorView?.setPadding(0, 0, 0, 0)
lp?.width = PhoneUtils.getScreenWidth(AppliContext.get())
lp?.height = ViewGroup.LayoutParams.MATCH_PARENT
if (gravity == Gravity.TOP) {
lp?.height = PhoneUtils.getScreenHeight(AppliContext.get())
}
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
window?.attributes = lp
if (animation > 0)
window?.setWindowAnimations(animation)//设置动画
return mDialogView
}
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
package com.ym.game.view
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.util.Log
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.ImageView
import com.ym.task.module.listener.CustomAnimatiorListener
/**
*Craeted by ${junqi.li}
*Craeted by 2020/9/10
*/
abstract class TurntableUtils {
private var start = 0f
private var end = 1440f
private var single = 1111
private var double = 2222
private var status = double
private var isCancel = false
private var objectAnimator1: ObjectAnimator? = null
private var animatorSet: AnimatorSet? = null
private val TAG = "TurntableUtils"
fun initAnim() {
animatorSet = AnimatorSet()
animatorSet?.interpolator = AccelerateDecelerateInterpolator()
animatorSet?.addListener(object : CustomAnimatiorListener() {
override fun onAnimStart(animation: Animator?) {
}
override fun onAnimationEnd(animation: Animator?) {
super.onAnimationEnd(animation)
Log.d(TAG, "onAnimationEnd")
animEnd()
if (!isCancel) {
// showDialog()
}
isCancel = false
}
override fun onAnimationCancel(animation: Animator?) {
super.onAnimationCancel(animation)
isCancel = true
Log.d(TAG, "onAnimationCancel")
}
})
}
fun startAnim(type: Int, img: ImageView) {
var num = type
if (type == 1) {
num = 0
} else {
if (start >= 60f) {
} else {
num -= 1
}
}
// if (type == 1) {
// if (start >= 60f) {
// num = 0
// } else {
// num = 1
// }
// } else {
// if (start >= 60f) {
// num = 1
// } else {
// num = 0
// }
//
// }
end = (4 * 360f) - (num * 60f)
objectAnimator1 = ObjectAnimator.ofFloat(img, "rotation", start, end).setDuration(3000)
objectAnimator1?.addUpdateListener {
val value = it.getAnimatedValue().toString().toFloat()
val a = (value / 360f).toInt()
val x = value - (a * 360f)
val n = (x / 120f).toInt()
val z = x - (n * 120)
// Log.d(
// TAG,
// "value:" + value + " a:" + a + " x:" + x + " n:" + n + " z:" + z
// )
start = z
}
// Log.d(TAG, " start:" + start + " end:" + end)
animatorSet?.play(objectAnimator1)
animatorSet?.start()
// start = (num * 60f)
if (type == 1) {
status = single
} else {
status = double
}
}
// abstract fun awardVideoClose()
//
// abstract fun showDialog()
//
abstract fun animEnd()
}
\ No newline at end of file
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromYDelta="100%p"
android:toYDelta="0" />
<alpha
android:duration="200"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
\ No newline at end of file
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="200"
android:fromYDelta="0"
android:toYDelta="50%p" />
<alpha
android:duration="200"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="359"
android:pivotX="50%"
android:pivotY="50%"
android:duration="5000"
android:interpolator="@android:anim/linear_interpolator"
android:repeatCount="-1"/>
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:ignore="MissingDefaultResource"
android:duration="5000"
android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="0.8"
android:fromYScale="0.8"
android:toXScale="1"
android:toYScale="1"
android:repeatMode="reverse"
android:repeatCount="infinite"/>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment