diff --git a/app/src/main/java/org/ole/planet/myplanet/base/BaseRecyclerFragment.kt b/app/src/main/java/org/ole/planet/myplanet/base/BaseRecyclerFragment.kt index cfb2abc90a..64dfbbb1f9 100644 --- a/app/src/main/java/org/ole/planet/myplanet/base/BaseRecyclerFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/base/BaseRecyclerFragment.kt @@ -298,6 +298,7 @@ abstract class BaseRecyclerFragment
  • : BaseRecyclerParentFragment(), On "submission" -> (v as TextView).setText(R.string.no_submissions) "teams" -> (v as TextView).setText(R.string.no_teams) "chatHistory" -> (v as TextView).setText(R.string.no_chats) + "feedback" -> (v as TextView).setText(R.string.no_feedback) else -> (v as TextView).setText(R.string.no_data_available_please_check_and_try_again) } } diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/courses/CourseStepFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/courses/CourseStepFragment.kt index fd61014b61..e2a44d1c8d 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/courses/CourseStepFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/courses/CourseStepFragment.kt @@ -25,7 +25,7 @@ import org.ole.planet.myplanet.model.RealmSubmission import org.ole.planet.myplanet.model.RealmUserModel import org.ole.planet.myplanet.service.UserProfileDbHandler import org.ole.planet.myplanet.ui.exam.TakeExamFragment -import org.ole.planet.myplanet.utilities.CameraUtils.CapturePhoto +import org.ole.planet.myplanet.utilities.CameraUtils.capturePhoto import org.ole.planet.myplanet.utilities.CameraUtils.ImageCaptureCallback import org.ole.planet.myplanet.utilities.Constants import org.ole.planet.myplanet.utilities.Constants.showBetaFeature @@ -164,7 +164,7 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback { takeExam.arguments = b homeItemClickListener?.openCallFragment(takeExam) context?.let { it1 -> - CapturePhoto(it1, object : ImageCaptureCallback { + capturePhoto(it1, object : ImageCaptureCallback { override fun onImageCapture(fileUri: String?) { } }) diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/exam/TakeExamFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/exam/TakeExamFragment.kt index b698a9102f..e47cb79318 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/exam/TakeExamFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/exam/TakeExamFragment.kt @@ -21,7 +21,7 @@ import org.ole.planet.myplanet.model.RealmExamQuestion import org.ole.planet.myplanet.model.RealmSubmission import org.ole.planet.myplanet.model.RealmSubmission.Companion.createSubmission import org.ole.planet.myplanet.service.UserProfileDbHandler -import org.ole.planet.myplanet.utilities.CameraUtils.CapturePhoto +import org.ole.planet.myplanet.utilities.CameraUtils.capturePhoto import org.ole.planet.myplanet.utilities.CameraUtils.ImageCaptureCallback import org.ole.planet.myplanet.utilities.JsonParserUtils.getStringAsJsonArray import org.ole.planet.myplanet.utilities.JsonUtils.getString @@ -210,7 +210,7 @@ class TakeExamFragment : BaseExamFragment(), View.OnClickListener, CompoundButto try { if (isCertified && !isMySurvey) { context?.let { it1 -> - CapturePhoto(it1, object : ImageCaptureCallback { + capturePhoto(it1, object : ImageCaptureCallback { override fun onImageCapture(fileUri: String?) { } }) diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/feedback/FeedbackListFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/feedback/FeedbackListFragment.kt index 09d5b33970..bf49250c18 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/feedback/FeedbackListFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/feedback/FeedbackListFragment.kt @@ -14,6 +14,7 @@ import org.ole.planet.myplanet.model.RealmFeedback import org.ole.planet.myplanet.model.RealmUserModel import org.ole.planet.myplanet.service.UserProfileDbHandler import org.ole.planet.myplanet.ui.feedback.FeedbackFragment.OnFeedbackSubmittedListener +import org.ole.planet.myplanet.base.BaseRecyclerFragment.Companion.showNoData class FeedbackListFragment : Fragment(), OnFeedbackSubmittedListener { private lateinit var fragmentFeedbackListBinding: FragmentFeedbackListBinding @@ -25,6 +26,7 @@ class FeedbackListFragment : Fragment(), OnFeedbackSubmittedListener { fragmentFeedbackListBinding = FragmentFeedbackListBinding.inflate(inflater, container, false) mRealm = DatabaseService(requireActivity()).realmInstance userModel = UserProfileDbHandler(requireContext()).userModel + fragmentFeedbackListBinding.fab.setOnClickListener { val feedbackFragment = FeedbackFragment() feedbackFragment.setOnFeedbackSubmittedListener(this) @@ -33,15 +35,13 @@ class FeedbackListFragment : Fragment(), OnFeedbackSubmittedListener { } } - mRealm.executeTransactionAsync( - Realm.Transaction { }, - Realm.Transaction.OnSuccess { - feedbackList = mRealm.where(RealmFeedback::class.java) - .equalTo("owner", userModel?.name).findAllAsync() - feedbackList?.addChangeListener { results -> - updatedFeedbackList(results) - } - }) + feedbackList = mRealm.where(RealmFeedback::class.java) + .equalTo("owner", userModel?.name).findAllAsync() + + feedbackList?.addChangeListener { results -> + updatedFeedbackList(results) + } + return fragmentFeedbackListBinding.root } @@ -53,6 +53,11 @@ class FeedbackListFragment : Fragment(), OnFeedbackSubmittedListener { if (userModel?.isManager() == true) list = mRealm.where(RealmFeedback::class.java).findAll() val adapterFeedback = AdapterFeedback(requireActivity(), list) fragmentFeedbackListBinding.rvFeedback.adapter = adapterFeedback + + val itemCount = feedbackList?.size ?: 0 + showNoData(fragmentFeedbackListBinding.tvMessage, itemCount, "feedback") + + updateTextViewsVisibility(itemCount) } override fun onDestroy() { @@ -74,11 +79,25 @@ class FeedbackListFragment : Fragment(), OnFeedbackSubmittedListener { updatedFeedbackList(updatedList) }) } + private fun updatedFeedbackList(updatedList: RealmResults?) { activity?.runOnUiThread { val adapterFeedback = updatedList?.let { AdapterFeedback(requireActivity(), it) } fragmentFeedbackListBinding.rvFeedback.adapter = adapterFeedback adapterFeedback?.notifyDataSetChanged() + + val itemCount = updatedList?.size ?: 0 + showNoData(fragmentFeedbackListBinding.tvMessage, itemCount, "feedback") + updateTextViewsVisibility(itemCount) } } + + private fun updateTextViewsVisibility(itemCount: Int) { + val visibility = if (itemCount == 0) View.GONE else View.VISIBLE + fragmentFeedbackListBinding.tvTitle.visibility = visibility + fragmentFeedbackListBinding.tvType.visibility = visibility + fragmentFeedbackListBinding.tvPriority.visibility = visibility + fragmentFeedbackListBinding.tvStatus.visibility = visibility + fragmentFeedbackListBinding.tvOpenDate.visibility = visibility + } } diff --git a/app/src/main/java/org/ole/planet/myplanet/utilities/CameraUtils.kt b/app/src/main/java/org/ole/planet/myplanet/utilities/CameraUtils.kt index 59efc46ee8..b9caaf7d66 100644 --- a/app/src/main/java/org/ole/planet/myplanet/utilities/CameraUtils.kt +++ b/app/src/main/java/org/ole/planet/myplanet/utilities/CameraUtils.kt @@ -6,24 +6,28 @@ import android.content.pm.PackageManager import android.graphics.ImageFormat import android.graphics.SurfaceTexture import android.hardware.camera2.* +import android.hardware.camera2.params.OutputConfiguration +import android.hardware.camera2.params.SessionConfiguration import android.media.ImageReader +import android.os.Build import android.os.Handler import android.os.HandlerThread -import android.util.Size import android.view.Surface import androidx.core.content.ContextCompat import java.io.File import java.io.FileOutputStream import java.util.* +import java.util.concurrent.Executors object CameraUtils { private var cameraDevice: CameraDevice? = null private var captureSession: CameraCaptureSession? = null private var imageReader: ImageReader? = null private var backgroundHandler: Handler - private var backgroundThread: HandlerThread + private var backgroundThread: HandlerThread = HandlerThread("CameraBackground") + @JvmStatic - fun CapturePhoto(context: Context, callback: ImageCaptureCallback) { + fun capturePhoto(context: Context, callback: ImageCaptureCallback) { if (ContextCompat.checkSelfPermission( context, Manifest.permission.CAMERA @@ -48,11 +52,7 @@ object CameraUtils { captureBuilder?.addTarget(imageReader!!.surface) captureBuilder?.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE) - val captureCallback = object : CameraCaptureSession.CaptureCallback() { - override fun onCaptureCompleted(session: CameraCaptureSession, request: CaptureRequest, result: TotalCaptureResult) { - super.onCaptureCompleted(session, request, result) - } - } + val captureCallback = object : CameraCaptureSession.CaptureCallback() {} captureSession?.stopRepeating() captureSession?.abortCaptures() @@ -83,13 +83,6 @@ object CameraUtils { val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager try { val cameraId = manager.cameraIdList[0] // Assuming we want to use the first (rear) camera - val characteristics = manager.getCameraCharacteristics(cameraId) - val map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) - val largest = Collections.max( - listOf(*map!!.getOutputSizes(ImageFormat.JPEG)), - CompareSizesByArea() - ) - val reader = ImageReader.newInstance(largest.width, largest.height, ImageFormat.JPEG, 2) manager.openCamera(cameraId, object : CameraDevice.StateCallback() { override fun onOpened(camera: CameraDevice) { cameraDevice = camera @@ -117,9 +110,10 @@ object CameraUtils { val surface = Surface(texture) val captureRequestBuilder = cameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW) captureRequestBuilder.addTarget(surface) - cameraDevice!!.createCaptureSession( - listOf(surface), - object : CameraCaptureSession.StateCallback() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + val outputConfigurations = listOf(OutputConfiguration(surface)) + val executor = Executors.newSingleThreadExecutor() + val stateCallback = object : CameraCaptureSession.StateCallback() { override fun onConfigured(session: CameraCaptureSession) { if (cameraDevice == null) return captureSession = session @@ -139,9 +133,44 @@ object CameraUtils { } override fun onConfigureFailed(session: CameraCaptureSession) {} - }, - backgroundHandler - ) + } + + val sessionConfiguration = SessionConfiguration( + SessionConfiguration.SESSION_REGULAR, + outputConfigurations, + executor, + stateCallback + ) + + cameraDevice!!.createCaptureSession(sessionConfiguration) + } else { + @Suppress("DEPRECATION") + cameraDevice!!.createCaptureSession( + listOf(surface), + object : CameraCaptureSession.StateCallback() { + override fun onConfigured(session: CameraCaptureSession) { + if (cameraDevice == null) return + captureSession = session + try { + captureRequestBuilder.set( + CaptureRequest.CONTROL_AF_MODE, + CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE + ) + captureSession!!.setRepeatingRequest( + captureRequestBuilder.build(), + null, + backgroundHandler + ) + } catch (e: CameraAccessException) { + e.printStackTrace() + } + } + + override fun onConfigureFailed(session: CameraCaptureSession) {} + }, + backgroundHandler + ) + } } catch (e: CameraAccessException) { e.printStackTrace() } @@ -151,13 +180,7 @@ object CameraUtils { fun onImageCapture(fileUri: String?) } - private class CompareSizesByArea : Comparator { - override fun compare(lhs: Size, rhs: Size): Int { - return java.lang.Long.signum(lhs.width.toLong() * lhs.height - rhs.width.toLong() * rhs.height) - } - } init { - backgroundThread = HandlerThread("CameraBackground") backgroundThread.start() backgroundHandler = Handler(backgroundThread.looper) } diff --git a/app/src/main/java/org/ole/planet/myplanet/utilities/FileUtils.kt b/app/src/main/java/org/ole/planet/myplanet/utilities/FileUtils.kt index d1436a27a1..f8f48ebf93 100644 --- a/app/src/main/java/org/ole/planet/myplanet/utilities/FileUtils.kt +++ b/app/src/main/java/org/ole/planet/myplanet/utilities/FileUtils.kt @@ -1,5 +1,6 @@ package org.ole.planet.myplanet.utilities +import android.app.PendingIntent import android.app.usage.StorageStatsManager import android.content.Context import android.content.Intent @@ -13,9 +14,8 @@ import android.provider.MediaStore import android.text.TextUtils import android.webkit.MimeTypeMap import androidx.annotation.RequiresApi -import androidx.core.content.FileProvider -import org.ole.planet.myplanet.BuildConfig import org.ole.planet.myplanet.MainApplication +import android.content.pm.PackageInstaller import org.ole.planet.myplanet.R import java.io.BufferedReader import java.io.File @@ -116,29 +116,42 @@ object FileUtils { @JvmStatic fun installApk(activity: Context, file: String?) { + if (!file?.endsWith("apk")!!) return + val toInstall = File(file) + if (!toInstall.exists()) return try { - if (!file?.endsWith("apk")!!) return - val toInstall = getSDPathFromUrl(file) - toInstall.setReadable(true, false) - val apkUri: Uri - val intent: Intent - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - apkUri = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".provider", toInstall) - intent = Intent(Intent.ACTION_INSTALL_PACKAGE) - intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - intent.setData(apkUri) - } else { - apkUri = Uri.fromFile(toInstall) - intent = Intent(Intent.ACTION_VIEW) - intent.setDataAndType(apkUri, "application/vnd.android.package-archive") - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - } - activity.startActivity(intent) + val packageInstaller = activity.packageManager.packageInstaller + val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL) + val sessionId = packageInstaller.createSession(params) + val session = packageInstaller.openSession(sessionId) + addApkToInstallSession(toInstall, session) + val intent = Intent(activity, activity.javaClass) + val pendingIntent = PendingIntent.getActivity(activity, 0, intent, + PendingIntent.FLAG_IMMUTABLE) + val intentSender = pendingIntent.intentSender + session.commit(intentSender) + session.close() } catch (e: Exception) { e.printStackTrace() } } + @Throws(IOException::class) + private fun addApkToInstallSession(apkFile: File, session: PackageInstaller.Session) { + val out: OutputStream = session.openWrite("my_app_session", 0, -1) + val fis = FileInputStream(apkFile) + fis.use { input -> + out.use { output -> + val buffer = ByteArray(4096) + var length: Int + while (input.read(buffer).also { length = it } != -1) { + output.write(buffer, 0, length) + } + session.fsync(out) + } + } + } + private fun getMimeType(url: String): String? { var type: String? = null val extension = MimeTypeMap.getFileExtensionFromUrl(url) @@ -223,24 +236,39 @@ object FileUtils { @JvmStatic fun getImagePath(context: Context, uri: Uri?): String? { - var cursor = uri?.let { context.contentResolver.query(it, null, null, null, null) } - return if (cursor != null && cursor.moveToFirst()) { - var document_id = cursor.getString(0) - document_id = document_id.substring(document_id.lastIndexOf(":") + 1) - cursor.close() - cursor = context.contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", arrayOf(document_id), null) + if (uri == null) return null + val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA) + var cursor: Cursor? = null + try { + cursor = context.contentResolver.query(uri, projection, null, null, null) if (cursor != null && cursor.moveToFirst()) { - val path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)) - cursor.close() - path - } else { - // Handle the case when the cursor is empty or null - null // or return an appropriate default value or handle the error accordingly + val documentIdIndex = cursor.getColumnIndex(MediaStore.Images.Media._ID) + if (documentIdIndex >= 0) { + val documentId = cursor.getString(documentIdIndex) + cursor.close() + val selection = "${MediaStore.Images.Media._ID} = ?" + val selectionArgs = arrayOf(documentId) + cursor = context.contentResolver.query( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + projection, + selection, + selectionArgs, + null + ) + if (cursor != null && cursor.moveToFirst()) { + val dataIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA) + if (dataIndex >= 0) { + val path = cursor.getString(dataIndex) + cursor.close() + return path + } + } + } } - } else { - // Handle the case when the cursor is empty or null - null // or return an appropriate default value or handle the error accordingly + } finally { + cursor?.close() } + return null } @JvmStatic @@ -417,7 +445,7 @@ object FileUtils { fun nameWithoutExtension(fileName: String?): String?{ extractFileName(fileName) - val nameWithExtension = FileUtils.extractFileName(fileName) + val nameWithExtension = extractFileName(fileName) val nameWithoutExtension = nameWithExtension?.substringBeforeLast(".") return nameWithoutExtension } diff --git a/app/src/main/res/layout/fragment_feedback_list.xml b/app/src/main/res/layout/fragment_feedback_list.xml index b430b2fde6..a566f95885 100644 --- a/app/src/main/res/layout/fragment_feedback_list.xml +++ b/app/src/main/res/layout/fragment_feedback_list.xml @@ -22,7 +22,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - - - - \ No newline at end of file + + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 228ad83a45..1ff4fea205 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -1051,6 +1051,7 @@ كوكب %s التقديمات غير متاحة لا توجد محادثات سابقة + لا توجد تعليقات متاحة %s diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 47d2cb2eec..cc2c828a20 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1051,6 +1051,7 @@ %s Planeta envíos no disponibles no hay chats anteriores + No hay comentarios aquí %s diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 1c26669b65..e9f31a26a5 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1051,6 +1051,7 @@ %s planète soumissions non disponibles aucune discussion précédente + aucun commentaire disponible %s diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index c75d0b674e..855313a00a 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -1051,6 +1051,7 @@ %s ग्रह पेशाहरू उपलब्ध छैनन् अघिल्ला कुराकानीहरू छैनन् + कुनै प्रतिक्रिया उपलब्ध छैन %s diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml index 38c3ada43d..ccedfc34df 100644 --- a/app/src/main/res/values-so/strings.xml +++ b/app/src/main/res/values-so/strings.xml @@ -1051,6 +1051,7 @@ %s Meerah soo gudbin lama heli karo ma jiraan wada sheekaysi hore + wax jawaab celin ah lama hayo %s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 599bfa36ff..f35f36b6e2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1051,6 +1051,7 @@ %s\'s Planet submissions not available no previous chats + no feedback available %s