Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
Y
YPPos
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
朱世闯
YPPos
Commits
2d054348
Commit
2d054348
authored
Sep 22, 2021
by
UIUANG\Zsc
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
可切换服务器环境
parent
142206b6
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
193 additions
and
34 deletions
+193
-34
build.gradle
app/build.gradle
+5
-0
PosApp.kt
app/src/main/java/com/ypsx/yppos/PosApp.kt
+21
-3
NetworkApi.kt
app/src/main/java/com/ypsx/yppos/http/NetworkApi.kt
+2
-1
InsertOrderProductDTO.kt
...va/com/ypsx/yppos/http/data/bean/InsertOrderProductDTO.kt
+1
-0
HttpRequestManger.kt
...m/ypsx/yppos/http/repository/request/HttpRequestManger.kt
+3
-1
ServerHostKit.kt
app/src/main/java/com/ypsx/yppos/kit/ServerHostKit.kt
+68
-0
PosDatabase.kt
...src/main/java/com/ypsx/yppos/room/database/PosDatabase.kt
+7
-3
SettingsPopupWindow.kt
.../main/java/com/ypsx/yppos/ui/popup/SettingsPopupWindow.kt
+3
-2
BigDecimalUtils.java
app/src/main/java/com/ypsx/yppos/utils/BigDecimalUtils.java
+7
-0
CacheUtil.kt
app/src/main/java/com/ypsx/yppos/utils/CacheUtil.kt
+25
-6
PrintUtils.kt
app/src/main/java/com/ypsx/yppos/utils/PrintUtils.kt
+42
-12
RequestMainViewModel.kt
.../com/ypsx/yppos/viewmodel/request/RequestMainViewModel.kt
+8
-6
strings.xml
app/src/main/res/values/strings.xml
+1
-0
No files found.
app/build.gradle
View file @
2d054348
...
...
@@ -112,6 +112,7 @@ dependencies {
implementation
"com.afollestad.material-dialogs:lifecycle:3.3.0"
implementation
"com.afollestad.material-dialogs:core:3.3.0"
implementation
'com.afollestad.material-dialogs:input:3.3.0'
//微信开源项目,替代SP
implementation
'com.tencent:mmkv:1.2.10'
...
...
@@ -129,6 +130,7 @@ dependencies {
implementation
'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'
def
room_version
=
"2.3.0"
def
lastversion
=
"3.5.0"
implementation
(
"androidx.room:room-runtime:$room_version"
)
annotationProcessor
"androidx.room:room-compiler:$room_version"
...
...
@@ -143,6 +145,9 @@ dependencies {
implementation
'com.github.jenly1314.AppUpdater:app-updater:1.1.0'
implementation
'com.github.getActivity:ToastUtils:9.5'
implementation
'com.aliyun.dpa:oss-android-sdk:2.1.0'
debugImplementation
"io.github.didi.dokit:dokitx:${lastversion}"
releaseImplementation
"io.github.didi.dokit:dokitx-no-op:${lastversion}"
// val work_version = "2.6.0"
// Kotlin + coroutines
// implementation("androidx.work:work-runtime-ktx:$work_version")
...
...
app/src/main/java/com/ypsx/yppos/PosApp.kt
View file @
2d054348
package
com.ypsx.yppos
import
android.content.Intent
import
android.os.Build
import
android.os.Process
import
com.didichuxing.doraemonkit.DoKit
import
com.didichuxing.doraemonkit.kit.AbstractKit
import
com.elvishew.xlog.LogConfiguration
import
com.elvishew.xlog.LogLevel
import
com.elvishew.xlog.XLog
...
...
@@ -10,12 +14,9 @@ import com.elvishew.xlog.formatter.message.throwable.DefaultThrowableFormatter
import
com.elvishew.xlog.formatter.message.xml.DefaultXmlFormatter
import
com.elvishew.xlog.formatter.stacktrace.DefaultStackTraceFormatter
import
com.elvishew.xlog.formatter.thread.DefaultThreadFormatter
import
com.elvishew.xlog.interceptor.BlacklistTagsFilterInterceptor
import
com.elvishew.xlog.printer.AndroidPrinter
import
com.elvishew.xlog.printer.ConsolePrinter
import
com.elvishew.xlog.printer.Printer
import
com.elvishew.xlog.printer.file.FilePrinter
import
com.elvishew.xlog.printer.file.backup.FileSizeBackupStrategy
import
com.elvishew.xlog.printer.file.backup.FileSizeBackupStrategy2
import
com.elvishew.xlog.printer.file.backup.NeverBackupStrategy
import
com.elvishew.xlog.printer.file.clean.FileLastModifiedCleanStrategy
...
...
@@ -25,6 +26,7 @@ import com.tencent.mmkv.MMKV
import
com.ypsx.base.base.BaseApp
import
com.ypsx.yppos.app.event.AppViewModel
import
com.ypsx.yppos.app.event.EventViewModel
import
com.ypsx.yppos.kit.ServerHostKit
import
com.ypsx.yppos.room.database.PosDatabase
import
com.ypsx.yppos.utils.PathUtils
import
com.ypsx.yppos.utils.XLogFlattener
...
...
@@ -48,6 +50,11 @@ class PosApp : BaseApp() {
MMKV
.
initialize
(
this
)
// 初始化 Toast 框架
ToastUtils
.
init
(
this
);
var
list
=
arrayListOf
<
AbstractKit
>()
list
.
add
(
ServerHostKit
())
DoKit
.
Builder
(
this
)
.
customKits
(
listOf
(
ServerHostKit
()))
.
build
()
instance
=
this
PosDatabase
.
getDatabase
(
instance
)
eventViewModelInstance
=
getAppViewModelProvider
().
get
(
EventViewModel
::
class
.
java
)
...
...
@@ -106,4 +113,15 @@ class PosApp : BaseApp() {
}
/**
* 重启当前应用
*/
fun
restartApplication
()
{
val
intent
=
packageManager
.
getLaunchIntentForPackage
(
packageName
)
intent
!!
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TOP
)
startActivity
(
intent
)
Process
.
killProcess
(
Process
.
myPid
())
}
}
\ No newline at end of file
app/src/main/java/com/ypsx/yppos/http/NetworkApi.kt
View file @
2d054348
...
...
@@ -7,6 +7,7 @@ import com.ypsx.base.network.BaseNetworkApi
import
com.ypsx.base.network.interceptor.CacheInterceptor
import
com.ypsx.base.network.interceptor.logging.LogInterceptor
import
com.ypsx.yppos.BuildConfig
import
com.ypsx.yppos.utils.CacheUtil
import
okhttp3.Cache
import
okhttp3.OkHttpClient
import
retrofit2.Retrofit
...
...
@@ -24,7 +25,7 @@ import java.util.concurrent.TimeUnit
//双重校验锁式-单例 封装NetApiService 方便直接快速调用简单的接口
val
apiService
:
ApiService
by
lazy
(
mode
=
LazyThreadSafetyMode
.
SYNCHRONIZED
)
{
NetworkApi
.
INSTANCE
.
getApi
(
ApiService
::
class
.
java
,
BuildConfig
.
HOST
)
NetworkApi
.
INSTANCE
.
getApi
(
ApiService
::
class
.
java
,
CacheUtil
.
getHost
()
)
}
class
NetworkApi
:
BaseNetworkApi
()
{
...
...
app/src/main/java/com/ypsx/yppos/http/data/bean/InsertOrderProductDTO.kt
View file @
2d054348
...
...
@@ -15,6 +15,7 @@ data class InsertOrderProductDTO(
var
deleted
:
Boolean
=
false
,
//商品项优惠总金额
var
discountTotal
:
Double
=
0.0
,
var
discountPrice
:
Double
=
0.0
,
//是否虚拟商品
var
isVirtual
:
Boolean
=
false
,
//会员价
...
...
app/src/main/java/com/ypsx/yppos/http/repository/request/HttpRequestManger.kt
View file @
2d054348
...
...
@@ -12,6 +12,8 @@ import com.ypsx.yppos.http.data.entity.PosCommandType
import
com.ypsx.yppos.http.data.entity.PosPayMethod
import
com.ypsx.yppos.http.data.entity.PosStatus
import
com.ypsx.yppos.http.data.request.*
import
com.ypsx.yppos.room.database.PosDatabase
import
com.ypsx.yppos.room.database.name
import
com.ypsx.yppos.room.repository.PosConfigRepository
import
com.ypsx.yppos.room.repository.PosProductRepository
import
com.ypsx.yppos.ui.popup.PayAmountPopupWindow
...
...
@@ -204,7 +206,7 @@ class HttpRequestManger {
}
PosCommandType
.
UPLOAD_DB
.
name
->
{
val
databasePath
=
appContext
.
getDatabasePath
(
"yp_pos"
)
val
databasePath
=
appContext
.
getDatabasePath
(
name
)
val
currentTimeMillis
=
System
.
currentTimeMillis
()
val
zipUrl
:
String
=
PathUtils
.
getZipUrl
(
commandResponse
.
id
.
toString
(),
".zip"
)
...
...
app/src/main/java/com/ypsx/yppos/kit/ServerHostKit.kt
0 → 100644
View file @
2d054348
package
com.ypsx.yppos.kit
import
android.app.Activity
import
android.content.Context
import
androidx.appcompat.app.AlertDialog
import
com.afollestad.materialdialogs.MaterialDialog
import
com.afollestad.materialdialogs.input.InputCallback
import
com.afollestad.materialdialogs.input.input
import
com.afollestad.materialdialogs.list.SingleChoiceListener
import
com.afollestad.materialdialogs.list.listItemsSingleChoice
import
com.didichuxing.doraemonkit.kit.AbstractKit
import
com.didichuxing.doraemonkit.util.ActivityUtils
import
com.ypsx.yppos.PosApp
import
com.ypsx.yppos.R
import
com.ypsx.yppos.room.database.PosDatabase
import
com.ypsx.yppos.utils.CacheUtil
class
ServerHostKit
:
AbstractKit
()
{
private
val
hostMap
=
mapOf
(
"sit开发环境Host"
to
"https://sit-cpos.ypshengxian.com/"
,
"预发Host"
to
"https://pre-cpos.ypshengxian.com/"
,
"线上正式Host"
to
"https://cpos.ypshengxian.com/"
,
)
private
val
hosts
=
hostMap
.
values
.
toTypedArray
()
private
val
names
=
hostMap
.
keys
.
toList
()
override
val
icon
:
Int
get
()
=
R
.
mipmap
.
icon_yp_logo
override
val
name
:
Int
get
()
=
R
.
string
.
environment_kit
override
fun
onClickWithReturn
(
activity
:
Activity
):
Boolean
{
val
activity
=
ActivityUtils
.
getTopActivity
()
//选中的host
val
checkHost
=
CacheUtil
.
getHost
()
var
checkedIndex
=
hosts
.
indexOf
(
checkHost
)
if
(
checkedIndex
<
0
)
checkedIndex
=
names
.
size
-
1
//也就是研发Native那个
//启用输入的host
MaterialDialog
(
activity
).
title
(
text
=
"切换Server接口"
)
.
cancelable
(
false
)
.
cancelOnTouchOutside
(
false
)
.
listItemsSingleChoice
(
items
=
names
,
initialSelection
=
checkedIndex
,
selection
=
object
:
SingleChoiceListener
{
override
fun
invoke
(
dialog
:
MaterialDialog
,
index
:
Int
,
text
:
CharSequence
)
{
//如果选择了研发native,index就会超过host的index
if
(
index
<
hosts
.
size
)
{
CacheUtil
.
setHost
(
hosts
[
index
])
CacheUtil
.
clearAll
()
PosDatabase
.
clearAllTables
()
PosApp
.
instance
.
restartApplication
()
}
}
})
.
positiveButton
(
text
=
"确定"
)
.
negativeButton
(
text
=
"取消"
)
.
show
()
return
true
}
override
fun
onAppInit
(
context
:
Context
?)
{
}
}
\ No newline at end of file
app/src/main/java/com/ypsx/yppos/room/database/PosDatabase.kt
View file @
2d054348
...
...
@@ -6,7 +6,7 @@ import androidx.room.Room
import
androidx.room.RoomDatabase
import
com.ypsx.yppos.room.dao.*
import
com.ypsx.yppos.room.entity.*
const
val
name
:
String
=
"yp_pos.db"
@Database
(
entities
=
[
PosConfig
::
class
,
PosProduct
::
class
,
PosBuy
::
class
,
PosBuyPart
::
class
,
PosBuyPayment
::
class
],
version
=
1
,
exportSchema
=
false
...
...
@@ -24,7 +24,7 @@ abstract class PosDatabase : RoomDatabase() {
companion
object
{
@Volatile
private
var
INSTANCE
:
PosDatabase
?
=
null
val
name
:
String
=
"yp_pos.db"
fun
getDatabase
(
context
:
Context
):
PosDatabase
{
val
tempInstance
=
INSTANCE
...
...
@@ -36,12 +36,16 @@ abstract class PosDatabase : RoomDatabase() {
val
instance
=
Room
.
databaseBuilder
(
context
.
applicationContext
,
PosDatabase
::
class
.
java
,
"yp_pos"
name
).
allowMainThreadQueries
()
.
fallbackToDestructiveMigration
().
build
()
INSTANCE
=
instance
return
instance
}
}
fun
clearAllTables
()
{
INSTANCE
?.
clearAllTables
()
}
}
}
\ No newline at end of file
app/src/main/java/com/ypsx/yppos/ui/popup/SettingsPopupWindow.kt
View file @
2d054348
...
...
@@ -63,7 +63,7 @@ class SettingsPopupWindow(context: Context?) : BasePopupWindow(context) {
val
posConfig
=
PosConfigRepository
.
getInstance
().
loadConfig
()
val
posBuy
=
PosBuyRepository
.
getInstance
().
query
()
if
(
posBuy
==
null
)
{
if
(
posBuy
==
null
||
posConfig
==
null
)
{
"无记录,无法打印"
.
toastSign
()
}
else
{
val
posBuyParts
=
...
...
@@ -73,7 +73,7 @@ class SettingsPopupWindow(context: Context?) : BasePopupWindow(context) {
PosBuyRepository
.
getInstance
()
.
queryPosBuyPaymentByOrderNo
(
posBuy
.
id
)
posBuyPayment
.
toString
().
dXLog
()
PrintUtils
.
printLast
(
posConfig
!!
,
posBuyPayment
,
posBuy
,
posBuyParts
)
PrintUtils
.
printLast
(
posConfig
,
posBuyPayment
,
posBuy
,
posBuyParts
)
}
}
}.
onSuccess
{
...
...
@@ -102,6 +102,7 @@ class SettingsPopupWindow(context: Context?) : BasePopupWindow(context) {
}
}.
onSuccess
{
if
(
it
.
isSuccess
())
{
messagePopupWindow
.
dismiss
()
"${CacheUtil.getRealName()}主动退出主界面"
.
dXLog
()
val
mainActivity
=
this
@SettingsPopupWindow
.
context
as
MainActivity
...
...
app/src/main/java/com/ypsx/yppos/utils/BigDecimalUtils.java
View file @
2d054348
...
...
@@ -10,4 +10,11 @@ public class BigDecimalUtils {
result
=
bigDecimal
.
setScale
(
2
,
BigDecimal
.
ROUND_HALF_UP
);
return
result
.
doubleValue
();
}
public
static
double
forPlus2
(
double
amount
)
{
BigDecimal
bigDecimal
=
new
BigDecimal
(
amount
);
BigDecimal
result
=
null
;
result
=
bigDecimal
.
setScale
(
2
,
BigDecimal
.
ROUND_HALF_UP
);
return
result
.
stripTrailingZeros
().
doubleValue
();
}
}
app/src/main/java/com/ypsx/yppos/utils/CacheUtil.kt
View file @
2d054348
...
...
@@ -3,6 +3,7 @@ package com.ypsx.yppos.utils
import
android.text.TextUtils
import
com.google.gson.Gson
import
com.tencent.mmkv.MMKV
import
com.ypsx.yppos.BuildConfig
import
com.ypsx.yppos.http.data.bean.LoginResponse
const
val
dfs_aliyunDomain
=
"dfs_aliyunDomain"
//阿里云绑定的域名
...
...
@@ -41,7 +42,6 @@ object CacheUtil {
}
/**
* 设置首页是否开启获取指定文章
*/
...
...
@@ -50,6 +50,12 @@ object CacheUtil {
return
kv
.
encode
(
"updateTimeBigger"
,
time
)
}
fun
clearAll
()
{
val
kv
=
MMKV
.
mmkvWithID
(
"app"
)
kv
.
removeValueForKey
(
"updateTimeBigger"
)
kv
.
removeValueForKey
(
user
)
}
/**
* 首页是否开启获取指定文章
*/
...
...
@@ -59,8 +65,6 @@ object CacheUtil {
}
fun
getAliYunKey
():
String
{
return
arrayOf
(
dfs_aliyunAccessKeyId
,
dfs_aliyunAccessKeySecret
,
dfs_aliyunBucketName
,
...
...
@@ -68,18 +72,33 @@ object CacheUtil {
).
joinToString
(
","
)
}
fun
setAliYunKey
(
key
:
String
,
value
:
String
)
:
Boolean
{
fun
setAliYunKey
(
key
:
String
,
value
:
String
)
:
Boolean
{
val
kv
=
MMKV
.
mmkvWithID
(
"app"
)
return
kv
.
encode
(
key
,
value
)
}
fun
getAliYunKey
(
key
:
String
):
String
?
{
val
kv
=
MMKV
.
mmkvWithID
(
"app"
)
return
kv
.
decodeString
(
key
,
""
)
return
kv
.
decodeString
(
key
,
""
)
}
fun
getRealName
():
String
{
fun
getRealName
():
String
{
return
"操作人:${getLoginResponse()?.loginUser?.realName.toString()}"
}
fun
setHost
(
host
:
String
):
Boolean
{
val
kv
=
MMKV
.
mmkvWithID
(
"app"
)
return
kv
.
encode
(
"host"
,
host
)
}
fun
getHost
():
String
{
return
if
(
BuildConfig
.
DEBUG
)
{
val
kv
=
MMKV
.
mmkvWithID
(
"app"
)
kv
.
decodeString
(
"host"
,
"https://sit-cpos.ypshengxian.com/"
).
toString
()
}
else
{
"https://cpos.ypshengxian.com/"
}
}
}
\ No newline at end of file
app/src/main/java/com/ypsx/yppos/utils/PrintUtils.kt
View file @
2d054348
...
...
@@ -127,21 +127,37 @@ object PrintUtils {
}
for
((
index
,
product
)
in
orderResponse
.
products
.
withIndex
())
{
var
discountMoney
=
0.0
if
(
product
.
activitys
!=
null
)
{
product
.
activitys
!!
.
forEach
{
item
->
var
d
=
product
.
price
-
item
.
activityPrice
discountMoney
=
product
.
price
-
item
.
activityPrice
if
(
item
.
activityType
==
ProductActivityType
.
TIMESHARE_ACTIVITY
.
name
)
{
discountTime
+=
d
discountTime
+=
d
iscountMoney
}
else
{
if
(
d
>
0.0
)
{
discountSpecial
+=
d
if
(
d
iscountMoney
>
0.0
)
{
discountSpecial
+=
d
iscountMoney
}
}
}
}
var
isPromotion
=
false
orderResponse
.
activitys
?.
forEach
{
item
->
for
(
productPromotionDetailDTO
in
item
.
productIds
)
{
if
(
productPromotionDetailDTO
.
productId
==
product
.
productId
)
{
isPromotion
=
true
break
}
}
}
val
name
=
if
(
discountMoney
>
0.0
&&
isPromotion
)
{
"${index + 1} *${product.name}*"
}
else
{
"${index + 1} ${product.name}"
}
height
+=
printerManager
.
drawTextEx
(
"${index + 1} ${product.name}"
,
name
,
0
,
height
,
384
,
...
...
@@ -567,14 +583,14 @@ object PrintUtils {
if
(!
posBuyParts
.
isNullOrEmpty
())
{
for
((
index
,
product
)
in
posBuyParts
.
withIndex
())
{
val
list
:
List
<
ActivityInfoDTO
>
=
val
activityInfoDTO
:
List
<
ActivityInfoDTO
>
=
GsonUtils
.
fromJson
(
product
.
activitys
,
object
:
TypeToken
<
List
<
ActivityInfoDTO
>>()
{}.
type
)
// if (product.activitys != null) {
list
.
forEach
{
item
->
val
discountMoney
=
product
.
price
-
item
.
activityPrice
var
discountMoney
=
0.0
activityInfoDTO
.
forEach
{
item
->
discountMoney
=
product
.
price
-
item
.
activityPrice
if
(
item
.
activityType
==
ProductActivityType
.
TIMESHARE_ACTIVITY
.
name
)
{
discountTime
+=
discountMoney
}
else
{
...
...
@@ -583,9 +599,23 @@ object PrintUtils {
}
}
}
// }
var
isPromotion
=
false
list
.
forEach
{
item
->
for
(
productPromotionDetailDTO
in
item
.
productIds
)
{
if
(
productPromotionDetailDTO
.
productId
==
product
.
productId
)
{
isPromotion
=
true
break
}
}
}
val
name
=
if
(
discountMoney
>
0.0
&&
isPromotion
)
{
"${index + 1} *${product.name}*"
}
else
{
"${index + 1} ${product.name}"
}
height
+=
printerManager
.
drawTextEx
(
"${index + 1} ${product.name}"
,
name
,
0
,
height
,
384
,
...
...
@@ -708,7 +738,7 @@ object PrintUtils {
"扫码支付"
}
PosPayMethod
.
CARDPAY
.
name
->
{
"会员余额"
"会员余额
支付
"
}
else
->
{
""
...
...
app/src/main/java/com/ypsx/yppos/viewmodel/request/RequestMainViewModel.kt
View file @
2d054348
...
...
@@ -232,17 +232,18 @@ class RequestMainViewModel : BaseViewModel() {
}
}
var
activity
s
=
product
.
activityInfo
var
activitys
List
:
ArrayList
<
ActivityInfoDTO
>?
=
null
if
(
activity
s
!=
null
)
{
activitysList
=
arrayListOf
(
activitys
)
var
activity
Info
=
product
.
activityInfo
var
activitys
:
ArrayList
<
ActivityInfoDTO
>
=
arrayListOf
()
if
(
activity
Info
!=
null
)
{
activitys
.
add
(
activityInfo
)
}
var
activityPrice
=
activity
s
?.
activityPrice
?:
0.0
var
activityPrice
=
activity
Info
?.
activityPrice
?:
0.0
val
posBuyPart
=
InsertOrderProductDTO
(
activitys
=
activitys
List
,
activitys
=
activitys
,
activityPrice
=
activityPrice
,
amount
=
product
.
payApportionAmount
?:
0.0
,
discountTotal
=
product
.
discountTotal
?:
0.0
,
discountPrice
=
product
.
discountTotal
.
div
(
product
.
quantity
),
memberPrice
=
product
.
memberPrice
?:
0.0
,
barCode
=
posProduct
?.
barCode
!!
,
cardNumber
=
null
,
...
...
@@ -261,6 +262,7 @@ class RequestMainViewModel : BaseViewModel() {
pluLevel
=
posProduct
.
pluLevel
,
merchantItemId
=
posProduct
.
merchantItemId
,
productNumber
=
posProduct
.
productNumber
,
payApportionAmount
=
product
.
payApportionAmount
,
isPromotion
=
isPromotion
,
isVirtual
=
posProduct
.
isVirtual
)
...
...
app/src/main/res/values/strings.xml
View file @
2d054348
...
...
@@ -13,4 +13,5 @@
<string
name=
"account"
>
账号
</string>
<string
name=
"password"
>
密码
</string>
<string
name=
"discount"
>
-¥%s
</string>
<string
name=
"environment_kit"
>
环境切换
</string>
</resources>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment