diff --git a/README.md b/README.md index fc9da27..adb325c 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,4 @@ ### Release key key0: prime24 + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index b28b990..81b6091 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,13 +15,13 @@ android { namespace 'in.sminnovations.hpostesting' // dev -> development, quality -> qc, uat -> User Acceptance Testing, preprod -> preproduction, prod -> production, iocl -> iocl-iisc production + // server -> for server switching defaultConfig { - applicationId "in.sminnovations.hpostesting.dev" + applicationId "in.sminnovations.hpostesting.server" minSdk 21 targetSdk 34 - versionCode 127 - versionName "2.1.127" - + versionCode 128 + versionName "2.1.128" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -124,7 +124,6 @@ dependencies { implementation 'com.github.mik3y:usb-serial-for-android:3.8.0' implementation "androidx.fragment:fragment-ktx:1.6.2" - // CSV read, write implementation 'com.opencsv:opencsv:5.9' diff --git a/app/google-services.json b/app/google-services.json deleted file mode 100644 index a73fe1e..0000000 --- a/app/google-services.json +++ /dev/null @@ -1,208 +0,0 @@ -{ - "project_info": { - "project_number": "650071678820", - "project_id": "hpos-af3cc", - "storage_bucket": "hpos-af3cc.appspot.com" - }, - "client": [ - { - "client_info": { - "mobilesdk_app_id": "1:650071678820:android:f1435a1c07f710036c6471", - "android_client_info": { - "package_name": "com.example.hposconsentform" - } - }, - "oauth_client": [ - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:650071678820:android:7865bef608cdee6f6c6471", - "android_client_info": { - "package_name": "com.smi.counselling" - } - }, - "oauth_client": [ - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:650071678820:android:2925e9ce3417d2386c6471", - "android_client_info": { - "package_name": "in.sminnovations.hemocube" - } - }, - "oauth_client": [ - { - "client_id": "650071678820-srhm9spm9hjn4frcd3r6o02gdhdbtd15.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "in.sminnovations.hemocube", - "certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a" - } - }, - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:650071678820:android:7569c1cad4fc99916c6471", - "android_client_info": { - "package_name": "in.sminnovations.hposregistration" - } - }, - "oauth_client": [ - { - "client_id": "650071678820-70kp5jvjda4r5diqch2kn4lc40p4f42g.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "in.sminnovations.hposregistration", - "certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a" - } - }, - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:650071678820:android:f96be19e5d43102b6c6471", - "android_client_info": { - "package_name": "in.sminnovations.hpostesting" - } - }, - "oauth_client": [ - { - "client_id": "650071678820-l87dnr0bdj95get0khgnvfv2an1k6ogq.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "in.sminnovations.hpostesting", - "certificate_hash": "7714b9268a81d0cf0fb178b0af8dbb630f8fc70a" - } - }, - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ] - } - } - }, - { - "client_info": { - "mobilesdk_app_id": "1:650071678820:android:a53292637abb7c0d6c6471", - "android_client_info": { - "package_name": "in.sminnovations.hpostesting.dev" - } - }, - "oauth_client": [ - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "650071678820-to41afi9f0gi5r3k6v7pe1e5p96nupcs.apps.googleusercontent.com", - "client_type": 3 - } - ] - } - } - } - ], - "configuration_version": "1" -} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 183d582..91b6fb9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,6 +25,12 @@ + + + + + + Log.d("UPLOAD", "Failed to upload data: ${exception.message} ${localdb.app.name}") + } + } private suspend fun safeApiCall(apiCall: suspend () -> T): Result { return try { val response = apiCall.invoke() @@ -108,13 +129,13 @@ class DatabaseRepository @Inject constructor( override suspend fun addTestToDatabase(data: HemoCubeTestData?): Response { return try { val userdata = - db.collection("patientData").whereEqualTo("_id", data!!._id).get().await() + localdb.collection("patientData").whereEqualTo("_id", data!!._id).get().await() if (userdata.documents.isNotEmpty()) { userdata.documents.forEach { - db.collection("patientData").document(it.id).update("testStatus", true) + localdb.collection("patientData").document(it.id).update("testStatus", true) } } - db.collection("testData").add(data).await() + localdb.collection("testData").add(data).await() Response.Success(data._id) } catch (e: Exception) { Response.Error(e) @@ -123,7 +144,7 @@ class DatabaseRepository @Inject constructor( override suspend fun addQcTestToDatabase(data: HemoCubeTestData?): Response { return try { - db.collection("qcData").add(data!!).await() + localdb.collection("qcData").add(data!!).await() Response.Success(data._id) } catch (e: Exception) { @@ -137,7 +158,7 @@ class DatabaseRepository @Inject constructor( override suspend fun addTestToDatabaseforBufferCheck(data: BufferCheckData?): Response { return try { - db.collection("buffers").add(data!!).await() + localdb.collection("buffers").add(data!!).await() Response.Success(data.kitno) } catch (e: Exception) { Firebase.crashlytics.recordException(e) @@ -147,7 +168,7 @@ class DatabaseRepository @Inject constructor( override suspend fun addDiagnostics(data: DiagnosticsData?): Response { return try { - db.collection("diagnostics").add(data!!).await() + localdb.collection("diagnostics").add(data!!).await() Response.Success(data.deviceId) } catch (e: Exception) { Firebase.crashlytics.recordException(e) @@ -158,7 +179,7 @@ class DatabaseRepository @Inject constructor( override suspend fun addTestJigData(data: JigData?): Response { return try { - db.collection("jigs").add(data!!).await() + localdb.collection("jigs").add(data!!).await() Response.Success(data.deviceId) } catch (e: Exception) { Firebase.crashlytics.recordException(e) @@ -172,7 +193,7 @@ class DatabaseRepository @Inject constructor( try { val file = Uri.fromFile(File(filePath)) - val riversRef = storage.reference.child("$patientID/${file.lastPathSegment}") + val riversRef = localStg.reference.child("$patientID/${file.lastPathSegment}") riversRef.putFile(file).await() return Response.Success(true) } catch (e: Exception) { @@ -183,7 +204,7 @@ class DatabaseRepository @Inject constructor( suspend fun addToPendingQueue(pendingUploads: PendingUploads): Response { return try { - db.collection("pendingUploads").document(pendingUploads.pendingId).set(pendingUploads) + localdb.collection("pendingUploads").document(pendingUploads.pendingId).set(pendingUploads) .await() Response.Success(true) @@ -196,7 +217,7 @@ class DatabaseRepository @Inject constructor( suspend fun getAllFromPendingQueue(): List { val pendingList = mutableListOf() return try { - val querySnapshot = db.collection("pendingUploads").orderBy("timeAdded").get().await() + val querySnapshot = localdb.collection("pendingUploads").orderBy("timeAdded").get().await() for (doc in querySnapshot.documents) { val pendingFile = doc.toObject(PendingUploads::class.java) @@ -214,7 +235,7 @@ class DatabaseRepository @Inject constructor( suspend fun removeFromPendingQueue(fileName: String): Response { return try { - db.collection("pendingUploads").document(fileName).delete().await() + localdb.collection("pendingUploads").document(fileName).delete().await() Response.Success(true) } catch (e: Exception) { @@ -224,11 +245,11 @@ class DatabaseRepository @Inject constructor( } suspend fun getDeviceData(): List { - return db.collection("devices").get().await().toObjects(DeviceData::class.java) + return localdb.collection("devices").get().await().toObjects(DeviceData::class.java) } override suspend fun getDeviceDataById(deviceId: String): DeviceData? { - val querySnapshot = db.collection("devices").get().await() + val querySnapshot = localdb.collection("devices").get().await() val allDeviceDataList = querySnapshot.toObjects(DeviceData::class.java) // Find the DeviceData object with the specified deviceId @@ -237,7 +258,7 @@ class DatabaseRepository @Inject constructor( override suspend fun getDeviceResponse(data: DeviceData?): Response { return try { - db.collection("devices").add(data!!).await() + localdb.collection("devices").add(data!!).await() Response.Success(data.deviceProvisionResponse) } catch (e: Exception) { Firebase.crashlytics.recordException(e) @@ -247,7 +268,7 @@ class DatabaseRepository @Inject constructor( override suspend fun uploadDeviceId(data: DeviceData): Response? { return try { - db.collection("devices").add(data!!).await() + localdb.collection("devices").add(data!!).await() Response.Success(data.deviceId) } catch (e: Exception) { Firebase.crashlytics.recordException(e) @@ -262,13 +283,13 @@ class DatabaseRepository @Inject constructor( override suspend fun addTestToDatabasefornew(data: HemoCubeTestData?): Response { return try { val userdata = - db.collection("patientData").whereEqualTo("_id", data!!._id).get().await() + localdb.collection("patientData").whereEqualTo("_id", data!!._id).get().await() if (userdata.documents.isNotEmpty()) { userdata.documents.forEach { - db.collection("patientData").document(it.id).update("testStatus", true) + localdb.collection("patientData").document(it.id).update("testStatus", true) } } - db.collection("testData").add(data).await() + localdb.collection("testData").add(data).await() Response.Success(data._id) } catch (e: Exception) { Firebase.crashlytics.recordException(e) diff --git a/app/src/main/java/com/example/hpostesting/di/AppModule.kt b/app/src/main/java/com/example/hpostesting/di/AppModule.kt index e82fc2b..2e46abe 100644 --- a/app/src/main/java/com/example/hpostesting/di/AppModule.kt +++ b/app/src/main/java/com/example/hpostesting/di/AppModule.kt @@ -21,7 +21,6 @@ import androidx.room.Room import com.example.hpostesting.data.api.MolbioAuthApi import com.example.hpostesting.data.api.MolbioResultApi import com.example.hpostesting.data.constant.Constants -import com.example.hpostesting.util.PropertyProvider import com.example.hpostesting.data.dao.HemoCubeBufferDao import com.example.hpostesting.data.dao.HemoCubeDao import com.example.hpostesting.data.dao.MyDatabase @@ -36,9 +35,13 @@ import com.example.hpostesting.domain.LogFileManager import com.example.hpostesting.domain.LogFileManagerImpl import com.example.hpostesting.domain.SaveRawData import com.example.hpostesting.domain.SaveRawDataTest +import com.example.hpostesting.firebase.FirebaseManager import com.example.hpostesting.presentation.utils.UsbServiceListener import com.example.hpostesting.presentation.utils.UsbServiceListenerImpl +import com.example.hpostesting.util.PropertyProvider import com.example.hpostesting.util.PropertyProviderImpl +import com.google.firebase.firestore.FirebaseFirestore +import com.google.firebase.storage.FirebaseStorage import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -107,22 +110,52 @@ object AppModule { return SaveRawDataTest(repository) } + @Provides + @Singleton + fun provideFirebaseFirestore(): FirebaseFirestore { + return FirebaseFirestore.getInstance() + } + + @Provides + @Singleton + fun provideFirebaseStorage(): FirebaseStorage { + return FirebaseStorage.getInstance() + } + + @Provides + @Singleton + fun provideFirebaseManager( + @ApplicationContext context: Context, + ): FirebaseManager { + return FirebaseManager(context) + } + @Provides @Singleton fun provideDatabaseRepository( + firebaseManager: FirebaseManager, @Named("Auth") molbioAuthApi: MolbioAuthApi, molbioResultApi: MolbioResultApi ): DatabaseRepository { - return DatabaseRepository(molbioAuthApi = molbioAuthApi, molbioResultApi = molbioResultApi) + return DatabaseRepository( + firebaseManager = firebaseManager, + molbioAuthApi = molbioAuthApi, + molbioResultApi = molbioResultApi + ) } @Provides @Singleton fun provideRepository( + firebaseManager: FirebaseManager, @Named("Auth") molbioAuthApi: MolbioAuthApi, molbioResultApi: MolbioResultApi ): Repository { - return DatabaseRepository(molbioAuthApi, molbioResultApi) + return DatabaseRepository( + firebaseManager = firebaseManager, + molbioAuthApi = molbioAuthApi, + molbioResultApi = molbioResultApi + ) } @Provides @@ -206,4 +239,9 @@ object AppModule { fun provideUsbServiceListener(context: Context): UsbServiceListener { return UsbServiceListenerImpl(context) } + + + + + } \ No newline at end of file diff --git a/app/src/main/java/com/example/hpostesting/firebase/FirebaseManage.kt b/app/src/main/java/com/example/hpostesting/firebase/FirebaseManage.kt new file mode 100644 index 0000000..df06a1c --- /dev/null +++ b/app/src/main/java/com/example/hpostesting/firebase/FirebaseManage.kt @@ -0,0 +1,153 @@ +package com.example.hpostesting.firebase +/* + * // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved. + * // Notice: All information contained herein is, and remains + * // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers, + * // if any. The intellectual and technical concepts contained + * // herein are proprietary to ShanMukha Innovations Pvt. Ltd. + * // and its suppliers and may be covered by Indian and Foreign Patents, + * // patents in process, and are protected by trade secret or copyright law. + * // Dissemination of this information or reproduction of this material + * // is strictly forbidden unless prior written permission is obtained + * // from ShanMukha Innovations Pvt. Ltd. + */ +import android.content.Context +import android.content.Intent +import android.os.Process +import com.google.firebase.FirebaseApp +import com.google.firebase.FirebaseOptions +import com.google.firebase.firestore.FirebaseFirestore +import com.google.firebase.storage.FirebaseStorage +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import javax.inject.Inject + +class FirebaseManager @Inject constructor(private val context: Context) { + + private val sharedPreferences = + context.getSharedPreferences("FirebaseConfigPrefs", Context.MODE_PRIVATE) + + private var currentFirestore: FirebaseFirestore = FirebaseFirestore.getInstance() + private var currentStorage: FirebaseStorage = FirebaseStorage.getInstance() + var updateStatus = false + + private val defaultServers = listOf( + // i have it in different place look down + firebaseConfig1, firebaseConfig2, firebaseConfig3, + ) + + init { + val lastSelectedServer = getLastSelectedServer() + switchServer(lastSelectedServer) + } + + fun getCurrentFirestore(): FirebaseFirestore = currentFirestore + fun getCurrentStorage(): FirebaseStorage = currentStorage + + fun switchServer(firebaseConfig: FirebaseConfig) { + saveSelectedServer(firebaseConfig) + val firebaseApp = getOrInitializeFirebaseApp(firebaseConfig) + currentFirestore = FirebaseFirestore.getInstance(firebaseApp) + currentStorage = FirebaseStorage.getInstance(firebaseApp) + updateStatus = true + + } + + private fun getOrInitializeFirebaseApp(firebaseConfig: FirebaseConfig): FirebaseApp { + val existingApp = FirebaseApp.getApps(context).find { it.name == firebaseConfig.serverName } + + return if (existingApp != null) { + + existingApp + } else { + + val options = FirebaseOptions.Builder().setProjectId(firebaseConfig.projectId) + .setApplicationId(firebaseConfig.appId).setApiKey(firebaseConfig.apiKey) + .setStorageBucket(firebaseConfig.storageBucket).build() + + FirebaseApp.initializeApp(context, options, firebaseConfig.serverName) + } + } + + private fun saveSelectedServer(firebaseConfig: FirebaseConfig) { + with(sharedPreferences.edit()) { + putString("selectedServerName", firebaseConfig.serverName) + putString("projectId", firebaseConfig.projectId) + putString("appId", firebaseConfig.appId) + putString("apiKey", firebaseConfig.apiKey) + putString("storageBucket", firebaseConfig.storageBucket) + apply() + } + + } + + fun restartApp() { + if (updateStatus) { + updateStatus = false + delayedRestart(context) + } + } + + fun getLastSelectedServer(): FirebaseConfig { + val selectedServerName = + sharedPreferences.getString("selectedServerName", defaultServers.first().serverName) + val projectId = sharedPreferences.getString("projectId", defaultServers.first().projectId) + val appId = sharedPreferences.getString("appId", defaultServers.first().appId) + val apiKey = sharedPreferences.getString("apiKey", defaultServers.first().apiKey) + val storageBucket = + sharedPreferences.getString("storageBucket", defaultServers.first().storageBucket) + + return FirebaseConfig( + serverName = selectedServerName ?: defaultServers.first().serverName, + projectId = projectId ?: defaultServers.first().projectId, + appId = appId ?: defaultServers.first().appId, + apiKey = apiKey ?: defaultServers.first().apiKey, + storageBucket = storageBucket ?: defaultServers.first().storageBucket + ) + } + + fun getAvailableServers(): List { + return defaultServers + } +} + +fun restartApp(context: Context) { + val intent = context.packageManager.getLaunchIntentForPackage(context.packageName) + intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(intent) + Process.killProcess(Process.myPid()) +} +@OptIn(DelicateCoroutinesApi::class) +fun delayedRestart(context: Context) { + GlobalScope.launch(Dispatchers.Main) { + delay(5000L) + restartApp(context) + } +} + +private val firebaseConfig1 = FirebaseConfig( + serverName = "dev", + apiKey = "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I", + appId = "1:650071678820:android:a53292637abb7c0d6c6471", + projectId = "hpos-af3cc", + storageBucket = "hpos-af3cc.appspot.com" +) + +private val firebaseConfig2 = FirebaseConfig( + serverName = "qc-qa", + apiKey = "AIzaSyC4d4GhWHr_NMJAeBvnztQ_yQ3Qe9MAnLs", + appId = "1:1004619739289:android:3dbcefb10ea99654e5c808", + projectId = "hpos-qa", + storageBucket = "hpos-qa.appspot.com" +) + +private val firebaseConfig3 = FirebaseConfig( + serverName = "prod", + apiKey = "AIzaSyDYySi27LioZGNisP1NfnNU5inJX_0FT38", + appId = "1:121176529204:android:a7bc0842f61e5095bbed61", + projectId = "hpos-preprod", + storageBucket = "hpos-preprod.appspot.com" +) diff --git a/app/src/main/java/com/example/hpostesting/firebase/dataClass.kt b/app/src/main/java/com/example/hpostesting/firebase/dataClass.kt new file mode 100644 index 0000000..d25ef8c --- /dev/null +++ b/app/src/main/java/com/example/hpostesting/firebase/dataClass.kt @@ -0,0 +1,21 @@ +package com.example.hpostesting.firebase +/* + * // Copyright (c) 2024 ShanMukha Innovations Pvt. Ltd. All rights reserved. + * // Notice: All information contained herein is, and remains + * // the property of ShanMukha Innovations Pvt. Ltd. and its suppliers, + * // if any. The intellectual and technical concepts contained + * // herein are proprietary to ShanMukha Innovations Pvt. Ltd. + * // and its suppliers and may be covered by Indian and Foreign Patents, + * // patents in process, and are protected by trade secret or copyright law. + * // Dissemination of this information or reproduction of this material + * // is strictly forbidden unless prior written permission is obtained + * // from ShanMukha Innovations Pvt. Ltd. + */ +data class FirebaseConfig( + val serverName: String, + val apiKey: String, + val appId: String, + val projectId: String, + val storageBucket: String +) + diff --git a/app/src/main/java/com/example/hpostesting/presentation/MainActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/MainActivity.kt index fec0c30..dbda545 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/MainActivity.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/MainActivity.kt @@ -30,10 +30,9 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.core.view.get -import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.Constants +import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.LanguageManager -import com.example.hpostesting.data.model.patient.UserData import com.example.hpostesting.data.model.test.TestType import com.example.hpostesting.presentation.dashboard.DashboardActivity import com.google.android.gms.location.FusedLocationProviderClient @@ -48,7 +47,6 @@ import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { - private lateinit var binding: ActivityMainBinding private var myMenu: Menu? = null private val TAG = "MainActivity" @@ -73,6 +71,7 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) binding.myToolbar.title = "Test Type" @@ -81,6 +80,7 @@ class MainActivity : AppCompatActivity() { setupListeners() fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) getLocation() + locationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult) { locationResult.lastLocation?.let { location -> @@ -92,7 +92,6 @@ class MainActivity : AppCompatActivity() { } } } - val usbFilter = IntentFilter().apply { addAction(UsbManager.ACTION_USB_DEVICE_DETACHED) addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED) @@ -117,6 +116,7 @@ class MainActivity : AppCompatActivity() { // } } + private fun checkAndUpdateUsbConnection() { val availableDrivers = UsbSerialProber.getDefaultProber() .findAllDrivers(getSystemService(Context.USB_SERVICE) as UsbManager) diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/ActivitiesFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/ActivitiesFragment.kt index a47b222..ef26f40 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/ActivitiesFragment.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/ActivitiesFragment.kt @@ -14,25 +14,17 @@ package com.example.hpostesting.presentation.dashboard import android.content.Context -import android.content.SharedPreferences import android.os.BatteryManager import android.os.Bundle import android.util.Log -import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels -import com.example.hpostesting.data.constant.Constants -import com.example.hpostesting.data.constant.DataHolder -import com.example.hpostesting.data.model.patient.HemoCubeTestData import com.example.hpostesting.presentation.adapter.OfflineUserListAdapter -import com.example.hpostesting.presentation.adapter.UserListAdapter import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel -import com.example.hpostesting.presentation.testRight.TestRightViewModel -import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.databinding.FragmentActivitiesBinding -import `in`.sminnovations.hpostesting.databinding.FragmentHomeBinding import java.text.SimpleDateFormat import java.util.Calendar import java.util.Date @@ -58,7 +50,7 @@ class ActivitiesFragment : Fragment() { if (userData.isNotEmpty()) { userData.forEach { user -> - if(isBetween15And30Minutes(user.incubationTime) > 30 && user.testStatus == false){ + if((isBetween15And30Minutes(user.incubationTime) > 30 || isBetween15And30Minutes(user.incubationTime) < 0 ) && user.testStatus == false){ hemoCubeViewModel.deleteByStatus() } } diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/AppVersionTapManage.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/AppVersionTapManage.kt new file mode 100644 index 0000000..661c2f8 --- /dev/null +++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/AppVersionTapManage.kt @@ -0,0 +1,18 @@ +package com.example.hpostesting.presentation.dashboard + +class AppVersionTapManager { + + private var tapCount = 0 + private val maxTapCount = 5 + + fun registerTap(onMaxTapsReached: () -> Unit) { + tapCount++ + if (tapCount >= maxTapCount) { + onMaxTapsReached() + reset() + } + } + private fun reset() { + tapCount = 0 + } +} diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt index 054c766..406f0a4 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/DashboardActivity.kt @@ -33,19 +33,15 @@ import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.navigateUp import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController -import com.example.hpostesting.util.Result import com.example.hpostesting.data.constant.Constants -import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.LanguageManager -import com.example.hpostesting.data.model.login.LoginRequest import com.example.hpostesting.data.model.updates.DeviceUpdateRequest -import com.example.hpostesting.presentation.utils.NatsManager +import com.example.hpostesting.data.repository.DatabaseRepository +import com.example.hpostesting.firebase.FirebaseManager import com.example.hpostesting.presentation.hemocube.HemoCubeViewModel import com.example.hpostesting.presentation.jig.JigActivity +import com.example.hpostesting.presentation.utils.NatsManager import com.google.android.material.navigation.NavigationView -import com.google.firebase.appdistribution.FirebaseAppDistribution -import com.google.firebase.appdistribution.FirebaseAppDistributionException -import com.google.firebase.crashlytics.FirebaseCrashlytics import com.google.firebase.ktx.Firebase import com.google.firebase.remoteconfig.FirebaseRemoteConfig import com.google.firebase.remoteconfig.ktx.remoteConfig @@ -56,6 +52,7 @@ import `in`.sminnovations.hpostesting.R import `in`.sminnovations.hpostesting.databinding.ActivityDashboardBinding import java.io.File import java.security.MessageDigest +import javax.inject.Inject interface NatsMessageCallback { fun onMessageReceived(topic: String, message: String) @@ -68,6 +65,8 @@ open interface IDataCollector: NatsMessageCallback { @AndroidEntryPoint class DashboardActivity : AppCompatActivity(), IDataCollector { + @Inject + lateinit var databaseRepository: DatabaseRepository private val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig val TAG = "DashboardActivity" private var isRegistered = false @@ -76,6 +75,7 @@ class DashboardActivity : AppCompatActivity(), IDataCollector { lateinit var sharedPreferences: SharedPreferences var responses: String = "" lateinit var nats: NatsManager + private var downloadId: Long = 0 // TODO: Remove hemocube viewmodel private val hemocubeViewModel: HemoCubeViewModel by viewModels() @@ -95,11 +95,20 @@ class DashboardActivity : AppCompatActivity(), IDataCollector { @SuppressLint("SetWorldReadable") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + val firebaseManager = FirebaseManager(this) binding = ActivityDashboardBinding.inflate(layoutInflater) sharedPreferences = this.getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) setContentView(binding.root) setSupportActionBar(binding.appBarDashboard.toolbar) nats = NatsManager(this) + + + // Load the last selected server or default to Server 1 + val lastSelectedServer = firebaseManager.getLastSelectedServer() + + // Switch to the last selected server + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { nats.connect() } @@ -250,6 +259,12 @@ class DashboardActivity : AppCompatActivity(), IDataCollector { + fun sendData(data:String){ + databaseRepository.addtodb(data) + Toast.makeText(this, "data uploaded", Toast.LENGTH_SHORT).show() + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { // Inflate the menu; this adds items to the action bar if it is present. menuInflater.inflate(R.menu.dashboard, menu) diff --git a/app/src/main/java/com/example/hpostesting/presentation/dashboard/SlideshowFragment.kt b/app/src/main/java/com/example/hpostesting/presentation/dashboard/SlideshowFragment.kt index f49a4f5..28e54ee 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/dashboard/SlideshowFragment.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/dashboard/SlideshowFragment.kt @@ -13,6 +13,7 @@ package com.example.hpostesting.presentation.dashboard +import android.app.AlertDialog import android.content.Context import android.content.SharedPreferences import android.content.pm.PackageManager @@ -23,7 +24,7 @@ import android.view.ViewGroup import android.widget.AdapterView import android.widget.ArrayAdapter import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.preference.ListPreference import androidx.preference.Preference @@ -31,127 +32,231 @@ import androidx.preference.PreferenceFragmentCompat import com.example.hpostesting.data.constant.Constants import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.LanguageManager -import com.example.hpostesting.data.model.TestState -import com.example.hpostesting.data.model.patient.toHemoCubeTestData +import com.example.hpostesting.data.repository.DatabaseRepository +import com.example.hpostesting.firebase.FirebaseConfig +import com.example.hpostesting.firebase.FirebaseManager import `in`.sminnovations.hpostesting.R -import `in`.sminnovations.hpostesting.databinding.FragmentHemoCubeReferenceBinding import `in`.sminnovations.hpostesting.databinding.FragmentSlideshowBinding private var isLanguageChanged = false -class SlideshowFragment : Fragment(){ +class SlideshowFragment : Fragment() { private var selectedItem = "10mm" private val values = arrayOf("10mm", "2mm") private lateinit var binding: FragmentSlideshowBinding private lateinit var sharedPreferences: SharedPreferences + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, ): View { binding = FragmentSlideshowBinding.inflate(inflater, container, false) - sharedPreferences = - requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) + sharedPreferences = requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding.nameEditText.setText(sharedPreferences.getString(Constants.LABNAME,"")) + binding.nameEditText.setText(sharedPreferences.getString(Constants.LABNAME, "")) - selectedItem = sharedPreferences.getString(Constants.CUVETTE_SIZE,"10mm").toString() - val time = sharedPreferences.getString(Constants.LAST_UPDATED,"NA").toString() + selectedItem = sharedPreferences.getString(Constants.CUVETTE_SIZE, "10mm").toString() + val time = sharedPreferences.getString(Constants.LAST_UPDATED, "NA").toString() binding.lastUpdated.text = "Last updated config: $time" binding.btnGo.setOnClickListener { var labname = binding.nameEditText.text.toString() DataHolder.hemoCubeTestData?.apply { this.labName = labname } - with(sharedPreferences.edit()) { putString(Constants.LABNAME, labname) apply() } Toast.makeText( - requireContext(), - "Lab Name is Added successfully.", - Toast.LENGTH_SHORT + requireContext(), "Lab Name is Added successfully.", Toast.LENGTH_SHORT ).show() } val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, values) adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) val pos: Int - if(selectedItem == "10mm"){ + if (selectedItem == "10mm") { pos = 0 - }else{ + } else { pos = 1 } binding.spinnerCuvette.adapter = adapter - binding.spinnerCuvette.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { - override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - // Handle item selection here - selectedItem = values[position] - } + binding.spinnerCuvette.onItemSelectedListener = + object : AdapterView.OnItemSelectedListener { + override fun onItemSelected( + parent: AdapterView<*>?, view: View?, position: Int, id: Long + ) { + // Handle item selection here + selectedItem = values[position] + } - override fun onNothingSelected(parent: AdapterView<*>?) { - // Do nothing here + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing here + } } - } binding.spinnerCuvette.setSelection(pos) binding.btnAddSize.setOnClickListener { with(sharedPreferences.edit()) { putString(Constants.CUVETTE_SIZE, selectedItem) apply() } - Toast.makeText(requireContext(), "Selected cuvette size: $selectedItem", Toast.LENGTH_SHORT).show() + Toast.makeText( + requireContext(), "Selected cuvette size: $selectedItem", Toast.LENGTH_SHORT + ).show() } - childFragmentManager.beginTransaction().replace(binding.container.id,PrefsFragment()).commit() + childFragmentManager.beginTransaction().replace(binding.container.id, PrefsFragment()) + .commit() } } -class PrefsFragment: PreferenceFragmentCompat(){ + +class PrefsFragment : PreferenceFragmentCompat(){ + private lateinit var tapManager: AppVersionTapManager + private var isServerSelectionVisible = false + private lateinit var serverPreference: Preference + private lateinit var currentServerPreference: Preference + lateinit var firebaseManager: FirebaseManager + lateinit var databaseRepository: DatabaseRepository + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + firebaseManager = FirebaseManager(requireContext()) + databaseRepository = (activity as DashboardActivity).databaseRepository + + tapManager = AppVersionTapManager() + val sharedPreference = + requireContext().getSharedPreferences("HEMOCUBE", Context.MODE_PRIVATE) val preferenceScreen = preferenceManager.createPreferenceScreen(requireContext()) + val currentServer = firebaseManager.getLastSelectedServer().serverName - val languagePreference = ListPreference(requireContext()) - languagePreference.key = "language_preference" - languagePreference.title = getString(R.string.app_language) - languagePreference.summary = getString(R.string.select_language) - languagePreference.entries = arrayOf("English", "Kannada", "Hindi") - languagePreference.entryValues = arrayOf("en", "kn", "hi") - languagePreference.setDefaultValue("en") + // Language Preference + val languagePreference = ListPreference(requireContext()).apply { + key = "language_preference" + title = getString(R.string.app_language) + summary = getString(R.string.select_language) + entries = arrayOf("English", "Kannada", "Hindi") + entryValues = arrayOf("en", "kn", "hi") + setDefaultValue("en") + icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_translate_24) - languagePreference.onPreferenceChangeListener = - Preference.OnPreferenceChangeListener { _, newValue -> + onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> val languageCode = newValue as String updateLanguage(requireContext(), languageCode) true } - + } preferenceScreen.addPreference(languagePreference) - setPreferenceScreen(preferenceScreen) - // App Version Preference - val appVersionPreference = Preference(requireContext()) - appVersionPreference.title = "App Version" - appVersionPreference.summary = - getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) + " ]" + val appVersionPreference = Preference(requireContext()).apply { + title = "App Version" + summary = + getAppVersion(requireContext()) + " [ " + getAppEnvironment(requireContext()) +"->"+currentServer+"]" + icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_info_24) - preferenceScreen.addPreference(languagePreference) + setOnPreferenceClickListener { + if ((sharedPreference.getString(Constants.USER_ID, "").toString() == "ADMIN")) { + tapManager.registerTap { + if (!isServerSelectionVisible) { + showServerSelection() + } + } + } else { + + } + true + } + + } preferenceScreen.addPreference(appVersionPreference) + + + currentServerPreference = Preference(requireContext()).apply { + key = "current_server_preference" + title = "Current Server" + summary = "No server selected" + isVisible = false + icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_cloud_done_24) + + setOnPreferenceClickListener { + (activity as? DashboardActivity)?.sendData("hello test data") + Toast.makeText(context, "data sent", Toast.LENGTH_SHORT).show() + true + } + } + preferenceScreen.addPreference(currentServerPreference) setPreferenceScreen(preferenceScreen) + if (isLanguageChanged) { Toast.makeText(requireContext(), R.string.language_update, Toast.LENGTH_SHORT).show() } + } + + + private fun showServerSelection() { + val currentServer = firebaseManager.getLastSelectedServer().serverName + serverPreference = Preference(requireContext()).apply { + title = "Select Server" + summary = "Choose your server" + icon = ContextCompat.getDrawable(requireContext(), R.drawable.baseline_cloud_sync_24) + setOnPreferenceClickListener { + showServerSelectionDialog() + true + } + } + + + + preferenceScreen.addPreference(serverPreference) + currentServerPreference.isVisible = true + currentServerPreference.summary = "Current Server: $currentServer" + + Toast.makeText(requireContext(), "Server selection now available", Toast.LENGTH_SHORT).show() + } + + private fun showServerSelectionDialog() { + val servers = firebaseManager.getAvailableServers() + + val serverNames = servers.map { it.serverName }.toTypedArray() + val builder = AlertDialog.Builder(requireContext()) + builder.setTitle("Select Server") + .setItems(serverNames) { _, which -> + val selectedServer = servers[which] + + switchFirebaseServer(selectedServer) + } + .setNegativeButton("Cancel", null) + .show() + } + + + private fun switchFirebaseServer(firebaseConfig: FirebaseConfig) { + firebaseManager.switchServer(firebaseConfig) + Toast.makeText(requireContext(), "Switched to ${firebaseConfig.serverName}", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), "Restart needed restarting the app", Toast.LENGTH_SHORT).show() + firebaseManager.restartApp() + currentServerPreference.summary = "Current Server: ${firebaseConfig.serverName}" } + + + private fun switchCurrentServer(serverCode: String) { + Toast.makeText(requireContext(), "Switched to server: $serverCode", Toast.LENGTH_SHORT) + .show() + currentServerPreference.summary = "Current Server: $serverCode" + + } + private fun updateLanguage(context: Context, languageCode: String) { LanguageManager.persistLanguagePreference(context, languageCode) LanguageManager.setLocale(context, languageCode) - requireActivity().recreate() // Recreate activity to apply language changes + requireActivity().recreate() isLanguageChanged = true } + private fun getAppVersion(context: Context): String { return try { val pInfo = context.packageManager.getPackageInfo(context.packageName, 0) @@ -169,4 +274,6 @@ class PrefsFragment: PreferenceFragmentCompat(){ "N/A" } } -} \ No newline at end of file +} + + diff --git a/app/src/main/java/com/example/hpostesting/presentation/hb_test/HBTestActivity.kt b/app/src/main/java/com/example/hpostesting/presentation/hb_test/HBTestActivity.kt index 8f1ebf2..46d910f 100644 --- a/app/src/main/java/com/example/hpostesting/presentation/hb_test/HBTestActivity.kt +++ b/app/src/main/java/com/example/hpostesting/presentation/hb_test/HBTestActivity.kt @@ -33,19 +33,24 @@ import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.core.view.get -import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.Constants +import com.example.hpostesting.data.constant.DataHolder import com.example.hpostesting.data.constant.LanguageManager +import com.example.hpostesting.data.repository.DatabaseRepository +import com.example.hpostesting.firebase.FirebaseManager import com.example.hpostesting.util.UsbService import com.hoho.android.usbserial.driver.UsbSerialDriver import com.hoho.android.usbserial.driver.UsbSerialProber import dagger.hilt.android.AndroidEntryPoint import `in`.sminnovations.hpostesting.R -import `in`.sminnovations.hpostesting.databinding.ActivityAutoDacBinding import `in`.sminnovations.hpostesting.databinding.ActivityHbTestBinding +import javax.inject.Inject @AndroidEntryPoint class HBTestActivity : AppCompatActivity() { + + @Inject + lateinit var databaseRepository: DatabaseRepository private lateinit var binding: ActivityHbTestBinding val viewModel: HBTestViewModel by viewModels() private var myMenu: Menu? = null @@ -97,6 +102,10 @@ class HBTestActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + val firebaseManager = FirebaseManager(this) + val lastSelectedServer = firebaseManager.getLastSelectedServer() +// switchFirebaseServer(lastSelectedServer) + Log.d("CURRENT SERVR......","server : ${lastSelectedServer.serverName}") binding = ActivityHbTestBinding.inflate(layoutInflater) setContentView(binding.root) // setSupportActionBar(binding.myToolbar) @@ -105,7 +114,11 @@ class HBTestActivity : AppCompatActivity() { connectUsb(false) } - +// private fun switchFirebaseServer(config: FirebaseConfig) { +// val (newFirestore, newStorage) = firebaseManager.switchFirestoreServer(config) +// databaseRepository.switchServer(newFirestore, newStorage) +//// Toast.makeText(this, "server switched", Toast.LENGTH_SHORT).show()// Update repository with new Firestore and Storage +// } private fun setupListener() { DataHolder.usbConnected.observe(this) { Log.d("USB OBSERVE", "HemoCube called -> $it") diff --git a/app/src/main/res/drawable/baseline_cloud_done_24.xml b/app/src/main/res/drawable/baseline_cloud_done_24.xml new file mode 100644 index 0000000..8360863 --- /dev/null +++ b/app/src/main/res/drawable/baseline_cloud_done_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/baseline_cloud_sync_24.xml b/app/src/main/res/drawable/baseline_cloud_sync_24.xml new file mode 100644 index 0000000..96a5abb --- /dev/null +++ b/app/src/main/res/drawable/baseline_cloud_sync_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/baseline_info_24.xml b/app/src/main/res/drawable/baseline_info_24.xml new file mode 100644 index 0000000..ef3a1fe --- /dev/null +++ b/app/src/main/res/drawable/baseline_info_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/layout/activity_kit_scan.xml b/app/src/main/res/layout/activity_kit_scan.xml index 3d1ebd0..9e3f4cf 100644 --- a/app/src/main/res/layout/activity_kit_scan.xml +++ b/app/src/main/res/layout/activity_kit_scan.xml @@ -45,6 +45,7 @@ android:layout_marginHorizontal="24dp" android:layout_marginTop="16dp" android:text="@string/scan_qr_code_of_the_kit" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/app_bar_layout" /> @@ -58,6 +59,7 @@ android:textColor="@color/black" app:backgroundTint="@color/blue_app_light" app:cornerRadius="100dp" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv_title" /> diff --git a/app/src/main/res/layout/fragment_jig.xml b/app/src/main/res/layout/fragment_jig.xml index 7a4bd3f..5b42796 100644 --- a/app/src/main/res/layout/fragment_jig.xml +++ b/app/src/main/res/layout/fragment_jig.xml @@ -76,6 +76,7 @@ android:textColor="@color/black" app:backgroundTint="@color/blue_app_light" app:cornerRadius="100dp" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv_title" /> @@ -103,9 +104,9 @@ android:clickable="false" android:gravity="center" android:text="Refresh" - android:visibility="visible" android:textColor="@color/white" - app:layout_constraintEnd_toEndOf="@id/btn_scan_now" + android:visibility="visible" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_scan_now" /> diff --git a/app/src/main/res/layout/fragment_register_one_create_abha.xml b/app/src/main/res/layout/fragment_register_one_create_abha.xml index c6a88be..66dac6c 100644 --- a/app/src/main/res/layout/fragment_register_one_create_abha.xml +++ b/app/src/main/res/layout/fragment_register_one_create_abha.xml @@ -53,6 +53,7 @@ android:textColor="@color/black" app:backgroundTint="@color/blue_app_light" app:cornerRadius="100dp" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv_title2" /> diff --git a/app/src/main/res/layout/server_selector_drop_down.xml b/app/src/main/res/layout/server_selector_drop_down.xml new file mode 100644 index 0000000..aec52d6 --- /dev/null +++ b/app/src/main/res/layout/server_selector_drop_down.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + diff --git a/app/src/test/java/com/example/hpostesting/SlideShowFragmentTest.kt b/app/src/test/java/com/example/hpostesting/SlideShowFragmentTest.kt new file mode 100644 index 0000000..6e92925 --- /dev/null +++ b/app/src/test/java/com/example/hpostesting/SlideShowFragmentTest.kt @@ -0,0 +1,72 @@ +package com.example.hpostesting + + +import android.content.Context +import com.example.hpostesting.firebase.AppRestarter +import com.example.hpostesting.firebase.FirebaseConfig +import com.example.hpostesting.firebase.FirebaseManager +import com.example.hpostesting.firebase.SharedPreferencesWrapper +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito.* +import org.mockito.MockitoAnnotations + +class FirebaseManagerTest { + @Mock + private lateinit var context: Context + + @Mock + private lateinit var sharedPreferencesWrapper: SharedPreferencesWrapper + + @Mock + private lateinit var appRestarter: AppRestarter + + private lateinit var firebaseManager: FirebaseManager + + @Before + fun setup() { + MockitoAnnotations.openMocks(this) + firebaseManager = FirebaseManager(context, sharedPreferencesWrapper, appRestarter) + } + + @Test + fun testSwitchServer() { + val testConfig = FirebaseConfig("test", "testProject", "testApp", "testKey", "testBucket") + firebaseManager.switchServer(testConfig) + + verify(sharedPreferencesWrapper).saveSelectedServer(testConfig) + assert(firebaseManager.updateStatus) + } + + + + @Test + fun testGetLastSelectedServer() { + val defaultConfig = FirebaseConfig("default", "defaultProject", "defaultApp", "defaultKey", "defaultBucket") + `when`(sharedPreferencesWrapper.getLastSelectedServer(any())).thenReturn(defaultConfig) + + val result = firebaseManager.getLastSelectedServer() + assert(result == defaultConfig) + } + + @Test + fun testGetAvailableServers() { + val servers = firebaseManager.getAvailableServers() + assert(servers.size == 2) // Assuming we have two default servers + } +} +//private val firebaseConfig2 = FirebaseConfig( +// serverName = "dev", +// apiKey = "AIzaSyAVdNGCev_AFX0qmuZJF6kxzRzXUTeAW5I", +// appId = "1:650071678820:android:a53292637abb7c0d6c6471", +// projectId = "hpos-af3cc", +// storageBucket = "hpos-af3cc.appspot.com" +//) +//private val firebaseConfig1 = FirebaseConfig( +// serverName = "custom", +// apiKey = "AIzaSyC26TIlV4alLHdKeQ6EAMQ5HYexCPFcAfA", +// appId = "1:536584948074:android:754565f322a5cdeaa9fd13", +// projectId = "remotesereverforhops1", +// storageBucket = "remotesereverforhops1.appspot.com" +//)