Merge pull request #22 from alone-wolf/main

主要修改:接入appleId,当前处于几乎可用状态
This commit is contained in:
Easy 2022-01-21 08:37:05 +08:00 committed by GitHub
commit 330554a55b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 334 additions and 167 deletions

View File

@ -7,11 +7,12 @@
* MiPush状态已调通、已接入
* miui 12.5.6 正常
* 原生、类原生 可成功注册,无法收到推送,可能和地区识别有关,待解决
* miui下处于"几乎可用"的状态,已接入 appleId
### TODO
* ~~调通 MiPush~~
* 接入 MiPush
* ~~接入 MiPush~~
* 完善 log ~~采集~~ 回传机制,便于调试
* 测试不同厂商设备上的通知推送效果
* ~~接入 PushDeer~~
@ -21,6 +22,11 @@
* ~~增加侧滑手势相关动作~~
* 增加各种操作前的二次确认弹窗,包括自动登陆
* 增加非Miui设备的权限获取
* 增加手动修改服务器地址/退出登陆的逻辑(并放置到登陆界面)
* 增加登陆过程中的图形提示
* 增加对PushKey重命名的逻辑
* 增加对设备重命名的逻辑
* 增加长按复制消息内容的逻辑
### 日志
@ -88,6 +94,14 @@
* 调整项目文件结构
* 将数据库用作message列表的直接数据来源
* 2022-01-20
* 修改 /device/reg post参数增加 type=android
* 集成 SignIn With Apple
* 调整设备列表加号的显示和操作逻辑
* 将自动注册设备修改为手动点击加号注册设备
* 当前app几乎处于可以使用的状态
### 感谢
https://github.com/taoweiji/MixPush

View File

@ -9,7 +9,7 @@ android {
defaultConfig {
applicationId "com.pushdeer.os"
minSdk 21
minSdk 22
targetSdk 31
versionCode 1
versionName "1.0"
@ -106,6 +106,8 @@ dependencies {
implementation "io.noties.markwon:html:$markwon_version"
implementation "io.coil-kt:coil:1.4.0"
implementation 'com.github.vishalkumarsinghvi:sign-in-with-apple-button-android:0.6'
// implementation 'com.github.bumptech.glide:glide:4.12.0'
// annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
}

View File

@ -24,7 +24,7 @@ class App : Application() {
val repositoryKeeper by lazy { RepositoryKeeper(database) }
val pushDeerService by lazy {
Retrofit.Builder()
.baseUrl("http://0.0.0.0:8800")
.baseUrl(PushDeerApi.baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
@ -45,7 +45,7 @@ class App : Application() {
MiPushClient.registerPush(this, AppKeys.MiPush_Id, AppKeys.MiPush_Key)
}
//打开Log
val newLogger: LoggerInterface = object : LoggerInterface {
Logger.setLogger(this, object : LoggerInterface {
override fun setTag(tag: String) {
// ignore
}
@ -57,8 +57,7 @@ class App : Application() {
override fun log(content: String) {
Log.d(TAG, content)
}
}
Logger.setLogger(this, newLogger)
})
}
private fun shouldInit(): Boolean {

View File

@ -11,6 +11,7 @@ import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
@ -19,6 +20,7 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.core.view.WindowCompat
import androidx.fragment.app.FragmentManager
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
@ -28,10 +30,10 @@ import com.google.accompanist.insets.ProvideWindowInsets
import com.google.accompanist.insets.statusBarsPadding
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.pushdeer.os.activity.QrScanActivity
import com.pushdeer.os.data.api.data.request.DeviceInfo
import com.pushdeer.os.holder.RequestHolder
import com.pushdeer.os.store.SettingStore
import com.pushdeer.os.ui.compose.page.LogDaoPage
import com.pushdeer.os.ui.compose.componment.MyAlertDialog
import com.pushdeer.os.ui.compose.page.LogDogPage
import com.pushdeer.os.ui.compose.page.LoginPage
import com.pushdeer.os.ui.compose.page.main.MainPage
import com.pushdeer.os.ui.theme.PushDeerTheme
@ -49,7 +51,7 @@ import kotlinx.coroutines.launch
import java.util.*
class MainActivity : ComponentActivity(), RequestHolder {
class MainActivity : AppCompatActivity(), RequestHolder {
private val viewModelFactory by lazy { (application as App).viewModelFactory }
private val repositoryKeeper by lazy { (application as App).repositoryKeeper }
@ -59,6 +61,7 @@ class MainActivity : ComponentActivity(), RequestHolder {
override val logDogViewModel: LogDogViewModel by viewModels { viewModelFactory }
override val messageViewModel: MessageViewModel by viewModels { viewModelFactory }
override val settingStore: SettingStore by lazy { (application as App).storeKeeper.settingStore }
override val fragmentManager: FragmentManager by lazy { this.supportFragmentManager }
override val coilImageLoader: ImageLoader by lazy {
ImageLoader.Builder(this)
@ -69,6 +72,7 @@ class MainActivity : ComponentActivity(), RequestHolder {
}
.build()
}
override val alert: RequestHolder.AlertRequest = object : RequestHolder.AlertRequest() {}
override val markdown: Markwon by lazy {
Markwon.builder(this)
@ -106,40 +110,22 @@ class MainActivity : ComponentActivity(), RequestHolder {
val useDarkIcons = MaterialTheme.colors.isLight
val systemUiController = rememberSystemUiController()
when {
SystemUtil.isMiui() -> {
systemUiController.setStatusBarColor(Color.Transparent, useDarkIcons)
}
else -> {
systemUiController.setSystemBarsColor(Color.Transparent, useDarkIcons)
}
SystemUtil.isMiui() -> systemUiController.setStatusBarColor(Color.Transparent, useDarkIcons)
else -> systemUiController.setSystemBarsColor(Color.Transparent, useDarkIcons)
}
WindowCompat.setDecorFitsSystemWindows(window, true)
miPushRepository.regId.observe(this) {
// 这个操作放到注册成功后进行
settingStore.thisDeviceId = it
coroutineScope.launch {
if (pushDeerViewModel.shouldRegDevice()) {
pushDeerViewModel.deviceReg(DeviceInfo().apply {
this.name = SystemUtil.getDeviceModel()
this.device_id = it
this.is_clip = 0
})
}
}
}
SideEffect {
coroutineScope.launch {
pushDeerViewModel.login().also {
pushDeerViewModel.userInfo()
pushDeerViewModel.keyList()
pushDeerViewModel.deviceList()
pushDeerViewModel.messageList()
pushDeerViewModel.login(onReturn = {
globalNavController.navigate("main") {
globalNavController.popBackStack()
}
}
})
}
}
@ -155,13 +141,14 @@ class MainActivity : ComponentActivity(), RequestHolder {
LoginPage(requestHolder = this@MainActivity)
}
composable("logdog") {
LogDaoPage(requestHolder = this@MainActivity)
LogDogPage(requestHolder = this@MainActivity)
}
composable("main") {
MainPage(requestHolder = this@MainActivity)
}
}
}
MyAlertDialog(alertRequest = alert)
}
}
}

View File

@ -4,6 +4,14 @@ import com.pushdeer.os.data.api.data.response.*
import retrofit2.http.*
interface PushDeerApi {
companion object {
val baseUrl = "https://api2.pushdeer.com"
}
@FormUrlEncoded
@POST("/login/idtoken")
suspend fun loginIdToken(@Field("idToken") idToken: String): ReturnData<TokenOnly>
@GET("/login/fake")
suspend fun fakeLogin(): ReturnData<TokenOnly>
@ -21,7 +29,7 @@ interface PushDeerApi {
@FormUrlEncoded
@POST("/device/remove")
suspend fun deviceRemove(@Field("token") token: String,@Field("id") id:Int): String
suspend fun deviceRemove(@Field("token") token: String, @Field("id") id: Int): String
@FormUrlEncoded
@POST("/key/gen")
@ -49,5 +57,5 @@ interface PushDeerApi {
@FormUrlEncoded
@POST("/message/remove")
suspend fun messageRemove(@Field("token")token:String,@Field("id")id:Int): String
suspend fun messageRemove(@Field("token") token: String, @Field("id") id: Int): String
}

View File

@ -13,7 +13,8 @@ class DeviceInfo {
"token" to token,
"name" to name,
"device_id" to device_id,
"is_clip" to is_clip.toString()
"is_clip" to is_clip.toString(),
"type" to "android"
)
}

View File

@ -10,6 +10,7 @@ class Message : MessageEntity() {
this.text = this@Message.text
this.desp = this@Message.desp
this.type = this@Message.type
this.pushkey_name = this@Message.pushkey_name
this.created_at = this@Message.created_at
}
}

View File

@ -13,6 +13,7 @@ public class MessageEntity {
public String text;
public String desp;
public String type;
public String pushkey_name;
public String created_at;
@ -20,10 +21,11 @@ public class MessageEntity {
Message m = new Message();
m.id = id;
m.uid = uid;
m.created_at = created_at;
m.desp = desp;
m.text = text;
m.desp = desp;
m.type = type;
m.pushkey_name = pushkey_name;
m.created_at = created_at;
return m;
}
}

View File

@ -6,6 +6,11 @@ import android.content.Intent
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.fragment.app.FragmentManager
import androidx.navigation.NavHostController
import coil.ImageLoader
import com.pushdeer.os.activity.QrScanActivity
@ -26,7 +31,7 @@ interface RequestHolder {
val uiViewModel: UiViewModel
val pushDeerViewModel: PushDeerViewModel
val logDogViewModel: LogDogViewModel
val messageViewModel:MessageViewModel
val messageViewModel: MessageViewModel
val settingStore: SettingStore
val globalNavController: NavHostController
val coroutineScope: CoroutineScope
@ -35,6 +40,10 @@ interface RequestHolder {
val activityOpener: ActivityResultLauncher<Intent>
val coilImageLoader: ImageLoader
val fragmentManager:FragmentManager
val alert: AlertRequest
val clipboardManager: ClipboardManager
fun copyPlainString(str: String) {
@ -64,7 +73,7 @@ interface RequestHolder {
}
}
fun deviceReg(deviceInfo: DeviceInfo){
fun deviceReg(deviceInfo: DeviceInfo) {
coroutineScope.launch {
pushDeerViewModel.deviceReg(deviceInfo)
}
@ -83,18 +92,20 @@ interface RequestHolder {
}
}
fun messagePushTest(desp: String) {
fun messagePushTest(text: String) {
if (pushDeerViewModel.keyList.isNotEmpty()) {
messagePush("pushtest", desp, "markdown", pushDeerViewModel.keyList[0].key)
messagePush(text, "pushtest", "markdown", pushDeerViewModel.keyList[0].key)
coroutineScope.launch {
delay(1000)
pushDeerViewModel.messageList()
}
} else
} else {
alert.alert("Alert", "You Should Add One PushKey", onOk = {})
Log.d("WH_", "messagePushTest: keylist is empty")
}
}
fun messageRemove(message: Message,onDone:()->Unit={}) {
fun messageRemove(message: Message, onDone: () -> Unit = {}) {
coroutineScope.launch {
// pushDeerViewModel.messageList.remove(message)
pushDeerViewModel.messageRemove(message.id)
@ -112,4 +123,33 @@ interface RequestHolder {
logDogViewModel.clear()
}
}
abstract class AlertRequest {
val show: MutableState<Boolean> = mutableStateOf(false)
var title: String = ""
var content: @Composable () -> Unit = {}
var onOKAction: () -> Unit = {}
var onCancelAction: () -> Unit = {}
fun alert(
title: String,
content: @Composable () -> Unit,
onOk: () -> Unit,
onCancel: () -> Unit = {}
) {
this.title = title
this.content = content
this.onOKAction = onOk
this.onCancelAction = onCancel
this.show.value = true
}
fun alert(title: String, content: String, onOk: () -> Unit, onCancel: () -> Unit = {}) {
this.title = title
this.content = { Text(text = content) }
this.onOKAction = onOk
this.onCancelAction = onCancel
this.show.value = true
}
}
}

View File

@ -4,7 +4,10 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.Card
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -18,7 +21,6 @@ import androidx.compose.ui.viewinterop.AndroidView
import com.pushdeer.os.R
import com.pushdeer.os.data.database.entity.MessageEntity
import com.pushdeer.os.holder.RequestHolder
import com.pushdeer.os.ui.theme.MBlue
import com.pushdeer.os.util.CurrentTimeUtil
import com.pushdeer.os.values.ConstValues
@ -129,18 +131,18 @@ fun MarkdownMessageItem(message: MessageEntity, requestHolder: RequestHolder) {
contentDescription = "",
modifier = Modifier.size(40.dp)
)
Icon(
painter = painterResource(id = R.drawable.ic_markdown),
contentDescription = "",
tint = MaterialTheme.colors.MBlue,
modifier = Modifier
.size(20.dp)
.align(alignment = Alignment.BottomCenter)
)
// Icon(
// painter = painterResource(id = R.drawable.ic_markdown),
// contentDescription = "",
// tint = MaterialTheme.colors.MBlue,
// modifier = Modifier
// .size(20.dp)
// .align(alignment = Alignment.BottomCenter)
// )
}
Text(
text = "${message.text}·${
text = "${message.pushkey_name}·${
CurrentTimeUtil.resolveUTCTimeAndNow(
message.created_at,
System.currentTimeMillis()
@ -155,7 +157,7 @@ fun MarkdownMessageItem(message: MessageEntity, requestHolder: RequestHolder) {
android.widget.TextView(ctx).apply {
this.post {
// requestHolder.markdown.configuration().theme().
requestHolder.markdown.setMarkdown(this, message.desp)
requestHolder.markdown.setMarkdown(this, message.text)
}
}

View File

@ -0,0 +1,36 @@
package com.pushdeer.os.ui.compose.componment
import androidx.compose.material.AlertDialog
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import com.pushdeer.os.holder.RequestHolder
@Composable
fun MyAlertDialog(alertRequest: RequestHolder.AlertRequest) {
if (alertRequest.show.value) {
AlertDialog(
onDismissRequest = { alertRequest.show.value = false },
confirmButton = {
TextButton(onClick = {
alertRequest.onOKAction.invoke()
alertRequest.show.value = false
}) {
Text(text = "Ok")
}
},
dismissButton = {
TextButton(onClick = {
alertRequest.onCancelAction.invoke()
alertRequest.show.value = false
}) {
Text(text = "Cancel")
}
},
title = { Text(text = alertRequest.title) },
text = alertRequest.content
)
}
}

View File

@ -7,7 +7,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Done
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
@ -20,13 +19,13 @@ import com.pushdeer.os.values.ConstValues
@ExperimentalMaterialApi
@Composable
fun SwipeToDismissItem(
onDismiss: () -> Unit,
onAction: () -> Unit,
sidePadding: Boolean = false,
content: @Composable RowScope.() -> Unit
) {
val dismissState = rememberDismissState()
if (dismissState.isDismissed(DismissDirection.EndToStart)) {
onDismiss()
onAction()
}
Column(modifier = Modifier
.fillMaxWidth()
@ -34,7 +33,7 @@ fun SwipeToDismissItem(
SwipeToDismiss(
state = dismissState,
background = {
val direction = dismissState.dismissDirection ?: return@SwipeToDismiss
// val direction = dismissState.dismissDirection ?: return@SwipeToDismiss
val color by animateColorAsState(
when (dismissState.targetValue) {
@ -44,15 +43,18 @@ fun SwipeToDismissItem(
}
)
val alignment = when (direction) {
DismissDirection.StartToEnd -> Alignment.CenterStart
DismissDirection.EndToStart -> Alignment.CenterEnd
}
// val alignment = when (direction) {
// DismissDirection.StartToEnd -> Alignment.CenterStart
// DismissDirection.EndToStart -> Alignment.CenterEnd
// }
//
// val icon = when (direction) {
// DismissDirection.StartToEnd -> Icons.Default.Done
// DismissDirection.EndToStart -> Icons.Default.Delete
// }
val icon = when (direction) {
DismissDirection.StartToEnd -> Icons.Default.Done
DismissDirection.EndToStart -> Icons.Default.Delete
}
val alignment = Alignment.CenterEnd
val icon = Icons.Default.Delete
Box(
contentAlignment = alignment,
@ -69,7 +71,7 @@ fun SwipeToDismissItem(
)
}
},
directions = setOf(DismissDirection.EndToStart, DismissDirection.EndToStart),
directions = setOf(DismissDirection.EndToStart),
dismissThresholds = { direction ->
FractionalThreshold(if (direction == DismissDirection.EndToStart) 0.45f else 0.57f)
},

View File

@ -25,7 +25,7 @@ import com.pushdeer.os.ui.compose.page.main.MainPageFrame
@ExperimentalMaterialApi
@Composable
fun LogDaoPage(requestHolder: RequestHolder) {
fun LogDogPage(requestHolder: RequestHolder) {
MainPageFrame(
titleStringId = R.string.global_logdog,
sideIcon = Icons.Default.Delete,

View File

@ -1,7 +1,9 @@
package com.pushdeer.os.ui.compose.page
import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@ -16,24 +18,86 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.pushdeer.os.R
import com.pushdeer.os.holder.RequestHolder
import com.pushdeer.os.ui.theme.MainBlue
import com.pushdeer.os.ui.theme.MainGreen
import com.willowtreeapps.signinwithapplebutton.SignInWithAppleConfiguration
import com.willowtreeapps.signinwithapplebutton.SignInWithAppleResult
import com.willowtreeapps.signinwithapplebutton.view.SignInWithAppleButton
import kotlinx.coroutines.launch
@ExperimentalMaterialApi
@Composable
fun LoginPage(requestHolder: RequestHolder) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
val configuration = SignInWithAppleConfiguration.Builder()
.clientId("com.pushdeer.site")
.redirectUri("https://api2.pushdeer.com/callback/apple")
.responseType(SignInWithAppleConfiguration.ResponseType.ALL)
.scope(SignInWithAppleConfiguration.Scope.EMAIL)
.build()
Image(
painter = painterResource(R.drawable.logo_com_x2),
contentDescription = "big push deer logo"
contentDescription = "big push deer logo",
modifier = Modifier.clickable {
requestHolder.globalNavController.navigate("logdog")
}
)
AndroidView(
factory = {
SignInWithAppleButton(it).apply {
setUpSignInWithAppleOnClick(
requestHolder.fragmentManager,
configuration
) { result ->
when (result) {
is SignInWithAppleResult.Success -> {
Log.d("WH_", "apple-id_token:${result.idToken}")
requestHolder.coroutineScope.launch {
requestHolder.pushDeerViewModel.login(result.idToken) {
requestHolder.globalNavController.navigate("main") {
requestHolder.globalNavController.popBackStack()
}
}
}
}
is SignInWithAppleResult.Failure -> {
requestHolder.alert.alert("Warning", {
result.error.message
}, onOk = {})
Log.d(
"WH_",
"Received error from Apple Sign In ${result.error.message}"
)
}
is SignInWithAppleResult.Cancel -> {
Log.d("WH_", "User canceled Apple Sign In")
}
}
}
}
},
modifier = Modifier
.padding(bottom = 16.dp)
.border(
width = 1.dp,
color = MainBlue,
shape = RoundedCornerShape(4.dp)
)
)
Card(
onClick = { /*TODO*/ },
onClick = {
},
shape = RoundedCornerShape(4.dp),
modifier = Modifier
.padding(bottom = 16.dp)

View File

@ -1,23 +1,18 @@
package com.pushdeer.os.ui.compose.page.main
import android.os.Build
import android.text.TextUtils
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.Card
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.pushdeer.os.R
import com.pushdeer.os.data.api.data.request.DeviceInfo
import com.pushdeer.os.data.api.data.response.UserInfo
import com.pushdeer.os.holder.RequestHolder
import com.pushdeer.os.ui.compose.componment.CardItemSingleLineWithIcon
import com.pushdeer.os.ui.compose.componment.ListBottomBlankItem
@ -32,78 +27,54 @@ fun DeviceListPage(requestHolder: RequestHolder) {
MainPageFrame(
titleStringId = Page.Devices.labelStringId,
onSideIconClick = {
requestHolder.deviceReg(
deviceInfo = DeviceInfo().apply {
name = System.currentTimeMillis().toString()
device_id = "sdsdf"
is_clip = 0
}
)
}
if (requestHolder.settingStore.thisDeviceId == "") {
requestHolder.alert.alert(
title = "Confirm",
content = "This Device Registered Failed in PushSDK",
onOk = {})
// device regid got failed
} else {
requestHolder.deviceReg(
deviceInfo = DeviceInfo().apply {
name = SystemUtil.getDeviceModel()
device_id = requestHolder.settingStore.thisDeviceId
is_clip = 0
}
)
}
},
showSideIcon = requestHolder.pushDeerViewModel.shouldRegDevice()
) {
val state = rememberLazyListState()
LazyColumn(state = state) {
items(
items = requestHolder.pushDeerViewModel.deviceList,
key = { item: DeviceInfo -> item.id }) { deviceInfo: DeviceInfo ->
SwipeToDismissItem(onDismiss = { requestHolder.deviceRemove(deviceInfo) }) {
CardItemSingleLineWithIcon(
onClick = {},
resId = R.drawable.ipad_landscape2x,
text = if (deviceInfo.device_id == requestHolder.settingStore.thisDeviceId) "${deviceInfo.name} (this device)" else deviceInfo.name
)
if (requestHolder.pushDeerViewModel.deviceList.isEmpty()) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "It's Empty, Click '+' to Add New Device"
)
}
} else {
val state = rememberLazyListState()
LazyColumn(state = state) {
items(
items = requestHolder.pushDeerViewModel.deviceList,
key = { item: DeviceInfo -> item.id }) { deviceInfo: DeviceInfo ->
SwipeToDismissItem(
onAction = { requestHolder.deviceRemove(deviceInfo) }
) {
CardItemSingleLineWithIcon(
onClick = {},
resId = R.drawable.ipad_landscape2x,
text = if (deviceInfo.device_id == requestHolder.settingStore.thisDeviceId) "${deviceInfo.name} (this device) " else deviceInfo.name
)
}
}
}
item {
ListBottomBlankItem()
}
}
}
}
@ExperimentalMaterialApi
@Composable
fun DeviceListPage(userInfo: UserInfo, token: String, regid: String) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 8.dp)
.padding(top = 8.dp)
) {
item {
Card(elevation = 5.dp, onClick = {}, modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier.padding(horizontal = 16.dp, vertical = 14.dp)) {
Text(text = "当前版本 Android ${SystemUtil.getSystemVersion()}")
Text(text = "本机品牌 ${SystemUtil.getDeviceBrand()}")
Text(text = "本机型号 ${SystemUtil.getDeviceModel()}")
Text(text = "产品名称 ${Build.PRODUCT}")
MiuiVersion()
item {
ListBottomBlankItem()
}
}
}
item {
Card(elevation = 5.dp, onClick = {}, modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier.padding(horizontal = 16.dp, vertical = 14.dp)) {
Text(text = "id ${userInfo.id}")
Text(text = "name ${userInfo.name}")
Text(text = "email ${userInfo.email}")
Text(text = "app_id ${userInfo.app_id}")
Text(text = "wechat_id ${userInfo.wechat_id}")
Text(text = "created_at ${userInfo.created_at}")
Text(text = "updated_at ${userInfo.updated_at}")
Text(text = "level ${userInfo.level}")
Text(text = "token $token")
Text(text = "regid $regid")
}
}
}
}
}
@Composable
fun MiuiVersion() {
val v = SystemUtil.getMiuiVersion()
if (!TextUtils.isEmpty(v)) {
Text(text = "Miui 版本 ${v}")
}
}

View File

@ -1,10 +1,15 @@
package com.pushdeer.os.ui.compose.page.main
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.pushdeer.os.data.api.data.response.PushKey
import com.pushdeer.os.holder.RequestHolder
@ -20,17 +25,29 @@ fun KeyListPage(requestHolder: RequestHolder) {
titleStringId = Page.Keys.labelStringId,
onSideIconClick = { requestHolder.keyGen() }
) {
LazyColumn(modifier = Modifier.fillMaxWidth()) {
items(
requestHolder.pushDeerViewModel.keyList,
key = { item: PushKey -> item.id }) { pushKey: PushKey ->
SwipeToDismissItem(onDismiss = { requestHolder.keyRemove(pushKey) }
) {
KeyItem(key = pushKey, requestHolder = requestHolder)
}
if(requestHolder.pushDeerViewModel.keyList.isEmpty()){
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "It's Empty, Click '+' to Add New Key"
)
}
item {
ListBottomBlankItem()
}else{
LazyColumn(modifier = Modifier.fillMaxWidth()) {
items(
requestHolder.pushDeerViewModel.keyList,
key = { item: PushKey -> item.id }) { pushKey: PushKey ->
SwipeToDismissItem(onAction = { requestHolder.keyRemove(pushKey) }
) {
KeyItem(key = pushKey, requestHolder = requestHolder)
}
}
item {
ListBottomBlankItem()
}
}
}
}

View File

@ -26,12 +26,22 @@ import com.pushdeer.os.holder.RequestHolder
import com.pushdeer.os.ui.navigation.Page
import com.pushdeer.os.ui.navigation.pageList
import com.pushdeer.os.ui.theme.mainBottomBtn
import kotlinx.coroutines.launch
@ExperimentalAnimationApi
@ExperimentalMaterialApi
@Composable
fun MainPage(requestHolder: RequestHolder) {
SideEffect {
requestHolder.coroutineScope.launch {
requestHolder.pushDeerViewModel.userInfo()
requestHolder.pushDeerViewModel.keyList()
requestHolder.pushDeerViewModel.deviceList()
requestHolder.pushDeerViewModel.messageList()
}
}
var titleStringId by remember {
mutableStateOf(Page.Devices.labelStringId)
}

View File

@ -87,15 +87,13 @@ fun MessageListPage(requestHolder: RequestHolder) {
items = messageList,
key = { item: MessageEntity -> item.id }) { message: MessageEntity ->
SwipeToDismissItem(
onDismiss = {
onAction = {
requestHolder.messageRemove(message.toMessage(), onDone = {
requestHolder.messageViewModel.delete(message)
})
},
// sidePadding = false
sidePadding = message.type != "image"
) {
// ImageMessageItem(message)
when (message.type) {
"markdown" -> MarkdownMessageItem(message, requestHolder)
"text" -> PlainTextMessageItem(message)

View File

@ -19,7 +19,7 @@ import kotlinx.coroutines.withContext
class PushDeerViewModel(
private val settingStore: SettingStore,
private val logDogRepository: LogDogRepository,
private val pushDeerService:PushDeerApi,
private val pushDeerService: PushDeerApi,
private val messageRepository: MessageRepository
) : ViewModel() {
private val TAG = "WH_"
@ -30,14 +30,18 @@ class PushDeerViewModel(
val keyList = mutableStateListOf<PushKey>()
// var messageList = mutableStateListOf<Message>()
suspend fun login(onReturn: (String) -> Unit = {}) {
suspend fun login(idToken: String = "", onReturn: (String) -> Unit = {}) {
withContext(Dispatchers.IO) {
if (token == "") {
if (token == "" && idToken != "") {
try {
pushDeerService.fakeLogin().let {
pushDeerService.loginIdToken(idToken).let {
it.content?.let { tokenOnly ->
settingStore.userToken = tokenOnly.token
token = tokenOnly.token
Log.d(TAG, "login: $token")
withContext(Dispatchers.Main) {
onReturn.invoke(token)
}
}
}
} catch (e: Exception) {
@ -45,18 +49,26 @@ class PushDeerViewModel(
logDogRepository.loge("login", "", e.toString())
return@withContext
}
logDogRepository.logi("login","normally","nothing happened")
logDogRepository.logi("login", "normally", "nothing happened")
} else if (token == "" && idToken == "") {
return@withContext
} else if (token != "") {
withContext(Dispatchers.Main) {
onReturn.invoke(token)
}
}
// Log.d(TAG, "login: token $token")
}
}
suspend fun userInfo(onReturn: (UserInfo) -> Unit = {}) {
suspend fun userInfo(onOk: (UserInfo) -> Unit = {}, onFailed: () -> Unit = {}) {
withContext(Dispatchers.IO) {
try {
pushDeerService.userInfo(token).let {
it.content?.let { ita ->
userInfo = ita
withContext(Dispatchers.Main) {
onOk(userInfo)
}
}
}
} catch (e: Exception) {
@ -107,7 +119,6 @@ class PushDeerViewModel(
}
fun shouldRegDevice(): Boolean {
// Log.d(TAG, "isDeviceReged: current device id ${settingStore.thisDeviceId}")
return deviceList.none { it.device_id == settingStore.thisDeviceId }
}

View File

@ -6,6 +6,7 @@ buildscript {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.4"

View File

@ -3,6 +3,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
// maven { url 'https://developer.huawei.com/repo/' }
}
}