fix: 增加Message禁用功能
This commit is contained in:
commit
cf72615d96
@ -2,9 +2,10 @@ plugins {
|
|||||||
id 'com.android.application'
|
id 'com.android.application'
|
||||||
id 'org.jetbrains.kotlin.android'
|
id 'org.jetbrains.kotlin.android'
|
||||||
id 'kotlin-android'
|
id 'kotlin-android'
|
||||||
id 'kotlin-parcelize'
|
id 'kotlin-parcelize' // 序列化
|
||||||
id 'kotlin-kapt'
|
id 'kotlin-kapt'
|
||||||
id 'dagger.hilt.android.plugin'
|
id 'dagger.hilt.android.plugin' //hilt 依赖注入
|
||||||
|
id "com.google.protobuf" version "0.8.17" //Proto DataStore 插件
|
||||||
// id 'com.google.dagger.hilt.android'
|
// id 'com.google.dagger.hilt.android'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ dependencies {
|
|||||||
|
|
||||||
//room 数据库相关
|
//room 数据库相关
|
||||||
implementation 'com.tencent.wcdb:room:1.1-19' // 代替 room-runtime,同时也不需要再引用 wcdb-android
|
implementation 'com.tencent.wcdb:room:1.1-19' // 代替 room-runtime,同时也不需要再引用 wcdb-android
|
||||||
api 'androidx.sqlite:sqlite:2.2.0'
|
implementation 'androidx.sqlite:sqlite-ktx:2.2.0'
|
||||||
implementation 'androidx.room:room-runtime:2.4.3'
|
implementation 'androidx.room:room-runtime:2.4.3'
|
||||||
implementation 'androidx.room:room-ktx:2.4.3'
|
implementation 'androidx.room:room-ktx:2.4.3'
|
||||||
annotationProcessor 'androidx.room:room-compiler:2.4.3'
|
annotationProcessor 'androidx.room:room-compiler:2.4.3'
|
||||||
@ -90,13 +91,12 @@ dependencies {
|
|||||||
kapt 'android.arch.persistence.room:compiler:1.1.1'// compiler 需要用 room 的
|
kapt 'android.arch.persistence.room:compiler:1.1.1'// compiler 需要用 room 的
|
||||||
kapt 'androidx.room:room-compiler:2.4.3'
|
kapt 'androidx.room:room-compiler:2.4.3'
|
||||||
kapt 'androidx.room:room-ktx:2.4.3'
|
kapt 'androidx.room:room-ktx:2.4.3'
|
||||||
|
|
||||||
//分页加载
|
//分页加载
|
||||||
implementation "androidx.room:room-paging:2.4.3"
|
implementation "androidx.room:room-paging:2.4.3"
|
||||||
implementation "androidx.paging:paging-runtime-ktx:3.1.1"
|
implementation "androidx.paging:paging-runtime-ktx:3.1.1"
|
||||||
|
|
||||||
androidTestImplementation "android.arch.persistence.room:testing:1.1.1"
|
androidTestImplementation "android.arch.persistence.room:testing:1.1.1"
|
||||||
// implementation "android.arch.lifecycle:extensions:1.1.1"
|
|
||||||
// annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
|
|
||||||
implementation 'com.tencent.wcdb:wcdb-android:1.1-19'
|
implementation 'com.tencent.wcdb:wcdb-android:1.1-19'
|
||||||
|
|
||||||
|
|
||||||
@ -108,29 +108,20 @@ dependencies {
|
|||||||
|
|
||||||
//带侧滑的自定义列表
|
//带侧滑的自定义列表
|
||||||
implementation 'com.yanzhenjie.recyclerview:x:1.3.2'
|
implementation 'com.yanzhenjie.recyclerview:x:1.3.2'
|
||||||
// implementation 'androidx.appcompat:appcompat:1.5.1'
|
//下拉刷新,上拉加载
|
||||||
|
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||||
// // Koin
|
|
||||||
// implementation("io.insert-koin:koin-android:3.3.2")
|
|
||||||
// implementation("io.insert-koin:koin-core:3.3.2")
|
|
||||||
|
|
||||||
// Retrofit 网络请求相关
|
// Retrofit 网络请求相关
|
||||||
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||||
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
||||||
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
||||||
// const val chuck = "com.readystatesoftware.chuck:library:${Versions.chuck}"
|
|
||||||
// const val chuckNoOp = "com.readystatesoftware.chuck:library-no-op:${Versions.chuck}"
|
|
||||||
implementation("com.squareup.okhttp3:okhttp:4.9.0")
|
implementation("com.squareup.okhttp3:okhttp:4.9.0")
|
||||||
implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
|
implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
|
||||||
implementation("com.google.code.gson:gson:2.8.6")
|
implementation("com.google.code.gson:gson:2.8.6")
|
||||||
|
|
||||||
|
|
||||||
//hilt
|
//hilt
|
||||||
implementation "com.google.dagger:hilt-android:2.41"
|
implementation "com.google.dagger:hilt-android:2.41"
|
||||||
kapt "com.google.dagger:hilt-compiler:2.41"
|
kapt "com.google.dagger:hilt-compiler:2.41"
|
||||||
// implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
|
|
||||||
// androidTestImplementation "com.google.dagger:hilt-android-testing:2.41"
|
|
||||||
// kaptAndroidTest "com.google.dagger:hilt-android-compiler:2.41"
|
|
||||||
|
|
||||||
// 显示错误提示 https://github.com/nhaarman/supertooltips
|
// 显示错误提示 https://github.com/nhaarman/supertooltips
|
||||||
implementation 'com.nhaarman.supertooltips:library:3.0.0'
|
implementation 'com.nhaarman.supertooltips:library:3.0.0'
|
||||||
@ -155,6 +146,30 @@ dependencies {
|
|||||||
// 图片查看器 https://github.com/XiaoGe-1996/ImageViewer
|
// 图片查看器 https://github.com/XiaoGe-1996/ImageViewer
|
||||||
implementation 'com.github.XiaoGe-1996:ImageViewer:v1.0.0'
|
implementation 'com.github.XiaoGe-1996:ImageViewer:v1.0.0'
|
||||||
implementation 'com.github.majidarabi:AndroidFilePicker:0.2.1'
|
implementation 'com.github.majidarabi:AndroidFilePicker:0.2.1'
|
||||||
|
// 数据存储 Preferences DataStore 键值对
|
||||||
|
implementation "androidx.datastore:datastore-preferences:1.0.0"
|
||||||
|
// 数据存储 Proto DataStore 对象
|
||||||
|
implementation "androidx.datastore:datastore-core:1.0.0"
|
||||||
|
implementation "com.google.protobuf:protobuf-javalite:3.18.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
//Proto DataStore 数据存储插件
|
||||||
|
protobuf {
|
||||||
|
protoc {
|
||||||
|
artifact = "com.google.protobuf:protoc:3.14.0"
|
||||||
|
}
|
||||||
|
// Generates the java Protobuf-lite code for the Protobufs in this project. See
|
||||||
|
// https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
|
||||||
|
// for more information.
|
||||||
|
generateProtoTasks {
|
||||||
|
all().each { task ->
|
||||||
|
task.builtins {
|
||||||
|
java {
|
||||||
|
option 'lite'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kapt {
|
kapt {
|
||||||
|
@ -24,14 +24,15 @@
|
|||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
android:icon="@mipmap/volvo_logo_small"
|
android:icon="@mipmap/volvo_logo_small"
|
||||||
android:requestLegacyExternalStorage="true"
|
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
android:requestLegacyExternalStorage="true"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.NavinfoVolvo"
|
android:theme="@style/Theme.NavinfoVolvo"
|
||||||
android:usesCleartextTraffic="true">
|
android:usesCleartextTraffic="true">
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.message.MessageActivity"
|
android:name=".ui.message.MessageActivity"
|
||||||
|
android:configChanges="orientation"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:label="@string/title_activity_second"
|
android:label="@string/title_activity_second"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
@ -54,6 +55,8 @@
|
|||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.app.lib_name"
|
android:name="android.app.lib_name"
|
||||||
android:value="" />
|
android:value="" />
|
||||||
<meta-data android:name="ScopedStorage" android:value="true" />
|
<meta-data
|
||||||
|
android:name="ScopedStorage"
|
||||||
|
android:value="true" />
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
@ -9,6 +9,8 @@ class Constant {
|
|||||||
*/
|
*/
|
||||||
const val SERVER_ADDRESS = "http://ec2-52-81-73-5.cn-north-1.compute.amazonaws.com.cn:8088/"
|
const val SERVER_ADDRESS = "http://ec2-52-81-73-5.cn-north-1.compute.amazonaws.com.cn:8088/"
|
||||||
val DEBUG = Boolean.parseBoolean("true")
|
val DEBUG = Boolean.parseBoolean("true")
|
||||||
|
|
||||||
|
const val message_status_late = "预约,待发送"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,8 +1,39 @@
|
|||||||
package com.navinfo.volvo
|
package com.navinfo.volvo
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.os.Bundle
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
|
|
||||||
@HiltAndroidApp
|
@HiltAndroidApp
|
||||||
open class MyApplication : Application() {
|
open class MyApplication : Application() {
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
|
||||||
|
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
|
||||||
|
|
||||||
|
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||||
|
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityStarted(activity: Activity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityResumed(activity: Activity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityPaused(activity: Activity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityStopped(activity: Activity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityDestroyed(activity: Activity) {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,191 +0,0 @@
|
|||||||
//package com.navinfo.volvo.database;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//import android.content.Context;
|
|
||||||
//
|
|
||||||
//import androidx.annotation.NonNull;
|
|
||||||
//import androidx.room.Database;
|
|
||||||
//import androidx.room.Room;
|
|
||||||
//import androidx.room.RoomDatabase;
|
|
||||||
//import androidx.sqlite.db.SupportSQLiteDatabase;
|
|
||||||
//import androidx.sqlite.db.SupportSQLiteOpenHelper;
|
|
||||||
//
|
|
||||||
//import com.navinfo.volvo.database.dao.MessageDao;
|
|
||||||
//import com.navinfo.volvo.database.dao.UserDao;
|
|
||||||
//import com.navinfo.volvo.database.entity.Message;
|
|
||||||
//import com.navinfo.volvo.database.entity.Attachment;
|
|
||||||
//import com.navinfo.volvo.database.entity.User;
|
|
||||||
//import com.tencent.wcdb.database.SQLiteCipherSpec;
|
|
||||||
//import com.tencent.wcdb.database.SQLiteDatabase;
|
|
||||||
//
|
|
||||||
//import com.tencent.wcdb.room.db.WCDBOpenHelperFactory;
|
|
||||||
//
|
|
||||||
//import android.os.AsyncTask;
|
|
||||||
//import android.util.Log;
|
|
||||||
//
|
|
||||||
//import com.tencent.wcdb.repair.BackupKit;
|
|
||||||
//import com.tencent.wcdb.repair.RecoverKit;
|
|
||||||
//import com.tencent.wcdb.room.db.WCDBDatabase;
|
|
||||||
//
|
|
||||||
//@Database(entities = {Message.class, Attachment.class, User.class}, version = 1, exportSchema = false)
|
|
||||||
//public abstract class MapLifeDataBase extends RoomDatabase {
|
|
||||||
// // marking the instance as volatile to ensure atomic access to the variable
|
|
||||||
// /**
|
|
||||||
// * 数据库单例对象
|
|
||||||
// */
|
|
||||||
// private static volatile MapLifeDataBase INSTANCE;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 要素数据库类
|
|
||||||
// */
|
|
||||||
// public abstract MessageDao getMessageDao();
|
|
||||||
//
|
|
||||||
// public abstract UserDao getUserDao();
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 数据库秘钥
|
|
||||||
// */
|
|
||||||
// private final static String DB_PASSWORD = "123456";
|
|
||||||
//
|
|
||||||
// public static MapLifeDataBase getDatabase(final Context context, final String name) {
|
|
||||||
// if (INSTANCE == null) {
|
|
||||||
// synchronized (MapLifeDataBase.class) {
|
|
||||||
// if (INSTANCE == null) {
|
|
||||||
// // [WCDB] To use Room library with WCDB, pass a WCDBOpenHelper factory object
|
|
||||||
// // to the database builder with .openHelperFactory(...). In the factory object,
|
|
||||||
// // you can specify passphrase and cipher options to open or create encrypted
|
|
||||||
// // database, as well as optimization options like asynchronous checkpoint.
|
|
||||||
// SQLiteCipherSpec cipherSpec = new SQLiteCipherSpec()
|
|
||||||
// .setPageSize(1024)
|
|
||||||
// .setSQLCipherVersion(3);
|
|
||||||
// WCDBOpenHelperFactory factory = new WCDBOpenHelperFactory()
|
|
||||||
// .passphrase(DB_PASSWORD.getBytes()) // passphrase to the database, remove this line for plain-text
|
|
||||||
// .cipherSpec(cipherSpec) // cipher to use, remove for default settings
|
|
||||||
// .writeAheadLoggingEnabled(true) // enable WAL mode, remove if not needed
|
|
||||||
// .asyncCheckpointEnabled(true); // enable asynchronous checkpoint, remove if not needed
|
|
||||||
//
|
|
||||||
// INSTANCE = Room.databaseBuilder(context.getApplicationContext(), MapLifeDataBase.class, name)
|
|
||||||
//
|
|
||||||
// // [WCDB] Specify open helper to use WCDB database implementation instead
|
|
||||||
// // of the Android framework.
|
|
||||||
// .openHelperFactory((SupportSQLiteOpenHelper.Factory) factory)
|
|
||||||
//
|
|
||||||
// // Wipes and rebuilds instead of migrating if no Migration object.
|
|
||||||
// // Migration is not part of this codelab.
|
|
||||||
// .fallbackToDestructiveMigration().addCallback(sRoomDatabaseCallback).build();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return INSTANCE;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Override the onOpen method to populate the database.
|
|
||||||
// * For this sample, we clear the database every time it is created or opened.
|
|
||||||
// * <p>
|
|
||||||
// * If you want to populate the database only when the database is created for the 1st time,
|
|
||||||
// * override RoomDatabase.Callback()#onCreate
|
|
||||||
// */
|
|
||||||
// private static Callback sRoomDatabaseCallback = new Callback() {
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onOpen(@NonNull SupportSQLiteDatabase db) {
|
|
||||||
// super.onOpen(db);
|
|
||||||
// // If you want to keep the data through app restarts,
|
|
||||||
// // comment out the following line.
|
|
||||||
// new PopulateDbAsync(INSTANCE).execute();
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Populate the database in the background.
|
|
||||||
// * If you want to start with more words, just add them.
|
|
||||||
// */
|
|
||||||
// private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {
|
|
||||||
//
|
|
||||||
// private final MessageDao messageDao;
|
|
||||||
//
|
|
||||||
// PopulateDbAsync(MapLifeDataBase db) {
|
|
||||||
// messageDao = db.getMessageDao();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// protected Void doInBackground(final Void... params) {
|
|
||||||
// // Start the app with a clean database every time.
|
|
||||||
// // Not needed if you only populate on creation.
|
|
||||||
// //mDao.deleteAll();
|
|
||||||
// Log.e("qj", "doInBackground");
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 数据恢复
|
|
||||||
// */
|
|
||||||
// protected boolean recoverData() {
|
|
||||||
// if (INSTANCE != null) {
|
|
||||||
// SQLiteDatabase sqlite = ((WCDBDatabase) INSTANCE.getOpenHelper().getWritableDatabase()).getInnerDatabase();
|
|
||||||
// RecoverKit recover = new RecoverKit(sqlite, // 要恢复到的目标 DB
|
|
||||||
// sqlite.getPath() + "-backup", // 备份文件
|
|
||||||
// DB_PASSWORD.getBytes() // 加密备份文件的密钥,非 DB 密钥
|
|
||||||
// );
|
|
||||||
// int result = recover.run(false); // fatal 参数传 false 表示遇到错误忽略并继续,
|
|
||||||
// // 若传 true 遇到错误则中止并返回 FAILED
|
|
||||||
// switch (result) {
|
|
||||||
// case RecoverKit.RESULT_OK:
|
|
||||||
// /* 成功 */
|
|
||||||
// Log.e("qj", "sRoomDatabaseCallback==RecoverKit成功");
|
|
||||||
// return true;
|
|
||||||
// case RecoverKit.RESULT_CANCELED: /* 取消操作 */
|
|
||||||
// Log.e("qj", "sRoomDatabaseCallback==RecoverKit取消操作");
|
|
||||||
// break;
|
|
||||||
// case RecoverKit.RESULT_FAILED: /* 失败 */
|
|
||||||
// Log.e("qj", "sRoomDatabaseCallback==RecoverKit失败");
|
|
||||||
// break;
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// recover.release();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 备份数据
|
|
||||||
// */
|
|
||||||
// protected boolean backup() {
|
|
||||||
// Log.e("qj", "sRoomDatabaseCallback===backup==start");
|
|
||||||
// if (INSTANCE != null) {
|
|
||||||
// //备份文件
|
|
||||||
// SQLiteDatabase sqlite = ((WCDBDatabase) INSTANCE.getOpenHelper().getWritableDatabase()).getInnerDatabase();
|
|
||||||
// BackupKit backup = new BackupKit(sqlite, // 要备份的 DB
|
|
||||||
// sqlite.getPath() + "-backup", // 备份文件
|
|
||||||
// "123456".getBytes(), // 加密备份文件的密钥,非 DB 密钥
|
|
||||||
// 0, null);
|
|
||||||
// int result = backup.run();
|
|
||||||
// switch (result) {
|
|
||||||
// case BackupKit.RESULT_OK:
|
|
||||||
// /* 成功 */
|
|
||||||
// Log.e("qj", "sRoomDatabaseCallback==成功");
|
|
||||||
// return true;
|
|
||||||
// case BackupKit.RESULT_CANCELED:
|
|
||||||
// /* 取消操作 */
|
|
||||||
// Log.e("qj", "sRoomDatabaseCallback==取消操作");
|
|
||||||
// break;
|
|
||||||
// case BackupKit.RESULT_FAILED:
|
|
||||||
// /* 失败 */
|
|
||||||
// Log.e("qj", "sRoomDatabaseCallback==失败");
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// backup.release();
|
|
||||||
// }
|
|
||||||
// Log.e("qj", "sRoomDatabaseCallback===backup==end");
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// protected void release() {
|
|
||||||
// INSTANCE = null;
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -1,21 +1,28 @@
|
|||||||
package com.navinfo.volvo.database.dao
|
package com.navinfo.volvo.database.dao
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.paging.PagingSource
|
import androidx.paging.PagingSource
|
||||||
import androidx.room.*
|
import androidx.room.*
|
||||||
|
import com.navinfo.volvo.Constant
|
||||||
import com.navinfo.volvo.database.entity.GreetingMessage
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface GreetingMessageDao {
|
interface GreetingMessageDao {
|
||||||
|
|
||||||
|
@Query("DELETE from GreetingMessage WHERE id=:id")
|
||||||
|
suspend fun deleteById(id: Long)
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
fun insert(message: GreetingMessage): Long
|
suspend fun insert(message: GreetingMessage): Long
|
||||||
|
|
||||||
@Update(onConflict = OnConflictStrategy.REPLACE)
|
@Update(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun update(message: GreetingMessage)
|
suspend fun update(message: GreetingMessage)
|
||||||
|
|
||||||
|
/**
|
||||||
@Query("SELECT count(id) FROM GreetingMessage WHERE read = 0")
|
* 未读消息统计
|
||||||
|
*/
|
||||||
|
@Query("SELECT count(id) FROM GreetingMessage WHERE status = '${Constant.message_status_late}'")
|
||||||
fun countUnreadByFlow(): Flow<Long>
|
fun countUnreadByFlow(): Flow<Long>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,18 +34,29 @@ interface GreetingMessageDao {
|
|||||||
/**
|
/**
|
||||||
* 检查某条数据是否存在
|
* 检查某条数据是否存在
|
||||||
*/
|
*/
|
||||||
@Query("SELECT id From GreetingMessage WHERE id = :id LIMIT 1")
|
@Query("SELECT uuid From GreetingMessage WHERE id = :id LIMIT 1")
|
||||||
fun getMessageId(id: Long): Long
|
suspend fun getMessageId(id: Long): Long?
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Transaction
|
@Transaction
|
||||||
suspend fun insertOrUpdate(list: List<GreetingMessage>) {
|
suspend fun insertOrUpdate(list: List<GreetingMessage>) {
|
||||||
for (message in list) {
|
for (message in list) {
|
||||||
val id = getMessageId(message.id)
|
Log.e("jingo", "insertOrUpdate ${message.id}")
|
||||||
if (id == 0L) {
|
val uuid = getMessageId(message.id)
|
||||||
insert(message)
|
Log.e("jingo", "insertOrUpdate $uuid")
|
||||||
}else{
|
if (uuid == null || uuid == 0L) {
|
||||||
|
Log.e("jingo", "insertOrUpdate start ")
|
||||||
|
val l = insert(message)
|
||||||
|
Log.e("jingo", "insertOrUpdate $l ")
|
||||||
|
} else {
|
||||||
|
message.uuid = uuid
|
||||||
update(message)
|
update(message)
|
||||||
}
|
}
|
||||||
|
Log.e("jingo", "insertOrUpdate end")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -22,6 +22,7 @@ import javax.inject.Singleton
|
|||||||
@Module
|
@Module
|
||||||
class NetworkUtilModule {
|
class NetworkUtilModule {
|
||||||
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideContext(application: Application): Context {
|
fun provideContext(application: Application): Context {
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
package com.navinfo.volvo.di.module
|
package com.navinfo.volvo.di.module
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.navinfo.volvo.util.SharedPreferenceHelper
|
import androidx.datastore.core.DataStore
|
||||||
|
import androidx.datastore.core.DataStoreFactory
|
||||||
|
import androidx.datastore.core.Serializer
|
||||||
|
import androidx.datastore.dataStoreFile
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import androidx.datastore.preferences.preferencesDataStore
|
||||||
|
import com.navinfo.volvo.model.proto.LoginUser
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
@ -14,7 +20,12 @@ class UtilModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideSharedPreferencesHelper(context: Context): SharedPreferenceHelper {
|
fun provideLoginUserDataStore(
|
||||||
return SharedPreferenceHelper.getInstance(context)
|
context: Context,
|
||||||
}
|
serializer: Serializer<LoginUser>
|
||||||
|
): DataStore<LoginUser> = DataStoreFactory.create(
|
||||||
|
serializer = serializer,
|
||||||
|
produceFile = { context.dataStoreFile("login_user") }
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.navinfo.volvo.di.module
|
||||||
|
|
||||||
|
import androidx.datastore.core.Serializer
|
||||||
|
import com.navinfo.volvo.model.proto.LoginUser
|
||||||
|
import com.navinfo.volvo.model.proto.LoginUserSerializer
|
||||||
|
import com.navinfo.volvo.repository.preferences.PreferencesRepository
|
||||||
|
import com.navinfo.volvo.repository.preferences.PreferencesRepositoryImp
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
@Module
|
||||||
|
abstract class UtilRepositoryModule {
|
||||||
|
@Binds
|
||||||
|
abstract fun providePreferencesRepository(preferencesRepositoryImp: PreferencesRepositoryImp): PreferencesRepository
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun userLocalSerializer(impl: LoginUserSerializer): Serializer<LoginUser>
|
||||||
|
}
|
@ -1,35 +1,35 @@
|
|||||||
package com.navinfo.volvo.di.module
|
//package com.navinfo.volvo.di.module
|
||||||
|
//
|
||||||
import androidx.lifecycle.ViewModel
|
//import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
//import androidx.lifecycle.ViewModelProvider
|
||||||
import javax.inject.Inject
|
//import javax.inject.Inject
|
||||||
import javax.inject.Provider
|
//import javax.inject.Provider
|
||||||
import javax.inject.Singleton
|
//import javax.inject.Singleton
|
||||||
|
//
|
||||||
|
//
|
||||||
/**
|
///**
|
||||||
* Factory for all ViewModels.
|
// * Factory for all ViewModels.
|
||||||
* reference : https://github.com/googlesamples/android-architecture-components
|
// * reference : https://github.com/googlesamples/android-architecture-components
|
||||||
*/
|
// */
|
||||||
@Singleton
|
//@Singleton
|
||||||
class ViewModelFactory @Inject constructor(
|
//class ViewModelFactory @Inject constructor(
|
||||||
private val viewModelMap: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
|
// private val viewModelMap: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
|
||||||
) : ViewModelProvider.Factory {
|
//) : ViewModelProvider.Factory {
|
||||||
|
//
|
||||||
@Suppress("UNCHECKED_CAST")
|
// @Suppress("UNCHECKED_CAST")
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
// override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||||
var viewModel = viewModelMap[modelClass]
|
// var viewModel = viewModelMap[modelClass]
|
||||||
|
//
|
||||||
if (viewModel == null) {
|
// if (viewModel == null) {
|
||||||
for (entry in viewModelMap) {
|
// for (entry in viewModelMap) {
|
||||||
if (modelClass.isAssignableFrom(entry.key)) {
|
// if (modelClass.isAssignableFrom(entry.key)) {
|
||||||
viewModel = entry.value
|
// viewModel = entry.value
|
||||||
break
|
// break
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (viewModel == null) throw IllegalArgumentException("Unknown model class $modelClass")
|
// if (viewModel == null) throw IllegalArgumentException("Unknown model class $modelClass")
|
||||||
return viewModel.get() as T
|
// return viewModel.get() as T
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
@ -1,44 +1,44 @@
|
|||||||
package com.navinfo.volvo.di.module
|
//package com.navinfo.volvo.di.module
|
||||||
|
//
|
||||||
import androidx.lifecycle.ViewModel
|
//import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
//import androidx.lifecycle.ViewModelProvider
|
||||||
import com.navinfo.volvo.di.key.ViewModelKey
|
//import com.navinfo.volvo.di.key.ViewModelKey
|
||||||
import com.navinfo.volvo.ui.MainActivityViewModel
|
//import com.navinfo.volvo.ui.MainActivityViewModel
|
||||||
import com.navinfo.volvo.ui.fragments.home.HomeViewModel
|
//import com.navinfo.volvo.ui.fragments.home.HomeViewModel
|
||||||
import com.navinfo.volvo.ui.fragments.login.LoginViewModel
|
//import com.navinfo.volvo.ui.fragments.login.LoginViewModel
|
||||||
import com.navinfo.volvo.ui.fragments.message.ObtainMessageViewModel
|
//import com.navinfo.volvo.ui.fragments.message.ObtainMessageViewModel
|
||||||
import dagger.Binds
|
//import dagger.Binds
|
||||||
import dagger.Module
|
//import dagger.Module
|
||||||
import dagger.hilt.InstallIn
|
//import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.components.SingletonComponent
|
//import dagger.hilt.components.SingletonComponent
|
||||||
import dagger.multibindings.IntoMap
|
//import dagger.multibindings.IntoMap
|
||||||
|
//
|
||||||
@InstallIn(SingletonComponent::class)
|
//@InstallIn(SingletonComponent::class)
|
||||||
@Module
|
//@Module
|
||||||
abstract class ViewModelModule {
|
//abstract class ViewModelModule {
|
||||||
|
//
|
||||||
@Binds
|
// @Binds
|
||||||
abstract fun bindViewModelFactory(viewModelFactory: ViewModelFactory): ViewModelProvider.Factory
|
// abstract fun bindViewModelFactory(viewModelFactory: ViewModelFactory): ViewModelProvider.Factory
|
||||||
|
//
|
||||||
@IntoMap
|
// @IntoMap
|
||||||
@Binds
|
// @Binds
|
||||||
@ViewModelKey(MainActivityViewModel::class)
|
// @ViewModelKey(MainActivityViewModel::class)
|
||||||
abstract fun bindMainViewModel(viewModel: MainActivityViewModel): ViewModel
|
// abstract fun bindMainViewModel(viewModel: MainActivityViewModel): ViewModel
|
||||||
|
//
|
||||||
@IntoMap
|
// @IntoMap
|
||||||
@Binds
|
// @Binds
|
||||||
@ViewModelKey(LoginViewModel::class)
|
// @ViewModelKey(LoginViewModel::class)
|
||||||
abstract fun bindLoginFragmentViewModel(viewModel: LoginViewModel): ViewModel
|
// abstract fun bindLoginFragmentViewModel(viewModel: LoginViewModel): ViewModel
|
||||||
|
//
|
||||||
@IntoMap
|
// @IntoMap
|
||||||
@Binds
|
// @Binds
|
||||||
@ViewModelKey(HomeViewModel::class)
|
// @ViewModelKey(HomeViewModel::class)
|
||||||
abstract fun bindMessageFragmentViewModel(viewModel: HomeViewModel): ViewModel
|
// abstract fun bindMessageFragmentViewModel(viewModel: HomeViewModel): ViewModel
|
||||||
|
//
|
||||||
@IntoMap
|
// @IntoMap
|
||||||
@Binds
|
// @Binds
|
||||||
@ViewModelKey(ObtainMessageViewModel::class)
|
// @ViewModelKey(ObtainMessageViewModel::class)
|
||||||
abstract fun bindObtainMessageFragmentViewModel(viewModel: ObtainMessageViewModel): ViewModel
|
// abstract fun bindObtainMessageFragmentViewModel(viewModel: ObtainMessageViewModel): ViewModel
|
||||||
|
//
|
||||||
|
//
|
||||||
}
|
//}
|
@ -1,9 +0,0 @@
|
|||||||
package com.navinfo.volvo.model
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 登录用户信息
|
|
||||||
*/
|
|
||||||
data class LoginUser(
|
|
||||||
var name: String,
|
|
||||||
var password: String
|
|
||||||
)
|
|
@ -1,8 +1,8 @@
|
|||||||
package com.navinfo.volvo.model.messagelist
|
package com.navinfo.volvo.model.network
|
||||||
|
|
||||||
import com.navinfo.volvo.database.entity.GreetingMessage
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
|
|
||||||
data class NetworkMessageListResponse(
|
data class NetworkMessageListResponse(
|
||||||
val total: Int,
|
val total: Int,
|
||||||
val rows: List<GreetingMessage>
|
val rows: List<GreetingMessage>?
|
||||||
)
|
)
|
@ -1,4 +1,4 @@
|
|||||||
package com.navinfo.volvo.model.messagelist
|
package com.navinfo.volvo.model.network
|
||||||
|
|
||||||
data class NetworkMessageListPost(
|
data class NetworkMessageListPost(
|
||||||
val name: String,//问候名称,非必填项
|
val name: String,//问候名称,非必填项
|
||||||
@ -13,3 +13,7 @@ data class NetworkMessageListPost(
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class NetworkDeleteMessagePost(
|
||||||
|
val id: Long
|
||||||
|
)
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.navinfo.volvo.model.proto
|
||||||
|
|
||||||
|
import androidx.datastore.core.CorruptionException
|
||||||
|
import androidx.datastore.core.Serializer
|
||||||
|
import androidx.datastore.preferences.protobuf.InvalidProtocolBufferException
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.io.OutputStream
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class LoginUserSerializer @Inject constructor(): Serializer<LoginUser> {
|
||||||
|
override val defaultValue: LoginUser = LoginUser.getDefaultInstance()
|
||||||
|
|
||||||
|
override suspend fun readFrom(input: InputStream): LoginUser {
|
||||||
|
try {
|
||||||
|
return LoginUser.parseFrom(input)
|
||||||
|
} catch (exception: InvalidProtocolBufferException) {
|
||||||
|
throw CorruptionException("Cannot read proto.", exception)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun writeTo(t: LoginUser, output: OutputStream) = t.writeTo(output)
|
||||||
|
}
|
@ -11,12 +11,14 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class DatabaseRepositoryImp @Inject constructor(
|
class DatabaseRepositoryImp @Inject constructor(
|
||||||
private val messageDao: GreetingMessageDao,
|
private val messageDao: GreetingMessageDao,
|
||||||
private val database: AppDatabase
|
|
||||||
) : DatabaseRepository {
|
) : DatabaseRepository {
|
||||||
companion object {
|
companion object {
|
||||||
const val PAGE_SIZE = 20
|
const val PAGE_SIZE = 20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页加载消息
|
||||||
|
*/
|
||||||
override fun getMessageByPaging(): Flow<PagingData<GreetingMessage>> {
|
override fun getMessageByPaging(): Flow<PagingData<GreetingMessage>> {
|
||||||
return Pager(PagingConfig(PAGE_SIZE)) {
|
return Pager(PagingConfig(PAGE_SIZE)) {
|
||||||
messageDao.findAllByDataSource()
|
messageDao.findAllByDataSource()
|
||||||
|
@ -1,13 +1,22 @@
|
|||||||
package com.navinfo.volvo.repository.network
|
package com.navinfo.volvo.repository.network
|
||||||
|
|
||||||
import com.navinfo.volvo.http.DefaultResponse
|
import com.navinfo.volvo.http.DefaultResponse
|
||||||
import com.navinfo.volvo.model.messagelist.NetworkMessageListPost
|
import com.navinfo.volvo.model.network.NetworkDeleteMessagePost
|
||||||
import com.navinfo.volvo.model.messagelist.NetworkMessageListResponse
|
import com.navinfo.volvo.model.network.NetworkMessageListPost
|
||||||
|
import com.navinfo.volvo.model.network.NetworkMessageListResponse
|
||||||
import com.navinfo.volvo.util.NetResult
|
import com.navinfo.volvo.util.NetResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 网络访问接口
|
* 网络访问接口
|
||||||
*/
|
*/
|
||||||
interface NetworkRepository {
|
interface NetworkRepository {
|
||||||
suspend fun getCardList(message: NetworkMessageListPost): NetResult<DefaultResponse<NetworkMessageListResponse>>
|
/**
|
||||||
|
* 获取问候列表
|
||||||
|
*/
|
||||||
|
suspend fun getMessageList(message: NetworkMessageListPost): NetResult<DefaultResponse<NetworkMessageListResponse>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
*删除问候
|
||||||
|
*/
|
||||||
|
suspend fun deleteMessage(message: NetworkDeleteMessagePost): NetResult<DefaultResponse<*>>
|
||||||
}
|
}
|
@ -1,11 +1,12 @@
|
|||||||
package com.navinfo.volvo.repository.network
|
package com.navinfo.volvo.repository.network
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
import com.navinfo.volvo.database.dao.GreetingMessageDao
|
import com.navinfo.volvo.database.dao.GreetingMessageDao
|
||||||
import com.navinfo.volvo.di.scope.IoDispatcher
|
import com.navinfo.volvo.di.scope.IoDispatcher
|
||||||
import com.navinfo.volvo.http.DefaultResponse
|
import com.navinfo.volvo.http.DefaultResponse
|
||||||
import com.navinfo.volvo.model.messagelist.NetworkMessageListPost
|
import com.navinfo.volvo.model.network.NetworkDeleteMessagePost
|
||||||
import com.navinfo.volvo.model.messagelist.NetworkMessageListResponse
|
import com.navinfo.volvo.model.network.NetworkMessageListPost
|
||||||
import com.navinfo.volvo.tools.GsonUtil
|
import com.navinfo.volvo.model.network.NetworkMessageListResponse
|
||||||
import com.navinfo.volvo.util.NetResult
|
import com.navinfo.volvo.util.NetResult
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@ -16,22 +17,47 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class NetworkRepositoryImp @Inject constructor(
|
class NetworkRepositoryImp @Inject constructor(
|
||||||
private val netWorkService: NetworkService,
|
private val netWorkService: NetworkService,
|
||||||
private val messageDao: GreetingMessageDao,
|
private val gson: Gson,
|
||||||
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
||||||
) : NetworkRepository {
|
) : NetworkRepository {
|
||||||
|
/**
|
||||||
override suspend fun getCardList(message: NetworkMessageListPost): NetResult<DefaultResponse<NetworkMessageListResponse>> =
|
* 获取问候列表
|
||||||
|
*/
|
||||||
|
override suspend fun getMessageList(message: NetworkMessageListPost): NetResult<DefaultResponse<NetworkMessageListResponse>> =
|
||||||
withContext(ioDispatcher) {
|
withContext(ioDispatcher) {
|
||||||
return@withContext try {
|
return@withContext try {
|
||||||
val stringBody = GsonUtil.getInstance().toJson(message)
|
val stringBody = gson.toJson(message)
|
||||||
.toRequestBody("application/json;charset=utf-8".toMediaType())
|
.toRequestBody("application/json;charset=utf-8".toMediaType())
|
||||||
val result = netWorkService.queryCardListByApp(stringBody)
|
val result = netWorkService.queryMessageListByApp(stringBody)
|
||||||
if (result.isSuccessful) {
|
if (result.isSuccessful) {
|
||||||
val body = result.body()
|
if (result.body()!!.code == 200) {
|
||||||
if(body!!.data != null && body.data!!.rows != null){
|
NetResult.Success(result.body())
|
||||||
messageDao.insertOrUpdate(body.data!!.rows)
|
} else {
|
||||||
|
NetResult.Failure(result.body()!!.code, result.body()!!.msg)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NetResult.Success(null)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
NetResult.Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除问候
|
||||||
|
*/
|
||||||
|
override suspend fun deleteMessage(message: NetworkDeleteMessagePost): NetResult<DefaultResponse<*>> =
|
||||||
|
withContext(ioDispatcher) {
|
||||||
|
return@withContext try {
|
||||||
|
val stringBody = gson.toJson(message)
|
||||||
|
.toRequestBody("application/json;charset=utf-8".toMediaType())
|
||||||
|
val result = netWorkService.deleteMessage(stringBody)
|
||||||
|
if (result.isSuccessful) {
|
||||||
|
if (result.body()!!.code == 200) {
|
||||||
|
NetResult.Success(result.body())
|
||||||
|
} else {
|
||||||
|
NetResult.Failure(result.body()!!.code, result.body()!!.msg)
|
||||||
}
|
}
|
||||||
NetResult.Success(body)
|
|
||||||
} else {
|
} else {
|
||||||
NetResult.Success(null)
|
NetResult.Success(null)
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,23 @@
|
|||||||
package com.navinfo.volvo.repository.network
|
package com.navinfo.volvo.repository.network
|
||||||
|
|
||||||
import com.navinfo.volvo.http.DefaultResponse
|
import com.navinfo.volvo.http.DefaultResponse
|
||||||
import com.navinfo.volvo.model.messagelist.NetworkMessageListResponse
|
import com.navinfo.volvo.model.network.NetworkMessageListResponse
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.POST
|
import retrofit2.http.POST
|
||||||
|
|
||||||
interface NetworkService {
|
interface NetworkService {
|
||||||
|
/**
|
||||||
|
* 获取问候列表
|
||||||
|
*/
|
||||||
@POST("/navi/cardDelivery/queryCardListByApp")
|
@POST("/navi/cardDelivery/queryCardListByApp")
|
||||||
suspend fun queryCardListByApp(@Body body: RequestBody): Response<DefaultResponse<NetworkMessageListResponse>>
|
suspend fun queryMessageListByApp(@Body body: RequestBody): Response<DefaultResponse<NetworkMessageListResponse>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除问候
|
||||||
|
*/
|
||||||
|
@POST("/navi/cardDelivery/deleteCardByApp")
|
||||||
|
suspend fun deleteMessage(@Body body: RequestBody): Response<DefaultResponse<*>>
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.navinfo.volvo.repository.preferences
|
||||||
|
|
||||||
|
import com.navinfo.volvo.model.proto.LoginUser
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库操作接口
|
||||||
|
*/
|
||||||
|
interface PreferencesRepository {
|
||||||
|
suspend fun saveLoginUser(id: String, name: String, password: String)
|
||||||
|
fun loginUser(): Flow<LoginUser?>
|
||||||
|
suspend fun saveString(key: String, content: String)
|
||||||
|
suspend fun getString(key: String): Flow<String?>
|
||||||
|
suspend fun saveInt(key: String, content: Int)
|
||||||
|
suspend fun getInt(key: String): Flow<Int?>
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.navinfo.volvo.repository.preferences
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.datastore.core.DataStore
|
||||||
|
import androidx.datastore.preferences.core.Preferences
|
||||||
|
import androidx.datastore.preferences.core.edit
|
||||||
|
import androidx.datastore.preferences.core.intPreferencesKey
|
||||||
|
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||||
|
import androidx.datastore.preferences.preferencesDataStore
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.navinfo.volvo.model.proto.LoginUser
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
|
const val DataStore_NAME = "ShardPreferences"
|
||||||
|
val Context.datastore: DataStore<Preferences> by preferencesDataStore(name = DataStore_NAME)
|
||||||
|
|
||||||
|
class PreferencesRepositoryImp @Inject constructor(
|
||||||
|
private val context: Context,
|
||||||
|
private val loginUser: DataStore<LoginUser>
|
||||||
|
) : PreferencesRepository {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val NAME = stringPreferencesKey("NAME")
|
||||||
|
val PHONE_NUMBER = stringPreferencesKey("PHONE")
|
||||||
|
val address = stringPreferencesKey("ADDRESS")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun saveLoginUser(id: String, name: String, password: String) {
|
||||||
|
loginUser.updateData { preference ->
|
||||||
|
preference.toBuilder().setUsername(name).setPassword(password).build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun saveString(key: String, content: String) {
|
||||||
|
context.datastore.edit {
|
||||||
|
it[stringPreferencesKey(key)] = content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getString(key: String): Flow<String?> = context.datastore.data.map {
|
||||||
|
it[stringPreferencesKey(key)]
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun saveInt(key: String, content: Int) {
|
||||||
|
context.datastore.edit {
|
||||||
|
it[intPreferencesKey(key)] = content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getInt(key: String): Flow<Int?> = context.datastore.data.map {
|
||||||
|
it[intPreferencesKey(key)]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loginUser(): Flow<LoginUser?> = loginUser.data
|
||||||
|
|
||||||
|
}
|
@ -6,6 +6,6 @@ import androidx.lifecycle.ViewModelProvider
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
abstract class BaseActivity : AppCompatActivity() {
|
abstract class BaseActivity : AppCompatActivity() {
|
||||||
@Inject
|
// @Inject
|
||||||
lateinit var viewModelFactoryProvider: ViewModelProvider.Factory
|
// lateinit var viewModelFactoryProvider: ViewModelProvider.Factory
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
package com.navinfo.volvo.ui
|
package com.navinfo.volvo.ui
|
||||||
|
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
@ -11,6 +11,9 @@ import androidx.navigation.findNavController
|
|||||||
import androidx.navigation.ui.AppBarConfiguration
|
import androidx.navigation.ui.AppBarConfiguration
|
||||||
import androidx.navigation.ui.setupActionBarWithNavController
|
import androidx.navigation.ui.setupActionBarWithNavController
|
||||||
import androidx.navigation.ui.setupWithNavController
|
import androidx.navigation.ui.setupWithNavController
|
||||||
|
import androidx.transition.Slide
|
||||||
|
import androidx.transition.Transition
|
||||||
|
import androidx.transition.TransitionManager
|
||||||
import com.easytools.tools.FileUtils
|
import com.easytools.tools.FileUtils
|
||||||
import com.elvishew.xlog.BuildConfig
|
import com.elvishew.xlog.BuildConfig
|
||||||
import com.elvishew.xlog.LogConfiguration
|
import com.elvishew.xlog.LogConfiguration
|
||||||
@ -30,16 +33,17 @@ import com.hjq.permissions.Permission
|
|||||||
import com.hjq.permissions.XXPermissions
|
import com.hjq.permissions.XXPermissions
|
||||||
import com.navinfo.volvo.R
|
import com.navinfo.volvo.R
|
||||||
import com.navinfo.volvo.databinding.ActivityMainBinding
|
import com.navinfo.volvo.databinding.ActivityMainBinding
|
||||||
import com.navinfo.volvo.ui.message.MessageActivity
|
|
||||||
import com.navinfo.volvo.utils.SystemConstant
|
import com.navinfo.volvo.utils.SystemConstant
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : BaseActivity() {
|
class MainActivity : BaseActivity() {
|
||||||
|
|
||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
private val viewModel by viewModels<MainActivityViewModel> { viewModelFactoryProvider }
|
private val viewModel by viewModels<MainActivityViewModel>()
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -47,7 +51,6 @@ class MainActivity : BaseActivity() {
|
|||||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
|
||||||
XXPermissions.with(this)
|
XXPermissions.with(this)
|
||||||
// 申请单个权限
|
// 申请单个权限
|
||||||
.permission(Permission.WRITE_EXTERNAL_STORAGE)
|
.permission(Permission.WRITE_EXTERNAL_STORAGE)
|
||||||
@ -98,7 +101,6 @@ class MainActivity : BaseActivity() {
|
|||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
viewModel.getUnreadCount().collect {
|
viewModel.getUnreadCount().collect {
|
||||||
runOnUiThread {
|
|
||||||
if (it == 0L) {
|
if (it == 0L) {
|
||||||
navView.removeBadge(R.id.navigation_home)
|
navView.removeBadge(R.id.navigation_home)
|
||||||
} else {
|
} else {
|
||||||
@ -107,19 +109,21 @@ class MainActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
navController.addOnDestinationChangedListener { controller, destination, arguments ->
|
navController.addOnDestinationChangedListener { controller, destination, arguments ->
|
||||||
if (destination.id == R.id.navigation_home
|
if (destination.id == R.id.navigation_home || destination.id == R.id.navigation_dashboard || destination.id == R.id.navigation_notifications) {
|
||||||
|| destination.id == R.id.navigation_dashboard
|
|
||||||
|| destination.id == R.id.navigation_notifications
|
|
||||||
) {
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
|
val transition: Transition = Slide(Gravity.BOTTOM)
|
||||||
|
transition.duration = 300;
|
||||||
|
TransitionManager.beginDelayedTransition(binding.root, transition);
|
||||||
navView.visibility = View.VISIBLE
|
navView.visibility = View.VISIBLE
|
||||||
newMessageView.visibility = View.VISIBLE
|
newMessageView.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
|
val transition: Transition = Slide(Gravity.BOTTOM)
|
||||||
|
transition.duration = 300;
|
||||||
|
TransitionManager.beginDelayedTransition(binding.root, transition);
|
||||||
navView.visibility = View.GONE
|
navView.visibility = View.GONE
|
||||||
newMessageView.visibility = View.GONE
|
newMessageView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
@ -132,6 +136,7 @@ class MainActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onSupportNavigateUp() =
|
override fun onSupportNavigateUp() =
|
||||||
findNavController(R.id.nav_host_fragment_activity_main).navigateUp()
|
findNavController(R.id.nav_host_fragment_activity_main).navigateUp()
|
||||||
|
|
||||||
@ -151,13 +156,10 @@ class MainActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun xLogInit(logFolder: String) {
|
fun xLogInit(logFolder: String) {
|
||||||
val config = LogConfiguration.Builder()
|
val config = LogConfiguration.Builder().logLevel(
|
||||||
.logLevel(
|
if (BuildConfig.DEBUG) LogLevel.ALL // 指定日志级别,低于该级别的日志将不会被打印,默认为 LogLevel.ALL
|
||||||
if (BuildConfig.DEBUG)
|
|
||||||
LogLevel.ALL // 指定日志级别,低于该级别的日志将不会被打印,默认为 LogLevel.ALL
|
|
||||||
else LogLevel.NONE
|
else LogLevel.NONE
|
||||||
)
|
).tag("Volvo") // 指定 TAG,默认为 "X-LOG"
|
||||||
.tag("Volvo") // 指定 TAG,默认为 "X-LOG"
|
|
||||||
.enableThreadInfo() // 允许打印线程信息,默认禁止
|
.enableThreadInfo() // 允许打印线程信息,默认禁止
|
||||||
.enableStackTrace(2) // 允许打印深度为 2 的调用栈信息,默认禁止
|
.enableStackTrace(2) // 允许打印深度为 2 的调用栈信息,默认禁止
|
||||||
.enableBorder() // 允许打印日志边框,默认禁止
|
.enableBorder() // 允许打印日志边框,默认禁止
|
||||||
@ -165,8 +167,7 @@ class MainActivity : BaseActivity() {
|
|||||||
BlacklistTagsFilterInterceptor( // 添加黑名单 TAG 过滤器
|
BlacklistTagsFilterInterceptor( // 添加黑名单 TAG 过滤器
|
||||||
"blacklist1", "blacklist2", "blacklist3"
|
"blacklist1", "blacklist2", "blacklist3"
|
||||||
)
|
)
|
||||||
)
|
).build()
|
||||||
.build()
|
|
||||||
|
|
||||||
val androidPrinter: Printer = AndroidPrinter(true) // 通过 android.util.Log 打印日志的打印器
|
val androidPrinter: Printer = AndroidPrinter(true) // 通过 android.util.Log 打印日志的打印器
|
||||||
|
|
||||||
@ -181,8 +182,7 @@ class MainActivity : BaseActivity() {
|
|||||||
XLog.init( // 初始化 XLog
|
XLog.init( // 初始化 XLog
|
||||||
config, // 指定日志配置,如果不指定,会默认使用 new LogConfiguration.Builder().build()
|
config, // 指定日志配置,如果不指定,会默认使用 new LogConfiguration.Builder().build()
|
||||||
androidPrinter, // 添加任意多的打印器。如果没有添加任何打印器,会默认使用 AndroidPrinter(Android)/ConsolePrinter(java)
|
androidPrinter, // 添加任意多的打印器。如果没有添加任何打印器,会默认使用 AndroidPrinter(Android)/ConsolePrinter(java)
|
||||||
consolePrinter,
|
consolePrinter, filePrinter
|
||||||
filePrinter
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,14 +190,11 @@ class MainActivity : BaseActivity() {
|
|||||||
fun showRationaleForSDCard(permissions: MutableList<String>) {
|
fun showRationaleForSDCard(permissions: MutableList<String>) {
|
||||||
// showRationaleDialog(R.string.permission_camera_rationale, request)
|
// showRationaleDialog(R.string.permission_camera_rationale, request)
|
||||||
// Toast.makeText(context, "当前操作需要您授权相机权限!", Toast.LENGTH_SHORT).show()
|
// Toast.makeText(context, "当前操作需要您授权相机权限!", Toast.LENGTH_SHORT).show()
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(this).setTitle("提示").setMessage("当前操作需要您授权读写SD卡权限!")
|
||||||
.setTitle("提示")
|
|
||||||
.setMessage("当前操作需要您授权读写SD卡权限!")
|
|
||||||
.setPositiveButton("确定", DialogInterface.OnClickListener { dialogInterface, i ->
|
.setPositiveButton("确定", DialogInterface.OnClickListener { dialogInterface, i ->
|
||||||
dialogInterface.dismiss()
|
dialogInterface.dismiss()
|
||||||
XXPermissions.startPermissionActivity(this@MainActivity, permissions)
|
XXPermissions.startPermissionActivity(this@MainActivity, permissions)
|
||||||
})
|
}).show()
|
||||||
.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @OnPermissionDenied(Manifest.permission.MANAGE_EXTERNAL_STORAGE)
|
// @OnPermissionDenied(Manifest.permission.MANAGE_EXTERNAL_STORAGE)
|
||||||
|
@ -4,9 +4,12 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.paging.PagingData
|
import androidx.paging.PagingData
|
||||||
import com.navinfo.volvo.database.dao.GreetingMessageDao
|
import com.navinfo.volvo.database.dao.GreetingMessageDao
|
||||||
import com.navinfo.volvo.database.entity.GreetingMessage
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
class MainActivityViewModel @Inject constructor(
|
class MainActivityViewModel @Inject constructor(
|
||||||
private val messageDao: GreetingMessageDao,
|
private val messageDao: GreetingMessageDao,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
@ -5,6 +5,6 @@ import androidx.lifecycle.ViewModelProvider
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
abstract class BaseFragment : Fragment() {
|
abstract class BaseFragment : Fragment() {
|
||||||
@Inject
|
// @Inject
|
||||||
lateinit var viewModelFactoryProvider: ViewModelProvider.Factory
|
// lateinit var viewModelFactoryProvider: ViewModelProvider.Factory
|
||||||
}
|
}
|
@ -19,23 +19,11 @@ class HomeAdapter(fragment: Fragment) :
|
|||||||
PagingDataAdapter<GreetingMessage, HomeAdapter.MyViewHolder>(DiffCallback()) {
|
PagingDataAdapter<GreetingMessage, HomeAdapter.MyViewHolder>(DiffCallback()) {
|
||||||
|
|
||||||
val fragment = fragment
|
val fragment = fragment
|
||||||
// var itemList = ArrayList<GreetingMessage>()
|
|
||||||
//
|
|
||||||
// fun addItem(message: GreetingMessage) {
|
|
||||||
// itemList.add(message)
|
|
||||||
// notifyItemInserted(itemList.size - 1)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun setItems(messageList: List<GreetingMessage>) {
|
|
||||||
// itemList.clear()
|
|
||||||
// itemList.addAll(messageList)
|
|
||||||
// notifyDataSetChanged()
|
|
||||||
// }
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
||||||
val mDataBinding: AdapterHomeBinding =
|
val mDataBinding: AdapterHomeBinding =
|
||||||
DataBindingUtil.inflate(
|
DataBindingUtil.inflate(
|
||||||
LayoutInflater.from(fragment.context),
|
LayoutInflater.from(parent.context),
|
||||||
R.layout.adapter_home,
|
R.layout.adapter_home,
|
||||||
parent,
|
parent,
|
||||||
false
|
false
|
||||||
@ -47,9 +35,11 @@ class HomeAdapter(fragment: Fragment) :
|
|||||||
holder.onBind(position)
|
holder.onBind(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
// override fun getItemCount(): Int {
|
|
||||||
// return itemList.size
|
fun getItemData(position: Int): GreetingMessage {
|
||||||
// }
|
return getItem(position)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inner class MyViewHolder(private val mDataBinding: AdapterHomeBinding) :
|
inner class MyViewHolder(private val mDataBinding: AdapterHomeBinding) :
|
||||||
RecyclerView.ViewHolder(mDataBinding.root) {
|
RecyclerView.ViewHolder(mDataBinding.root) {
|
||||||
@ -63,12 +53,11 @@ class HomeAdapter(fragment: Fragment) :
|
|||||||
.error(R.mipmap.volvo_logo_small)
|
.error(R.mipmap.volvo_logo_small)
|
||||||
.into(mDataBinding.messageHeadIcon)
|
.into(mDataBinding.messageHeadIcon)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DiffCallback : DiffUtil.ItemCallback<GreetingMessage>() {
|
class DiffCallback : DiffUtil.ItemCallback<GreetingMessage>() {
|
||||||
override fun areItemsTheSame(oldItem: GreetingMessage, newItem: GreetingMessage): Boolean {
|
override fun areItemsTheSame(oldItem: GreetingMessage, newItem: GreetingMessage): Boolean {
|
||||||
return oldItem.uuid == newItem.uuid
|
return oldItem.uuid == newItem.uuid && oldItem.status == newItem.status
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun areContentsTheSame(
|
override fun areContentsTheSame(
|
||||||
|
@ -1,96 +1,172 @@
|
|||||||
package com.navinfo.volvo.ui.fragments.home
|
package com.navinfo.volvo.ui.fragments.home
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.databinding.DataBindingUtil
|
import android.widget.Toast
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.paging.LoadState
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.easytools.tools.ThreadPoolUtils.runOnUiThread
|
||||||
import com.navinfo.volvo.R
|
import com.navinfo.volvo.R
|
||||||
import com.navinfo.volvo.databinding.FragmentHomeBinding
|
import com.navinfo.volvo.databinding.FragmentHomeBinding
|
||||||
|
import com.navinfo.volvo.databinding.HomeAdapterNotingBinding
|
||||||
|
import com.navinfo.volvo.databinding.LoadStateViewBinding
|
||||||
import com.navinfo.volvo.tools.DisplayUtil
|
import com.navinfo.volvo.tools.DisplayUtil
|
||||||
import com.navinfo.volvo.ui.fragments.BaseFragment
|
import com.navinfo.volvo.ui.fragments.BaseFragment
|
||||||
import com.yanzhenjie.recyclerview.*
|
import com.yanzhenjie.recyclerview.*
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class HomeFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListener {
|
class HomeFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListener {
|
||||||
|
|
||||||
private var _binding: FragmentHomeBinding? = null
|
private var _binding: FragmentHomeBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and
|
||||||
// onDestroyView.
|
// onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private val viewModel by viewModels<HomeViewModel> { viewModelFactoryProvider }
|
private val viewModel by viewModels<HomeViewModel>()
|
||||||
|
|
||||||
private lateinit var messageAdapter: HomeAdapter
|
|
||||||
|
|
||||||
|
private val messageAdapter by lazy { HomeAdapter(this) }
|
||||||
|
private var headBinding: HomeAdapterNotingBinding? = null
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View {
|
): View {
|
||||||
_binding = FragmentHomeBinding.inflate(inflater, container, false)
|
_binding = FragmentHomeBinding.inflate(inflater, container, false)
|
||||||
val root: View = binding.root
|
val root: View = binding.root
|
||||||
|
|
||||||
|
headBinding = HomeAdapterNotingBinding.inflate(inflater, container, false)
|
||||||
initView()
|
initView()
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initView() {
|
private fun initView() {
|
||||||
// mDataBinding.homeViewModel = viewModel
|
|
||||||
messageAdapter = HomeAdapter(this)
|
|
||||||
val recyclerview: SwipeRecyclerView = binding.homeRecyclerview
|
|
||||||
recyclerview.adapter = null //先设置null,否则会报错
|
|
||||||
//创建菜单选项
|
//创建菜单选项
|
||||||
//注意:使用滑动菜单不能开启滑动删除,否则只有滑动删除没有滑动菜单
|
//注意:使用滑动菜单不能开启滑动删除,否则只有滑动删除没有滑动菜单
|
||||||
var mSwipeMenuCreator =
|
var mSwipeMenuCreator = SwipeMenuCreator { _, rightMenu, _ ->
|
||||||
SwipeMenuCreator { _, rightMenu, position ->
|
|
||||||
//添加菜单自动添加至尾部
|
//添加菜单自动添加至尾部
|
||||||
var deleteItem = SwipeMenuItem(context)
|
var deleteItem = SwipeMenuItem(context)
|
||||||
deleteItem.height = DisplayUtil.dip2px(context!!, 60f)
|
deleteItem.height = DisplayUtil.dip2px(requireContext(), 60f)
|
||||||
deleteItem.width = DisplayUtil.dip2px(context!!, 80f)
|
deleteItem.width = DisplayUtil.dip2px(requireContext(), 80f)
|
||||||
deleteItem.background = context!!.getDrawable(R.color.red)
|
deleteItem.background = requireContext().getDrawable(R.color.red)
|
||||||
deleteItem.text = context!!.getString(R.string.delete)
|
deleteItem.text = requireContext().getString(R.string.delete)
|
||||||
rightMenu.addMenuItem(deleteItem)
|
rightMenu.addMenuItem(deleteItem)
|
||||||
|
|
||||||
//分享
|
//分享
|
||||||
var shareItem = SwipeMenuItem(context)
|
var shareItem = SwipeMenuItem(context)
|
||||||
shareItem.height = DisplayUtil.dip2px(context!!, 60f)
|
shareItem.height = DisplayUtil.dip2px(requireContext(), 60f)
|
||||||
shareItem.width = DisplayUtil.dip2px(context!!, 80f)
|
shareItem.width = DisplayUtil.dip2px(requireContext(), 80f)
|
||||||
shareItem.background = context!!.getDrawable(R.color.gray)
|
shareItem.background = requireContext().getDrawable(R.color.gray)
|
||||||
shareItem.text = context!!.getString(R.string.share)
|
shareItem.text = requireContext().getString(R.string.share)
|
||||||
shareItem.setTextColor(R.color.white)
|
shareItem.setTextColor(requireContext().getColor(R.color.white))
|
||||||
rightMenu.addMenuItem(shareItem)
|
rightMenu.addMenuItem(shareItem)
|
||||||
}
|
}
|
||||||
val layoutManager = LinearLayoutManager(context)
|
//侧滑按钮
|
||||||
|
binding.homeRecyclerview.setOnItemMenuClickListener { menuBridge, position ->
|
||||||
|
menuBridge.closeMenu()
|
||||||
|
// val direction: Int = menuBridge.getDirection() // 左侧还是右侧菜单。
|
||||||
|
|
||||||
recyclerview.layoutManager = layoutManager
|
when (menuBridge.position) {// 菜单在RecyclerView的Item中的Position。
|
||||||
recyclerview.addItemDecoration(DividerItemDecoration(context, layoutManager.orientation))
|
0 -> {//删除按钮
|
||||||
recyclerview.setSwipeMenuCreator(mSwipeMenuCreator)
|
viewModel.deleteMessage(messageAdapter.getItemData(position).id)
|
||||||
recyclerview.setOnItemClickListener(this)
|
}
|
||||||
// recyclerview.useDefaultLoadMore()
|
1 -> {//分享按钮
|
||||||
// recyclerview.setLoadMoreListener {
|
}
|
||||||
//
|
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val layoutManager = LinearLayoutManager(context)
|
||||||
|
binding.homeRecyclerview.layoutManager = layoutManager
|
||||||
|
//自动增加分割线
|
||||||
|
binding.homeRecyclerview.addItemDecoration(
|
||||||
|
DividerItemDecoration(
|
||||||
|
context, layoutManager.orientation
|
||||||
|
)
|
||||||
|
)
|
||||||
|
//增加侧滑按钮
|
||||||
|
binding.homeRecyclerview.setSwipeMenuCreator(mSwipeMenuCreator)
|
||||||
|
//单项点击
|
||||||
|
binding.homeRecyclerview.setOnItemClickListener(this)
|
||||||
|
//使用下拉加载
|
||||||
|
// binding.homeRecyclerview.useDefaultLoadMore() // 使用默认的加载更多的View。
|
||||||
|
|
||||||
|
binding.homeRecyclerview.setLoadMoreListener {
|
||||||
|
Log.e("jingo", "下拉加载开始")
|
||||||
|
|
||||||
|
} // 加载更多的监听。
|
||||||
|
|
||||||
|
//开始下拉刷新
|
||||||
|
binding.homeSwipeRefreshLayout.setOnRefreshListener {
|
||||||
|
Log.e("jingo", "开始刷新")
|
||||||
|
viewModel.getNetMessageList()
|
||||||
|
}
|
||||||
|
|
||||||
|
//列表自动分页
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
viewModel.messageList.collectLatest {
|
viewModel.messageList.collect {
|
||||||
messageAdapter.submitData(it)
|
messageAdapter.submitData(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// messageAdapter.withLoadStateFooter(
|
binding.homeRecyclerview.adapter = messageAdapter
|
||||||
// footer = RecLoadStateAdapter { messageAdapter.retry() }
|
|
||||||
// )
|
//初始状态添加监听
|
||||||
|
messageAdapter.addLoadStateListener {
|
||||||
|
when (it.refresh) {
|
||||||
|
is LoadState.NotLoading -> {
|
||||||
|
if (messageAdapter.itemCount == 0)
|
||||||
|
binding.homeRecyclerview.addHeaderView(headBinding!!.root)
|
||||||
|
else{
|
||||||
|
binding.homeRecyclerview.removeHeaderView(headBinding!!.root)
|
||||||
|
}
|
||||||
|
Log.d("jingo", "is NotLoading")
|
||||||
|
}
|
||||||
|
is LoadState.Loading -> {
|
||||||
|
Log.d("jingo", "is Loading")
|
||||||
|
}
|
||||||
|
is LoadState.Error -> {
|
||||||
|
Log.d("jingo", "is Error:")
|
||||||
|
when ((it.refresh as LoadState.Error).error) {
|
||||||
|
is IOException -> {
|
||||||
|
Log.d("jingo", "IOException")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Log.d("jingo", "others exception")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadMoreFinish()
|
||||||
|
//监听数据请求是否结束
|
||||||
|
viewModel.isLoading.observe(viewLifecycleOwner, Observer {
|
||||||
|
if (!it) loadMoreFinish()
|
||||||
|
})
|
||||||
|
|
||||||
// messageAdapter.withLoadStateHeader()
|
|
||||||
recyclerview.adapter = messageAdapter
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadMoreFinish() {
|
||||||
|
binding.homeSwipeRefreshLayout.isRefreshing = false
|
||||||
|
|
||||||
|
// 第一次加载数据:一定要掉用这个方法。
|
||||||
|
// 第一个参数:表示此次数据是否为空,假如你请求到的list为空(== null || list.size == 0),那么这里就要true。
|
||||||
|
// 第二个参数:表示是否还有更多数据,根据服务器返回给你的page等信息判断是否还有更多,这样可以提供性能,如果不能判断则传true。
|
||||||
|
binding.homeRecyclerview.loadMoreFinish(false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
viewModel.getNetMessageList()
|
viewModel.getNetMessageList()
|
||||||
@ -100,6 +176,7 @@ class HomeFragment : BaseFragment(), OnItemClickListener, OnItemMenuClickListene
|
|||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
|
headBinding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemClick(view: View?, adapterPosition: Int) {
|
override fun onItemClick(view: View?, adapterPosition: Int) {
|
||||||
|
@ -1,49 +1,100 @@
|
|||||||
package com.navinfo.volvo.ui.fragments.home
|
package com.navinfo.volvo.ui.fragments.home
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.paging.PagingData
|
import androidx.paging.PagingData
|
||||||
import com.navinfo.volvo.database.dao.GreetingMessageDao
|
import com.navinfo.volvo.database.dao.GreetingMessageDao
|
||||||
import com.navinfo.volvo.database.entity.GreetingMessage
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
import com.navinfo.volvo.model.messagelist.NetworkMessageListPost
|
import com.navinfo.volvo.model.network.NetworkDeleteMessagePost
|
||||||
|
import com.navinfo.volvo.model.network.NetworkMessageListPost
|
||||||
import com.navinfo.volvo.repository.database.DatabaseRepository
|
import com.navinfo.volvo.repository.database.DatabaseRepository
|
||||||
import com.navinfo.volvo.repository.network.NetworkRepository
|
import com.navinfo.volvo.repository.network.NetworkRepository
|
||||||
|
import com.navinfo.volvo.repository.preferences.PreferencesRepository
|
||||||
import com.navinfo.volvo.util.NetResult
|
import com.navinfo.volvo.util.NetResult
|
||||||
import com.navinfo.volvo.util.asLiveData
|
import com.navinfo.volvo.util.asLiveData
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
class HomeViewModel @Inject constructor(
|
class HomeViewModel @Inject constructor(
|
||||||
|
private val application: Application,
|
||||||
private val netRepository: NetworkRepository,
|
private val netRepository: NetworkRepository,
|
||||||
private val dataRepository: DatabaseRepository
|
private val dataRepository: DatabaseRepository,
|
||||||
|
private val messageDao: GreetingMessageDao,
|
||||||
|
private val shard: PreferencesRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val _isLoading = MutableLiveData<Boolean>()
|
private val _isLoading = MutableLiveData<Boolean>()
|
||||||
val isLoading = _isLoading.asLiveData()
|
val isLoading = _isLoading.asLiveData()
|
||||||
|
|
||||||
|
|
||||||
// private val _messageList = MutableLiveData<List<GreetingMessage>>()
|
// private val _messageList = MutableLiveData<List<GreetingMessage>>()
|
||||||
// val messageList = _messageList.asLiveData()
|
// val messageList = _messageList.asLiveData()
|
||||||
|
|
||||||
|
|
||||||
val messageList: Flow<PagingData<GreetingMessage>>
|
val messageList: Flow<PagingData<GreetingMessage>>
|
||||||
get() = dataRepository.getMessageByPaging()
|
get() = dataRepository.getMessageByPaging()
|
||||||
|
|
||||||
|
lateinit var userName: String
|
||||||
|
|
||||||
fun getNetMessageList() {
|
init {
|
||||||
_isLoading.postValue(true)
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val messagePost = NetworkMessageListPost(who = "", toWho = "")
|
shard.loginUser().collect {
|
||||||
when (val result = netRepository.getCardList(messagePost)) {
|
userName = it!!.username
|
||||||
is NetResult.Success -> {
|
}
|
||||||
_isLoading.value = false
|
}
|
||||||
// if (result.data != null) {
|
|
||||||
// val list = (result.data.data as NetworkMessageListResponse).rows
|
|
||||||
// _messageList.value = list
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getNetMessageList() {
|
||||||
|
if (_isLoading.value == true)
|
||||||
|
return
|
||||||
|
_isLoading.postValue(true)
|
||||||
|
viewModelScope.launch {
|
||||||
|
val messagePost = NetworkMessageListPost(who = userName, toWho = "")
|
||||||
|
when (val result = netRepository.getMessageList(messagePost)) {
|
||||||
|
is NetResult.Success -> {
|
||||||
|
_isLoading.value = false
|
||||||
|
if ((result.data!!.data != null) && (result.data.data!!.rows != null)) {
|
||||||
|
messageDao.insertOrUpdate(result.data.data!!.rows!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is NetResult.Failure -> {
|
||||||
|
_isLoading.value = false
|
||||||
|
Toast.makeText(application, "${result.code}:${result.msg}", Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
is NetResult.Error -> {
|
||||||
|
_isLoading.value = false
|
||||||
|
}
|
||||||
|
is NetResult.Loading -> {
|
||||||
|
_isLoading.postValue(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteMessage(id: Long) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val post = NetworkDeleteMessagePost(id)
|
||||||
|
netRepository.deleteMessage(post)
|
||||||
|
messageDao.deleteById(id)
|
||||||
|
when (val result = netRepository.deleteMessage(post)) {
|
||||||
|
is NetResult.Success -> {
|
||||||
|
_isLoading.value = false
|
||||||
|
}
|
||||||
|
is NetResult.Failure -> {
|
||||||
|
_isLoading.value = false
|
||||||
|
Toast.makeText(
|
||||||
|
application,
|
||||||
|
"服务返回信息:${result.code}:${result.msg}",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
is NetResult.Error -> {
|
is NetResult.Error -> {
|
||||||
_isLoading.value = false
|
_isLoading.value = false
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.navinfo.volvo.ui.fragments.home
|
||||||
|
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.paging.LoadState
|
||||||
|
import androidx.paging.LoadStateAdapter
|
||||||
|
|
||||||
|
class LoadStateAdapter(private val retry: () -> Unit) :
|
||||||
|
LoadStateAdapter<LoadStateViewHolder>() {
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: LoadStateViewHolder, loadState: LoadState) {
|
||||||
|
holder.bindState(loadState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, loadState: LoadState): LoadStateViewHolder {
|
||||||
|
return LoadStateViewHolder(parent, retry)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.navinfo.volvo.ui.fragments.home
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.paging.LoadState
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.navinfo.volvo.R
|
||||||
|
import com.navinfo.volvo.databinding.LoadStateViewBinding
|
||||||
|
|
||||||
|
class LoadStateViewHolder(parent: ViewGroup, var retry: () -> Unit) : RecyclerView.ViewHolder(
|
||||||
|
LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.load_state_view, parent, false)
|
||||||
|
) {
|
||||||
|
|
||||||
|
var itemLoadStateBindingUtil: LoadStateViewBinding = LoadStateViewBinding.bind(itemView)
|
||||||
|
|
||||||
|
fun bindState(loadState: LoadState) {
|
||||||
|
when (loadState) {
|
||||||
|
is LoadState.Error -> {
|
||||||
|
itemLoadStateBindingUtil.loadStateLayout.visibility = View.VISIBLE
|
||||||
|
// itemLoadStateBindingUtil.btnRetry.setOnClickListener {
|
||||||
|
// retry()
|
||||||
|
// }
|
||||||
|
Log.d("jingo", "error了吧")
|
||||||
|
}
|
||||||
|
is LoadState.Loading -> {
|
||||||
|
itemLoadStateBindingUtil.loadStateLayout.visibility = View.VISIBLE
|
||||||
|
Log.d("jingo", "该显示了")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Log.d("jingo", "--其他的错误")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,51 +0,0 @@
|
|||||||
//package com.navinfo.volvo.ui.fragments.home
|
|
||||||
//
|
|
||||||
//import android.view.LayoutInflater
|
|
||||||
//import android.view.View
|
|
||||||
//import android.view.ViewGroup
|
|
||||||
//import androidx.core.view.isVisible
|
|
||||||
//import androidx.paging.LoadState
|
|
||||||
//import androidx.paging.LoadStateAdapter
|
|
||||||
//import androidx.recyclerview.widget.RecyclerView
|
|
||||||
//import com.example.picsapp.R
|
|
||||||
//import com.example.picsapp.databinding.LoadStateViewBinding
|
|
||||||
//
|
|
||||||
//class RecLoadStateAdapter(
|
|
||||||
// private val retry: () -> Unit
|
|
||||||
//) : LoadStateAdapter<RecLoadStateAdapter.LoadStateViewHolder>() {
|
|
||||||
//
|
|
||||||
// override fun onCreateViewHolder(parent: ViewGroup, loadState: LoadState): LoadStateViewHolder {
|
|
||||||
//
|
|
||||||
// val binding = LoadStateViewBinding
|
|
||||||
// .inflate(LayoutInflater.from(parent.context), parent, false)
|
|
||||||
//
|
|
||||||
// return LoadStateViewHolder(binding)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onBindViewHolder(holder: LoadStateViewHolder, loadState: LoadState) {
|
|
||||||
// holder.onBind(loadState)
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// inner class LoadStateViewHolder(private val binding: LoadStateViewBinding) : RecyclerView.ViewHolder(binding.root){
|
|
||||||
// fun onBind(loadState: LoadState) {
|
|
||||||
// val progress = binding.loadStateProgress
|
|
||||||
// val btnRetry = binding.loadStateRetry
|
|
||||||
// val txtErrorMessage = binding.loadStateErrorMessage
|
|
||||||
//
|
|
||||||
// btnRetry.isVisible = loadState !is LoadState.Loading
|
|
||||||
// txtErrorMessage.isVisible = loadState !is LoadState.Loading
|
|
||||||
// progress.isVisible = loadState is LoadState.Loading
|
|
||||||
//
|
|
||||||
// if (loadState is LoadState.Error){
|
|
||||||
// txtErrorMessage.text = loadState.error.localizedMessage
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// btnRetry.setOnClickListener {
|
|
||||||
// retry.invoke()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
@ -4,13 +4,18 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.navinfo.volvo.R
|
import com.navinfo.volvo.R
|
||||||
import com.navinfo.volvo.databinding.FragmentLoginBinding
|
import com.navinfo.volvo.databinding.FragmentLoginBinding
|
||||||
import com.navinfo.volvo.ui.fragments.BaseFragment
|
import com.navinfo.volvo.ui.fragments.BaseFragment
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -20,7 +25,7 @@ class LoginFragment : BaseFragment() {
|
|||||||
private lateinit var viewBinding: FragmentLoginBinding
|
private lateinit var viewBinding: FragmentLoginBinding
|
||||||
|
|
||||||
|
|
||||||
private val viewModel by viewModels<LoginViewModel> { viewModelFactoryProvider }
|
private val viewModel by viewModels<LoginViewModel>()
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
@ -34,11 +39,30 @@ class LoginFragment : BaseFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initView() {
|
private fun initView() {
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
viewModel.user.collect {
|
||||||
|
if (it != null){
|
||||||
|
viewBinding.loginUser = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
viewBinding.loginFragmentRegisterButton.setOnClickListener {
|
viewBinding.loginFragmentRegisterButton.setOnClickListener {
|
||||||
|
|
||||||
}
|
}
|
||||||
viewBinding.loginFragmentLoginButton.setOnClickListener {
|
viewBinding.loginFragmentLoginButton.setOnClickListener {
|
||||||
// viewModel.login(viewBinding.loginFragmentUserLayout)
|
if (viewBinding.loginUsername.text!!.isEmpty()) {
|
||||||
|
Toast.makeText(context, "请输入用户名", Toast.LENGTH_SHORT).show()
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
if (viewBinding.loginPassword.text!!.isEmpty()) {
|
||||||
|
Toast.makeText(context, "请输入密码", Toast.LENGTH_SHORT).show()
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
viewModel.onClickLogin(
|
||||||
|
viewBinding.loginUsername.text.toString(),
|
||||||
|
viewBinding.loginPassword.text.toString()
|
||||||
|
)
|
||||||
findNavController().navigate(R.id.action_login_to_home)
|
findNavController().navigate(R.id.action_login_to_home)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,29 @@
|
|||||||
package com.navinfo.volvo.ui.fragments.login
|
package com.navinfo.volvo.ui.fragments.login
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.navinfo.volvo.database.AppDatabase
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.navinfo.volvo.database.entity.User
|
import com.navinfo.volvo.repository.preferences.PreferencesRepository
|
||||||
import com.navinfo.volvo.util.SharedPreferenceHelper
|
import com.navinfo.volvo.util.asLiveData
|
||||||
|
//import com.navinfo.volvo.repository.preferences.PreferencesRepository
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LoginViewModel @Inject constructor(private val sharedPreferenceHelper: SharedPreferenceHelper) : ViewModel() {
|
@HiltViewModel
|
||||||
|
class LoginViewModel @Inject constructor(private val repository: PreferencesRepository) :
|
||||||
|
ViewModel() {
|
||||||
|
|
||||||
// val user: LiveData<User> = _user
|
val user = repository.loginUser()
|
||||||
|
|
||||||
fun liveDataOnclick(view: View) {
|
|
||||||
|
|
||||||
|
fun onClickLogin(name: String, password: String) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
repository.saveLoginUser(id = "", name = name, password = password)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun userRegister(username: String, password: String) {
|
fun onClickLoginRegister(username: String, password: String) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,7 +7,8 @@ import android.text.TextUtils
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.*
|
import android.view.View.GONE
|
||||||
|
import android.view.View.VISIBLE
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.AdapterView.OnItemSelectedListener
|
import android.widget.AdapterView.OnItemSelectedListener
|
||||||
@ -17,15 +18,11 @@ import android.widget.Toast
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.widget.addTextChangedListener
|
import androidx.core.widget.addTextChangedListener
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.navigation.Navigation
|
import androidx.navigation.Navigation
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.easytools.tools.DateUtils
|
import com.easytools.tools.*
|
||||||
import com.easytools.tools.DisplayUtils
|
|
||||||
import com.easytools.tools.FileIOUtils
|
|
||||||
import com.easytools.tools.ResourceUtils
|
|
||||||
import com.easytools.tools.ToastUtils
|
|
||||||
import com.elvishew.xlog.XLog
|
import com.elvishew.xlog.XLog
|
||||||
import com.github.file_picker.FileType
|
import com.github.file_picker.FileType
|
||||||
import com.github.file_picker.ListDirection
|
import com.github.file_picker.ListDirection
|
||||||
@ -52,6 +49,7 @@ import com.navinfo.volvo.util.PhotoLoader
|
|||||||
import com.navinfo.volvo.utils.EasyMediaFile
|
import com.navinfo.volvo.utils.EasyMediaFile
|
||||||
import com.navinfo.volvo.utils.SystemConstant
|
import com.navinfo.volvo.utils.SystemConstant
|
||||||
import com.nhaarman.supertooltips.ToolTip
|
import com.nhaarman.supertooltips.ToolTip
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import indi.liyi.viewer.Utils
|
import indi.liyi.viewer.Utils
|
||||||
import indi.liyi.viewer.ViewData
|
import indi.liyi.viewer.ViewData
|
||||||
import top.zibin.luban.Luban
|
import top.zibin.luban.Luban
|
||||||
@ -62,12 +60,10 @@ import java.util.*
|
|||||||
import kotlin.streams.toList
|
import kotlin.streams.toList
|
||||||
|
|
||||||
|
|
||||||
//@RuntimePermissions
|
@AndroidEntryPoint
|
||||||
class ObtainMessageFragment: Fragment() {
|
class ObtainMessageFragment : Fragment() {
|
||||||
private var _binding: FragmentObtainMessageBinding? = null
|
private var _binding: FragmentObtainMessageBinding? = null
|
||||||
private val obtainMessageViewModel by lazy {
|
private val obtainMessageViewModel by viewModels<ObtainMessageViewModel>()
|
||||||
ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java)
|
|
||||||
}
|
|
||||||
private val photoHelper by lazy {
|
private val photoHelper by lazy {
|
||||||
EasyMediaFile().setCrop(true)
|
EasyMediaFile().setCrop(true)
|
||||||
}
|
}
|
||||||
@ -91,18 +87,17 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
_binding = FragmentObtainMessageBinding.inflate(inflater, container, false)
|
_binding = FragmentObtainMessageBinding.inflate(inflater, container, false)
|
||||||
val root: View = binding.root
|
val root: View = binding.root
|
||||||
|
|
||||||
val greetingMessage = GreetingMessage()
|
obtainMessageViewModel.setCurrentMessage(GreetingMessage(who = obtainMessageViewModel.username))
|
||||||
obtainMessageViewModel.setCurrentMessage(greetingMessage)
|
|
||||||
|
|
||||||
obtainMessageViewModel?.getMessageLiveData()?.observe(
|
obtainMessageViewModel.getMessageLiveData().observe(
|
||||||
viewLifecycleOwner, Observer {
|
viewLifecycleOwner, Observer {
|
||||||
// 初始化界面显示内容
|
// 初始化界面显示内容
|
||||||
if(it.name?.isNotEmpty() == true)
|
if (it.name?.isNotEmpty() == true)
|
||||||
binding.tvMessageTitle?.setText(it.name)
|
binding.tvMessageTitle?.setText(it.name)
|
||||||
if (it.sendDate?.isNotEmpty() == true) {
|
if (it.sendDate?.isNotEmpty() == true) {
|
||||||
// 获取当前发送时间,如果早于当前时间,则显示现在
|
// 获取当前发送时间,如果早于当前时间,则显示现在
|
||||||
val sendDate = DateUtils.str2Date(it.sendDate, dateSendFormat)
|
val sendDate = DateUtils.str2Date(it.sendDate, dateSendFormat)
|
||||||
if (sendDate<=Date()) {
|
if (sendDate <= Date()) {
|
||||||
binding.btnSendTime.text = "现在"
|
binding.btnSendTime.text = "现在"
|
||||||
} else {
|
} else {
|
||||||
binding.btnSendTime.text = it.sendDate
|
binding.btnSendTime.text = it.sendDate
|
||||||
@ -112,39 +107,47 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
var hasPhoto = false
|
var hasPhoto = false
|
||||||
var hasAudio = false
|
var hasAudio = false
|
||||||
if (it.imageUrl!=null&&it.imageUrl?.isNotEmpty() == true) {
|
if (it.imageUrl != null && it.imageUrl?.isNotEmpty() == true) {
|
||||||
hasPhoto = true
|
hasPhoto = true
|
||||||
// Glide.with(this@ObtainMessageFragment)
|
// Glide.with(this@ObtainMessageFragment)
|
||||||
// .asBitmap().fitCenter()
|
// .asBitmap().fitCenter()
|
||||||
// .load(it.imageUrl)
|
// .load(it.imageUrl)
|
||||||
// .diskCacheStrategy(DiskCacheStrategy.ALL)
|
// .diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
// .into(binding.imgMessageAttachment)
|
// .into(binding.imgMessageAttachment)
|
||||||
// 如果当前attachment文件是本地文件,开始尝试网络上传
|
// 如果当前attachment文件是本地文件,开始尝试网络上传
|
||||||
val str = it.imageUrl?.replace("\\", "/")
|
val str = it.imageUrl?.replace("\\", "/")
|
||||||
binding.tvPhotoName.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG )
|
binding.tvPhotoName.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG)
|
||||||
if (!str!!.startsWith("http")) {
|
if (!str!!.startsWith("http")) {
|
||||||
obtainMessageViewModel.uploadAttachment(File(it.imageUrl), AttachmentType.PIC)
|
obtainMessageViewModel.uploadAttachment(
|
||||||
|
File(it.imageUrl),
|
||||||
|
AttachmentType.PIC
|
||||||
|
)
|
||||||
binding.tvPhotoName.text = str.substringAfterLast("/", "picture.jpg")
|
binding.tvPhotoName.text = str.substringAfterLast("/", "picture.jpg")
|
||||||
} else {
|
} else {
|
||||||
if (str.contains("?")) {
|
if (str.contains("?")) {
|
||||||
binding.tvPhotoName.text = str.substring(str.lastIndexOf("/")+1, str.indexOf("?"))
|
binding.tvPhotoName.text =
|
||||||
|
str.substring(str.lastIndexOf("/") + 1, str.indexOf("?"))
|
||||||
} else {
|
} else {
|
||||||
binding.tvPhotoName.text = str.substringAfterLast("/")
|
binding.tvPhotoName.text = str.substringAfterLast("/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.mediaUrl!=null&&it.mediaUrl?.isNotEmpty() == true) {
|
if (it.mediaUrl != null && it.mediaUrl?.isNotEmpty() == true) {
|
||||||
hasAudio = true
|
hasAudio = true
|
||||||
binding.tvAudioName.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG )
|
binding.tvAudioName.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG)
|
||||||
// 如果当前attachment文件是本地文件,开始尝试网络上传
|
// 如果当前attachment文件是本地文件,开始尝试网络上传
|
||||||
val str = it.mediaUrl?.replace("\\", "/")
|
val str = it.mediaUrl?.replace("\\", "/")
|
||||||
if (!str!!.startsWith("http")) {
|
if (!str!!.startsWith("http")) {
|
||||||
obtainMessageViewModel.uploadAttachment(File(it.mediaUrl),AttachmentType.AUDIO)
|
obtainMessageViewModel.uploadAttachment(
|
||||||
|
File(it.mediaUrl),
|
||||||
|
AttachmentType.AUDIO
|
||||||
|
)
|
||||||
binding.tvAudioName.text = str.substringAfterLast("/", "audio.m4a")
|
binding.tvAudioName.text = str.substringAfterLast("/", "audio.m4a")
|
||||||
} else {
|
} else {
|
||||||
if (str.contains("?")) {
|
if (str.contains("?")) {
|
||||||
binding.tvAudioName.text = str.substring(str.lastIndexOf("/")+1, str.indexOf("?"))
|
binding.tvAudioName.text =
|
||||||
|
str.substring(str.lastIndexOf("/") + 1, str.indexOf("?"))
|
||||||
} else {
|
} else {
|
||||||
binding.tvAudioName.text = str.substringAfterLast("/")
|
binding.tvAudioName.text = str.substringAfterLast("/")
|
||||||
}
|
}
|
||||||
@ -152,7 +155,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
binding.layerPhotoResult.visibility = if (hasPhoto) VISIBLE else GONE
|
binding.layerPhotoResult.visibility = if (hasPhoto) VISIBLE else GONE
|
||||||
binding.layerGetPhoto.visibility = if (hasPhoto) GONE else VISIBLE
|
binding.layerGetPhoto.visibility = if (hasPhoto) GONE else VISIBLE
|
||||||
// binding.imgMessageAttachment.visibility = if (hasPhoto) VISIBLE else GONE
|
// binding.imgMessageAttachment.visibility = if (hasPhoto) VISIBLE else GONE
|
||||||
|
|
||||||
binding.layerAudioResult.visibility = if (hasAudio) VISIBLE else GONE
|
binding.layerAudioResult.visibility = if (hasAudio) VISIBLE else GONE
|
||||||
binding.layerGetAudio.visibility = if (hasAudio) GONE else VISIBLE
|
binding.layerGetAudio.visibility = if (hasAudio) GONE else VISIBLE
|
||||||
@ -188,7 +191,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
obtainMessageViewModel.getMessageLiveData().value?.name = it.toString()
|
obtainMessageViewModel.getMessageLiveData().value?.name = it.toString()
|
||||||
})
|
})
|
||||||
|
|
||||||
binding.edtSendFrom.addTextChangedListener (afterTextChanged = {
|
binding.edtSendFrom.addTextChangedListener(afterTextChanged = {
|
||||||
obtainMessageViewModel.getMessageLiveData().value?.who = it.toString()
|
obtainMessageViewModel.getMessageLiveData().value?.who = it.toString()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -201,8 +204,11 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
val sendToArray = mutableListOf<VolvoModel>(VolvoModel("XC60", "智雅", "LYVXFEFEXNL754427"))
|
val sendToArray = mutableListOf<VolvoModel>(VolvoModel("XC60", "智雅", "LYVXFEFEXNL754427"))
|
||||||
binding.edtSendTo.adapter = ArrayAdapter<String>(requireContext(),
|
binding.edtSendTo.adapter = ArrayAdapter<String>(requireContext(),
|
||||||
android.R.layout.simple_dropdown_item_1line, android.R.id.text1, sendToArray.stream().map { it -> "${it.version} ${it.model} ${it.num}" }.toList())
|
android.R.layout.simple_dropdown_item_1line,
|
||||||
binding.edtSendTo.onItemSelectedListener = object: OnItemSelectedListener {
|
android.R.id.text1,
|
||||||
|
sendToArray.stream().map { it -> "${it.version} ${it.model} ${it.num}" }.toList()
|
||||||
|
)
|
||||||
|
binding.edtSendTo.onItemSelectedListener = object : OnItemSelectedListener {
|
||||||
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
|
override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
|
||||||
obtainMessageViewModel.getMessageLiveData().value?.toWho = sendToArray[p2].num
|
obtainMessageViewModel.getMessageLiveData().value?.toWho = sendToArray[p2].num
|
||||||
}
|
}
|
||||||
@ -219,9 +225,19 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
override fun onClickListener(selectTime: String) {
|
override fun onClickListener(selectTime: String) {
|
||||||
val sendDate = DateUtils.str2Date(selectTime, dateShowFormat)
|
val sendDate = DateUtils.str2Date(selectTime, dateShowFormat)
|
||||||
if (sendDate <= Date()) {
|
if (sendDate <= Date()) {
|
||||||
obtainMessageViewModel.updateMessageSendTime(DateUtils.date2Str(Date(), dateSendFormat))
|
obtainMessageViewModel.updateMessageSendTime(
|
||||||
|
DateUtils.date2Str(
|
||||||
|
Date(),
|
||||||
|
dateSendFormat
|
||||||
|
)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
obtainMessageViewModel.updateMessageSendTime(DateUtils.date2Str(sendDate, dateSendFormat))
|
obtainMessageViewModel.updateMessageSendTime(
|
||||||
|
DateUtils.date2Str(
|
||||||
|
sendDate,
|
||||||
|
dateSendFormat
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,7 +254,8 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
|
|
||||||
override fun onGranted(permissions: MutableList<String>, all: Boolean) {
|
override fun onGranted(permissions: MutableList<String>, all: Boolean) {
|
||||||
if (!all) {
|
if (!all) {
|
||||||
Toast.makeText(activity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT).show()
|
Toast.makeText(activity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 开始启动拍照界面
|
// 开始启动拍照界面
|
||||||
@ -280,13 +297,23 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
// Do something here with selected files
|
// Do something here with selected files
|
||||||
val audioFile = files.get(0).file
|
val audioFile = files.get(0).file
|
||||||
if (!audioFile.parentFile.parentFile.absolutePath.equals(SystemConstant.SoundFolder)) {
|
if (!audioFile.parentFile.parentFile.absolutePath.equals(SystemConstant.SoundFolder)) {
|
||||||
val copyResult = FileIOUtils.writeFileFromIS(File(SystemConstant.SoundFolder, audioFile.name), FileInputStream(audioFile))
|
val copyResult = FileIOUtils.writeFileFromIS(
|
||||||
XLog.e("拷贝结果:"+copyResult)
|
File(
|
||||||
|
SystemConstant.SoundFolder,
|
||||||
|
audioFile.name
|
||||||
|
), FileInputStream(audioFile)
|
||||||
|
)
|
||||||
|
XLog.e("拷贝结果:" + copyResult)
|
||||||
if (!copyResult) {
|
if (!copyResult) {
|
||||||
ToastUtils.showToast("无法访问该文件,请重新选择其他文件")
|
ToastUtils.showToast("无法访问该文件,请重新选择其他文件")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
obtainMessageViewModel.updateMessageAudio(File(SystemConstant.SoundFolder, audioFile.name).absolutePath)
|
obtainMessageViewModel.updateMessageAudio(
|
||||||
|
File(
|
||||||
|
SystemConstant.SoundFolder,
|
||||||
|
audioFile.name
|
||||||
|
).absolutePath
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
obtainMessageViewModel.updateMessageAudio(audioFile.absolutePath)
|
obtainMessageViewModel.updateMessageAudio(audioFile.absolutePath)
|
||||||
}
|
}
|
||||||
@ -299,7 +326,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
ToastUtils.showToast("只能选择.m4a文件")
|
ToastUtils.showToast("只能选择.m4a文件")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (media.file.length()>2*1000*1000) {
|
if (media.file.length() > 2 * 1000 * 1000) {
|
||||||
ToastUtils.showToast("文件不能超过2M!")
|
ToastUtils.showToast("文件不能超过2M!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -330,23 +357,25 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
.request(object : OnPermissionCallback {
|
.request(object : OnPermissionCallback {
|
||||||
override fun onGranted(permissions: MutableList<String>, all: Boolean) {
|
override fun onGranted(permissions: MutableList<String>, all: Boolean) {
|
||||||
if (!all) {
|
if (!all) {
|
||||||
Toast.makeText(activity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT).show()
|
Toast.makeText(activity, "获取部分权限成功,但部分权限未正常授予", Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
when(motionEvent.action) {
|
when (motionEvent.action) {
|
||||||
MotionEvent.ACTION_DOWN-> {
|
MotionEvent.ACTION_DOWN -> {
|
||||||
// 申请权限
|
// 申请权限
|
||||||
recorderLifecycleObserver.initAndStartRecorder()
|
recorderLifecycleObserver.initAndStartRecorder()
|
||||||
startRecordTime = System.currentTimeMillis()
|
startRecordTime = System.currentTimeMillis()
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
MotionEvent.ACTION_UP -> {
|
MotionEvent.ACTION_UP -> {
|
||||||
if (System.currentTimeMillis() - startRecordTime<2000) {
|
if (System.currentTimeMillis() - startRecordTime < 2000) {
|
||||||
ToastUtils.showToast("录音时间太短!")
|
ToastUtils.showToast("录音时间太短!")
|
||||||
recorderLifecycleObserver.stopAndReleaseRecorder()
|
recorderLifecycleObserver.stopAndReleaseRecorder()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val recorderAudioPath = recorderLifecycleObserver.stopAndReleaseRecorder()
|
val recorderAudioPath =
|
||||||
|
recorderLifecycleObserver.stopAndReleaseRecorder()
|
||||||
if (File(recorderAudioPath).exists()) {
|
if (File(recorderAudioPath).exists()) {
|
||||||
obtainMessageViewModel.updateMessageAudio(recorderAudioPath)
|
obtainMessageViewModel.updateMessageAudio(recorderAudioPath)
|
||||||
}
|
}
|
||||||
@ -376,7 +405,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
photoHelper.setCallback {
|
photoHelper.setCallback {
|
||||||
if (it.exists()) {
|
if (it.exists()) {
|
||||||
val fileName = it.name.lowercase()
|
val fileName = it.name.lowercase()
|
||||||
if (fileName.endsWith(".jpg")||fileName.endsWith(".jpeg")||fileName.endsWith(".png")) {
|
if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") || fileName.endsWith(".png")) {
|
||||||
// 获取选中的图片,自动压缩图片质量
|
// 获取选中的图片,自动压缩图片质量
|
||||||
// 压缩图片文件
|
// 压缩图片文件
|
||||||
Luban.with(context)
|
Luban.with(context)
|
||||||
@ -400,13 +429,29 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
// 如果当前文件不在camera缓存文件夹下,则移动该文件
|
// 如果当前文件不在camera缓存文件夹下,则移动该文件
|
||||||
if (!file!!.parentFile.absolutePath.equals(SystemConstant.CameraFolder)) {
|
if (!file!!.parentFile.absolutePath.equals(SystemConstant.CameraFolder)) {
|
||||||
val copyResult = FileIOUtils.writeFileFromIS(File(SystemConstant.CameraFolder, fileName), FileInputStream(file))
|
try {
|
||||||
XLog.e("拷贝结果:"+copyResult)
|
val copyResult = FileIOUtils.writeFileFromIS(
|
||||||
|
File(
|
||||||
|
SystemConstant.CameraFolder,
|
||||||
|
fileName
|
||||||
|
), FileInputStream(file)
|
||||||
|
)
|
||||||
|
XLog.e("拷贝结果:$copyResult")
|
||||||
// 跳转回原Fragment,展示拍摄的照片
|
// 跳转回原Fragment,展示拍摄的照片
|
||||||
ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java).updateMessagePic(File(SystemConstant.CameraFolder, fileName).absolutePath)
|
obtainMessageViewModel
|
||||||
|
.updateMessagePic(
|
||||||
|
File(
|
||||||
|
SystemConstant.CameraFolder,
|
||||||
|
fileName
|
||||||
|
).absolutePath
|
||||||
|
)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
XLog.e("崩溃:${e.message}")
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// 跳转回原Fragment,展示拍摄的照片
|
// 跳转回原Fragment,展示拍摄的照片
|
||||||
ViewModelProvider(requireActivity()).get(ObtainMessageViewModel::class.java).updateMessagePic(file!!.absolutePath)
|
obtainMessageViewModel.updateMessagePic(file!!.absolutePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,12 +459,23 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
XLog.d("压缩图片失败:${e.message}")
|
XLog.d("压缩图片失败:${e.message}")
|
||||||
}
|
}
|
||||||
}).launch()
|
}).launch()
|
||||||
} else if (fileName.endsWith(".mp3")||fileName.endsWith(".wav")||fileName.endsWith(".amr")||fileName.endsWith(".m4a")) {
|
} else if (fileName.endsWith(".mp3") || fileName.endsWith(".wav") || fileName.endsWith(
|
||||||
|
".amr"
|
||||||
|
) || fileName.endsWith(".m4a")
|
||||||
|
) {
|
||||||
ToastUtils.showToast(it.absolutePath)
|
ToastUtils.showToast(it.absolutePath)
|
||||||
if (!it.parentFile.parentFile.absolutePath.equals(SystemConstant.SoundFolder)) {
|
if (!it.parentFile.parentFile.absolutePath.equals(SystemConstant.SoundFolder)) {
|
||||||
val copyResult = FileIOUtils.writeFileFromIS(File(SystemConstant.SoundFolder, fileName), FileInputStream(it))
|
val copyResult = FileIOUtils.writeFileFromIS(
|
||||||
XLog.e("拷贝结果:"+copyResult)
|
File(SystemConstant.SoundFolder, fileName),
|
||||||
obtainMessageViewModel.updateMessageAudio(File(SystemConstant.SoundFolder, fileName).absolutePath)
|
FileInputStream(it)
|
||||||
|
)
|
||||||
|
XLog.e("拷贝结果:" + copyResult)
|
||||||
|
obtainMessageViewModel.updateMessageAudio(
|
||||||
|
File(
|
||||||
|
SystemConstant.SoundFolder,
|
||||||
|
fileName
|
||||||
|
).absolutePath
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
obtainMessageViewModel.updateMessageAudio(it.absolutePath)
|
obtainMessageViewModel.updateMessageAudio(it.absolutePath)
|
||||||
}
|
}
|
||||||
@ -432,12 +488,14 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.tvAudioName.setOnClickListener {
|
binding.tvAudioName.setOnClickListener {
|
||||||
binding.llAudioPlay.visibility = if (binding.llAudioPlay.visibility == VISIBLE) GONE else VISIBLE
|
binding.llAudioPlay.visibility =
|
||||||
|
if (binding.llAudioPlay.visibility == VISIBLE) GONE else VISIBLE
|
||||||
// 判断当前播放的文件是否在缓存文件夹内,如果不在首先下载该文件
|
// 判断当前播放的文件是否在缓存文件夹内,如果不在首先下载该文件
|
||||||
val fileUrl = obtainMessageViewModel.getMessageLiveData().value!!.mediaUrl!!
|
val fileUrl = obtainMessageViewModel.getMessageLiveData().value!!.mediaUrl!!
|
||||||
val localFile = obtainMessageViewModel.getLocalFileFromNetUrl(fileUrl, AttachmentType.AUDIO)
|
val localFile =
|
||||||
|
obtainMessageViewModel.getLocalFileFromNetUrl(fileUrl, AttachmentType.AUDIO)
|
||||||
if (!localFile.exists()) {
|
if (!localFile.exists()) {
|
||||||
obtainMessageViewModel.downLoadFile(fileUrl, localFile, object: DownloadCallback {
|
obtainMessageViewModel.downLoadFile(fileUrl, localFile, object : DownloadCallback {
|
||||||
override fun progress(progress: Int) {
|
override fun progress(progress: Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,7 +513,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.btnObtainMessageBack.setOnClickListener {
|
binding.btnObtainMessageBack.setOnClickListener {
|
||||||
Navigation.findNavController(it).popBackStack()
|
findNavController().popBackStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.btnObtainMessageConfirm.setOnClickListener {
|
binding.btnObtainMessageConfirm.setOnClickListener {
|
||||||
@ -476,7 +534,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
toolTipRelativeLayout.showToolTipForView(toolTip, binding.tiLayoutTitle)
|
toolTipRelativeLayout.showToolTipForView(toolTip, binding.tiLayoutTitle)
|
||||||
checkResult = false
|
checkResult = false
|
||||||
} else {
|
} else {
|
||||||
if (messageData?.name!!.length>10) {
|
if (messageData?.name!!.length > 10) {
|
||||||
val toolTipRelativeLayout =
|
val toolTipRelativeLayout =
|
||||||
binding.ttTitle
|
binding.ttTitle
|
||||||
val toolTip = ToolTip()
|
val toolTip = ToolTip()
|
||||||
@ -514,7 +572,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
checkResult = false
|
checkResult = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messageData?.who?.isEmpty()==true) {
|
if (messageData?.who?.isEmpty() == true) {
|
||||||
val toolTipRelativeLayout =
|
val toolTipRelativeLayout =
|
||||||
binding.ttSendFrom
|
binding.ttSendFrom
|
||||||
val toolTip = ToolTip()
|
val toolTip = ToolTip()
|
||||||
@ -526,7 +584,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
toolTipRelativeLayout.showToolTipForView(toolTip, binding.edtSendFrom)
|
toolTipRelativeLayout.showToolTipForView(toolTip, binding.edtSendFrom)
|
||||||
checkResult = false
|
checkResult = false
|
||||||
}
|
}
|
||||||
if (messageData?.toWho?.isEmpty()==true) {
|
if (messageData?.toWho?.isEmpty() == true) {
|
||||||
val toolTipRelativeLayout =
|
val toolTipRelativeLayout =
|
||||||
binding.ttSendTo
|
binding.ttSendTo
|
||||||
val toolTip = ToolTip()
|
val toolTip = ToolTip()
|
||||||
@ -547,21 +605,29 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
localAttachmentList.add(imageAttachment)
|
localAttachmentList.add(imageAttachment)
|
||||||
}
|
}
|
||||||
if (messageData?.mediaUrl?.startsWith("http") == false) {
|
if (messageData?.mediaUrl?.startsWith("http") == false) {
|
||||||
val audioAttachment = Attachment("", messageData.mediaUrl!!, AttachmentType.AUDIO)
|
val audioAttachment =
|
||||||
|
Attachment("", messageData.mediaUrl!!, AttachmentType.AUDIO)
|
||||||
localAttachmentList.add(audioAttachment)
|
localAttachmentList.add(audioAttachment)
|
||||||
}
|
}
|
||||||
if (localAttachmentList.isNotEmpty()) {
|
if (localAttachmentList.isNotEmpty()) {
|
||||||
MaterialAlertDialogBuilder(requireContext())
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
.setTitle("提示")
|
.setTitle("提示")
|
||||||
.setMessage("当前照片及音频内容需首先上传,是否尝试上传?")
|
.setMessage("当前照片及音频内容需首先上传,是否尝试上传?")
|
||||||
.setPositiveButton("确定", DialogInterface.OnClickListener { dialogInterface, i ->
|
.setPositiveButton(
|
||||||
|
"确定",
|
||||||
|
DialogInterface.OnClickListener { dialogInterface, i ->
|
||||||
dialogInterface.dismiss()
|
dialogInterface.dismiss()
|
||||||
for (attachment in localAttachmentList) {
|
for (attachment in localAttachmentList) {
|
||||||
obtainMessageViewModel.uploadAttachment(File(attachment.pathUrl), attachment.attachmentType)
|
obtainMessageViewModel.uploadAttachment(
|
||||||
|
File(attachment.pathUrl),
|
||||||
|
attachment.attachmentType
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton("取消", DialogInterface.OnClickListener {
|
.setNegativeButton(
|
||||||
dialogInterface, i -> dialogInterface.dismiss()
|
"取消",
|
||||||
|
DialogInterface.OnClickListener { dialogInterface, i ->
|
||||||
|
dialogInterface.dismiss()
|
||||||
})
|
})
|
||||||
.show()
|
.show()
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
@ -571,7 +637,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
val sendDate = DateUtils.str2Date(messageData?.sendDate, dateSendFormat)
|
val sendDate = DateUtils.str2Date(messageData?.sendDate, dateSendFormat)
|
||||||
val cal = Calendar.getInstance()
|
val cal = Calendar.getInstance()
|
||||||
cal.time = Date()
|
cal.time = Date()
|
||||||
cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE)+1)
|
cal.set(Calendar.MINUTE, cal.get(Calendar.MINUTE) + 1)
|
||||||
if (sendDate.time < cal.time.time) { // 发送时间设置小于当前时间1分钟后,Toast提示用户并自动设置发送时间
|
if (sendDate.time < cal.time.time) { // 发送时间设置小于当前时间1分钟后,Toast提示用户并自动设置发送时间
|
||||||
messageData?.sendDate = DateUtils.date2Str(cal.time, dateSendFormat)
|
messageData?.sendDate = DateUtils.date2Str(cal.time, dateSendFormat)
|
||||||
ToastUtils.showToast("自动调整发送时间为1分钟后发送")
|
ToastUtils.showToast("自动调整发送时间为1分钟后发送")
|
||||||
@ -581,7 +647,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 开始网络提交数据
|
// 开始网络提交数据
|
||||||
if (obtainMessageViewModel.getMessageLiveData().value?.id==0L) { // 如果网络id为空,则调用更新操作
|
if (obtainMessageViewModel.getMessageLiveData().value?.id == 0L) { // 如果网络id为空,则调用更新操作
|
||||||
obtainMessageViewModel.insertCardByApp(confirmCallback)
|
obtainMessageViewModel.insertCardByApp(confirmCallback)
|
||||||
} else {
|
} else {
|
||||||
obtainMessageViewModel.updateCardByApp(confirmCallback)
|
obtainMessageViewModel.updateCardByApp(confirmCallback)
|
||||||
@ -593,7 +659,8 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
val viewData = ViewData()
|
val viewData = ViewData()
|
||||||
viewData.imageSrc = obtainMessageViewModel.getMessageLiveData().value!!.imageUrl
|
viewData.imageSrc = obtainMessageViewModel.getMessageLiveData().value!!.imageUrl
|
||||||
viewData.targetX = Utils.dp2px(context, 10F).toFloat()
|
viewData.targetX = Utils.dp2px(context, 10F).toFloat()
|
||||||
viewData.targetWidth = DisplayUtils.getScreenWidthPixels(activity) - Utils.dp2px(context, 20F)
|
viewData.targetWidth =
|
||||||
|
DisplayUtils.getScreenWidthPixels(activity) - Utils.dp2px(context, 20F)
|
||||||
viewData.targetHeight = Utils.dp2px(context, 200F)
|
viewData.targetHeight = Utils.dp2px(context, 200F)
|
||||||
val viewDataList = listOf(viewData)
|
val viewDataList = listOf(viewData)
|
||||||
binding.imageViewer.overlayStatusBar(true) // ImageViewer 是否会占据 StatusBar 的空间
|
binding.imageViewer.overlayStatusBar(true) // ImageViewer 是否会占据 StatusBar 的空间
|
||||||
@ -603,11 +670,13 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
.watch(0) // 开启浏览
|
.watch(0) // 开启浏览
|
||||||
|
|
||||||
}
|
}
|
||||||
|
binding.edtSendFrom.setText(obtainMessageViewModel.username)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val confirmCallback = object: ObtainMessageViewModel.MyConfirmCallback {
|
val confirmCallback = object : ObtainMessageViewModel.MyConfirmCallback {
|
||||||
override fun onSucess() {
|
override fun onSucess() {
|
||||||
findNavController().navigate(R.id.navigation_home)
|
findNavController().popBackStack()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,6 +717,7 @@ class ObtainMessageFragment: Fragment() {
|
|||||||
})
|
})
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onRecorderDenied() {
|
fun onRecorderDenied() {
|
||||||
ToastUtils.showToast("当前操作需要您授权录音权限!")
|
ToastUtils.showToast("当前操作需要您授权录音权限!")
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,47 @@
|
|||||||
package com.navinfo.volvo.ui.fragments.message
|
package com.navinfo.volvo.ui.fragments.message
|
||||||
|
|
||||||
import android.security.ConfirmationCallback
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.easytools.tools.FileIOUtils
|
import com.easytools.tools.FileIOUtils
|
||||||
import com.easytools.tools.FileUtils
|
import com.easytools.tools.FileUtils
|
||||||
import com.easytools.tools.ToastUtils
|
import com.easytools.tools.ToastUtils
|
||||||
import com.elvishew.xlog.XLog
|
import com.elvishew.xlog.XLog
|
||||||
import com.navinfo.volvo.database.entity.Attachment
|
|
||||||
import com.navinfo.volvo.database.entity.AttachmentType
|
import com.navinfo.volvo.database.entity.AttachmentType
|
||||||
import com.navinfo.volvo.database.entity.GreetingMessage
|
import com.navinfo.volvo.database.entity.GreetingMessage
|
||||||
import com.navinfo.volvo.http.DownloadCallback
|
import com.navinfo.volvo.http.DownloadCallback
|
||||||
import com.navinfo.volvo.http.DownloadManager
|
import com.navinfo.volvo.http.DownloadManager
|
||||||
import com.navinfo.volvo.http.DownloadState
|
import com.navinfo.volvo.http.DownloadState
|
||||||
import com.navinfo.volvo.http.NavinfoVolvoCall
|
import com.navinfo.volvo.http.NavinfoVolvoCall
|
||||||
|
import com.navinfo.volvo.repository.preferences.PreferencesRepository
|
||||||
import com.navinfo.volvo.utils.SystemConstant
|
import com.navinfo.volvo.utils.SystemConstant
|
||||||
import kotlinx.coroutines.flow.Flow
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import okhttp3.MediaType
|
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
class ObtainMessageViewModel @Inject constructor(): ViewModel() {
|
class ObtainMessageViewModel @Inject constructor(
|
||||||
|
private val pre: PreferencesRepository,
|
||||||
|
) : ViewModel() {
|
||||||
private val msgLiveData: MutableLiveData<GreetingMessage> by lazy {
|
private val msgLiveData: MutableLiveData<GreetingMessage> by lazy {
|
||||||
MutableLiveData<GreetingMessage>()
|
MutableLiveData<GreetingMessage>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var username: String = ""
|
||||||
|
|
||||||
|
init {
|
||||||
|
viewModelScope.launch {
|
||||||
|
pre.loginUser().collect {
|
||||||
|
username = it!!.username
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun setCurrentMessage(msg: GreetingMessage) {
|
fun setCurrentMessage(msg: GreetingMessage) {
|
||||||
msgLiveData.postValue(msg)
|
msgLiveData.postValue(msg)
|
||||||
}
|
}
|
||||||
@ -131,7 +142,11 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
|
|||||||
try {
|
try {
|
||||||
val requestFile: RequestBody =
|
val requestFile: RequestBody =
|
||||||
RequestBody.create("multipart/form-data".toMediaTypeOrNull(), attachmentFile)
|
RequestBody.create("multipart/form-data".toMediaTypeOrNull(), attachmentFile)
|
||||||
val body = MultipartBody.Part.createFormData("picture", attachmentFile.getName(), requestFile)
|
val body = MultipartBody.Part.createFormData(
|
||||||
|
"picture",
|
||||||
|
attachmentFile.getName(),
|
||||||
|
requestFile
|
||||||
|
)
|
||||||
val result = NavinfoVolvoCall.getApi().uploadAttachment(body)
|
val result = NavinfoVolvoCall.getApi().uploadAttachment(body)
|
||||||
XLog.d(result.code)
|
XLog.d(result.code)
|
||||||
if (result.code == 200) { // 请求成功
|
if (result.code == 200) { // 请求成功
|
||||||
@ -144,17 +159,19 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
|
|||||||
if (destFile.exists()) {
|
if (destFile.exists()) {
|
||||||
FileUtils.deleteFile(destFile)
|
FileUtils.deleteFile(destFile)
|
||||||
}
|
}
|
||||||
val copyResult = FileIOUtils.writeFileFromIS(destFile, FileInputStream(attachmentFile))
|
val copyResult =
|
||||||
XLog.e("拷贝结果:"+copyResult)
|
FileIOUtils.writeFileFromIS(destFile, FileInputStream(attachmentFile))
|
||||||
|
XLog.e("拷贝结果:" + copyResult)
|
||||||
} else {
|
} else {
|
||||||
val destFile = File(SystemConstant.SoundFolder, newFileName)
|
val destFile = File(SystemConstant.SoundFolder, newFileName)
|
||||||
if (destFile.exists()) {
|
if (destFile.exists()) {
|
||||||
FileUtils.deleteFile(destFile)
|
FileUtils.deleteFile(destFile)
|
||||||
}
|
}
|
||||||
val copyResult = FileIOUtils.writeFileFromIS(destFile, FileInputStream(attachmentFile))
|
val copyResult =
|
||||||
XLog.e("拷贝结果:"+copyResult)
|
FileIOUtils.writeFileFromIS(destFile, FileInputStream(attachmentFile))
|
||||||
|
XLog.e("拷贝结果:" + copyResult)
|
||||||
}
|
}
|
||||||
if (fileKey!=null) {
|
if (fileKey != null) {
|
||||||
downloadAttachment(fileKey, attachmentType)
|
downloadAttachment(fileKey, attachmentType)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -179,7 +196,7 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
|
|||||||
if (result.code == 200) { // 请求成功
|
if (result.code == 200) { // 请求成功
|
||||||
// 获取上传后的结果
|
// 获取上传后的结果
|
||||||
val imageUrl = result.data
|
val imageUrl = result.data
|
||||||
if (imageUrl!=null) {
|
if (imageUrl != null) {
|
||||||
XLog.d("downloadAttachment-imageUrl:${imageUrl}")
|
XLog.d("downloadAttachment-imageUrl:${imageUrl}")
|
||||||
// 获取到图片的网络地址
|
// 获取到图片的网络地址
|
||||||
if (attachmentType == AttachmentType.PIC) {
|
if (attachmentType == AttachmentType.PIC) {
|
||||||
@ -198,7 +215,7 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun downLoadFile(url: String, destFile: File, downloadCallback: DownloadCallback){
|
fun downLoadFile(url: String, destFile: File, downloadCallback: DownloadCallback) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
DownloadManager.download(
|
DownloadManager.download(
|
||||||
url,
|
url,
|
||||||
@ -236,7 +253,8 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
|
|||||||
"sendDate" to message?.sendDate,
|
"sendDate" to message?.sendDate,
|
||||||
"version" to message?.version
|
"version" to message?.version
|
||||||
)
|
)
|
||||||
val result = NavinfoVolvoCall.getApi().insertCardByApp(insertData as Map<String, String>)
|
val result =
|
||||||
|
NavinfoVolvoCall.getApi().insertCardByApp(insertData as Map<String, String>)
|
||||||
XLog.d("insertCardByApp:${result.code}")
|
XLog.d("insertCardByApp:${result.code}")
|
||||||
if (result.code == 200) { // 请求成功
|
if (result.code == 200) { // 请求成功
|
||||||
// 获取上传后的结果
|
// 获取上传后的结果
|
||||||
@ -269,7 +287,8 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
|
|||||||
"sendDate" to message?.sendDate,
|
"sendDate" to message?.sendDate,
|
||||||
"version" to message?.version
|
"version" to message?.version
|
||||||
)
|
)
|
||||||
val result = NavinfoVolvoCall.getApi().updateCardByApp(updateData as Map<String, String>)
|
val result =
|
||||||
|
NavinfoVolvoCall.getApi().updateCardByApp(updateData as Map<String, String>)
|
||||||
XLog.d("updateCardByApp:${result.code}")
|
XLog.d("updateCardByApp:${result.code}")
|
||||||
if (result.code == 200) { // 请求成功
|
if (result.code == 200) { // 请求成功
|
||||||
// 数据更新成功
|
// 数据更新成功
|
||||||
@ -289,14 +308,14 @@ class ObtainMessageViewModel @Inject constructor(): ViewModel() {
|
|||||||
/**
|
/**
|
||||||
* 根据网络地址获取本地的缓存文件路径
|
* 根据网络地址获取本地的缓存文件路径
|
||||||
* */
|
* */
|
||||||
fun getLocalFileFromNetUrl(url: String, attachmentType: AttachmentType):File {
|
fun getLocalFileFromNetUrl(url: String, attachmentType: AttachmentType): File {
|
||||||
if (url.startsWith("http")) {
|
if (url.startsWith("http")) {
|
||||||
val folder = when(attachmentType) {
|
val folder = when (attachmentType) {
|
||||||
AttachmentType.PIC-> SystemConstant.CameraFolder
|
AttachmentType.PIC -> SystemConstant.CameraFolder
|
||||||
else -> SystemConstant.SoundFolder
|
else -> SystemConstant.SoundFolder
|
||||||
}
|
}
|
||||||
var name = if (url.contains("?")) {
|
var name = if (url.contains("?")) {
|
||||||
url.substring(url.lastIndexOf("/")+1, url.indexOf("?"))
|
url.substring(url.lastIndexOf("/") + 1, url.indexOf("?"))
|
||||||
} else {
|
} else {
|
||||||
url.substringAfterLast("/")
|
url.substringAfterLast("/")
|
||||||
}
|
}
|
||||||
|
@ -11,14 +11,16 @@ package com.navinfo.volvo.util
|
|||||||
sealed class NetResult<out R> {
|
sealed class NetResult<out R> {
|
||||||
|
|
||||||
data class Success<out T>(val data: T?) : NetResult<T>()
|
data class Success<out T>(val data: T?) : NetResult<T>()
|
||||||
|
data class Failure(val code: Int, val msg: String) : NetResult<Nothing>()
|
||||||
data class Error(val exception: Exception) : NetResult<Nothing>()
|
data class Error(val exception: Exception) : NetResult<Nothing>()
|
||||||
object Loading : NetResult<Nothing>()
|
object Loading : NetResult<Nothing>()
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is Success<*> -> "Success[data=$data]"
|
is Success<*> -> "网络访问成功,返回正确结果Success[data=$data]"
|
||||||
is Error -> "Error[exception=$exception]"
|
is Failure -> "网络访问成功,返回错误结果Failure[$msg]"
|
||||||
is Loading -> "Loading"
|
is Error -> "网络访问出错 Error[exception=$exception]"
|
||||||
|
is Loading -> "网络访问中 Loading"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,131 +0,0 @@
|
|||||||
package com.navinfo.volvo.util
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.preference.PreferenceManager
|
|
||||||
import androidx.core.content.edit
|
|
||||||
import com.google.gson.Gson
|
|
||||||
|
|
||||||
|
|
||||||
class SharedPreferenceHelper {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
private const val WEATHER_PREF_TIME = "Weather pref time"
|
|
||||||
private const val WEATHER_FORECAST_PREF_TIME = "Forecast pref time"
|
|
||||||
private const val CITY_ID = "City ID"
|
|
||||||
private var prefs: SharedPreferences? = null
|
|
||||||
private const val LOCATION = "LOCATION"
|
|
||||||
|
|
||||||
@Volatile
|
|
||||||
private var instance: SharedPreferenceHelper? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This checks if there is an existing instance of the [SharedPreferences] in the
|
|
||||||
* specified [context] and creates one if there isn't or else, it returns the
|
|
||||||
* already existing instance. This function ensures that the [SharedPreferences] is
|
|
||||||
* accessed at any instance by a single thread.
|
|
||||||
*/
|
|
||||||
fun getInstance(context: Context): SharedPreferenceHelper {
|
|
||||||
synchronized(this) {
|
|
||||||
val _instance = instance
|
|
||||||
if (_instance == null) {
|
|
||||||
prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
|
||||||
instance = _instance
|
|
||||||
}
|
|
||||||
return SharedPreferenceHelper()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function saves the initial time [System.nanoTime] at which the weather information
|
|
||||||
* at the user's location is accessed.
|
|
||||||
* @param time the value of [System.nanoTime] when the weather information is received.
|
|
||||||
*/
|
|
||||||
fun saveTimeOfInitialWeatherFetch(time: Long) {
|
|
||||||
prefs?.edit(commit = true) {
|
|
||||||
putLong(WEATHER_PREF_TIME, time)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns the saved value of [System.nanoTime] when the weather information
|
|
||||||
* at the user's location was accessed.
|
|
||||||
* @see saveTimeOfInitialWeatherFetch
|
|
||||||
*/
|
|
||||||
fun getTimeOfInitialWeatherFetch() = prefs?.getLong(WEATHER_PREF_TIME, 0L)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function saves the initial time [System.nanoTime] at which the weather forecast
|
|
||||||
* at the user's location is accessed.
|
|
||||||
* @param time the value of [System.nanoTime] when the weather forecast is received.
|
|
||||||
*/
|
|
||||||
fun saveTimeOfInitialWeatherForecastFetch(time: Long) {
|
|
||||||
prefs?.edit(commit = true) {
|
|
||||||
putLong(WEATHER_FORECAST_PREF_TIME, time)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns the saved value of [System.nanoTime] when the weather forecast
|
|
||||||
* at the user's location was accessed.
|
|
||||||
* @see saveTimeOfInitialWeatherForecastFetch
|
|
||||||
*/
|
|
||||||
fun getTimeOfInitialWeatherForecastFetch() = prefs?.getLong(WEATHER_FORECAST_PREF_TIME, 0L)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function saves the [cityId] of the location whose weather information has been
|
|
||||||
* received.
|
|
||||||
* @param cityId the id of the location whose weather has been received
|
|
||||||
*/
|
|
||||||
fun saveCityId(cityId: Int) {
|
|
||||||
prefs?.edit(commit = true) {
|
|
||||||
putInt(CITY_ID, cityId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns the id of the location whose weather information has been received.
|
|
||||||
* @see saveCityId
|
|
||||||
*/
|
|
||||||
fun getCityId() = prefs?.getInt(CITY_ID, 0)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function gets the value of the cache duration the user set in the
|
|
||||||
* Settings Fragment.
|
|
||||||
*/
|
|
||||||
fun getUserSetCacheDuration() = prefs?.getString("cache_key", "0")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function gets the value of the app theme the user set in the
|
|
||||||
* Settings Fragment.
|
|
||||||
*/
|
|
||||||
fun getSelectedThemePref() = prefs?.getString("theme_key", "")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function gets the value of the temperature unit the user set in the
|
|
||||||
* Settings Fragment.
|
|
||||||
*/
|
|
||||||
fun getSelectedTemperatureUnit() = prefs?.getString("unit_key", "")
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * This function saves a [LocationModel]
|
|
||||||
// */
|
|
||||||
// fun saveLocation(location: LocationModel) {
|
|
||||||
// prefs?.edit(commit = true) {
|
|
||||||
// val gson = Gson()
|
|
||||||
// val json = gson.toJson(location)
|
|
||||||
// putString(LOCATION, json)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * This function gets the value of the saved [LocationModel]
|
|
||||||
// */
|
|
||||||
// fun getLocation(): LocationModel {
|
|
||||||
// val gson = Gson()
|
|
||||||
// val json = prefs?.getString(LOCATION, null)
|
|
||||||
// return gson.fromJson(json, LocationModel::class.java)
|
|
||||||
// }
|
|
||||||
}
|
|
9
app/src/main/proto/LoginUser.proto
Normal file
9
app/src/main/proto/LoginUser.proto
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option java_package = "com.navinfo.volvo.model.proto";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
message LoginUser {
|
||||||
|
string username = 1;
|
||||||
|
string password = 2;
|
||||||
|
}
|
@ -1,12 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<layout xmlns:tools="http://schemas.android.com/tools"
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
|
|
||||||
|
<import type="com.navinfo.volvo.Constant" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="greetingMessage"
|
name="greetingMessage"
|
||||||
type="com.navinfo.volvo.database.entity.GreetingMessage" />
|
type="com.navinfo.volvo.database.entity.GreetingMessage" />
|
||||||
@ -17,15 +19,17 @@
|
|||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
||||||
<ImageView
|
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||||
android:id="@+id/message_head_icon"
|
android:id="@+id/message_head_icon"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:src="@mipmap/volvo_logo_small"
|
android:scaleType="fitXY"
|
||||||
|
android:src="@mipmap/ic_launcher"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:roundPercent="0.4" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/message_badge"
|
android:id="@+id/message_badge"
|
||||||
@ -34,6 +38,7 @@
|
|||||||
android:background="@drawable/shape_circular"
|
android:background="@drawable/shape_circular"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:textColor="#000000"
|
android:textColor="#000000"
|
||||||
|
android:visibility="@{Constant.message_status_late.equals(greetingMessage.status)?View.VISIBLE:View.INVISIBLE}"
|
||||||
app:layout_constraintCircle="@id/message_head_icon"
|
app:layout_constraintCircle="@id/message_head_icon"
|
||||||
app:layout_constraintCircleAngle="45"
|
app:layout_constraintCircleAngle="45"
|
||||||
app:layout_constraintCircleRadius="40dp"
|
app:layout_constraintCircleRadius="40dp"
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="20dp"
|
android:layout_marginLeft="20dp"
|
||||||
android:layout_marginRight="20dp"
|
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
@ -23,8 +23,8 @@
|
|||||||
android:hint="请输入查询内容" />
|
android:hint="请输入查询内容" />
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.yanzhenjie.recyclerview.SwipeRecyclerView
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:id="@+id/home_recyclerview"
|
android:id="@+id/home_SwipeRefreshLayout"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginTop="10dp"
|
android:layout_marginTop="10dp"
|
||||||
@ -33,7 +33,14 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/home_search" />
|
app:layout_constraintTop_toBottomOf="@id/home_search">
|
||||||
|
|
||||||
|
<com.yanzhenjie.recyclerview.SwipeRecyclerView
|
||||||
|
android:id="@+id/home_recyclerview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<data>
|
<data>
|
||||||
<variable
|
<variable
|
||||||
name="loginUser"
|
name="loginUser"
|
||||||
type="com.navinfo.volvo.model.LoginUser" />
|
type="com.navinfo.volvo.model.proto.LoginUser" />
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
@ -14,11 +14,11 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context="com.navinfo.volvo.ui.fragments.login.LoginFragment">
|
tools:context="com.navinfo.volvo.ui.fragments.login.LoginFragment">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
|
||||||
android:id="@+id/login_fragment_logo"
|
android:id="@+id/login_fragment_logo"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="100dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="100dp"
|
||||||
|
android:scaleType="fitXY"
|
||||||
android:src="@mipmap/volvo_logo_small"
|
android:src="@mipmap/volvo_logo_small"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
@ -40,9 +40,10 @@
|
|||||||
app:layout_constraintVertical_bias="0.4">
|
app:layout_constraintVertical_bias="0.4">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/login_username"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@{loginUser.name}"
|
android:text="@{loginUser.username}"
|
||||||
android:hint="请输入用户名" />
|
android:hint="请输入用户名" />
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
@ -54,6 +55,7 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/login_fragment_user_layout">
|
app:layout_constraintTop_toBottomOf="@id/login_fragment_user_layout">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/login_password"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="textPassword"
|
android:inputType="textPassword"
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="@dimen/activity_default_padding"
|
android:padding="@dimen/activity_default_padding"
|
||||||
tools:context=".ui.message.ObtainMessageFragment">
|
tools:context="com.navinfo.volvo.ui.fragments.message.ObtainMessageFragment">
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@ -300,6 +300,7 @@
|
|||||||
android:text="我是谁:"></TextView>
|
android:text="我是谁:"></TextView>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatEditText
|
<androidx.appcompat.widget.AppCompatEditText
|
||||||
|
android:enabled="false"
|
||||||
android:id="@+id/edt_send_from"
|
android:id="@+id/edt_send_from"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -333,6 +334,13 @@
|
|||||||
android:id="@+id/edt_send_to"
|
android:id="@+id/edt_send_to"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"></androidx.appcompat.widget.AppCompatSpinner>
|
android:layout_height="wrap_content"></androidx.appcompat.widget.AppCompatSpinner>
|
||||||
|
|
||||||
|
<indi.liyi.viewer.ImageViewer
|
||||||
|
android:id="@+id/imageViewer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
app:ivr_dragMode="agile" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.nhaarman.supertooltips.ToolTipRelativeLayout
|
<com.nhaarman.supertooltips.ToolTipRelativeLayout
|
||||||
@ -404,10 +412,4 @@
|
|||||||
android:text="确认提交"></com.google.android.material.button.MaterialButton>
|
android:text="确认提交"></com.google.android.material.button.MaterialButton>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<indi.liyi.viewer.ImageViewer
|
|
||||||
android:id="@+id/imageViewer"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
app:ivr_dragMode="agile" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
12
app/src/main/res/layout/home_adapter_noting.xml
Normal file
12
app/src/main/res/layout/home_adapter_noting.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="暂无数据,可下拉刷新"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
23
app/src/main/res/layout/load_state_view.xml
Normal file
23
app/src/main/res/layout/load_state_view.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/load_state_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</layout>
|
@ -13,12 +13,9 @@
|
|||||||
<action
|
<action
|
||||||
android:id="@+id/action_login_to_home"
|
android:id="@+id/action_login_to_home"
|
||||||
app:destination="@id/navigation_home"
|
app:destination="@id/navigation_home"
|
||||||
app:enterAnim="@anim/from_left"
|
|
||||||
app:exitAnim="@anim/to_right"
|
|
||||||
app:popEnterAnim="@anim/from_right"
|
|
||||||
app:popExitAnim="@anim/to_left"
|
|
||||||
app:popUpTo="@id/navigation_login"
|
app:popUpTo="@id/navigation_login"
|
||||||
app:popUpToInclusive="true" />
|
app:popUpToInclusive="true" />
|
||||||
|
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/navigation_home"
|
android:id="@+id/navigation_home"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user