Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix HTML Text rendering in course section and discussion #357

Merged
merged 2 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class CourseSectionDelegate(activity: Activity) : AdapterDelegate<List<CourseCon
val vh = holder as CourseSectionViewHolder
val section = items[position] as CourseSection
vh.sectionName.text = section.name
val summary = Utils.trimWhiteSpace(HtmlCompat.fromHtml(section.summary.trim { it <= ' ' },
val summary = Utils.trimWhiteSpace(HtmlCompat.fromHtml(section.summary,
HtmlCompat.FROM_HTML_MODE_COMPACT))
if (summary.isNotEmpty()) {
vh.sectionDescription.visibility = View.VISIBLE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package crux.bphc.cms.fragments

import android.os.Bundle
import android.text.method.LinkMovementMethod
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
Expand All @@ -24,9 +23,9 @@ import crux.bphc.cms.helper.CourseRequestHandler
import crux.bphc.cms.models.forum.Attachment
import crux.bphc.cms.models.forum.Discussion
import crux.bphc.cms.utils.Utils
import crux.bphc.cms.widgets.HtmlTextView
import crux.bphc.cms.widgets.PropertiesAlertDialog
import io.realm.Realm
import io.realm.RealmList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -92,7 +91,7 @@ class DiscussionFragment : Fragment() {
binding.subject.text = discussion.subject
binding.userName.text = discussion.userFullName
binding.modifiedTime.text = Utils.formatDate(discussion.timeModified)
binding.message.text = discussion.message
binding.message.text = HtmlTextView.parseHtml(discussion.message)
Glide.with(requireContext())
.load(Urls.getProfilePicUrl(discussion.userPictureUrl))
.into(binding.userPic)
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/crux/bphc/cms/fragments/ForumFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import crux.bphc.cms.helper.CourseRequestHandler
import crux.bphc.cms.interfaces.ClickListener
import crux.bphc.cms.models.forum.Discussion
import crux.bphc.cms.utils.Utils
import crux.bphc.cms.widgets.HtmlTextView
import io.realm.Realm
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand Down Expand Up @@ -185,7 +186,7 @@ class ForumFragment : Fragment() {

itemBinding.subject.text = discussion.subject
itemBinding.userName.text = discussion.userFullName
itemBinding.message.text = discussion.message
itemBinding.message.text = HtmlTextView.parseHtml(discussion.message)
itemBinding.modifiedTime.text = Utils.formatDate(discussion.timeModified)

if (!discussion.isPinned) {
Expand Down
40 changes: 32 additions & 8 deletions app/src/main/java/crux/bphc/cms/models/course/CourseSection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package crux.bphc.cms.models.course
import androidx.core.text.HtmlCompat
import com.google.gson.annotations.SerializedName
import crux.bphc.cms.interfaces.CourseContent
import crux.bphc.cms.models.UserAccount
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import java.util.regex.Matcher
import java.util.regex.Pattern

/**
* @author Harshit Agarwal (17-Dec-2016)
Expand All @@ -15,24 +18,41 @@ open class CourseSection(
@PrimaryKey @SerializedName("id") var id: Int = 0,
name: String = "",
@SerializedName("section") var sectionNum: Int = 0,
@SerializedName("summary") var summary: String = "",
summary: String = "",
@SerializedName("modules") var modules: RealmList<Module> = RealmList<Module>(),
var courseId: Int = 0,
) : RealmObject(), CourseContent {

@SerializedName("name") var name: String = name
get() {
return HtmlCompat.fromHtml(field, HtmlCompat.FROM_HTML_MODE_COMPACT).toString()
.trim { it <= ' ' }
.trim { it <= ' ' }
}

@SerializedName("summary") var summary: String = summary
get() {
val pattern: Pattern = Pattern.compile(URL_REGEX)
val matcher: Matcher = pattern.matcher(field)

val summaryBuffer = StringBuffer(field.length)

while (matcher.find()) {
val foundLink = matcher.group(1)
val replaceWith = "<a href=\"$foundLink?token=${UserAccount.token}\">"
matcher.appendReplacement(summaryBuffer, replaceWith)
}
matcher.appendTail(summaryBuffer)

return summaryBuffer.toString().trim { it <= ' ' }
}

fun deepCopy(): CourseSection = CourseSection(
id,
name,
sectionNum,
summary,
RealmList<Module>(*modules.map { it.deepCopy() }.toTypedArray()),
courseId,
id,
name,
sectionNum,
summary,
RealmList<Module>(*modules.map { it.deepCopy() }.toTypedArray()),
courseId,
)

override fun equals(other: Any?): Boolean {
Expand All @@ -42,4 +62,8 @@ open class CourseSection(
override fun hashCode(): Int {
return id
}

companion object {
private const val URL_REGEX = "<a href=\"(.*?)\">"
}
}
68 changes: 46 additions & 22 deletions app/src/main/java/crux/bphc/cms/models/course/Module.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,31 @@ import androidx.core.text.HtmlCompat
import com.google.gson.annotations.SerializedName
import crux.bphc.cms.R
import crux.bphc.cms.interfaces.CourseContent
import crux.bphc.cms.models.UserAccount
import crux.bphc.cms.utils.FileUtils
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.Ignore
import io.realm.annotations.PrimaryKey
import java.util.*
import java.util.regex.Matcher
import java.util.regex.Pattern

/**
* @author Harshit Agarwal (16-Dec-2016)
* @author Abhijeet Viswa
*/
open class Module(
@PrimaryKey @SerializedName("id") var id: Int = 0,
@SerializedName("instance") var instance: Int = 0,
name: String = "",
@SerializedName("url") var url: String = "",
@SerializedName("modicon") var modIcon: String = "",
@SerializedName("modname") private var modName: String = "",
@SerializedName("description") var description: String = "",
@SerializedName("contents") var contents: RealmList<Content> = RealmList(),
var courseSectionId: Int = 0,
var isUnread: Boolean = false,
@PrimaryKey @SerializedName("id") var id: Int = 0,
@SerializedName("instance") var instance: Int = 0,
name: String = "",
@SerializedName("url") var url: String = "",
@SerializedName("modicon") var modIcon: String = "",
@SerializedName("modname") private var modName: String = "",
description: String = "",
@SerializedName("contents") var contents: RealmList<Content> = RealmList(),
var courseSectionId: Int = 0,
var isUnread: Boolean = false,
) : RealmObject(), CourseContent {
enum class Type {
RESOURCE, FORUM, LABEL, ASSIGNMENT, FOLDER, QUIZ, URL, PAGE, DEFAULT, BOOK
Expand All @@ -34,7 +37,24 @@ open class Module(
@SerializedName("name") var name: String = name
get() {
return HtmlCompat.fromHtml(field, HtmlCompat.FROM_HTML_MODE_COMPACT).toString()
.trim{ it <= ' ' }
.trim{ it <= ' ' }
}

@SerializedName("description") var description: String = description
get() {
val pattern: Pattern = Pattern.compile(URL_REGEX)
val matcher: Matcher = pattern.matcher(field)

val descriptionBuffer = StringBuffer(field.length)

while (matcher.find()) {
val foundLink = matcher.group(1)
val replaceWith = "<a href=\"$foundLink?token=${UserAccount.token}\">"
matcher.appendReplacement(descriptionBuffer, replaceWith)
}
matcher.appendTail(descriptionBuffer)

return descriptionBuffer.toString().trim { it <= ' ' }
}

@Ignore var modType: Type = Type.DEFAULT
Expand Down Expand Up @@ -67,20 +87,20 @@ open class Module(
}

fun deepCopy(): Module = Module(
id,
instance,
name,
url,
modIcon,
modName,
description,
RealmList<Content>(*contents.map { it.copy() }.toTypedArray()),
courseSectionId,
isUnread,
id,
instance,
name,
url,
modIcon,
modName,
description,
RealmList<Content>(*contents.map { it.copy() }.toTypedArray()),
courseSectionId,
isUnread,
)

private fun inferModuleTypeFromModuleName(): Type {
return when (modName.toLowerCase(Locale.ROOT)) {
return when (modName.lowercase(Locale.ROOT)) {
"resource" -> Type.RESOURCE
"forum" -> Type.FORUM
"label" -> Type.LABEL
Expand All @@ -100,4 +120,8 @@ open class Module(
override fun hashCode(): Int {
return id
}

companion object {
private const val URL_REGEX = "<a href=\"(.*?)\">"
}
}
Loading
Loading