From ee63619debbe0944d2081e4fcd235ff83ca11725 Mon Sep 17 00:00:00 2001 From: dogi Date: Wed, 3 Jul 2024 16:11:45 -0400 Subject: [PATCH 01/13] actions: better release outputs (fixes #3761) (#3768) --- .github/workflows/android-build.yml | 10 ++++----- .github/workflows/android-release.yml | 31 +++++++++++++++------------ app/build.gradle | 4 ++-- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml index 4ca389421e..7920396235 100644 --- a/.github/workflows/android-build.yml +++ b/.github/workflows/android-build.yml @@ -15,7 +15,7 @@ jobs: matrix: build: [default, lite] env: - FILES: | + LITES: | app/src/main/AndroidManifest.xml app/src/main/java/org/ole/planet/myplanet/base/PermissionActivity.kt app/src/main/java/org/ole/planet/myplanet/base/BaseContainerFragment.kt @@ -30,7 +30,7 @@ jobs: - name: check for .lite diffs if: matrix.build == 'lite' run: | - echo "${{ env.FILES }}" | xargs -n 1 | while read file; do + echo "${{ env.LITES }}" | xargs -n 1 | while read file; do ls -al $file* diff "$file" "$file.lite" || true done @@ -52,12 +52,12 @@ jobs: - name: diff the code to get lite if: matrix.build == 'lite' run: | - echo "${{ env.FILES }}" | xargs -n 1 | while read file; do + ls -al app/build.gradle + sed -i 's/\(versionName "[0-9.]\+\)"/\1-lite"/' app/build.gradle + echo "${{ env.LITES }}" | xargs -n 1 | while read file; do ls -al $file* cp "${file}.lite" "$file" done - ls -al app/build.gradle - sed -i 's/\(versionName "[0-9.]\+\)"/\1-lite"/' app/build.gradle - name: build debug as test run: ./gradlew assembleDebug --configuration-cache --no-daemon diff --git a/.github/workflows/android-release.yml b/.github/workflows/android-release.yml index a63f98508b..4e5b487e8c 100644 --- a/.github/workflows/android-release.yml +++ b/.github/workflows/android-release.yml @@ -15,11 +15,16 @@ jobs: matrix: build: [default, lite] env: - FILES: | + LITES: | app/src/main/AndroidManifest.xml app/src/main/java/org/ole/planet/myplanet/base/PermissionActivity.kt app/src/main/java/org/ole/planet/myplanet/base/BaseContainerFragment.kt app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt + OUTPUTS: | + .apk + .apk.sha256 + .aab + .aab.sha256 steps: - name: checkout repository code @@ -44,13 +49,13 @@ jobs: - name: diff the code to get lite if: matrix.build == 'lite' run: | - echo "${{ env.FILES }}" | xargs -n 1 | while read file; do + echo ANDROID_VERSION_LITE=$(grep -oP 'versionName "\K[^\"]+' app/build.gradle) >> $GITHUB_ENV + ls -al app/build.gradle + sed -i 's/\(versionName "[0-9.]\+\)"/\1-lite"/' app/build.gradle + echo "${{ env.LITES }}" | xargs -n 1 | while read file; do ls -al $file* cp "${file}.lite" "$file" done - ls -al app/build.gradle - echo ANDROID_VERSION_LITE=$(grep -oP 'versionName "\K[^\"]+' app/build.gradle) >> $GITHUB_ENV - sed -i 's/\(versionName "[0-9.]\+\)"/\1-lite"/' app/build.gradle - name: build release APK and AAB run: | @@ -108,12 +113,11 @@ jobs: - name: rename APK and AAB with version and branch for artifact if: github.event_name == 'workflow_dispatch' run: | - echo "BRANCHNAME=${GITHUB_REF##*/}" >> $GITHUB_ENV - mv output/myPlanet.apk output/myPlanet-${{ env.ANDROID_VERSION_NAME }}-${{ env.BRANCHNAME }}.apk - mv output/myPlanet.apk.sha256 output/myPlanet-${{ env.ANDROID_VERSION_NAME }}-${{ env.BRANCHNAME }}.apk.sha256 - mv output/myPlanet.aab output/myPlanet-${{ env.ANDROID_VERSION_NAME }}-${{ env.BRANCHNAME }}.aab - mv output/myPlanet.aab.sha256 output/myPlanet-${{ env.ANDROID_VERSION_NAME }}-${{ env.BRANCHNAME }}.aab.sha256 + echo "${{ env.OUTPUTS }}" | xargs -n 1 | while read type; do + mv "output/myPlanet${type}" "output/myPlanet-${{ env.ANDROID_VERSION_NAME }}-${GITHUB_REF##*/}${type}" + done ls -alR output + echo "BRANCHNAME=${GITHUB_REF##*/}" >> $GITHUB_ENV - name: upload APK and AAB as build artifact if: github.event_name == 'workflow_dispatch' @@ -126,10 +130,9 @@ jobs: - name: pre-process files and tag for lite version if: github.event_name != 'workflow_dispatch' && matrix.build == 'lite' run: | - mv output/myPlanet.apk output/myPlanet-lite.apk - mv output/myPlanet.apk.sha256 output/myPlanet-lite.apk.sha256 - mv output/myPlanet.aab output/myPlanet-lite.aab - mv output/myPlanet.aab.sha256 output/myPlanet-lite.aab.sha256 + echo "${{ env.OUTPUTS }}" | xargs -n 1 | while read type; do + mv "output/myPlanet${type}" "output/myPlanet-lite${type}" + done echo "ANDROID_VERSION_NAME=${ANDROID_VERSION_LITE}" >> $GITHUB_ENV - name: release APK and AAB on GitHub diff --git a/app/build.gradle b/app/build.gradle index 62d8b3212d..1b6dd62cec 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1651 - versionName "0.16.51" + versionCode 1652 + versionName "0.16.52" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true From f4425543184e573e6c64e04dc9ca30f3f9a5e0ce Mon Sep 17 00:00:00 2001 From: dogi Date: Wed, 3 Jul 2024 16:18:43 -0400 Subject: [PATCH 02/13] actions: better `lite` build test (fixes #3695) (#3769) --- .github/workflows/android-build.yml | 2 +- app/build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml index 7920396235..7f286979e5 100644 --- a/.github/workflows/android-build.yml +++ b/.github/workflows/android-build.yml @@ -32,7 +32,7 @@ jobs: run: | echo "${{ env.LITES }}" | xargs -n 1 | while read file; do ls -al $file* - diff "$file" "$file.lite" || true + diff <(sed 's/^\s*\/\///; s/^\s*\s*$//' "$file") <(sed 's/^\s*\/\///; s/^\s*\s*$//' "$file.lite") done - name: setup JDK 17 diff --git a/app/build.gradle b/app/build.gradle index 1b6dd62cec..881dcc9cad 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1652 - versionName "0.16.52" + versionCode 1653 + versionName "0.16.53" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true From 40d20bcf3c61aecfb32488d80d559d3122efb925 Mon Sep 17 00:00:00 2001 From: Elijah Whang <59347000+ewhang5@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:54:09 -0500 Subject: [PATCH 03/13] actions: less warnings is more (fixes #3764) (#3765) Co-authored-by: dogi --- app/build.gradle | 4 ++-- .../myplanet/ui/helpwanted/HelpWantedFragment.kt | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 881dcc9cad..362b09d843 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1653 - versionName "0.16.53" + versionCode 1654 + versionName "0.16.54" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/helpwanted/HelpWantedFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/helpwanted/HelpWantedFragment.kt index c4fb467168..2bfec64605 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/helpwanted/HelpWantedFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/helpwanted/HelpWantedFragment.kt @@ -2,11 +2,14 @@ package org.ole.planet.myplanet.ui.helpwanted import android.content.Context import android.content.SharedPreferences +import android.os.Build import android.os.Bundle import android.text.Html import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.RequiresApi +import androidx.core.text.HtmlCompat import androidx.fragment.app.Fragment import com.google.gson.JsonObject import com.google.gson.JsonParser.parseString @@ -26,6 +29,7 @@ class HelpWantedFragment : Fragment() { return fragmentHelpWantedBinding.root } + @RequiresApi(Build.VERSION_CODES.N) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val boldName = "" + getString(R.string.name_colon) + "" @@ -33,9 +37,9 @@ class HelpWantedFragment : Fragment() { val boldPhone = "" + getString(R.string.phone_number_colon) + "" if (manager != null) { fragmentHelpWantedBinding.llData.visibility = View.VISIBLE - fragmentHelpWantedBinding.tvName.text = Html.fromHtml(boldName + getString("name", manager)) - fragmentHelpWantedBinding.tvEmail.text = Html.fromHtml(boldEmail + getString("name", manager)) - fragmentHelpWantedBinding.tvPhone.text = Html.fromHtml(boldPhone + getString("phoneNumber", manager)) + fragmentHelpWantedBinding.tvName.text = Html.fromHtml(boldName + getString("name", manager), HtmlCompat.FROM_HTML_MODE_LEGACY) + fragmentHelpWantedBinding.tvEmail.text = Html.fromHtml(boldEmail + getString("name", manager), HtmlCompat.FROM_HTML_MODE_LEGACY) + fragmentHelpWantedBinding.tvPhone.text = Html.fromHtml(boldPhone + getString("phoneNumber", manager), HtmlCompat.FROM_HTML_MODE_LEGACY) } else { fragmentHelpWantedBinding.llData.visibility = View.GONE fragmentHelpWantedBinding.tvNodata.setText(R.string.no_data_available) From 036b1202407c4f97931c854bdb68d619a47d565d Mon Sep 17 00:00:00 2001 From: Elijah Whang <59347000+ewhang5@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:17:10 -0500 Subject: [PATCH 04/13] chats: smoother text (fixes #3766) (#3767) Co-authored-by: dogi --- app/build.gradle | 4 +-- .../planet/myplanet/ui/chat/ChatAdapter.kt | 31 ++++++++++--------- .../myplanet/ui/chat/ChatDetailFragment.kt | 28 ++++++++--------- .../ui/chat/ChatHistoryListAdapter.kt | 2 +- .../ui/chat/ChatHistoryListFragment.kt | 6 ++-- app/src/main/res/values-ar/strings.xml | 2 ++ app/src/main/res/values-es/strings.xml | 2 ++ app/src/main/res/values-fr/strings.xml | 2 ++ app/src/main/res/values-ne/strings.xml | 2 ++ app/src/main/res/values-so/strings.xml | 2 ++ app/src/main/res/values/strings.xml | 2 ++ 11 files changed, 48 insertions(+), 35 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 362b09d843..f712ee31ab 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1654 - versionName "0.16.54" + versionCode 1655 + versionName "0.16.55" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatAdapter.kt b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatAdapter.kt index a327aa6c5a..d544fd62f4 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatAdapter.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatAdapter.kt @@ -8,6 +8,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView +import org.ole.planet.myplanet.R import org.ole.planet.myplanet.databinding.ItemAiResponseMessageBinding import org.ole.planet.myplanet.databinding.ItemUserMessageBinding @@ -16,8 +17,8 @@ class ChatAdapter(private val chatList: ArrayList, val context: Context, private lateinit var textAiMessageBinding: ItemAiResponseMessageBinding var responseSource: Int = RESPONSE_SOURCE_UNKNOWN - private val VIEW_TYPE_QUERY = 1 - private val VIEW_TYPE_RESPONSE = 2 + private val viewTypeQuery = 1 + private val viewTypeResponse = 2 companion object { const val RESPONSE_SOURCE_SHARED_VIEW_MODEL = 1 const val RESPONSE_SOURCE_NETWORK = 2 @@ -29,17 +30,17 @@ class ChatAdapter(private val chatList: ArrayList, val context: Context, } } - class ResponseViewHolder(private val textAiMessageBinding: ItemAiResponseMessageBinding) : RecyclerView.ViewHolder(textAiMessageBinding.root) { + class ResponseViewHolder(private val textAiMessageBinding: ItemAiResponseMessageBinding, val context: Context) : RecyclerView.ViewHolder(textAiMessageBinding.root) { fun bind(response: String, responseSource: Int) { if(responseSource == RESPONSE_SOURCE_NETWORK){ val typingDelayMillis = 10L val typingAnimationDurationMillis = response.length * typingDelayMillis - textAiMessageBinding.textGchatMessageOther.text = "" + textAiMessageBinding.textGchatMessageOther.text = context.getString(R.string.empty_text) Handler(Looper.getMainLooper()).postDelayed({ - animateTyping(response, typingDelayMillis) + animateTyping(response) }, typingAnimationDurationMillis) } else if(responseSource == RESPONSE_SOURCE_SHARED_VIEW_MODEL){ - if (response != "") { + if (response.isNotEmpty()) { textAiMessageBinding.textGchatMessageOther.text = response } else{ textAiMessageBinding.textGchatMessageOther.visibility = View.GONE @@ -47,18 +48,18 @@ class ChatAdapter(private val chatList: ArrayList, val context: Context, } } - private fun animateTyping(response: String, typingDelayMillis: Long) { + private fun animateTyping(response: String) { var currentIndex = 0 val typingRunnable = object : Runnable { override fun run() { if (currentIndex < response.length) { textAiMessageBinding.textGchatMessageOther.text = response.substring(0, currentIndex + 1) currentIndex++ - Handler(Looper.getMainLooper()).postDelayed(this, typingDelayMillis) + Handler(Looper.getMainLooper()).postDelayed(this, 10L) } } } - Handler(Looper.getMainLooper()).postDelayed(typingRunnable, typingDelayMillis) + Handler(Looper.getMainLooper()).postDelayed(typingRunnable, 10L) } } @@ -90,18 +91,18 @@ class ChatAdapter(private val chatList: ArrayList, val context: Context, } override fun getItemViewType(position: Int): Int { - return if (position % 2 == 0) VIEW_TYPE_QUERY else VIEW_TYPE_RESPONSE + return if (position % 2 == 0) viewTypeQuery else viewTypeResponse } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { - VIEW_TYPE_QUERY -> { + viewTypeQuery -> { textUserMessageBinding = ItemUserMessageBinding.inflate(LayoutInflater.from(context), parent, false) QueryViewHolder(textUserMessageBinding) } - VIEW_TYPE_RESPONSE -> { + viewTypeResponse -> { textAiMessageBinding = ItemAiResponseMessageBinding.inflate(LayoutInflater.from(context), parent, false) - ResponseViewHolder(textAiMessageBinding) + ResponseViewHolder(textAiMessageBinding, context) } else -> throw IllegalArgumentException("Invalid view type") } @@ -111,11 +112,11 @@ class ChatAdapter(private val chatList: ArrayList, val context: Context, val chatItem = chatList[position] Log.d("ChatAdapter", "chatList: $chatList") when (holder.itemViewType) { - VIEW_TYPE_QUERY -> { + viewTypeQuery -> { val queryViewHolder = holder as QueryViewHolder queryViewHolder.bind(chatItem) } - VIEW_TYPE_RESPONSE -> { + viewTypeResponse -> { val responseViewHolder = holder as ResponseViewHolder responseViewHolder.bind(chatItem, responseSource) } diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatDetailFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatDetailFragment.kt index 91e62b18b4..f5cc74baec 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatDetailFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatDetailFragment.kt @@ -123,12 +123,12 @@ class ChatDetailFragment : Fragment() { } } - sharedViewModel.getSelected_id().observe(viewLifecycleOwner) { selected_id -> - _id = selected_id + sharedViewModel.getSelected_id().observe(viewLifecycleOwner) { selectedId -> + _id = selectedId } - sharedViewModel.getSelected_rev().observe(viewLifecycleOwner) { selected_rev -> - _rev = selected_rev + sharedViewModel.getSelected_rev().observe(viewLifecycleOwner) { selectedRev -> + _rev = selectedRev } view.post { clearChatDetail() @@ -292,7 +292,7 @@ class ChatDetailFragment : Fragment() { } } else { fragmentChatDetailBinding.textGchatIndicator.visibility = View.VISIBLE - fragmentChatDetailBinding.textGchatIndicator.text = "${responseBody.message}" + fragmentChatDetailBinding.textGchatIndicator.text = context?.getString(R.string.message_placeholder, responseBody.message) val jsonObject = JsonObject() jsonObject.addProperty("_rev", "") jsonObject.addProperty("_id", "") @@ -361,7 +361,7 @@ class ChatDetailFragment : Fragment() { RealmChatHistory.insert(mRealm, jsonObject) } fragmentChatDetailBinding.textGchatIndicator.visibility = View.VISIBLE - fragmentChatDetailBinding.textGchatIndicator.text = "${t.message}" + fragmentChatDetailBinding.textGchatIndicator.text = context?.getString(R.string.message_placeholder, t.message) fragmentChatDetailBinding.buttonGchatSend.isEnabled = true fragmentChatDetailBinding.editGchatMessage.isEnabled = true fragmentChatDetailBinding.imageGchatLoading.visibility = View.INVISIBLE @@ -369,7 +369,7 @@ class ChatDetailFragment : Fragment() { }) } - private fun continueChatRequest(content: RequestBody, _id: String, query: String) { + private fun continueChatRequest(content: RequestBody, id: String, query: String) { fragmentChatDetailBinding.buttonGchatSend.isEnabled = false fragmentChatDetailBinding.editGchatMessage.isEnabled = false fragmentChatDetailBinding.imageGchatLoading.visibility = View.VISIBLE @@ -385,16 +385,16 @@ class ChatDetailFragment : Fragment() { mAdapter.responseSource = ChatAdapter.RESPONSE_SOURCE_NETWORK mAdapter.addResponse(chatResponse) _rev = "${response.body()?.couchDBResponse?.rev}" - continueConversationRealm(_id, query, chatResponse) + continueConversationRealm(id, query, chatResponse) } } else { fragmentChatDetailBinding.textGchatIndicator.visibility = View.VISIBLE - fragmentChatDetailBinding.textGchatIndicator.text = "${responseBody.message}" + fragmentChatDetailBinding.textGchatIndicator.text = context?.getString(R.string.message_placeholder, responseBody.message) } } else { fragmentChatDetailBinding.textGchatIndicator.visibility = View.VISIBLE fragmentChatDetailBinding.textGchatIndicator.text = getString(R.string.request_failed_please_retry) - continueConversationRealm(_id, query, "") + continueConversationRealm(id, query, "") } fragmentChatDetailBinding.buttonGchatSend.isEnabled = true @@ -403,9 +403,9 @@ class ChatDetailFragment : Fragment() { } override fun onFailure(call: Call, t: Throwable) { - continueConversationRealm(_id, query, "") + continueConversationRealm(id, query, "") fragmentChatDetailBinding.textGchatIndicator.visibility = View.VISIBLE - fragmentChatDetailBinding.textGchatIndicator.text = "${t.message}" + fragmentChatDetailBinding.textGchatIndicator.text = context?.getString(R.string.message_placeholder, t.message) fragmentChatDetailBinding.buttonGchatSend.isEnabled = true fragmentChatDetailBinding.editGchatMessage.isEnabled = true fragmentChatDetailBinding.imageGchatLoading.visibility = View.INVISIBLE @@ -413,9 +413,9 @@ class ChatDetailFragment : Fragment() { }) } - private fun continueConversationRealm(_id:String, query:String, chatResponse:String) { + private fun continueConversationRealm(id:String, query:String, chatResponse:String) { try { - addConversationToChatHistory(mRealm, _id, query, chatResponse) + addConversationToChatHistory(mRealm, id, query, chatResponse) mRealm.commitTransaction() } catch (e: Exception) { e.printStackTrace() diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListAdapter.kt b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListAdapter.kt index 8026674585..75b590868b 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListAdapter.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListAdapter.kt @@ -43,7 +43,7 @@ class ChatHistoryListAdapter(var context: Context, private var chatHistory: List private var newsList: RealmResults? = null interface ChatHistoryItemClickListener { - fun onChatHistoryItemClicked(conversations: RealmList?, _id: String, _rev: String?) + fun onChatHistoryItemClicked(conversations: RealmList?, id: String, rev: String?) } fun setChatHistoryItemClickListener(listener: ChatHistoryItemClickListener) { diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListFragment.kt index f4702e943d..513d47cb2f 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListFragment.kt @@ -75,10 +75,10 @@ class ChatHistoryListFragment : Fragment() { } val adapter = ChatHistoryListAdapter(requireContext(), list, this) adapter.setChatHistoryItemClickListener(object : ChatHistoryListAdapter.ChatHistoryItemClickListener { - override fun onChatHistoryItemClicked(conversations: RealmList?, _id: String, _rev:String?) { + override fun onChatHistoryItemClicked(conversations: RealmList?, id: String, rev:String?) { conversations?.let { sharedViewModel.setSelectedChatHistory(it) } - sharedViewModel.setSelected_id(_id) - _rev?.let { sharedViewModel.setSelected_rev(it) } + sharedViewModel.setSelected_id(id) + rev?.let { sharedViewModel.setSelected_rev(it) } fragmentChatHistoryListBinding.slidingPaneLayout.openPane() } diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 2a813cee63..228ad83a45 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -1051,5 +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 fabf3b6219..47d2cb2eec 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1051,5 +1051,7 @@ %s Planeta envíos no disponibles no hay chats anteriores + + %s diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 1dbbcabaec..1c26669b65 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1051,5 +1051,7 @@ %s planète soumissions non disponibles aucune discussion précédente + + %s diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index f71b84ba06..c75d0b674e 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -1051,5 +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 d682020cd4..38c3ada43d 100644 --- a/app/src/main/res/values-so/strings.xml +++ b/app/src/main/res/values-so/strings.xml @@ -1051,5 +1051,7 @@ %s Meerah soo gudbin lama heli karo ma jiraan wada sheekaysi hore + + %s diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f2db6b44ee..599bfa36ff 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1051,5 +1051,7 @@ %s\'s Planet submissions not available no previous chats + + %s From 46fcfdf0a5ad9b00a517ce5231c827649c85be67 Mon Sep 17 00:00:00 2001 From: Vivian Li <112584985+strawberrybread@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:12:10 -0400 Subject: [PATCH 05/13] actions: less warnings is more (fixes #3772) (#3773) Co-authored-by: dogi --- app/build.gradle | 4 +- .../planet/myplanet/utilities/FileUtils.kt | 98 ++++++++++++------- 2 files changed, 65 insertions(+), 37 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f712ee31ab..68f3233ff4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1655 - versionName "0.16.55" + versionCode 1656 + versionName "0.16.56" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true 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 } From 3a65ee9e6f4f8e913d5b5aabebe0d70658f847fb Mon Sep 17 00:00:00 2001 From: Elijah Whang <59347000+ewhang5@users.noreply.github.com> Date: Mon, 8 Jul 2024 13:38:14 -0500 Subject: [PATCH 06/13] actions: less warnings is more (fixes #3777) (#3781) Co-authored-by: dogi --- app/build.gradle | 4 +- .../myplanet/ui/courses/CourseStepFragment.kt | 4 +- .../myplanet/ui/exam/TakeExamFragment.kt | 4 +- .../planet/myplanet/utilities/CameraUtils.kt | 77 ++++++++++++------- 4 files changed, 56 insertions(+), 33 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 68f3233ff4..1997250c14 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1656 - versionName "0.16.56" + versionCode 1657 + versionName "0.16.57" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true 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/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) } From 54f59ed8d3d92f5f864e0031ff7fe2603163e4c0 Mon Sep 17 00:00:00 2001 From: rlam20 <52076121+rlam20@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:46:37 -0400 Subject: [PATCH 07/13] feedback: smoother empty list (fixes #3726) (#3783) Co-authored-by: dogi --- app/build.gradle | 4 +- .../myplanet/base/BaseRecyclerFragment.kt | 1 + .../ui/feedback/FeedbackListFragment.kt | 37 ++++++++++++++----- .../res/layout/fragment_feedback_list.xml | 11 ++++-- app/src/main/res/values-ar/strings.xml | 1 + app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-ne/strings.xml | 1 + app/src/main/res/values-so/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 10 files changed, 44 insertions(+), 15 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 1997250c14..798be1c95d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1657 - versionName "0.16.57" + versionCode 1658 + versionName "0.16.58" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true 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/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/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 From 8f4c631d035e469e34f409289f309ad1eb9de554 Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Mon, 8 Jul 2024 22:12:33 +0300 Subject: [PATCH 08/13] resources: safer transactions (fixes #3645) (#3785) Co-authored-by: dogi --- app/build.gradle | 4 +- .../ui/resources/ResourcesFragment.kt | 181 +++++++++--------- 2 files changed, 97 insertions(+), 88 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 798be1c95d..52eec789e6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1658 - versionName "0.16.58" + versionCode 1659 + versionName "0.16.59" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/resources/ResourcesFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/resources/ResourcesFragment.kt index ce94d8315c..06afdf6c7c 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/resources/ResourcesFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/resources/ResourcesFragment.kt @@ -39,21 +39,22 @@ import java.util.UUID class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItemSelected, ChipDeletedListener, TagClickListener, OnFilterListener { - private var tvAddToLib: TextView? = null - private var tvSelected: TextView? = null - var etSearch: EditText? = null - private var etTags: EditText? = null - var adapterLibrary: AdapterResource? = null - private var flexBoxTags: FlexboxLayout? = null - lateinit var searchTags: MutableList - var config: ChipCloudConfig? = null - private var clearTags: Button? = null - private var orderByTitle: Button? = null - private var orderByDate: Button? = null - private var selectAll: CheckBox? = null + private lateinit var tvAddToLib: TextView + private lateinit var tvSelected: TextView + private lateinit var etSearch: EditText + private lateinit var etTags: EditText + private lateinit var flexBoxTags: FlexboxLayout + private lateinit var searchTags: MutableList + private lateinit var config: ChipCloudConfig + private lateinit var clearTags: Button + private lateinit var orderByTitle: Button + private lateinit var orderByDate: Button + private lateinit var selectAll: CheckBox + private lateinit var filter: ImageButton + private lateinit var adapterLibrary: AdapterResource var map: HashMap? = null private var confirmation: AlertDialog? = null - var filter: ImageButton? = null + override fun getLayout(): Int { return R.layout.fragment_my_library } @@ -62,34 +63,34 @@ class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItem map = getRatings(mRealm, "resource", model?.id) val libraryList: List = getList(RealmMyLibrary::class.java).filterIsInstance() adapterLibrary = AdapterResource(requireActivity(), libraryList, map!!, mRealm) - adapterLibrary?.setRatingChangeListener(this) - adapterLibrary?.setListener(this) - return adapterLibrary!! + adapterLibrary.setRatingChangeListener(this) + adapterLibrary.setListener(this) + return adapterLibrary } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) searchTags = ArrayList() config = Utilities.getCloudConfig().showClose(R.color.black_overlay) - tvAddToLib = requireView().findViewById(R.id.tv_add) - etSearch = requireView().findViewById(R.id.et_search) - etTags = requireView().findViewById(R.id.et_tags) - clearTags = requireView().findViewById(R.id.btn_clear_tags) - tvSelected = requireView().findViewById(R.id.tv_selected) - flexBoxTags = requireView().findViewById(R.id.flexbox_tags) - selectAll = requireView().findViewById(R.id.selectAll) - tvDelete = requireView().findViewById(R.id.tv_delete) - filter = requireView().findViewById(R.id.filter) + tvAddToLib = view.findViewById(R.id.tv_add) + etSearch = view.findViewById(R.id.et_search) + etTags = view.findViewById(R.id.et_tags) + clearTags = view.findViewById(R.id.btn_clear_tags) + tvSelected = view.findViewById(R.id.tv_selected) + flexBoxTags = view.findViewById(R.id.flexbox_tags) + selectAll = view.findViewById(R.id.selectAll) + filter = view.findViewById(R.id.filter) + initArrays() updateTvDelete() - tvAddToLib?.setOnClickListener { + tvAddToLib.setOnClickListener { if ((selectedItems?.size ?: 0) > 0) { confirmation = createAlertDialog() confirmation?.show() addToMyList() selectedItems?.clear() - tvAddToLib?.isEnabled = false // After clearing selectedItems size is always 0 + tvAddToLib.isEnabled = false checkList() } } @@ -97,45 +98,54 @@ class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItem tvDelete?.setOnClickListener { AlertDialog.Builder(this.context) .setMessage(R.string.confirm_removal) - .setPositiveButton(R.string.yes) { _: DialogInterface?, _: Int -> + .setPositiveButton(R.string.yes) { _, _ -> deleteSelected(true) val newFragment = ResourcesFragment() recreateFragment(newFragment) } .setNegativeButton(R.string.no, null).show() } - etSearch?.addTextChangedListener(object : TextWatcher { + + etSearch.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { - adapterLibrary?.setLibraryList(applyFilter(filterLibraryByTag(etSearch?.text.toString().trim { it <= ' ' }, searchTags))) - showNoData(tvMessage, adapterLibrary?.itemCount, "resources") + adapterLibrary.setLibraryList( + applyFilter( + filterLibraryByTag( + etSearch.text.toString().trim(), searchTags + ) + ) + ) + showNoData(tvMessage, adapterLibrary.itemCount, "resources") } override fun afterTextChanged(s: Editable) {} }) - requireView().findViewById(R.id.btn_collections).setOnClickListener { + + view.findViewById(R.id.btn_collections).setOnClickListener { val f = CollectionsFragment.getInstance(searchTags, "resources") f.setListener(this@ResourcesFragment) f.show(childFragmentManager, "") } - showNoData(tvMessage, adapterLibrary?.itemCount, "resources") + showNoData(tvMessage, adapterLibrary.itemCount, "resources") clearTagsButton() - setupUI(requireView().findViewById(R.id.my_library_parent_layout), requireActivity()) + setupUI(view.findViewById(R.id.my_library_parent_layout), requireActivity()) changeButtonStatus() additionalSetup() - tvFragmentInfo = requireView().findViewById(R.id.tv_fragment_info) + tvFragmentInfo = view.findViewById(R.id.tv_fragment_info) if (isMyCourseLib) tvFragmentInfo.setText(R.string.txt_myLibrary) checkList() - selectAll?.setOnClickListener { + + selectAll.setOnClickListener { updateTvDelete() - val allSelected = selectedItems?.size == adapterLibrary?.getLibraryList()?.size - adapterLibrary?.selectAllItems(!allSelected) + val allSelected = selectedItems?.size == adapterLibrary.getLibraryList().size + adapterLibrary.selectAllItems(!allSelected) if (allSelected) { - selectAll?.isChecked = false - selectAll?.text = getString(R.string.select_all) + selectAll.isChecked = false + selectAll.text = getString(R.string.select_all) } else { - selectAll?.isChecked = true - selectAll?.text = getString(R.string.unselect_all) + selectAll.isChecked = true + selectAll.text = getString(R.string.unselect_all) } } } @@ -149,14 +159,14 @@ class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItem } private fun checkList() { - if (adapterLibrary?.getLibraryList()?.isEmpty() == true) { - selectAll?.visibility = View.GONE - etSearch?.visibility = View.GONE - tvAddToLib?.visibility = View.GONE - tvSelected?.visibility = View.GONE + if (adapterLibrary.getLibraryList().isEmpty()) { + selectAll.visibility = View.GONE + etSearch.visibility = View.GONE + tvAddToLib.visibility = View.GONE + tvSelected.visibility = View.GONE requireView().findViewById(R.id.btn_collections).visibility = View.GONE requireView().findViewById(R.id.filter).visibility = View.GONE - clearTags?.visibility = View.GONE + clearTags.visibility = View.GONE tvDelete?.visibility = View.GONE } } @@ -193,17 +203,17 @@ class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItem } private fun clearTagsButton() { - clearTags?.setOnClickListener { + clearTags.setOnClickListener { saveSearchActivity() searchTags.clear() - etSearch?.setText("") - tvSelected?.text = "" + etSearch.setText("") + tvSelected.text = "" levels.clear() mediums.clear() subjects.clear() languages.clear() - adapterLibrary?.setLibraryList(applyFilter(filterLibraryByTag("", searchTags))) - showNoData(tvMessage, adapterLibrary?.itemCount, "resources") + adapterLibrary.setLibraryList(applyFilter(filterLibraryByTag("", searchTags))) + showNoData(tvMessage, adapterLibrary.itemCount, "resources") } } @@ -214,30 +224,30 @@ class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItem } override fun onTagClicked(realmTag: RealmTag) { - flexBoxTags?.removeAllViews() + flexBoxTags.removeAllViews() val chipCloud = ChipCloud(activity, flexBoxTags, config) chipCloud.setDeleteListener(this) if (!searchTags.contains(realmTag)) searchTags.add(realmTag) chipCloud.addChips(searchTags) - adapterLibrary?.setLibraryList(applyFilter(filterLibraryByTag(etSearch?.text.toString(), searchTags))) + adapterLibrary.setLibraryList(applyFilter(filterLibraryByTag(etSearch.text.toString(), searchTags))) showTagText(searchTags, tvSelected) - showNoData(tvMessage, adapterLibrary?.itemCount, "resources") + showNoData(tvMessage, adapterLibrary.itemCount, "resources") } override fun onTagSelected(tag: RealmTag) { val li: MutableList = ArrayList() li.add(tag) searchTags = li - tvSelected?.text = "${getString(R.string.selected)}${tag.name}" - adapterLibrary?.setLibraryList(applyFilter(filterLibraryByTag(etSearch?.text.toString(), li))) - showNoData(tvMessage, adapterLibrary?.itemCount, "resources") + tvSelected.text = "${getString(R.string.selected)}${tag.name}" + adapterLibrary.setLibraryList(applyFilter(filterLibraryByTag(etSearch.text.toString(), li))) + showNoData(tvMessage, adapterLibrary.itemCount, "resources") } override fun onOkClicked(list: List?) { if (list?.isEmpty() == true) { searchTags.clear() - adapterLibrary?.setLibraryList(applyFilter(filterLibraryByTag(etSearch?.text.toString(), searchTags))) - showNoData(tvMessage, adapterLibrary?.itemCount, "resources") + adapterLibrary.setLibraryList(applyFilter(filterLibraryByTag(etSearch.text.toString(), searchTags))) + showNoData(tvMessage, adapterLibrary.itemCount, "resources") } else { for (tag in list ?: emptyList()) { onTagClicked(tag) @@ -246,20 +256,20 @@ class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItem } private fun changeButtonStatus() { - tvAddToLib?.isEnabled = (selectedItems?.size ?: 0) > 0 - if (adapterLibrary?.areAllSelected() == true) { - selectAll?.isChecked = true - selectAll?.text = getString(R.string.unselect_all) + tvAddToLib.isEnabled = (selectedItems?.size ?: 0) > 0 + if (adapterLibrary.areAllSelected()) { + selectAll.isChecked = true + selectAll.text = getString(R.string.unselect_all) } else { - selectAll?.isChecked = false - selectAll?.text = getString(R.string.select_all) + selectAll.isChecked = false + selectAll.text = getString(R.string.select_all) } } override fun chipDeleted(i: Int, s: String) { searchTags.removeAt(i) - adapterLibrary?.setLibraryList(applyFilter(filterLibraryByTag(etSearch?.text.toString(), searchTags))) - showNoData(tvMessage, adapterLibrary?.itemCount, "resources") + adapterLibrary.setLibraryList(applyFilter(filterLibraryByTag(etSearch.text.toString(), searchTags))) + showNoData(tvMessage, adapterLibrary.itemCount, "resources") } override fun filter(subjects: MutableSet, languages: MutableSet, mediums: MutableSet, levels: MutableSet) { @@ -267,14 +277,14 @@ class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItem this.languages = languages this.mediums = mediums this.levels = levels - adapterLibrary?.setLibraryList(applyFilter(filterLibraryByTag(etSearch?.text.toString().trim { it <= ' ' }, searchTags))) - showNoData(tvMessage, adapterLibrary?.itemCount, "resources") + adapterLibrary.setLibraryList(applyFilter(filterLibraryByTag(etSearch.text.toString().trim { it <= ' ' }, searchTags))) + showNoData(tvMessage, adapterLibrary.itemCount, "resources") } override fun getData(): Map> { - val libraryList = adapterLibrary?.getLibraryList()?.filterNotNull() + val libraryList = adapterLibrary.getLibraryList().filterNotNull() val b: MutableMap> = HashMap() - b["languages"] = libraryList?.let { getArrayList(it, "languages").filterNotNull().toSet() }!! + b["languages"] = libraryList.let { getArrayList(it, "languages").filterNotNull().toSet() } b["subjects"] = libraryList.let { getSubjects(it).toList().toSet() } b["mediums"] = getArrayList(libraryList, "mediums").filterNotNull().toSet() b["levels"] = getLevels(libraryList).toList().toSet() @@ -299,7 +309,7 @@ class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItem private fun filterApplied(): Boolean { return !(subjects.isEmpty() && languages.isEmpty() && mediums.isEmpty() && levels.isEmpty() - && searchTags.isEmpty() && "${etSearch?.text}".isEmpty()) + && searchTags.isEmpty() && "${etSearch.text}".isEmpty()) } private fun saveSearchActivity() { @@ -310,7 +320,7 @@ class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItem activity.time = Calendar.getInstance().timeInMillis activity.createdOn = model?.planetCode!! activity.parentCode = model?.parentCode!! - activity.text = etSearch?.text.toString() + activity.text = "${etSearch.text}" activity.type = "resources" val filter = JsonObject() filter.add("tags", getTagsArray(searchTags)) @@ -324,22 +334,21 @@ class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItem } private fun recreateFragment(fragment: Fragment) { - if (isMyCourseLib) { - val args = Bundle() - args.putBoolean("isMyCourseLib", true) - fragment.arguments = args - val transaction = parentFragmentManager.beginTransaction() - transaction.replace(R.id.fragment_container, fragment) - transaction.addToBackStack(null) - transaction.commit() - } else { + if (isAdded && activity != null && !requireActivity().isFinishing) { val transaction = parentFragmentManager.beginTransaction() + if (isMyCourseLib) { + val args = Bundle().apply { + putBoolean("isMyCourseLib", true) + } + fragment.arguments = args + } transaction.replace(R.id.fragment_container, fragment) transaction.addToBackStack(null) transaction.commit() } } + private fun additionalSetup() { val bottomSheet = requireView().findViewById(R.id.card_filter) requireView().findViewById(R.id.filter).setOnClickListener { @@ -353,7 +362,7 @@ class ResourcesFragment : BaseRecyclerFragment(), OnLibraryItem f.show(childFragmentManager, "") bottomSheet.visibility = View.GONE } - orderByDate?.setOnClickListener { adapterLibrary?.toggleSortOrder() } - orderByTitle?.setOnClickListener { adapterLibrary?.toggleTitleSortOrder() } + orderByDate.setOnClickListener { adapterLibrary.toggleSortOrder() } + orderByTitle.setOnClickListener { adapterLibrary.toggleTitleSortOrder() } } } \ No newline at end of file From d37137aab907825562c4c468d2b5fe493e8e0e7c Mon Sep 17 00:00:00 2001 From: Gideon Okuro Date: Mon, 8 Jul 2024 22:22:24 +0300 Subject: [PATCH 09/13] chat: smoother refresh (fixes #3784) (#3786) Co-authored-by: dogi --- app/build.gradle | 4 +- .../planet/myplanet/model/RealmChatHistory.kt | 2 + .../myplanet/ui/chat/ChatDetailFragment.kt | 64 ++++++------------- .../ui/chat/ChatHistoryListAdapter.kt | 20 +----- .../ui/chat/ChatHistoryListFragment.kt | 59 ++++++++--------- .../ui/dashboard/DashboardActivity.kt | 7 ++ .../ui/dashboard/DashboardActivity.kt.lite | 7 ++ 7 files changed, 68 insertions(+), 95 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 52eec789e6..965ab1eb33 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1659 - versionName "0.16.59" + versionCode 1660 + versionName "0.16.60" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true diff --git a/app/src/main/java/org/ole/planet/myplanet/model/RealmChatHistory.kt b/app/src/main/java/org/ole/planet/myplanet/model/RealmChatHistory.kt index 34cc5055d2..5e034ef2a1 100644 --- a/app/src/main/java/org/ole/planet/myplanet/model/RealmChatHistory.kt +++ b/app/src/main/java/org/ole/planet/myplanet/model/RealmChatHistory.kt @@ -18,6 +18,7 @@ open class RealmChatHistory : RealmObject() { var aiProvider: String? = null var title: String? = null var createdDate: String? = null + var updatedDate: String? = null var conversations: RealmList? = null companion object { @JvmStatic @@ -33,6 +34,7 @@ open class RealmChatHistory : RealmObject() { chatHistory._id = JsonUtils.getString("_id", act) chatHistory.title = JsonUtils.getString("title", act) chatHistory.createdDate = JsonUtils.getString("createdDate", act) + chatHistory.updatedDate = JsonUtils.getString("updatedDate", act) chatHistory.user = JsonUtils.getString("user", act) chatHistory.aiProvider = JsonUtils.getString("aiProvider", act) chatHistory.conversations = parseConversations(mRealm, JsonUtils.getJsonArray("conversations", act)) diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatDetailFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatDetailFragment.kt index f5cc74baec..e2d0bc44d7 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatDetailFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatDetailFragment.kt @@ -16,10 +16,12 @@ import org.ole.planet.myplanet.datamanager.* import org.ole.planet.myplanet.model.* import org.ole.planet.myplanet.model.RealmChatHistory.Companion.addConversationToChatHistory import org.ole.planet.myplanet.service.UserProfileDbHandler +import org.ole.planet.myplanet.ui.dashboard.DashboardActivity import org.ole.planet.myplanet.utilities.Utilities import retrofit2.Call import retrofit2.Callback import retrofit2.Response +import java.util.Date class ChatDetailFragment : Fragment() { lateinit var fragmentChatDetailBinding: FragmentChatDetailBinding @@ -30,6 +32,7 @@ class ChatDetailFragment : Fragment() { private var aiName: String = "" private var aiModel: String = "" private lateinit var mRealm: Realm + var user: RealmUserModel? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -43,7 +46,7 @@ class ChatDetailFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) mRealm = DatabaseService(requireContext()).realmInstance - val user = UserProfileDbHandler(requireContext()).userModel + user = UserProfileDbHandler(requireContext()).userModel mAdapter = ChatAdapter(ArrayList(), requireContext(), fragmentChatDetailBinding.recyclerGchat) fragmentChatDetailBinding.recyclerGchat.adapter = mAdapter val layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(requireContext()) @@ -268,6 +271,7 @@ class ChatDetailFragment : Fragment() { override fun onResponse(call: Call, response: Response) { val responseBody = response.body() if (response.isSuccessful && responseBody != null) { + val jsonObject = JsonObject() if (responseBody.status == "Success") { val chatResponse = response.body()?.chat if (chatResponse != null) { @@ -275,12 +279,13 @@ class ChatDetailFragment : Fragment() { mAdapter.addResponse(chatResponse) _id = "${response.body()?.couchDBResponse?.id}" _rev = "${response.body()?.couchDBResponse?.rev}" - val jsonObject = JsonObject() jsonObject.addProperty("_rev", "${response.body()?.couchDBResponse?.rev}") jsonObject.addProperty("_id", "${response.body()?.couchDBResponse?.id}") - jsonObject.addProperty("time", "") - jsonObject.addProperty("title", "") - jsonObject.addProperty("updatedTime", "") + jsonObject.addProperty("aiProvider", aiName) + jsonObject.addProperty("user", user?.name) + jsonObject.addProperty("title", query) + jsonObject.addProperty("createdTime", Date().time) + jsonObject.addProperty("updatedDate", "") val conversationsArray = JsonArray() val conversationObject = JsonObject() @@ -289,16 +294,22 @@ class ChatDetailFragment : Fragment() { conversationsArray.add(conversationObject) jsonObject.add("conversations", conversationsArray) + + requireActivity().runOnUiThread { + RealmChatHistory.insert(mRealm, jsonObject) + } + (requireActivity() as? DashboardActivity)?.refreshChatHistoryList() } } else { fragmentChatDetailBinding.textGchatIndicator.visibility = View.VISIBLE fragmentChatDetailBinding.textGchatIndicator.text = context?.getString(R.string.message_placeholder, responseBody.message) - val jsonObject = JsonObject() jsonObject.addProperty("_rev", "") jsonObject.addProperty("_id", "") - jsonObject.addProperty("time", "") - jsonObject.addProperty("title", "") - jsonObject.addProperty("updatedTime", "") + jsonObject.addProperty("aiProvider", aiName) + jsonObject.addProperty("user", user?.name) + jsonObject.addProperty("title", query) + jsonObject.addProperty("createdTime", Date().time) + jsonObject.addProperty("updatedDate", "") val conversationsArray = JsonArray() val conversationObject = JsonObject() @@ -310,6 +321,7 @@ class ChatDetailFragment : Fragment() { requireActivity().runOnUiThread { RealmChatHistory.insert(mRealm, jsonObject) } + (requireActivity() as? DashboardActivity)?.refreshChatHistoryList() } } else { fragmentChatDetailBinding.textGchatIndicator.visibility = View.VISIBLE @@ -318,23 +330,6 @@ class ChatDetailFragment : Fragment() { } else { response.message() } - val jsonObject = JsonObject() - jsonObject.addProperty("_rev", "") - jsonObject.addProperty("_id", "") - jsonObject.addProperty("time", "") - jsonObject.addProperty("title", "") - jsonObject.addProperty("updatedTime", "") - - val conversationsArray = JsonArray() - val conversationObject = JsonObject() - conversationObject.addProperty("query", query) - conversationObject.addProperty("response", "") - conversationsArray.add(conversationObject) - - jsonObject.add("conversations", conversationsArray) - requireActivity().runOnUiThread { - RealmChatHistory.insert(mRealm, jsonObject) - } } fragmentChatDetailBinding.buttonGchatSend.isEnabled = true @@ -343,23 +338,6 @@ class ChatDetailFragment : Fragment() { } override fun onFailure(call: Call, t: Throwable) { - val jsonObject = JsonObject() - jsonObject.addProperty("_rev", "") - jsonObject.addProperty("_id", "") - jsonObject.addProperty("time", "") - jsonObject.addProperty("title", "") - jsonObject.addProperty("updatedTime", "") - - val conversationsArray = JsonArray() - val conversationObject = JsonObject() - conversationObject.addProperty("query", query) - conversationObject.addProperty("response", "") - conversationsArray.add(conversationObject) - - jsonObject.add("conversations", conversationsArray) - requireActivity().runOnUiThread { - RealmChatHistory.insert(mRealm, jsonObject) - } fragmentChatDetailBinding.textGchatIndicator.visibility = View.VISIBLE fragmentChatDetailBinding.textGchatIndicator.text = context?.getString(R.string.message_placeholder, t.message) fragmentChatDetailBinding.buttonGchatSend.isEnabled = true diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListAdapter.kt b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListAdapter.kt index 75b590868b..82e78c7f30 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListAdapter.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListAdapter.kt @@ -55,10 +55,10 @@ class ChatHistoryListAdapter(var context: Context, private var chatHistory: List if (chat.conversations != null && chat.conversations?.isNotEmpty() == true) { chat.conversations?.get(0)?.query?.contains(query, ignoreCase = true) == true } else { - chat.title?.contains(query, ignoreCase = true) == true + chat.title?.contains(query, ignoreCase = true) ==true } } - notifyItemRangeChanged(0, filteredChatHistory.size) + notifyDataSetChanged() } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { @@ -77,23 +77,9 @@ class ChatHistoryListAdapter(var context: Context, private var chatHistory: List } fun updateChatHistory(newChatHistory: List) { - val oldListSize = chatHistory.size - val newListSize = newChatHistory.size chatHistory = newChatHistory filteredChatHistory = newChatHistory - if(oldListSizenewListSize){ - notifyItemRangeRemoved(newListSize,oldListSize-newListSize) - } - else{ - for(i in 0 until newListSize){ - if(chatHistory[i] != newChatHistory[i]){ - notifyItemChanged(i) - } - } - } + notifyDataSetChanged() } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListFragment.kt index 513d47cb2f..b740263e5e 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/chat/ChatHistoryListFragment.kt @@ -54,42 +54,13 @@ class ChatHistoryListFragment : Fragment() { } } - val mRealm = DatabaseService(requireActivity()).realmInstance - val chats = mRealm.where(RealmChatHistory::class.java).findAll() - - val list = mRealm.where(RealmChatHistory::class.java).equalTo("user", user?.name) - .sort("id", Sort.DESCENDING) - .findAll() - - val filteredHistoryList = ArrayList() - for (chat in chats) { - val model = list.find { it.id == chat.id } - if (model != null && !filteredHistoryList.contains(model)) { - filteredHistoryList.add(model) - } - } - showNoData(fragmentChatHistoryListBinding.noChats, filteredHistoryList.size, "chatHistory") - if (filteredHistoryList.isEmpty()) { - fragmentChatHistoryListBinding.searchBar.visibility = View.GONE - fragmentChatHistoryListBinding.recyclerView.visibility = View.GONE - } - val adapter = ChatHistoryListAdapter(requireContext(), list, this) - adapter.setChatHistoryItemClickListener(object : ChatHistoryListAdapter.ChatHistoryItemClickListener { - override fun onChatHistoryItemClicked(conversations: RealmList?, id: String, rev:String?) { - conversations?.let { sharedViewModel.setSelectedChatHistory(it) } - sharedViewModel.setSelected_id(id) - rev?.let { sharedViewModel.setSelected_rev(it) } - - fragmentChatHistoryListBinding.slidingPaneLayout.openPane() - } - }) - fragmentChatHistoryListBinding.recyclerView.adapter = adapter + refreshChatHistoryList() fragmentChatHistoryListBinding.searchBar.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { - adapter.filter(s.toString()) + (fragmentChatHistoryListBinding.recyclerView.adapter as? ChatHistoryListAdapter)?.filter(s.toString()) } override fun afterTextChanged(s: Editable?) {} @@ -102,8 +73,30 @@ class ChatHistoryListFragment : Fragment() { .sort("id", Sort.DESCENDING) .findAll() - val adapter = fragmentChatHistoryListBinding.recyclerView.adapter as ChatHistoryListAdapter - adapter.updateChatHistory(list) + val adapter = fragmentChatHistoryListBinding.recyclerView.adapter as? ChatHistoryListAdapter + if (adapter == null) { + val newAdapter = ChatHistoryListAdapter(requireContext(), list, this) + newAdapter.setChatHistoryItemClickListener(object : ChatHistoryListAdapter.ChatHistoryItemClickListener { + override fun onChatHistoryItemClicked(conversations: RealmList?, id: String, rev: String?) { + conversations?.let { sharedViewModel.setSelectedChatHistory(it) } + sharedViewModel.setSelected_id(id) + rev?.let { sharedViewModel.setSelected_rev(it) } + + fragmentChatHistoryListBinding.slidingPaneLayout.openPane() + } + }) + fragmentChatHistoryListBinding.recyclerView.adapter = newAdapter + } else { + adapter.updateChatHistory(list) + fragmentChatHistoryListBinding.searchBar.visibility = View.VISIBLE + fragmentChatHistoryListBinding.recyclerView.visibility = View.VISIBLE + } + + showNoData(fragmentChatHistoryListBinding.noChats, list.size, "chatHistory") + if (list.isEmpty()) { + fragmentChatHistoryListBinding.searchBar.visibility = View.GONE + fragmentChatHistoryListBinding.recyclerView.visibility = View.GONE + } } } diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt index 054e33a82a..ff7986587f 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt @@ -204,6 +204,13 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N }) } + fun refreshChatHistoryList() { + val fragment = supportFragmentManager.findFragmentById(R.id.fragment_container) + if (fragment is ChatHistoryListFragment) { + fragment.refreshChatHistoryList() + } + } + private fun hideWifi() { val nav_Menu = activityDashboardBinding.appBarBell.bellToolbar.menu nav_Menu.findItem(R.id.menu_goOnline) diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite index 3f3a9cf013..adc9634237 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite +++ b/app/src/main/java/org/ole/planet/myplanet/ui/dashboard/DashboardActivity.kt.lite @@ -204,6 +204,13 @@ class DashboardActivity : DashboardElementActivity(), OnHomeItemClickListener, N }) } + fun refreshChatHistoryList() { + val fragment = supportFragmentManager.findFragmentById(R.id.fragment_container) + if (fragment is ChatHistoryListFragment) { + fragment.refreshChatHistoryList() + } + } + private fun hideWifi() { val nav_Menu = activityDashboardBinding.appBarBell.bellToolbar.menu nav_Menu.findItem(R.id.menu_goOnline) From 2f0d82998b1af7b8d2057ac4e4d6d9baf1847fa4 Mon Sep 17 00:00:00 2001 From: Vivian Li <112584985+strawberrybread@users.noreply.github.com> Date: Tue, 9 Jul 2024 11:36:54 -0400 Subject: [PATCH 10/13] courses: smoother steps (fixes #3789) (#3790) Co-authored-by: dogi --- app/build.gradle | 4 ++-- .../planet/myplanet/ui/courses/CourseStepFragment.kt | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 965ab1eb33..3fb4d54968 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1660 - versionName "0.16.60" + versionCode 1661 + versionName "0.16.61" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true 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 e2a44d1c8d..8e6cd8be51 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 @@ -1,5 +1,6 @@ package org.ole.planet.myplanet.ui.courses +import android.os.Build import android.os.Bundle import android.text.Spannable import android.text.method.LinkMovementMethod @@ -7,6 +8,7 @@ import android.text.style.URLSpan import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.RequiresApi import androidx.fragment.app.Fragment import io.realm.Case import io.realm.Realm @@ -51,7 +53,6 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback { stepId = requireArguments().getString("stepId") stepNumber = requireArguments().getInt("stepNumber") } - userVisibleHint = false } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { @@ -89,6 +90,7 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback { } } + @RequiresApi(Build.VERSION_CODES.O) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) step = cRealm.where(RealmCourseStep::class.java).equalTo("id", stepId).findFirst()!! @@ -115,6 +117,9 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback { textWithSpans.removeSpan(urlSpan) } } + if (isVisible && isMyCourse(user?.id, step.courseId, cRealm)) { + saveCourseProgress() + } } private fun hideTestIfNoQuestion() { @@ -152,6 +157,7 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback { } } + @RequiresApi(Build.VERSION_CODES.O) private fun setListeners() { val notDownloadedResources: List = cRealm.where(RealmMyLibrary::class.java).equalTo("stepId", stepId).equalTo("resourceOffline", false).isNotNull("resourceLocalAddress").findAll() setResourceButton(notDownloadedResources, fragmentCourseStepBinding.btnResources) @@ -175,6 +181,7 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback { setOpenResourceButton(downloadedResources, fragmentCourseStepBinding.btnOpen) } + @RequiresApi(Build.VERSION_CODES.O) override fun onDownloadComplete() { super.onDownloadComplete() setListeners() @@ -184,7 +191,7 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback { companion object { fun prependBaseUrlToImages(markdownContent: String?, baseUrl: String): String { - val pattern = "!\\[.*?\\]\\((.*?)\\)" + val pattern = "!\\[.*?]\\((.*?)\\)" val imagePattern = Pattern.compile(pattern) val matcher = markdownContent?.let { imagePattern.matcher(it) } val result = StringBuffer() From 020db62b641e356822bf33a7d7964756de75beae Mon Sep 17 00:00:00 2001 From: Elijah Whang <59347000+ewhang5@users.noreply.github.com> Date: Tue, 9 Jul 2024 10:43:12 -0500 Subject: [PATCH 11/13] community: smoother tabs (fixes #3797) (#3798) Co-authored-by: dogi --- app/build.gradle | 4 ++-- .../ole/planet/myplanet/ui/community/AdapterLeader.kt | 11 ++++++----- .../myplanet/ui/community/CommunityTabFragment.kt | 1 - 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 3fb4d54968..d4bf5b9ceb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1661 - versionName "0.16.61" + versionCode 1662 + versionName "0.16.62" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/community/AdapterLeader.kt b/app/src/main/java/org/ole/planet/myplanet/ui/community/AdapterLeader.kt index c340cdf688..f3e6a0cf1a 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/community/AdapterLeader.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/community/AdapterLeader.kt @@ -4,10 +4,11 @@ import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView +import org.ole.planet.myplanet.R import org.ole.planet.myplanet.databinding.RowJoinedUserBinding import org.ole.planet.myplanet.model.RealmUserModel -class AdapterLeader(var context: Context, var leaders: List) : +class AdapterLeader(var context: Context, private var leaders: List) : RecyclerView.Adapter() { private lateinit var rowJoinedUserBinding: RowJoinedUserBinding override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { @@ -23,15 +24,15 @@ class AdapterLeader(var context: Context, var leaders: List) : if (leaders[position].firstName == null) { holder.title.text = leaders[position].name } else { - holder.title.text = "${leaders[position]}" + holder.title.text = context.getString(R.string.message_placeholder, leaders[position]) } - holder.tv_description.text = leaders[position].email + holder.tvDescription.text = leaders[position].email } } - internal inner class ViewHolderLeader(private val rowJoinedUserBinding: RowJoinedUserBinding) : RecyclerView.ViewHolder(rowJoinedUserBinding.root){ + internal inner class ViewHolderLeader(rowJoinedUserBinding: RowJoinedUserBinding) : RecyclerView.ViewHolder(rowJoinedUserBinding.root){ var title= rowJoinedUserBinding.tvTitle - var tv_description= rowJoinedUserBinding.tvDescription + var tvDescription= rowJoinedUserBinding.tvDescription var icon= rowJoinedUserBinding.icMore } } \ No newline at end of file diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/community/CommunityTabFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/community/CommunityTabFragment.kt index 36c550e783..200fa92e22 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/community/CommunityTabFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/community/CommunityTabFragment.kt @@ -9,7 +9,6 @@ import androidx.fragment.app.Fragment import com.google.android.material.tabs.TabLayoutMediator import org.ole.planet.myplanet.databinding.FragmentTeamDetailBinding import org.ole.planet.myplanet.service.UserProfileDbHandler -import org.ole.planet.myplanet.ui.sync.SyncActivity import org.ole.planet.myplanet.utilities.Constants.PREFS_NAME import org.ole.planet.myplanet.utilities.TimeUtils import java.util.Date From 091cc83615da0822f7dc9257bf24d1a874fcd6a0 Mon Sep 17 00:00:00 2001 From: Vivian Li <112584985+strawberrybread@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:00:29 -0400 Subject: [PATCH 12/13] login: show members username (fixes #3787) (#3788) Co-authored-by: Gideon Okuro Co-authored-by: dogi --- app/build.gradle | 4 ++-- .../main/java/org/ole/planet/myplanet/model/RealmUserModel.kt | 4 +--- .../java/org/ole/planet/myplanet/ui/sync/LoginActivity.kt | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d4bf5b9ceb..f681b3144a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1662 - versionName "0.16.62" + versionCode 1663 + versionName "0.16.63" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true diff --git a/app/src/main/java/org/ole/planet/myplanet/model/RealmUserModel.kt b/app/src/main/java/org/ole/planet/myplanet/model/RealmUserModel.kt index 451265b823..9d7fb5dca2 100644 --- a/app/src/main/java/org/ole/planet/myplanet/model/RealmUserModel.kt +++ b/app/src/main/java/org/ole/planet/myplanet/model/RealmUserModel.kt @@ -67,8 +67,6 @@ open class RealmUserModel : RealmObject() { @JvmField var birthPlace: String? = null @JvmField - var communityName: String? = null - @JvmField var userImage: String? = null @JvmField var key: String? = null @@ -172,7 +170,7 @@ open class RealmUserModel : RealmObject() { } override fun toString(): String { - return "$firstName $lastName" + return "$name" } companion object { diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/sync/LoginActivity.kt b/app/src/main/java/org/ole/planet/myplanet/ui/sync/LoginActivity.kt index 8a979e97ad..b29fabd589 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/sync/LoginActivity.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/sync/LoginActivity.kt @@ -259,7 +259,7 @@ class LoginActivity : SyncActivity(), TeamListAdapter.OnItemClickListener { if (selectedTeamId?.isNotEmpty() == true) { users = RealmMyTeam.getUsers(selectedTeamId, mRealm, "") val userList = (users as? MutableList)?.map { - User(it.getFullName(), it.name ?: "", "", it.userImage ?: "", "team") + User(it.name ?: "", it.name ?: "", "", it.userImage ?: "", "team") } ?: emptyList() val existingUsers = prefData.getSAVEDUSERS().toMutableList() From 50195c526aee8c1de476c0c2515494ea2b06647d Mon Sep 17 00:00:00 2001 From: rlam20 <52076121+rlam20@users.noreply.github.com> Date: Tue, 9 Jul 2024 13:42:03 -0400 Subject: [PATCH 13/13] actions: less warnings is more (fixes #3795) (#3796) Co-authored-by: dogi --- app/build.gradle | 4 ++-- .../java/org/ole/planet/myplanet/ui/team/BaseTeamFragment.kt | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f681b3144a..10a26fc456 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "org.ole.planet.myplanet" minSdkVersion 21 targetSdkVersion 34 - versionCode 1663 - versionName "0.16.63" + versionCode 1664 + versionName "0.16.64" ndkVersion '21.3.6528147' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true diff --git a/app/src/main/java/org/ole/planet/myplanet/ui/team/BaseTeamFragment.kt b/app/src/main/java/org/ole/planet/myplanet/ui/team/BaseTeamFragment.kt index 4d79015290..c9978aaa8e 100644 --- a/app/src/main/java/org/ole/planet/myplanet/ui/team/BaseTeamFragment.kt +++ b/app/src/main/java/org/ole/planet/myplanet/ui/team/BaseTeamFragment.kt @@ -2,7 +2,9 @@ package org.ole.planet.myplanet.ui.team import android.content.Context import android.content.SharedPreferences +import android.os.Build import android.os.Bundle +import androidx.annotation.RequiresApi import org.ole.planet.myplanet.base.BaseNewsFragment import org.ole.planet.myplanet.datamanager.DatabaseService import org.ole.planet.myplanet.model.RealmMyTeam @@ -10,6 +12,7 @@ import org.ole.planet.myplanet.model.RealmNews import org.ole.planet.myplanet.model.RealmUserModel import org.ole.planet.myplanet.utilities.Constants.PREFS_NAME +@RequiresApi(Build.VERSION_CODES.O) abstract class BaseTeamFragment : BaseNewsFragment() { lateinit var dbService: DatabaseService var user: RealmUserModel? = null