diff --git a/android/.idea/misc.xml b/android/.idea/misc.xml index 0dc9c62..9fc6b7d 100644 --- a/android/.idea/misc.xml +++ b/android/.idea/misc.xml @@ -13,6 +13,7 @@ + diff --git a/android/Readme.md b/android/Readme.md index cd6582e..6cd1893 100644 --- a/android/Readme.md +++ b/android/Readme.md @@ -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,19 @@ * 调整项目文件结构 * 将数据库用作message列表的直接数据来源 +* 2022-01-20 + * 修改 /device/reg post参数增加 type=android + * 集成 SignIn With Apple + * 调整设备列表加号的显示和操作逻辑 + * 将自动注册设备修改为手动点击加号注册设备 + * 当前app几乎处于可以使用的状态 + +* 2022-01-21 + * 修改登陆界面ui + * 增加key/device的重命名逻辑 + * 适配英语和中文 + + ### 感谢 https://github.com/taoweiji/MixPush \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index 5baf670..365c115 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -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' } \ No newline at end of file diff --git a/android/app/debug/output-metadata.json b/android/app/debug/output-metadata.json new file mode 100644 index 0000000..3258f2e --- /dev/null +++ b/android/app/debug/output-metadata.json @@ -0,0 +1,20 @@ +{ + "version": 3, + "artifactType": { + "type": "APK", + "kind": "Directory" + }, + "applicationId": "com.pushdeer.os", + "variantName": "debug", + "elements": [ + { + "type": "SINGLE", + "filters": [], + "attributes": [], + "versionCode": 1, + "versionName": "1.0", + "outputFile": "app-debug.apk" + } + ], + "elementType": "File" +} \ No newline at end of file diff --git a/android/app/debug/pushdeer-for-android-v1.0.apk b/android/app/debug/pushdeer-for-android-v1.0.apk new file mode 100644 index 0000000..e603594 Binary files /dev/null and b/android/app/debug/pushdeer-for-android-v1.0.apk differ diff --git a/android/app/src/main/java/com/pushdeer/os/App.kt b/android/app/src/main/java/com/pushdeer/os/App.kt index f03b233..06227e1 100644 --- a/android/app/src/main/java/com/pushdeer/os/App.kt +++ b/android/app/src/main/java/com/pushdeer/os/App.kt @@ -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 { diff --git a/android/app/src/main/java/com/pushdeer/os/MainActivity.kt b/android/app/src/main/java/com/pushdeer/os/MainActivity.kt index b1e6e31..740d9cc 100644 --- a/android/app/src/main/java/com/pushdeer/os/MainActivity.kt +++ b/android/app/src/main/java/com/pushdeer/os/MainActivity.kt @@ -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,8 @@ 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 resource: Resources by lazy { this.resource } override val coilImageLoader: ImageLoader by lazy { ImageLoader.Builder(this) @@ -69,6 +73,7 @@ class MainActivity : ComponentActivity(), RequestHolder { } .build() } + override val alert: RequestHolder.AlertRequest by lazy { object : RequestHolder.AlertRequest(resources) {} } override val markdown: Markwon by lazy { Markwon.builder(this) @@ -106,40 +111,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 +142,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) } } } diff --git a/android/app/src/main/java/com/pushdeer/os/data/api/PushDeerApi.kt b/android/app/src/main/java/com/pushdeer/os/data/api/PushDeerApi.kt index cf8c7a2..c02b721 100644 --- a/android/app/src/main/java/com/pushdeer/os/data/api/PushDeerApi.kt +++ b/android/app/src/main/java/com/pushdeer/os/data/api/PushDeerApi.kt @@ -1,11 +1,22 @@ package com.pushdeer.os.data.api import com.pushdeer.os.data.api.data.response.* -import retrofit2.http.* +import retrofit2.http.Field +import retrofit2.http.FieldMap +import retrofit2.http.FormUrlEncoded +import retrofit2.http.POST interface PushDeerApi { - @GET("/login/fake") - suspend fun fakeLogin(): ReturnData + companion object { + val baseUrl = "https://api2.pushdeer.com" + } + + @FormUrlEncoded + @POST("/login/idtoken") + suspend fun loginIdToken(@Field("idToken") idToken: String): ReturnData + +// @GET("/login/fake") +// suspend fun fakeLogin(): ReturnData @FormUrlEncoded @POST("/user/info") @@ -21,7 +32,15 @@ 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("/device/rename") + suspend fun deviceRename( + @Field("token") token: String, + @Field("id") id: Int, + @Field("name") newName: String + ): String @FormUrlEncoded @POST("/key/gen") @@ -39,6 +58,14 @@ interface PushDeerApi { @POST("/key/remove") suspend fun keyRemove(@FieldMap data: Map): String + @FormUrlEncoded + @POST("/key/rename") + suspend fun keyRename( + @Field("token") token: String, + @Field("id") id: String, + @Field("name") newName: String + ): String + @FormUrlEncoded @POST("/message/push") suspend fun messagePush(@FieldMap data: Map): String @@ -49,5 +76,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 } \ No newline at end of file diff --git a/android/app/src/main/java/com/pushdeer/os/data/api/data/request/DeviceInfo.kt b/android/app/src/main/java/com/pushdeer/os/data/api/data/request/DeviceInfo.kt index 9da0b94..8b565fc 100644 --- a/android/app/src/main/java/com/pushdeer/os/data/api/data/request/DeviceInfo.kt +++ b/android/app/src/main/java/com/pushdeer/os/data/api/data/request/DeviceInfo.kt @@ -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" ) } diff --git a/android/app/src/main/java/com/pushdeer/os/data/api/data/response/DeviceRemove.kt b/android/app/src/main/java/com/pushdeer/os/data/api/data/response/DeviceRemove.kt deleted file mode 100644 index d0658ef..0000000 --- a/android/app/src/main/java/com/pushdeer/os/data/api/data/response/DeviceRemove.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.pushdeer.os.data.api.data.response - -class DeviceRemove { - var token: String = "" - var id = "" - - fun toMap():Map { - return mapOf( - "token" to token, - "id" to id - ) - } -} \ No newline at end of file diff --git a/android/app/src/main/java/com/pushdeer/os/data/api/data/response/Message.kt b/android/app/src/main/java/com/pushdeer/os/data/api/data/response/Message.kt index 8cd09af..1aa8365 100644 --- a/android/app/src/main/java/com/pushdeer/os/data/api/data/response/Message.kt +++ b/android/app/src/main/java/com/pushdeer/os/data/api/data/response/Message.kt @@ -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 } } diff --git a/android/app/src/main/java/com/pushdeer/os/data/database/entity/MessageEntity.java b/android/app/src/main/java/com/pushdeer/os/data/database/entity/MessageEntity.java index 70d3c63..32895e6 100644 --- a/android/app/src/main/java/com/pushdeer/os/data/database/entity/MessageEntity.java +++ b/android/app/src/main/java/com/pushdeer/os/data/database/entity/MessageEntity.java @@ -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; } } diff --git a/android/app/src/main/java/com/pushdeer/os/holder/DataHolder.kt b/android/app/src/main/java/com/pushdeer/os/holder/DataHolder.kt deleted file mode 100644 index 46906c9..0000000 --- a/android/app/src/main/java/com/pushdeer/os/holder/DataHolder.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.pushdeer.os.holder - -interface DataHolder { -} \ No newline at end of file diff --git a/android/app/src/main/java/com/pushdeer/os/holder/RequestHolder.kt b/android/app/src/main/java/com/pushdeer/os/holder/RequestHolder.kt index 0af3822..d6640a0 100644 --- a/android/app/src/main/java/com/pushdeer/os/holder/RequestHolder.kt +++ b/android/app/src/main/java/com/pushdeer/os/holder/RequestHolder.kt @@ -3,11 +3,18 @@ package com.pushdeer.os.holder import android.content.ClipData import android.content.ClipboardManager import android.content.Intent -import android.util.Log +import android.content.res.Resources import androidx.activity.ComponentActivity import androidx.activity.result.ActivityResultLauncher +import androidx.annotation.StringRes +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.R import com.pushdeer.os.activity.QrScanActivity import com.pushdeer.os.data.api.data.request.DeviceInfo import com.pushdeer.os.data.api.data.response.Message @@ -26,7 +33,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 +42,12 @@ interface RequestHolder { val activityOpener: ActivityResultLauncher val coilImageLoader: ImageLoader +// val resource:Resources + + val fragmentManager: FragmentManager + + val alert: AlertRequest + val clipboardManager: ClipboardManager fun copyPlainString(str: String) { @@ -64,7 +77,17 @@ interface RequestHolder { } } - fun deviceReg(deviceInfo: DeviceInfo){ + fun keyRename(pushKey: PushKey){ + coroutineScope.launch { + pushDeerViewModel.keyRename(pushKey){ + coroutineScope.launch { + pushDeerViewModel.keyList() + } + } + } + } + + fun deviceReg(deviceInfo: DeviceInfo) { coroutineScope.launch { pushDeerViewModel.deviceReg(deviceInfo) } @@ -77,24 +100,38 @@ interface RequestHolder { } } + fun deviceRename(deviceInfo: DeviceInfo) { + coroutineScope.launch { + pushDeerViewModel.deviceRename(deviceInfo) { + coroutineScope.launch { + pushDeerViewModel.deviceList() + } + } + } + } + fun messagePush(text: String, desp: String, type: String, pushkey: String) { coroutineScope.launch { pushDeerViewModel.messagePush(text, desp, type, pushkey) } } - 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 - Log.d("WH_", "messagePushTest: keylist is empty") + } else { + alert.alert( + R.string.global_alert_title_alert, + R.string.main_message_send_alert, + onOk = {}) + } } - fun messageRemove(message: Message,onDone:()->Unit={}) { + fun messageRemove(message: Message, onDone: () -> Unit = {}) { coroutineScope.launch { // pushDeerViewModel.messageList.remove(message) pushDeerViewModel.messageRemove(message.id) @@ -112,4 +149,48 @@ interface RequestHolder { logDogViewModel.clear() } } + + abstract class AlertRequest(private val resources: Resources) { + val show: MutableState = 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 = {}) { + alert(title, { Text(text = content) }, onOk, onCancel) + } + + fun alert( + @StringRes title: Int, + @StringRes content: Int, + onOk: () -> Unit, + onCancel: () -> Unit = {} + ) { + alert(resources.getString(title), resources.getString(content), onOk, onCancel) + } + + fun alert( + @StringRes title: Int, + content: @Composable () -> Unit, + onOk: () -> Unit, + onCancel: () -> Unit={} + ) { + alert(resources.getString(title), content, onOk, onCancel) + } + } } \ No newline at end of file diff --git a/android/app/src/main/java/com/pushdeer/os/receiver/MessageReceiver.kt b/android/app/src/main/java/com/pushdeer/os/receiver/MessageReceiver.kt index aab03cd..510320e 100644 --- a/android/app/src/main/java/com/pushdeer/os/receiver/MessageReceiver.kt +++ b/android/app/src/main/java/com/pushdeer/os/receiver/MessageReceiver.kt @@ -33,7 +33,6 @@ class MessageReceiver : PushMessageReceiver() { override fun onReceivePassThroughMessage(context: Context, message: MiPushMessage) { init(context) -// Log.d("WH_", "onReceivePassThroughMessage: $message") mMessage = message.content if (!TextUtils.isEmpty(message.topic)) { mTopic = message.topic @@ -46,7 +45,6 @@ class MessageReceiver : PushMessageReceiver() { override fun onNotificationMessageClicked(context: Context, message: MiPushMessage) { init(context) -// Log.d("WH_", "onNotificationMessageClicked: $message") mMessage = message.content if (!TextUtils.isEmpty(message.topic)) { mTopic = message.topic @@ -59,7 +57,6 @@ class MessageReceiver : PushMessageReceiver() { override fun onNotificationMessageArrived(context: Context, message: MiPushMessage) { init(context) -// Log.d("WH_", "onNotificationMessageArrived: $message") mMessage = message.content if (!TextUtils.isEmpty(message.topic)) { mTopic = message.topic @@ -72,7 +69,6 @@ class MessageReceiver : PushMessageReceiver() { override fun onCommandResult(context: Context, message: MiPushCommandMessage) { init(context) -// Log.d("WH_", "onCommandResult: $message") val command = message.command val arguments = message.commandArguments val cmdArg1 = if (arguments != null && arguments.size > 0) arguments[0] else null @@ -108,7 +104,6 @@ class MessageReceiver : PushMessageReceiver() { override fun onReceiveRegisterResult(context: Context, message: MiPushCommandMessage) { init(context) -// Log.d("WH_", "onReceiveRegisterResult: $message") val command = message.command val arguments = message.commandArguments val cmdArg1 = if (arguments != null && arguments.size > 0) arguments[0] else null diff --git a/android/app/src/main/java/com/pushdeer/os/sss/MyActivityResultContract.kt b/android/app/src/main/java/com/pushdeer/os/sss/MyActivityResultContract.kt deleted file mode 100644 index ef8f91b..0000000 --- a/android/app/src/main/java/com/pushdeer/os/sss/MyActivityResultContract.kt +++ /dev/null @@ -1,19 +0,0 @@ -//package com.pushdeer.os.sss -// -//import android.content.Context -//import android.content.Intent -//import androidx.activity.result.contract.ActivityResultContract -//import com.pushdeer.os.activity.QrScanActivity -// -//class MyActivityResultContract : ActivityResultContract() { -// override fun createIntent(context: Context, input: String): Intent { -// return QrScanActivity.forScanResultIntent(context) -// } -// -// override fun parseResult(resultCode: Int, intent: Intent?): String { -// intent?.let { -// return it.getStringExtra(QrScanActivity.DataKey).toString() -// } -// return "" -// } -//} \ No newline at end of file diff --git a/android/app/src/main/java/com/pushdeer/os/store/SettingStore.kt b/android/app/src/main/java/com/pushdeer/os/store/SettingStore.kt index 508ac8c..3bdc95d 100644 --- a/android/app/src/main/java/com/pushdeer/os/store/SettingStore.kt +++ b/android/app/src/main/java/com/pushdeer/os/store/SettingStore.kt @@ -7,13 +7,13 @@ class SettingStore(context:Context) { val store = Store.create(context,"setting") var userToken by store.string("user-token","") - var deviceName by store.string("device-name","My Dear Deer") - var useRecv by store.boolean("use-recv",false) // 启用接收 - var useSend by store.boolean("use-send",false) - var useSendNotification by store.boolean("use-send-notification",false) - var notificationPackages by store.stringSet("notification-packages", emptySet()) - var useSendMissedCall by store.boolean("use-send=missed-call",false) - var useSendSMS by store.boolean("use-send-sms",false) +// var deviceName by store.string("device-name","My Dear Deer") +// var useRecv by store.boolean("use-recv",false) // 启用接收 +// var useSend by store.boolean("use-send",false) +// var useSendNotification by store.boolean("use-send-notification",false) +// var notificationPackages by store.stringSet("notification-packages", emptySet()) +// var useSendMissedCall by store.boolean("use-send=missed-call",false) +// var useSendSMS by store.boolean("use-send-sms",false) var showMessageSender by store.boolean("show-message-sender",true) var thisPushSdk by store.string("this-push-sdk","mi-push") diff --git a/android/app/src/main/java/com/pushdeer/os/typeExt/Flow.kt b/android/app/src/main/java/com/pushdeer/os/typeExt/Flow.kt deleted file mode 100644 index cf17130..0000000 --- a/android/app/src/main/java/com/pushdeer/os/typeExt/Flow.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.pushdeer.os.typeExt - -import androidx.lifecycle.LifecycleOwner -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.launch - diff --git a/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/KeyItem.kt b/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/KeyItem.kt index ae2d65f..d1b2b51 100644 --- a/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/KeyItem.kt +++ b/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/KeyItem.kt @@ -8,11 +8,12 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.DateRange -import androidx.compose.runtime.Composable +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -24,8 +25,37 @@ import com.wh.common.util.TimeUtils @ExperimentalMaterialApi @Composable -fun KeyItem(key: PushKey, requestHolder: RequestHolder) { - CardItemWithContent { +fun KeyItem(key: PushKey,requestHolder: RequestHolder) { + var name by remember { + mutableStateOf(key.name) + } + CardItemWithContent(onClick = { + requestHolder.alert.alert( + title = R.string.main_key_alert_changekeyname, + content = { + Column { + TextField( + value = name, + onValueChange = { name = it }, + shape = RoundedCornerShape(6.dp), + singleLine = true, + maxLines = 1, + label = { Text(text = stringResource(id = R.string.main_key_alert_keyname)) }, + colors = TextFieldDefaults.textFieldColors( + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + errorIndicatorColor = Color.Transparent, + ) + ) + } + }, + onOk = { + key.name = name + requestHolder.keyRename(key) + } + ) + }) { Column( modifier = Modifier .fillMaxWidth() @@ -113,7 +143,7 @@ fun KeyItem(key: PushKey, requestHolder: RequestHolder) { border = BorderStroke(1.dp, MaterialTheme.colors.MBlue), shape = RoundedCornerShape(6.dp) ) { - Text(text = "Reset") + Text(text = stringResource(id = R.string.main_key_reset)) } Button( onClick = { @@ -125,7 +155,7 @@ fun KeyItem(key: PushKey, requestHolder: RequestHolder) { ), shape = RoundedCornerShape(6.dp) ) { - Text(text = "Copy") + Text(text = stringResource(id = R.string.main_key_copy)) } } } diff --git a/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/MessageItem.kt b/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/MessageItem.kt index a2a5d1e..d10a873 100644 --- a/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/MessageItem.kt +++ b/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/MessageItem.kt @@ -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) } } diff --git a/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/MyAlertDialog.kt b/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/MyAlertDialog.kt new file mode 100644 index 0000000..8a428d4 --- /dev/null +++ b/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/MyAlertDialog.kt @@ -0,0 +1,38 @@ +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 androidx.compose.ui.res.stringResource +import com.pushdeer.os.R +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 = stringResource(id = R.string.global_alert_ok)) + } + + }, + dismissButton = { + TextButton(onClick = { + alertRequest.onCancelAction.invoke() + alertRequest.show.value = false + }) { + Text(text = stringResource(id = R.string.global_alert_cancel)) + } + + }, + title = { Text(text = alertRequest.title) }, + text = alertRequest.content + ) + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/SwipeToDismissItem.kt b/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/SwipeToDismissItem.kt index 6e910d0..7145826 100644 --- a/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/SwipeToDismissItem.kt +++ b/android/app/src/main/java/com/pushdeer/os/ui/compose/componment/SwipeToDismissItem.kt @@ -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) }, diff --git a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/LogDaoPage.kt b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/LogDogPage.kt similarity index 98% rename from android/app/src/main/java/com/pushdeer/os/ui/compose/page/LogDaoPage.kt rename to android/app/src/main/java/com/pushdeer/os/ui/compose/page/LogDogPage.kt index 9fba3f5..e9d3012 100644 --- a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/LogDaoPage.kt +++ b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/LogDogPage.kt @@ -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, diff --git a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/LoginPage.kt b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/LoginPage.kt index 187047f..c636595 100644 --- a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/LoginPage.kt +++ b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/LoginPage.kt @@ -1,76 +1,82 @@ 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.layout.Column +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -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.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 - ) { + Box(modifier = Modifier.fillMaxSize()) { + + 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" - ) - Card( - onClick = { /*TODO*/ }, - shape = RoundedCornerShape(4.dp), + contentDescription = "big push deer logo", modifier = Modifier - .padding(bottom = 16.dp) - .border( - width = 1.dp, - color = MainBlue, - shape = RoundedCornerShape(4.dp) - ) - ) { - Text( - text = "Sign in with Apple", - color = MainBlue, - textAlign = TextAlign.Center, - modifier = Modifier - .padding(vertical = 16.dp) - .fillMaxWidth(0.6F) - - ) - } - Card( - onClick = {}, - shape = RoundedCornerShape(4.dp), - modifier = Modifier.border( - width = 1.dp, - color = MainGreen, - shape = RoundedCornerShape(4.dp) - ) - ) { - Text( - text = "Sign in with WeChat", - color = MainGreen, - textAlign = TextAlign.Center, - modifier = Modifier - .padding(vertical = 16.dp) - .fillMaxWidth(0.6F) - ) - } + .clickable { requestHolder.globalNavController.navigate("logdog") } + .align(Alignment.TopCenter) + .padding(top = 50.dp) + ) + 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 + .align(alignment = Alignment.BottomCenter) + .padding(bottom = 100.dp) + ) } - } \ No newline at end of file diff --git a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/DeviceListPage.kt b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/DeviceListPage.kt index 5e1f9a7..933c3d7 100644 --- a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/DeviceListPage.kt +++ b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/DeviceListPage.kt @@ -1,23 +1,25 @@ package com.pushdeer.os.ui.compose.page.main -import android.os.Build -import android.text.TextUtils +import android.util.Log +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.foundation.shape.RoundedCornerShape import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.Text -import androidx.compose.runtime.Composable +import androidx.compose.material.TextField +import androidx.compose.material.TextFieldDefaults +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource 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 +34,89 @@ 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 = R.string.global_alert_title_confirm, + content = R.string.alert_device_register_failed_push_sdk, + 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 = stringResource(id = R.string.main_device_list_placeholder) + ) + } + } else { + val state = rememberLazyListState() + LazyColumn(state = state) { + items( + items = requestHolder.pushDeerViewModel.deviceList, + key = { item: DeviceInfo -> item.id }) { deviceInfo: DeviceInfo -> + var name by remember { + mutableStateOf(deviceInfo.name) + } + SwipeToDismissItem( + onAction = { requestHolder.deviceRemove(deviceInfo) } + ) { + CardItemSingleLineWithIcon( + onClick = { + requestHolder.alert.alert( + title = R.string.main_device_alert_changedevicename, + content = { + Column { +// Text(text = "type:${deviceInfo.type}") + TextField( + value = name, + onValueChange = { name = it }, + shape = RoundedCornerShape(6.dp), + singleLine = true, + maxLines = 1, + label = { Text(text = stringResource(id = R.string.main_device_alert_devicename)) }, + colors = TextFieldDefaults.textFieldColors( + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + disabledIndicatorColor = Color.Transparent, + errorIndicatorColor = Color.Transparent, + ) + ) + } + }, + onOk = { + deviceInfo.name = name + requestHolder.deviceRename(deviceInfo) + } + ) + }, + resId = R.drawable.ipad_landscape2x, + text = if (deviceInfo.device_id == requestHolder.settingStore.thisDeviceId) "${deviceInfo.name} (${ + stringResource( + id = R.string.main_device_this_device + ) + }) " else deviceInfo.name + ) + Log.d("WH_", "DeviceListPage: $deviceInfo") + } } - } - 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}") } } \ No newline at end of file diff --git a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/KeyListPage.kt b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/KeyListPage.kt index 39429a1..f1b97c3 100644 --- a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/KeyListPage.kt +++ b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/KeyListPage.kt @@ -1,11 +1,18 @@ 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 androidx.compose.ui.res.stringResource +import com.pushdeer.os.R import com.pushdeer.os.data.api.data.response.PushKey import com.pushdeer.os.holder.RequestHolder import com.pushdeer.os.ui.compose.componment.KeyItem @@ -20,17 +27,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 = stringResource(id = R.string.main_key_list_placeholder) + ) } - 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() + } } } } diff --git a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/MainPage.kt b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/MainPage.kt index 50c1f5d..543f5b0 100644 --- a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/MainPage.kt +++ b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/MainPage.kt @@ -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) } diff --git a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/MessageListPage.kt b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/MessageListPage.kt index 3f3658c..4265f5f 100644 --- a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/MessageListPage.kt +++ b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/MessageListPage.kt @@ -14,7 +14,9 @@ import androidx.compose.material.icons.filled.KeyboardArrowUp import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import com.pushdeer.os.R import com.pushdeer.os.data.database.entity.MessageEntity import com.pushdeer.os.holder.RequestHolder import com.pushdeer.os.ui.compose.componment.* @@ -78,7 +80,7 @@ fun MessageListPage(requestHolder: RequestHolder) { contentColor = Color.White ), ) { - Text(text = "Send") + Text(text = stringResource(id = R.string.main_message_send)) } } } @@ -87,15 +89,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) diff --git a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/SettingPage.kt b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/SettingPage.kt index 77baab1..1294670 100644 --- a/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/SettingPage.kt +++ b/android/app/src/main/java/com/pushdeer/os/ui/compose/page/main/SettingPage.kt @@ -1,13 +1,12 @@ package com.pushdeer.os.ui.compose.page.main -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.LazyColumn 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.res.stringResource +import com.pushdeer.os.R import com.pushdeer.os.holder.RequestHolder import com.pushdeer.os.ui.compose.componment.SettingItem import com.pushdeer.os.ui.navigation.Page @@ -24,8 +23,8 @@ fun SettingPage(requestHolder: RequestHolder) { ) { item { SettingItem( - text = "Hi ${requestHolder.pushDeerViewModel.userInfo.name} !", - buttonString = "Logout" + text = "${stringResource(id = R.string.main_setting_user_hi)} ${requestHolder.pushDeerViewModel.userInfo.name} !", + buttonString = stringResource(id = R.string.main_setting_user_logout) ) { requestHolder.settingStore.userToken = "" // logout 操作: @@ -33,26 +32,26 @@ fun SettingPage(requestHolder: RequestHolder) { // 删除保存的 token } } - item { - SettingItem( - text = "Customize Server", - buttonString = "Scan QR" - ) { - requestHolder.startQrScanActivity() - } - } - item { - SettingItem( - text = "Do you like PushDeer ?", - buttonString = "Like" - ) { - } - } +// item { +// SettingItem( +// text = "Customize Server", +// buttonString = "Scan QR" +// ) { +// requestHolder.startQrScanActivity() +// } +// } +// item { +// SettingItem( +// text = "Do you like PushDeer ?", +// buttonString = "Like" +// ) { +// } +// } item { SettingItem( - text = "LogDog", - buttonString = "Open" + text = stringResource(id = R.string.main_setting_logdog), + buttonString = stringResource(id = R.string.main_setting_logdog_open) ) { requestHolder.globalNavController.navigate("logdog") } @@ -61,12 +60,12 @@ fun SettingPage(requestHolder: RequestHolder) { } } -@Composable -fun TogglePreferenceItem(label: String) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxSize() - ) { - Text(text = label) - } -} \ No newline at end of file +//@Composable +//fun TogglePreferenceItem(label: String) { +// Row( +// verticalAlignment = Alignment.CenterVertically, +// modifier = Modifier.fillMaxSize() +// ) { +// Text(text = label) +// } +//} \ No newline at end of file diff --git a/android/app/src/main/java/com/pushdeer/os/viewmodel/PushDeerViewModel.kt b/android/app/src/main/java/com/pushdeer/os/viewmodel/PushDeerViewModel.kt index 8645b01..4c07bdf 100644 --- a/android/app/src/main/java/com/pushdeer/os/viewmodel/PushDeerViewModel.kt +++ b/android/app/src/main/java/com/pushdeer/os/viewmodel/PushDeerViewModel.kt @@ -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() // var messageList = mutableStateListOf() - 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) { @@ -97,17 +109,17 @@ class PushDeerViewModel( pushDeerService.deviceList(token).let { it.content?.let { deviceList.clear() - deviceList.addAll(it.devices) + deviceList.addAll(it.devices.reversed()) } } } catch (e: Exception) { Log.d(TAG, "deviceList: ${e.localizedMessage}") + logDogRepository.loge("deviceList", "", e.toString()) } } } fun shouldRegDevice(): Boolean { -// Log.d(TAG, "isDeviceReged: current device id ${settingStore.thisDeviceId}") return deviceList.none { it.device_id == settingStore.thisDeviceId } } @@ -120,6 +132,19 @@ class PushDeerViewModel( } } catch (e: Exception) { Log.d(TAG, "deviceRemove: ${e.localizedMessage}") + logDogRepository.loge("deviceRemove", "", e.toString()) + } + } + } + + suspend fun deviceRename(deviceInfo: DeviceInfo,onReturn: () -> Unit={}){ + withContext(Dispatchers.IO){ + try { + pushDeerService.deviceRename(token,deviceInfo.id,deviceInfo.name) + onReturn() + }catch (e:Exception){ + Log.d(TAG, "deviceRename: ${e.localizedMessage}") + logDogRepository.loge("deviceRename", "", e.toString()) } } } @@ -135,6 +160,7 @@ class PushDeerViewModel( } } catch (e: Exception) { Log.d(TAG, "keyGen: ${e.localizedMessage}") + logDogRepository.loge("keyGen", "", e.toString()) } } } @@ -152,6 +178,23 @@ class PushDeerViewModel( } } catch (e: Exception) { Log.d(TAG, "keyRegen: ${e.localizedMessage}") + logDogRepository.loge("keyRegen", "", e.toString()) + } + } + } + + suspend fun keyRename(key: PushKey,onReturn: () -> Unit={}){ + withContext(Dispatchers.IO){ + try { + pushDeerService.keyRename( + token, + key.id, + key.name + ) + onReturn() + }catch (e: Exception) { + Log.d(TAG, "keyRename: ${e.localizedMessage}") + logDogRepository.loge("keyRename", "", e.toString()) } } } @@ -167,6 +210,7 @@ class PushDeerViewModel( } } catch (e: Exception) { Log.d(TAG, "keyList: ${e.localizedMessage}") + logDogRepository.loge("keyList", "", e.toString()) } } } @@ -179,6 +223,7 @@ class PushDeerViewModel( } } catch (e: Exception) { Log.d(TAG, "keyRemove: ${e.localizedMessage}") + logDogRepository.loge("keyRemove", "", e.toString()) } } diff --git a/android/app/src/main/res/values-zh-rCN/strings.xml b/android/app/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000..392d959 --- /dev/null +++ b/android/app/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,4 @@ + + + PushDeer + \ No newline at end of file diff --git a/android/app/src/main/res/values-zh/strings.xml b/android/app/src/main/res/values-zh/strings.xml new file mode 100644 index 0000000..a394120 --- /dev/null +++ b/android/app/src/main/res/values-zh/strings.xml @@ -0,0 +1,29 @@ + + + PushDeer + 设备 + 密钥 + 消息 + 设置 + LogDog-罗格狗 + 重置 + 复制 + 打开 + 你好 + 注销 + LogDog-罗格狗 + 点击\"+\"创建新设备 + 本设备 + 确认 + 本设备在厂商推送服务注册失败 + 发送 + 警告 + 发送消息前请创建新的密钥 + 确认 + 取消 + 点击\"+\"创建新密钥 + 修改设备名称 + 设备名称 + 修改密钥名称 + 密钥名称 + \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 65eca7d..d4cba6d 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -5,4 +5,24 @@ Message Setting LogDog + Reset + Copy + Open + Hi + Logout + LogDog + It\'s Empty, Click \'+\' to Add New Device. + this device + Confirm + This Device Registered Failed in PushSDK + Send + Alert + You Should Add One PushKey + OK + Cancel + It\'s Empty, Click \'+\' to Add New Key. + Change Device Name + name + Change Key Name + name diff --git a/android/build.gradle b/android/build.gradle index 885ba20..0dfc4d0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -6,6 +6,7 @@ buildscript { repositories { google() mavenCentral() + maven { url 'https://jitpack.io' } } dependencies { classpath "com.android.tools.build:gradle:7.0.4" diff --git a/android/settings.gradle b/android/settings.gradle index f3fedc9..b6b75fc 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -3,6 +3,7 @@ dependencyResolutionManagement { repositories { google() mavenCentral() + maven { url 'https://jitpack.io' } // maven { url 'https://developer.huawei.com/repo/' } } }