Skip to content

Commit e6b356c

Browse files
Copilotdogi
andauthored
Merge remote-tracking branch 'origin/master' into fix-voices-adapter-listadapter-2559200356537418385
# Conflicts: # app/src/main/java/org/ole/planet/myplanet/ui/voices/VoicesAdapter.kt Co-authored-by: dogi <13684059+dogi@users.noreply.github.com>
2 parents 1730520 + 6488583 commit e6b356c

56 files changed

Lines changed: 1414 additions & 597 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ android {
1212
applicationId "org.ole.planet.myplanet"
1313
minSdk = 26
1414
targetSdk = 36
15-
versionCode = 5296
16-
versionName = "0.52.96"
15+
versionCode = 5329
16+
versionName = "0.53.29"
1717
ndkVersion = '26.3.11579264'
1818
vectorDrawables.useSupportLibrary = true
1919
}

app/src/main/java/org/ole/planet/myplanet/di/DatabaseModule.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ object DatabaseModule {
2929
@Singleton
3030
@RealmDispatcher
3131
fun provideRealmDispatcher(): CoroutineDispatcher {
32-
val handlerThread = HandlerThread("RealmQueryThread")
33-
handlerThread.start()
32+
// Realm async queries and change listeners require a thread with a Looper.
33+
val handlerThread = HandlerThread("RealmQueryThread").also { it.start() }
3434
return Handler(handlerThread.looper).asCoroutineDispatcher()
3535
}
3636

app/src/main/java/org/ole/planet/myplanet/model/RealmNews.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,18 @@ open class RealmNews : RealmObject() {
5151
var sharedBy: String? = null
5252
@Ignore
5353
var sortDate: Long = 0
54+
@Ignore
55+
var parsedViewIn: JsonArray? = null
56+
@Ignore
57+
var parsedConversations: List<RealmConversation>? = null
58+
@Ignore
59+
var parsedImageUrls: List<JsonObject>? = null
60+
@Ignore
61+
var rawViewIn: String? = null
62+
@Ignore
63+
var rawConversations: String? = null
64+
@Ignore
65+
var rawImageUrls: List<String>? = null
5466

5567
val imagesArray: JsonArray
5668
get() = if (images == null) JsonArray() else JsonUtils.gson.fromJson(images, JsonArray::class.java)

app/src/main/java/org/ole/planet/myplanet/repository/ChatRepository.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package org.ole.planet.myplanet.repository
22

33
import com.google.gson.JsonObject
4+
import org.ole.planet.myplanet.model.AiProvider
5+
import org.ole.planet.myplanet.model.ChatResponse
46
import org.ole.planet.myplanet.model.RealmChatHistory
7+
import retrofit2.Response
58

69
interface ChatRepository {
10+
suspend fun sendNewChatRequest(query: String, user: String?, aiProvider: AiProvider): Response<ChatResponse>
11+
suspend fun sendContinueChatRequest(message: String, user: String?, aiProvider: AiProvider, id: String, rev: String): Response<ChatResponse>
712
suspend fun fetchAiProviders(serverUrl: String, isServerReachable: suspend (String) -> Boolean): Map<String, Boolean>?
813
suspend fun getChatHistoryForUser(userName: String?): List<RealmChatHistory>
914
suspend fun getLatestRev(id: String): String?

app/src/main/java/org/ole/planet/myplanet/repository/ChatRepositoryImpl.kt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,22 @@ import java.util.Date
88
import javax.inject.Inject
99
import kotlinx.coroutines.CoroutineDispatcher
1010
import org.ole.planet.myplanet.data.DatabaseService
11+
import okhttp3.MediaType.Companion.toMediaTypeOrNull
12+
import okhttp3.RequestBody.Companion.toRequestBody
1113
import org.ole.planet.myplanet.data.api.ChatApiService
1214
import org.ole.planet.myplanet.di.RealmDispatcher
15+
import org.ole.planet.myplanet.model.AiProvider
16+
import org.ole.planet.myplanet.model.ChatRequest
17+
import org.ole.planet.myplanet.model.ChatResponse
18+
import org.ole.planet.myplanet.model.ContentData
19+
import org.ole.planet.myplanet.model.ContinueChatRequest
20+
import org.ole.planet.myplanet.model.Data
1321
import org.ole.planet.myplanet.model.RealmChatHistory
1422
import org.ole.planet.myplanet.model.RealmConversation
1523
import org.ole.planet.myplanet.services.SharedPrefManager
1624
import org.ole.planet.myplanet.services.sync.ServerUrlMapper
1725
import org.ole.planet.myplanet.utils.JsonUtils
26+
import retrofit2.Response
1827

1928
class ChatRepositoryImpl @Inject constructor(
2029
databaseService: DatabaseService,
@@ -24,6 +33,30 @@ class ChatRepositoryImpl @Inject constructor(
2433
private val sharedPrefManager: SharedPrefManager
2534
) : RealmRepository(databaseService, realmDispatcher), ChatRepository {
2635

36+
override suspend fun sendNewChatRequest(
37+
query: String,
38+
user: String?,
39+
aiProvider: AiProvider
40+
): Response<ChatResponse> {
41+
val chatData = ChatRequest(data = ContentData(user ?: "", query, aiProvider), save = true)
42+
val jsonContent = JsonUtils.gson.toJson(chatData)
43+
val requestBody = jsonContent.toRequestBody("application/json".toMediaTypeOrNull())
44+
return chatApiService.sendChatRequest(requestBody)
45+
}
46+
47+
override suspend fun sendContinueChatRequest(
48+
message: String,
49+
user: String?,
50+
aiProvider: AiProvider,
51+
id: String,
52+
rev: String
53+
): Response<ChatResponse> {
54+
val continueChatData = ContinueChatRequest(data = Data(user ?: "", message, aiProvider, id, rev), save = true)
55+
val jsonContent = JsonUtils.gson.toJson(continueChatData)
56+
val requestBody = jsonContent.toRequestBody("application/json".toMediaTypeOrNull())
57+
return chatApiService.sendChatRequest(requestBody)
58+
}
59+
2760
override suspend fun fetchAiProviders(serverUrl: String, isServerReachable: suspend (String) -> Boolean): Map<String, Boolean>? {
2861
val mapping = serverUrlMapper.processUrl(serverUrl)
2962
serverUrlMapper.updateServerIfNecessary(mapping, sharedPrefManager.rawPreferences) { url ->

app/src/main/java/org/ole/planet/myplanet/repository/CoursesRepositoryImpl.kt

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -56,37 +56,20 @@ class CoursesRepositoryImpl @Inject constructor(
5656
}
5757

5858
override fun getAllCourses(userId: String?, libs: List<RealmMyCourse>): List<RealmMyCourse> {
59-
val libraries: MutableList<RealmMyCourse> = ArrayList()
60-
for (item in libs) {
61-
item.isMyCourse = item.userId?.contains(userId) == true
62-
libraries.add(item)
63-
}
64-
return libraries
59+
return libs.onEach { it.isMyCourse = it.userId?.contains(userId) == true }
6560
}
6661

6762
override fun getMyCourseByUserId(userId: String?, libs: List<RealmMyCourse>?): List<RealmMyCourse> {
6863
return libs?.filter { it.userId?.contains(userId) == true } ?: emptyList()
6964
}
7065

7166
override fun getOurCourse(userId: String?, libs: List<RealmMyCourse>): List<RealmMyCourse> {
72-
val libraries: MutableList<RealmMyCourse> = ArrayList()
73-
for (item in libs) {
74-
if (item.userId?.contains(userId) != true) {
75-
libraries.add(item)
76-
}
77-
}
78-
return libraries
67+
return libs.filter { it.userId?.contains(userId) != true }
7968
}
8069

8170
override fun getMyCourses(userId: String?, courses: List<RealmMyCourse>): List<RealmMyCourse> {
82-
val myCourses: MutableList<RealmMyCourse> = ArrayList()
83-
if (userId == null) return myCourses
84-
for (course in courses) {
85-
if (course.userId?.contains(userId) == true) {
86-
myCourses.add(course)
87-
}
88-
}
89-
return myCourses
71+
if (userId == null) return emptyList()
72+
return courses.filter { it.userId?.contains(userId) == true }
9073
}
9174

9275
override suspend fun getMyCourses(userId: String): List<RealmMyCourse> {
@@ -628,9 +611,30 @@ class CoursesRepositoryImpl @Inject constructor(
628611
userId: String?
629612
): List<RealmMyCourse> {
630613
return withRealm { realm ->
631-
val data = realm.where(RealmMyCourse::class.java).findAll()
614+
var realmQuery = realm.where(RealmMyCourse::class.java)
615+
616+
if (tags.isNotEmpty()) {
617+
val tagIds = tags.mapNotNull { it.id }.toTypedArray()
618+
val linkedCourseIds = realm.where(RealmTag::class.java)
619+
.equalTo("db", "courses")
620+
.`in`("tagId", tagIds)
621+
.findAll()
622+
.mapNotNull { it.linkId }
623+
.toTypedArray()
624+
625+
if (linkedCourseIds.isEmpty()) {
626+
return@withRealm emptyList()
627+
}
628+
realmQuery = realmQuery.`in`("courseId", linkedCourseIds)
629+
}
630+
631+
if (isMyCourseLib && !userId.isNullOrBlank()) {
632+
realmQuery = realmQuery.equalTo("userId", userId)
633+
}
634+
635+
val data = realmQuery.findAll()
632636

633-
var list: List<RealmMyCourse> = if (query.isEmpty()) {
637+
val list: List<RealmMyCourse> = if (query.isEmpty()) {
634638
realm.copyFromRealm(data)
635639
} else {
636640
val queryParts = query.split(" ").filterNot { it.isEmpty() }
@@ -652,25 +656,11 @@ class CoursesRepositoryImpl @Inject constructor(
652656
realm.copyFromRealm(filteredData)
653657
}
654658

655-
list = if (isMyCourseLib) {
656-
getMyCourses(userId, list)
657-
} else {
658-
getAllCourses(userId, list)
659-
}
660-
661-
if (tags.isEmpty()) {
662-
return@withRealm list
659+
if (!isMyCourseLib) {
660+
list.forEach { it.isMyCourse = it.userId?.contains(userId) == true }
663661
}
664662

665-
val tagIds = tags.mapNotNull { it.id }.toTypedArray()
666-
val linkedCourseIds = realm.where(RealmTag::class.java)
667-
.equalTo("db", "courses")
668-
.`in`("tagId", tagIds)
669-
.findAll()
670-
.mapNotNull { it.linkId }
671-
.toSet()
672-
673-
list.filter { linkedCourseIds.contains(it.courseId) }.distinct()
663+
list.distinctBy { it.courseId }
674664
}
675665
}
676666

app/src/main/java/org/ole/planet/myplanet/repository/RatingsRepositoryImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class RatingsRepositoryImpl @Inject constructor(
2323
equalTo("type", type)
2424
}
2525
val aggregated = aggregateRatings(ratings, userId)
26-
val map = HashMap<String?, JsonObject>()
26+
val map = HashMap<String?, JsonObject>(Math.ceil(aggregated.size / 0.75).toInt())
2727
for ((item, aggregation) in aggregated) {
2828
map[item] = aggregation.toJson()
2929
}

app/src/main/java/org/ole/planet/myplanet/repository/ResourcesRepositoryImpl.kt

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,18 @@ class ResourcesRepositoryImpl @Inject constructor(
123123
return withRealm { realm ->
124124
val queryObj = realm.where(RealmMyLibrary::class.java).equalTo("isPrivate", false)
125125

126-
val data = if (isMyCourseLib) {
127-
queryObj.findAll().filter { it.userId?.contains(userId) == true }
128-
} else {
129-
queryObj.findAll().filter { it.userId?.contains(userId) == false }
126+
if (userId != null) {
127+
if (isMyCourseLib) {
128+
queryObj.equalTo("userId", userId)
129+
} else {
130+
queryObj.not().equalTo("userId", userId)
131+
}
132+
} else if (isMyCourseLib) {
133+
return@withRealm emptyList()
130134
}
131135

136+
val data = queryObj.findAll()
137+
132138
if (query.isEmpty()) {
133139
return@withRealm realm.copyFromRealm(data)
134140
}
@@ -179,9 +185,9 @@ class ResourcesRepositoryImpl @Inject constructor(
179185

180186
val results = queryList(RealmMyLibrary::class.java) {
181187
equalTo("isPrivate", false)
188+
equalTo("userId", userId)
182189
}
183190
return filterLibrariesNeedingUpdate(results)
184-
.filter { it.userId?.contains(userId) == true }
185191
}
186192

187193
override suspend fun getLibraryForSelectedUser(userId: String): List<RealmMyLibrary> {
@@ -217,9 +223,9 @@ class ResourcesRepositoryImpl @Inject constructor(
217223

218224
val results = queryList(RealmMyLibrary::class.java) {
219225
equalTo("isPrivate", false)
226+
equalTo("userId", userId)
220227
}
221-
return filterLibrariesNeedingUpdate(results)
222-
.count { it.userId?.contains(userId) == true }
228+
return filterLibrariesNeedingUpdate(results).size
223229
}
224230

225231
override suspend fun resourceTitleExists(title: String): Boolean {
@@ -323,10 +329,7 @@ class ResourcesRepositoryImpl @Inject constructor(
323329

324330
override suspend fun markAllResourcesOffline(isOffline: Boolean) {
325331
executeTransaction { realm ->
326-
val libraries = realm.where(RealmMyLibrary::class.java).findAll()
327-
for (library in libraries) {
328-
library.resourceOffline = isOffline
329-
}
332+
realm.where(RealmMyLibrary::class.java).findAll().setValue("resourceOffline", isOffline)
330333
}
331334
}
332335

@@ -408,12 +411,11 @@ class ResourcesRepositoryImpl @Inject constructor(
408411
resourceIds.chunked(chunkSize).forEach { chunk ->
409412
val libraryItems = realm.where(RealmMyLibrary::class.java)
410413
.`in`("resourceId", chunk.toTypedArray())
414+
.not().equalTo("userId", userId)
411415
.findAll()
412416

413417
libraryItems.forEach { libraryItem ->
414-
if (libraryItem.userId?.contains(userId) == false) {
415-
libraryItem.setUserId(userId)
416-
}
418+
libraryItem.setUserId(userId)
417419
}
418420

419421
val removedLogs = realm.where(org.ole.planet.myplanet.model.RealmRemovedLog::class.java)
@@ -456,19 +458,22 @@ class ResourcesRepositoryImpl @Inject constructor(
456458

457459
override suspend fun getDownloadSuggestionList(userId: String?): List<RealmMyLibrary> {
458460
val targetUserId = userId ?: sharedPrefManager.getUserId().ifEmpty { null }
459-
val results = queryList(RealmMyLibrary::class.java) {
460-
equalTo("isPrivate", false)
461-
}
462-
val allNeedingUpdate = filterLibrariesNeedingUpdate(results)
463461

464462
if (!targetUserId.isNullOrBlank()) {
465-
val userLibraries = allNeedingUpdate.filter { it.userId?.contains(targetUserId) == true }
466-
if (userLibraries.isNotEmpty()) {
467-
return userLibraries
463+
val userLibraries = queryList(RealmMyLibrary::class.java) {
464+
equalTo("isPrivate", false)
465+
equalTo("userId", targetUserId)
466+
}
467+
val userLibrariesNeedingUpdate = filterLibrariesNeedingUpdate(userLibraries)
468+
if (userLibrariesNeedingUpdate.isNotEmpty()) {
469+
return userLibrariesNeedingUpdate
468470
}
469471
}
470472

471-
return allNeedingUpdate
473+
val results = queryList(RealmMyLibrary::class.java) {
474+
equalTo("isPrivate", false)
475+
}
476+
return filterLibrariesNeedingUpdate(results)
472477
}
473478

474479
override suspend fun getLibraryByUserId(userId: String): List<RealmMyLibrary> {
@@ -605,7 +610,7 @@ class ResourcesRepositoryImpl @Inject constructor(
605610

606611
override suspend fun getResourceRatingsBulk(ids: List<String>, userId: String?): Map<String?, JsonObject> {
607612
val allRatings = ratingsRepository.getResourceRatings(userId)
608-
val filteredRatings = HashMap<String?, JsonObject>()
613+
val filteredRatings = HashMap<String?, JsonObject>(Math.ceil(ids.size / 0.75).toInt())
609614
for (id in ids) {
610615
allRatings[id]?.let {
611616
filteredRatings[id] = it

app/src/main/java/org/ole/planet/myplanet/repository/SubmissionsRepository.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,6 @@ interface SubmissionsRepository {
5151
suspend fun getPhotosByIds(ids: Array<String>): List<org.ole.planet.myplanet.model.RealmSubmitPhotos>
5252
fun bulkInsertFromSync(realm: io.realm.Realm, jsonArray: com.google.gson.JsonArray)
5353
fun insertSubmission(mRealm: io.realm.Realm, submission: com.google.gson.JsonObject)
54-
fun serializeExamResult(mRealm: io.realm.Realm, sub: org.ole.planet.myplanet.model.RealmSubmission, context: android.content.Context, spm: org.ole.planet.myplanet.services.SharedPrefManager): com.google.gson.JsonObject
54+
suspend fun getExamUploadPayload(submission: org.ole.planet.myplanet.model.RealmSubmission): com.google.gson.JsonObject
5555
fun serializeSubmission(mRealm: io.realm.Realm, submission: org.ole.planet.myplanet.model.RealmSubmission, context: android.content.Context, source: String, parentCode: String): com.google.gson.JsonObject
5656
}

app/src/main/java/org/ole/planet/myplanet/repository/SubmissionsRepositoryExporter.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ class SubmissionsRepositoryExporter @Inject constructor(
7575
.equalTo("examId", examId)
7676
.findAll()
7777

78+
val answersMap = submission.answers?.associateBy { it.questionId } ?: emptyMap()
79+
7880
questions.forEachIndexed { index, question ->
7981
if (yPosition > PAGE_HEIGHT - MARGIN - 100) {
8082
document.finishPage(page)
@@ -89,7 +91,7 @@ class SubmissionsRepositoryExporter @Inject constructor(
8991
yPosition = drawMultilineText(canvas, questionText, MARGIN, yPosition, headerPaint, PAGE_WIDTH - (2 * MARGIN))
9092
yPosition += LINE_HEIGHT / 2
9193

92-
val answer = submission.answers?.find { it.questionId == question.id }
94+
val answer = answersMap[question.id]
9395
val answerText = formatAnswer(answer)
9496
canvas.drawText("A: $answerText", MARGIN + 20, yPosition, normalPaint)
9597
yPosition += LINE_HEIGHT * 2
@@ -181,6 +183,8 @@ class SubmissionsRepositoryExporter @Inject constructor(
181183
canvas.drawText("Status: ${submission.status}", MARGIN + 20, yPosition, normalPaint)
182184
yPosition += LINE_HEIGHT * 2
183185

186+
val answersMap = submission.answers?.associateBy { it.questionId } ?: emptyMap()
187+
184188
questions.forEachIndexed { index, question ->
185189
if (yPosition > PAGE_HEIGHT - MARGIN - 100) {
186190
document.finishPage(page)
@@ -195,7 +199,7 @@ class SubmissionsRepositoryExporter @Inject constructor(
195199
yPosition = drawMultilineText(canvas, questionText, MARGIN + 20, yPosition, normalPaint, PAGE_WIDTH - (2 * MARGIN) - 20)
196200
yPosition += LINE_HEIGHT / 2
197201

198-
val answer = submission.answers?.find { it.questionId == question.id }
202+
val answer = answersMap[question.id]
199203
val answerText = formatAnswer(answer)
200204
yPosition = drawMultilineText(canvas, "A: $answerText", MARGIN + 40, yPosition, normalPaint, PAGE_WIDTH - (2 * MARGIN) - 40)
201205
yPosition += LINE_HEIGHT * 1.5f

0 commit comments

Comments
 (0)