mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-01-18 12:56:45 -06:00
[UI] Add text styling to manual events. (#96)
* [UI] Move text styling outside of messages module. * [UI] Add text styling to event manual dialog. * [UI/Events] Implement showing HTML-formatted content. * [UI] Fix searching in styled event topic. Create HtmlMode enum. * [UI] Add HTML Simple mode to text styling manager. Fix CharSequence replacing. * [Events] Disable self-shared event notifications. * [UI] Fix simple HTML mode format. Fix HTML in notifications. * [HTML] Replace usages of Html and HtmlCompat with BetterHtml. * [Events] Fix editing self-added events from other devices. * [Events] Implement receiving and fix showing HTML-formatted events. * [UI/Events] Add observing changes in event details dialog. * [Firebase] Disable self-shared event notifications.
This commit is contained in:
parent
7e0f69d95d
commit
74b766f18a
@ -1007,8 +1007,29 @@ inline fun <T> LongSparseArray<T>.filter(predicate: (T) -> Boolean): List<T> {
|
||||
return destination
|
||||
}
|
||||
|
||||
fun CharSequence.replace(oldValue: String, newValue: CharSequence, ignoreCase: Boolean = false): CharSequence =
|
||||
splitToSequence(oldValue, ignoreCase = ignoreCase).toList().concat(newValue)
|
||||
fun CharSequence.replaceSpanned(oldValue: String, newValue: CharSequence, ignoreCase: Boolean = false): CharSequence {
|
||||
var seq = this
|
||||
var index = seq.indexOf(oldValue, ignoreCase = ignoreCase)
|
||||
while (index != -1) {
|
||||
val sb = SpannableStringBuilder()
|
||||
sb.appendRange(seq, 0, index)
|
||||
sb.append(newValue)
|
||||
sb.appendRange(seq, index + oldValue.length, seq.length)
|
||||
seq = sb
|
||||
index = seq.indexOf(oldValue, startIndex = index + 1, ignoreCase = ignoreCase)
|
||||
}
|
||||
return seq
|
||||
}
|
||||
|
||||
fun SpannableStringBuilder.replaceSpan(spanClass: Class<*>, prefix: CharSequence, suffix: CharSequence): SpannableStringBuilder {
|
||||
getSpans(0, length, spanClass).forEach {
|
||||
val spanStart = getSpanStart(it)
|
||||
insert(spanStart, prefix)
|
||||
val spanEnd = getSpanEnd(it)
|
||||
insert(spanEnd, suffix)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun Int.toColorStateList(): ColorStateList {
|
||||
val states = arrayOf(
|
||||
|
@ -1,6 +1,5 @@
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
||||
|
||||
import android.text.Html
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
@ -9,6 +8,7 @@ import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
|
||||
class EdudziennikWebGetHomework(
|
||||
override val data: DataEdudziennik,
|
||||
@ -26,7 +26,8 @@ class EdudziennikWebGetHomework(
|
||||
webGet(TAG, "Homework/$id") { text ->
|
||||
val description = Regexes.EDUDZIENNIK_HOMEWORK_DESCRIPTION.find(text)?.get(1)?.trim()
|
||||
|
||||
if (description != null) event.topic = Html.fromHtml(description).toString()
|
||||
if (description != null)
|
||||
event.topic = BetterHtml.fromHtml(context = null, description).toString()
|
||||
|
||||
event.homeworkBody = ""
|
||||
event.isDownloaded = true
|
||||
|
@ -1,12 +1,12 @@
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia
|
||||
|
||||
import android.text.Html
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.jsoup.Jsoup
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusSynergia
|
||||
import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
|
||||
class LibrusSynergiaGetHomework(override val data: DataLibrus,
|
||||
val event: EventFull,
|
||||
@ -23,7 +23,10 @@ class LibrusSynergiaGetHomework(override val data: DataLibrus,
|
||||
val table = doc.select("table.decorated tbody > tr")
|
||||
|
||||
event.topic = table[1].select("td")[1].text()
|
||||
event.homeworkBody = Html.fromHtml(table[5].select("td")[1].html()).toString()
|
||||
event.homeworkBody = BetterHtml.fromHtml(
|
||||
context = null,
|
||||
html = table[5].select("td")[1].html(),
|
||||
).toString()
|
||||
event.isDownloaded = true
|
||||
|
||||
event.attachmentIds = mutableListOf()
|
||||
|
@ -4,12 +4,12 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
|
||||
|
||||
import android.text.Html
|
||||
import androidx.core.util.contains
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
|
||||
@ -26,7 +26,7 @@ class MobidziennikApiHomework(val data: DataMobidziennik, rows: List<String>) {
|
||||
val id = cols[0].toLong()
|
||||
val teacherId = cols[7].toLong()
|
||||
val subjectId = cols[6].toLong()
|
||||
val topic = Html.fromHtml(cols[1])?.toString()?.trim() ?: ""
|
||||
val topic = BetterHtml.fromHtml(context = null, cols[1]).toString().trim()
|
||||
val eventDate = Date.fromYmd(cols[2])
|
||||
val startTime = Time.fromYmdHm(cols[3])
|
||||
|
||||
|
@ -245,7 +245,10 @@ class SzkolnyApi(val app: App) : CoroutineScope {
|
||||
seen = profile.empty
|
||||
notified = profile.empty
|
||||
|
||||
if (profile.userCode == event.sharedBy) sharedBy = "self"
|
||||
if (profile.userCode == event.sharedBy) {
|
||||
sharedBy = "self"
|
||||
addedManually = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,80 +69,90 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
|
||||
}
|
||||
|
||||
private fun eventNotifications() {
|
||||
for (event in app.db.eventDao().getNotNotifiedNow().filter { it.date >= today }) {
|
||||
app.db.eventDao().getNotNotifiedNow().filter {
|
||||
it.date >= today
|
||||
}.forEach { event ->
|
||||
val text = if (event.isHomework)
|
||||
app.getString(
|
||||
if (event.subjectLongName.isNullOrEmpty())
|
||||
R.string.notification_homework_no_subject_format
|
||||
else
|
||||
R.string.notification_homework_format,
|
||||
event.subjectLongName,
|
||||
event.date.formattedString
|
||||
if (event.subjectLongName.isNullOrEmpty())
|
||||
R.string.notification_homework_no_subject_format
|
||||
else
|
||||
R.string.notification_homework_format,
|
||||
event.subjectLongName,
|
||||
event.date.formattedString
|
||||
)
|
||||
else
|
||||
app.getString(
|
||||
if (event.subjectLongName.isNullOrEmpty())
|
||||
R.string.notification_event_no_subject_format
|
||||
else
|
||||
R.string.notification_event_format,
|
||||
event.typeName ?: "wydarzenie",
|
||||
event.date.formattedString,
|
||||
event.subjectLongName
|
||||
if (event.subjectLongName.isNullOrEmpty())
|
||||
R.string.notification_event_no_subject_format
|
||||
else
|
||||
R.string.notification_event_format,
|
||||
event.typeName ?: "wydarzenie",
|
||||
event.date.formattedString,
|
||||
event.subjectLongName
|
||||
)
|
||||
val textLong = app.getString(
|
||||
R.string.notification_event_long_format,
|
||||
event.typeName ?: "-",
|
||||
event.subjectLongName ?: "-",
|
||||
event.date.formattedString,
|
||||
Week.getFullDayName(event.date.weekDay),
|
||||
event.time?.stringHM ?: app.getString(R.string.event_all_day),
|
||||
event.topic.take(200)
|
||||
R.string.notification_event_long_format,
|
||||
event.typeName ?: "-",
|
||||
event.subjectLongName ?: "-",
|
||||
event.date.formattedString,
|
||||
Week.getFullDayName(event.date.weekDay),
|
||||
event.time?.stringHM ?: app.getString(R.string.event_all_day),
|
||||
event.topic.take(200)
|
||||
)
|
||||
val type = if (event.isHomework) Notification.TYPE_NEW_HOMEWORK else Notification.TYPE_NEW_EVENT
|
||||
val type = if (event.isHomework)
|
||||
Notification.TYPE_NEW_HOMEWORK
|
||||
else
|
||||
Notification.TYPE_NEW_EVENT
|
||||
notifications += Notification(
|
||||
id = Notification.buildId(event.profileId, type, event.id),
|
||||
title = app.getNotificationTitle(type),
|
||||
text = text,
|
||||
textLong = textLong,
|
||||
type = type,
|
||||
profileId = event.profileId,
|
||||
profileName = profiles.singleOrNull { it.id == event.profileId }?.name,
|
||||
viewId = if (event.isHomework) MainActivity.DRAWER_ITEM_HOMEWORK else MainActivity.DRAWER_ITEM_AGENDA,
|
||||
addedDate = event.addedDate
|
||||
id = Notification.buildId(event.profileId, type, event.id),
|
||||
title = app.getNotificationTitle(type),
|
||||
text = text,
|
||||
textLong = textLong,
|
||||
type = type,
|
||||
profileId = event.profileId,
|
||||
profileName = profiles.singleOrNull { it.id == event.profileId }?.name,
|
||||
viewId = if (event.isHomework) MainActivity.DRAWER_ITEM_HOMEWORK else MainActivity.DRAWER_ITEM_AGENDA,
|
||||
addedDate = event.addedDate
|
||||
).addExtra("eventId", event.id).addExtra("eventDate", event.date.value.toLong())
|
||||
}
|
||||
}
|
||||
|
||||
fun sharedEventNotifications() {
|
||||
for (event in app.db.eventDao().getNotNotifiedNow().filter { it.date >= today && it.sharedBy != null }) {
|
||||
app.db.eventDao().getNotNotifiedNow().filter {
|
||||
it.date >= today && it.sharedBy != null && it.sharedBy != "self"
|
||||
}.forEach { event ->
|
||||
val text = app.getString(
|
||||
R.string.notification_shared_event_format,
|
||||
event.sharedByName,
|
||||
event.typeName ?: "wydarzenie",
|
||||
event.date.formattedString,
|
||||
event.topic
|
||||
R.string.notification_shared_event_format,
|
||||
event.sharedByName,
|
||||
event.typeName ?: "wydarzenie",
|
||||
event.date.formattedString,
|
||||
event.topicHtml
|
||||
)
|
||||
val textLong = app.getString(
|
||||
R.string.notification_shared_event_long_format,
|
||||
event.sharedByName,
|
||||
event.typeName ?: "-",
|
||||
event.subjectLongName ?: "-",
|
||||
event.date.formattedString,
|
||||
Week.getFullDayName(event.date.weekDay),
|
||||
event.time?.stringHM ?: app.getString(R.string.event_all_day),
|
||||
event.topic.take(200)
|
||||
R.string.notification_shared_event_long_format,
|
||||
event.sharedByName,
|
||||
event.typeName ?: "-",
|
||||
event.subjectLongName ?: "-",
|
||||
event.date.formattedString,
|
||||
Week.getFullDayName(event.date.weekDay),
|
||||
event.time?.stringHM ?: app.getString(R.string.event_all_day),
|
||||
event.topicHtml.take(200)
|
||||
)
|
||||
val type = if (event.isHomework) Notification.TYPE_NEW_HOMEWORK else Notification.TYPE_NEW_EVENT
|
||||
val type = if (event.isHomework)
|
||||
Notification.TYPE_NEW_HOMEWORK
|
||||
else
|
||||
Notification.TYPE_NEW_EVENT
|
||||
notifications += Notification(
|
||||
id = Notification.buildId(event.profileId, type, event.id),
|
||||
title = app.getNotificationTitle(type),
|
||||
text = text,
|
||||
textLong = textLong,
|
||||
type = type,
|
||||
profileId = event.profileId,
|
||||
profileName = profiles.singleOrNull { it.id == event.profileId }?.name,
|
||||
viewId = if (event.isHomework) MainActivity.DRAWER_ITEM_HOMEWORK else MainActivity.DRAWER_ITEM_AGENDA,
|
||||
addedDate = event.addedDate
|
||||
id = Notification.buildId(event.profileId, type, event.id),
|
||||
title = app.getNotificationTitle(type),
|
||||
text = text,
|
||||
textLong = textLong,
|
||||
type = type,
|
||||
profileId = event.profileId,
|
||||
profileName = profiles.singleOrNull { it.id == event.profileId }?.name,
|
||||
viewId = if (event.isHomework) MainActivity.DRAWER_ITEM_HOMEWORK else MainActivity.DRAWER_ITEM_AGENDA,
|
||||
addedDate = event.addedDate
|
||||
).addExtra("eventId", event.id).addExtra("eventDate", event.date.value.toLong())
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,10 @@ abstract class EventDao : BaseDao<Event, EventFull> {
|
||||
fun getAllByDateNow(profileId: Int, date: Date) =
|
||||
getRawNow("$QUERY WHERE $NOT_BLACKLISTED AND events.profileId = $profileId AND eventDate = '${date.stringY_m_d}' $ORDER_BY")
|
||||
|
||||
// GET ONE - LIVE DATA
|
||||
fun getById(profileId: Int, id: Long) =
|
||||
getOne("$QUERY WHERE events.profileId = $profileId AND eventId = $id")
|
||||
|
||||
// GET ONE - NOW
|
||||
fun getByIdNow(profileId: Int, id: Long) =
|
||||
getOneNow("$QUERY WHERE events.profileId = $profileId AND eventId = $id")
|
||||
|
@ -75,6 +75,7 @@ open class Event(
|
||||
|
||||
@ColumnInfo(name = "eventAddedManually")
|
||||
var addedManually: Boolean = false
|
||||
get() = field || sharedBy == "self"
|
||||
@ColumnInfo(name = "eventSharedBy")
|
||||
var sharedBy: String? = null
|
||||
@ColumnInfo(name = "eventSharedByName")
|
||||
|
@ -7,6 +7,7 @@ import androidx.room.Ignore
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.ui.modules.search.Searchable
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
|
||||
@ -48,6 +49,20 @@ class EventFull(
|
||||
var teamName: String? = null
|
||||
var teamCode: String? = null
|
||||
|
||||
@delegate:Ignore
|
||||
@delegate:Transient
|
||||
val topicHtml by lazy {
|
||||
BetterHtml.fromHtml(context = null, topic, nl2br = true)
|
||||
}
|
||||
|
||||
@delegate:Ignore
|
||||
@delegate:Transient
|
||||
val bodyHtml by lazy {
|
||||
homeworkBody?.let {
|
||||
BetterHtml.fromHtml(context = null, it, nl2br = true)
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Transient
|
||||
override var searchPriority = 0
|
||||
@ -60,7 +75,7 @@ class EventFull(
|
||||
@delegate:Transient
|
||||
override val searchKeywords by lazy {
|
||||
listOf(
|
||||
listOf(topic, homeworkBody),
|
||||
listOf(topicHtml.toString(), bodyHtml?.toString()),
|
||||
attachmentNames,
|
||||
listOf(subjectLongName),
|
||||
listOf(teacherName),
|
||||
|
@ -3,12 +3,12 @@
|
||||
*/
|
||||
package pl.szczodrzynski.edziennik.data.db.full
|
||||
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.Relation
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
|
||||
import pl.szczodrzynski.edziennik.ui.modules.search.Searchable
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
|
||||
class MessageFull(
|
||||
profileId: Int, id: Long, type: Int,
|
||||
@ -33,11 +33,10 @@ class MessageFull(
|
||||
@delegate:Transient
|
||||
val bodyHtml by lazy {
|
||||
body?.let {
|
||||
HtmlCompat.fromHtml(it, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||
BetterHtml.fromHtml(context = null, it)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Ignore
|
||||
@Transient
|
||||
override var searchPriority = 0
|
||||
|
@ -122,7 +122,7 @@ class SzkolnyAppFirebase(val app: App, val profiles: List<Profile>, val message:
|
||||
id = json.getLong("id") ?: return,
|
||||
date = json.getInt("eventDate")?.let { Date.fromValue(it) } ?: return,
|
||||
time = json.getInt("startTime")?.let { Time.fromValue(it) },
|
||||
topic = json.getString("topic") ?: "",
|
||||
topic = json.getString("topicHtml") ?: json.getString("topic") ?: "",
|
||||
color = json.getInt("color"),
|
||||
type = json.getLong("type") ?: 0,
|
||||
teacherId = json.getLong("teacherId") ?: -1,
|
||||
@ -135,7 +135,10 @@ class SzkolnyAppFirebase(val app: App, val profiles: List<Profile>, val message:
|
||||
|
||||
event.sharedBy = json.getString("sharedBy")
|
||||
event.sharedByName = json.getString("sharedByName")
|
||||
if (profile.userCode == event.sharedBy) event.sharedBy = "self"
|
||||
if (profile.userCode == event.sharedBy) {
|
||||
event.sharedBy = "self"
|
||||
event.addedManually = true
|
||||
}
|
||||
|
||||
val metadata = Metadata(
|
||||
event.profileId,
|
||||
@ -148,7 +151,7 @@ class SzkolnyAppFirebase(val app: App, val profiles: List<Profile>, val message:
|
||||
val type = if (event.isHomework) Notification.TYPE_NEW_SHARED_HOMEWORK else Notification.TYPE_NEW_SHARED_EVENT
|
||||
val notificationFilter = app.config.getFor(event.profileId).sync.notificationFilter
|
||||
|
||||
if (!notificationFilter.contains(type)) {
|
||||
if (!notificationFilter.contains(type) && event.sharedBy != "self") {
|
||||
val notification = Notification(
|
||||
id = Notification.buildId(event.profileId, type, event.id),
|
||||
title = app.getNotificationTitle(type),
|
||||
|
@ -9,7 +9,6 @@ import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.text.Html
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.work.*
|
||||
@ -20,6 +19,7 @@ import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@ -115,7 +115,7 @@ class UpdateWorker(val context: Context, val params: WorkerParameters) : Worker(
|
||||
.setStyle(NotificationCompat.BigTextStyle()
|
||||
.bigText(listOf(
|
||||
app.getString(R.string.notification_updates_text, update.versionName),
|
||||
update.releaseNotes?.let { Html.fromHtml(it) }
|
||||
update.releaseNotes?.let { BetterHtml.fromHtml(context = null, it) }
|
||||
).concat("\n")))
|
||||
.setColor(0xff2196f3.toInt())
|
||||
.setLights(0xFF00FFFF.toInt(), 2000, 2000)
|
||||
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2021-10-11.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs
|
||||
|
||||
import android.content.res.ColorStateList
|
||||
import android.text.Editable
|
||||
import android.text.SpannableStringBuilder
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.StyledTextDialogBinding
|
||||
import pl.szczodrzynski.edziennik.utils.DefaultTextStyles
|
||||
import pl.szczodrzynski.edziennik.utils.Themes
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode.SIMPLE
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.StylingConfig
|
||||
|
||||
class StyledTextDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val initialText: Editable?,
|
||||
val onSuccess: (text: Editable) -> Unit,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "StyledTextDialog"
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var b: StyledTextDialogBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
private lateinit var config: StylingConfig
|
||||
|
||||
private val manager
|
||||
get() = app.textStylingManager
|
||||
|
||||
init {
|
||||
show()
|
||||
}
|
||||
|
||||
fun show() {
|
||||
if (activity.isFinishing)
|
||||
return
|
||||
onShowListener?.invoke(TAG)
|
||||
app = activity.applicationContext as App
|
||||
b = StyledTextDialogBinding.inflate(activity.layoutInflater)
|
||||
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.styled_text_dialog_title)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.save) { _, _ ->
|
||||
onSuccess(b.editText.text ?: SpannableStringBuilder(""))
|
||||
}
|
||||
.setNeutralButton(R.string.cancel, null)
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
|
||||
config = StylingConfig(
|
||||
editText = b.editText,
|
||||
fontStyleGroup = b.fontStyle.styles,
|
||||
fontStyleClear = b.fontStyle.clear,
|
||||
styles = DefaultTextStyles.getAsList(b.fontStyle),
|
||||
textHtml = if (App.devMode) b.htmlText else null,
|
||||
htmlMode = SIMPLE,
|
||||
)
|
||||
|
||||
manager.attach(config)
|
||||
|
||||
b.editText.text = initialText
|
||||
|
||||
// this is awful
|
||||
if (Themes.isDark) {
|
||||
val colorStateList = ColorStateList.valueOf(0x40ffffff)
|
||||
b.fontStyle.bold.strokeColor = colorStateList
|
||||
b.fontStyle.italic.strokeColor = colorStateList
|
||||
b.fontStyle.underline.strokeColor = colorStateList
|
||||
b.fontStyle.strike.strokeColor = colorStateList
|
||||
b.fontStyle.subscript.strokeColor = colorStateList
|
||||
b.fontStyle.superscript.strokeColor = colorStateList
|
||||
b.fontStyle.clear.strokeColor = colorStateList
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs
|
||||
|
||||
import android.text.Html
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
@ -14,6 +13,7 @@ import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
|
||||
import pl.szczodrzynski.edziennik.sync.UpdateDownloaderService
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class UpdateAvailableDialog(
|
||||
@ -48,7 +48,7 @@ class UpdateAvailableDialog(
|
||||
R.string.update_available_format,
|
||||
BuildConfig.VERSION_NAME,
|
||||
update.versionName,
|
||||
update.releaseNotes?.let { Html.fromHtml(it) } ?: "---"
|
||||
update.releaseNotes?.let { BetterHtml.fromHtml(activity, it) } ?: "---"
|
||||
)
|
||||
.setPositiveButton(R.string.update_available_button) { dialog, _ ->
|
||||
activity.startService(Intent(app, UpdateDownloaderService::class.java))
|
||||
|
@ -5,7 +5,6 @@
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.changelog
|
||||
|
||||
import android.os.Build
|
||||
import android.text.Html
|
||||
import android.widget.ScrollView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
@ -18,6 +17,7 @@ import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.dp
|
||||
import pl.szczodrzynski.edziennik.utils.BetterLinkMovementMethod
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class ChangelogDialog(
|
||||
@ -52,12 +52,11 @@ class ChangelogDialog(
|
||||
text = text.replace("""\[(.+?)]\(@([A-z0-9-]+)\)""".toRegex(), "<a href=\"$commitsUrlPrefix$2\">$1</a>")
|
||||
text = text.replace("""\s@([A-z0-9-]+)""".toRegex(), " <a href=\"$commitsUrlPrefix$1\">@$1</a>")
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
textView.text = Html.fromHtml(text)
|
||||
}
|
||||
else {
|
||||
textView.text = Html.fromHtml(text.replace("<li>", "<br><li> - "))
|
||||
}
|
||||
val html = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||
text
|
||||
else
|
||||
text.replace("<li>", "<br><li> - ")
|
||||
textView.text = BetterHtml.fromHtml(activity, html)
|
||||
|
||||
textView.movementMethod = BetterLinkMovementMethod.getInstance()
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.sync
|
||||
|
||||
import android.text.Html
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
@ -14,6 +13,7 @@ import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||
import pl.szczodrzynski.edziennik.data.api.task.AppSync
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class RegistrationConfigDialog(
|
||||
@ -61,7 +61,7 @@ class RegistrationConfigDialog(
|
||||
onShowListener?.invoke(TAG + "Enable")
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.registration_config_title)
|
||||
.setMessage(Html.fromHtml(app.getString(R.string.registration_config_enable_text)))
|
||||
.setMessage(BetterHtml.fromHtml(activity, R.string.registration_config_enable_text))
|
||||
.setPositiveButton(R.string.i_agree) { _, _ ->
|
||||
enableRegistration()
|
||||
}
|
||||
@ -76,7 +76,7 @@ class RegistrationConfigDialog(
|
||||
onShowListener?.invoke(TAG + "Disable")
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.registration_config_title)
|
||||
.setMessage(Html.fromHtml(app.getString(R.string.registration_config_disable_text)))
|
||||
.setMessage(R.string.registration_config_disable_text)
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
disableRegistration()
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.Html
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.Toast
|
||||
@ -22,6 +21,7 @@ import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.ErrorReportRequest
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.utils.Themes.appTheme
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/*
|
||||
@ -90,7 +90,7 @@ class CrashActivity : AppCompatActivity(), CoroutineScope {
|
||||
moreInfoButton.setOnClickListener {
|
||||
MaterialAlertDialogBuilder(this, R.style.AppTheme_MaterialAlertDialogMonospace)
|
||||
.setTitle(R.string.crash_details)
|
||||
.setMessage(Html.fromHtml(getErrorString(intent, false)))
|
||||
.setMessage(BetterHtml.fromHtml(context = null, getErrorString(intent, false)))
|
||||
.setPositiveButton(R.string.close, null)
|
||||
.setNeutralButton(R.string.copy_to_clipboard) { _, _ -> copyErrorToClipboard() }
|
||||
.show()
|
||||
|
@ -31,6 +31,7 @@ import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class EventDetailsDialog(
|
||||
val activity: AppCompatActivity,
|
||||
// this event is observed for changes
|
||||
var event: EventFull,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
@ -85,7 +86,11 @@ class EventDetailsDialog(
|
||||
showRemoveEventDialog()
|
||||
}
|
||||
|
||||
update()
|
||||
// watch the event for changes
|
||||
app.db.eventDao().getById(event.profileId, event.id).observe(activity) {
|
||||
event = it ?: return@observe
|
||||
update()
|
||||
}
|
||||
}}
|
||||
|
||||
private fun update() {
|
||||
@ -93,6 +98,9 @@ class EventDetailsDialog(
|
||||
b.eventShared = eventShared
|
||||
b.eventOwn = eventOwn
|
||||
|
||||
b.topic.text = event.topicHtml
|
||||
b.body.text = event.bodyHtml
|
||||
|
||||
if (!event.seen) {
|
||||
manager.markAsSeen(event)
|
||||
}
|
||||
@ -170,8 +178,9 @@ class EventDetailsDialog(
|
||||
dialog.dismiss()
|
||||
return@EventManualDialog
|
||||
}
|
||||
event = it
|
||||
update()
|
||||
// this should not be needed as the event is observed by the ID
|
||||
// event = it
|
||||
// update()
|
||||
},
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
@ -350,7 +359,7 @@ class EventDetailsDialog(
|
||||
val intent = Intent(Intent.ACTION_EDIT).apply {
|
||||
data = Events.CONTENT_URI
|
||||
putExtra(Events.TITLE, title)
|
||||
putExtra(Events.DESCRIPTION, event.topic)
|
||||
putExtra(Events.DESCRIPTION, event.topicHtml.toString())
|
||||
|
||||
if (event.time == null) {
|
||||
putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, true)
|
||||
|
@ -13,6 +13,9 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialog
|
||||
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import kotlinx.coroutines.*
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
@ -27,9 +30,13 @@ import pl.szczodrzynski.edziennik.data.db.entity.*
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.data.db.full.LessonFull
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.StyledTextDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.sync.RegistrationConfigDialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.views.TimeDropdown.Companion.DISPLAY_LESSONS
|
||||
import pl.szczodrzynski.edziennik.utils.Anim
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode.SIMPLE
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.StylingConfigBase
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
@ -59,6 +66,10 @@ class EventManualDialog(
|
||||
private lateinit var b: DialogEventManualV2Binding
|
||||
private lateinit var dialog: AlertDialog
|
||||
private lateinit var profile: Profile
|
||||
private lateinit var stylingConfig: StylingConfigBase
|
||||
|
||||
private val textStylingManager
|
||||
get() = app.textStylingManager
|
||||
|
||||
private var customColor: Int? = null
|
||||
private val editingShared = editingEvent?.sharedBy != null
|
||||
@ -128,6 +139,23 @@ class EventManualDialog(
|
||||
}
|
||||
}
|
||||
|
||||
b.topicLayout.endIconDrawable = IconicsDrawable(activity, CommunityMaterial.Icon3.cmd_open_in_new).apply {
|
||||
sizeDp = 24
|
||||
}
|
||||
b.topicLayout.setEndIconOnClickListener {
|
||||
StyledTextDialog(
|
||||
activity,
|
||||
initialText = b.topic.text,
|
||||
onSuccess = {
|
||||
b.topic.text = it
|
||||
},
|
||||
onShowListener,
|
||||
onDismissListener
|
||||
)
|
||||
}
|
||||
|
||||
stylingConfig = StylingConfigBase(editText = b.topic, htmlMode = SIMPLE)
|
||||
|
||||
updateShareText()
|
||||
b.shareSwitch.onChange { _, isChecked ->
|
||||
updateShareText(isChecked)
|
||||
@ -332,7 +360,7 @@ class EventManualDialog(
|
||||
|
||||
// copy data from event being edited
|
||||
editingEvent?.let {
|
||||
b.topic.setText(it.topic)
|
||||
b.topic.setText(BetterHtml.fromHtml(activity, it.topic, nl2br = true))
|
||||
if (it.color != -1)
|
||||
customColor = it.color
|
||||
}
|
||||
@ -458,12 +486,13 @@ class EventManualDialog(
|
||||
|
||||
val id = System.currentTimeMillis()
|
||||
|
||||
val topicHtml = textStylingManager.getHtmlText(stylingConfig)
|
||||
val eventObject = Event(
|
||||
profileId = profileId,
|
||||
id = editingEvent?.id ?: id,
|
||||
date = date,
|
||||
time = startTime,
|
||||
topic = topic,
|
||||
topic = topicHtml,
|
||||
color = customColor,
|
||||
type = type?.id ?: Event.TYPE_DEFAULT,
|
||||
teacherId = teacher?.id ?: -1,
|
||||
|
@ -9,7 +9,6 @@ import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.mikepenz.iconics.utils.buildIconics
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.db.full.EventFull
|
||||
import pl.szczodrzynski.edziennik.databinding.EventListItemBinding
|
||||
@ -99,15 +98,13 @@ class EventViewHolder(
|
||||
/* 3$ */
|
||||
item.teamName?.let { bullet + it } ?: "",
|
||||
)
|
||||
// workaround for the span data lost during setText above
|
||||
val addedBySpanned = adapter.highlightSearchText(
|
||||
item = item,
|
||||
text = addedBy,
|
||||
color = colorHighlight
|
||||
)
|
||||
b.addedBy.text = b.addedBy.text.replace(addedBy, addedBySpanned)
|
||||
// for now, as CharSequence.replace() converts the original sequence to string,
|
||||
// so the Iconics span data is lost and the share icon set above does not display
|
||||
b.addedBy.buildIconics()
|
||||
b.addedBy.text = b.addedBy.text.replaceSpanned(addedBy, addedBySpanned)
|
||||
|
||||
b.attachmentIcon.isVisible = item.hasAttachments
|
||||
|
||||
|
@ -8,7 +8,6 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.plusAssign
|
||||
import androidx.core.view.setMargins
|
||||
@ -25,6 +24,7 @@ import pl.szczodrzynski.edziennik.ui.dialogs.UpdateAvailableDialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCard
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class HomeAvailabilityCard(
|
||||
@ -61,8 +61,8 @@ class HomeAvailabilityCard(
|
||||
|
||||
// show "register unavailable" only when disabled
|
||||
if (status?.userMessage != null) {
|
||||
b.homeAvailabilityTitle.text = HtmlCompat.fromHtml(status.userMessage.title, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||
b.homeAvailabilityText.text = HtmlCompat.fromHtml(status.userMessage.contentShort, HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||
b.homeAvailabilityTitle.text = BetterHtml.fromHtml(activity, status.userMessage.title)
|
||||
b.homeAvailabilityText.text = BetterHtml.fromHtml(activity, status.userMessage.contentShort)
|
||||
b.homeAvailabilityUpdate.isVisible = false
|
||||
b.homeAvailabilityIcon.setImageResource(R.drawable.ic_sync)
|
||||
if (status.userMessage.icon != null)
|
||||
|
@ -10,7 +10,6 @@ import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.text.Html
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -31,6 +30,7 @@ import pl.szczodrzynski.edziennik.ui.dialogs.RegisterUnavailableDialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackActivity
|
||||
import pl.szczodrzynski.edziennik.utils.BetterLinkMovementMethod
|
||||
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager.Error.Type
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
@ -218,7 +218,7 @@ class LoginChooserFragment : Fragment(), CoroutineScope {
|
||||
if (!app.config.privacyPolicyAccepted) {
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.privacy_policy)
|
||||
.setMessage(Html.fromHtml(activity.getString(R.string.privacy_policy_dialog_html)))
|
||||
.setMessage(BetterHtml.fromHtml(activity, R.string.privacy_policy_dialog_html))
|
||||
.setPositiveButton(R.string.i_agree) { _, _ ->
|
||||
app.config.privacyPolicyAccepted = true
|
||||
onLoginModeClicked(loginType, loginMode)
|
||||
|
@ -38,15 +38,17 @@ import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.databinding.MessagesComposeFragmentBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.MessagesConfigDialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.list.MessagesFragment
|
||||
import pl.szczodrzynski.edziennik.utils.DefaultTextStyles
|
||||
import pl.szczodrzynski.edziennik.utils.Themes
|
||||
import pl.szczodrzynski.edziennik.utils.managers.MessageManager.UIConfig
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode.COMPATIBLE
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode.ORIGINAL
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.StylingConfig
|
||||
import pl.szczodrzynski.edziennik.utils.span.*
|
||||
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
|
||||
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
|
||||
class MessagesComposeFragment : Fragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "MessagesComposeFragment"
|
||||
@ -103,6 +105,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
||||
b.breakpoints.visibility = if (App.devMode) View.VISIBLE else View.GONE
|
||||
b.breakpoints.setOnClickListener {
|
||||
b.breakpoints.isEnabled = true
|
||||
@SuppressLint("SetTextI18n")
|
||||
b.breakpoints.text = "Breakpoints!"
|
||||
// do your job
|
||||
}
|
||||
@ -232,45 +235,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
||||
b.subjectLayout.isEnabled = false
|
||||
b.textLayout.isEnabled = false
|
||||
|
||||
val styles = listOf(
|
||||
StylingConfig.Style(
|
||||
button = b.fontStyleBold,
|
||||
spanClass = BoldSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_bold,
|
||||
hint = R.string.hint_style_bold,
|
||||
),
|
||||
StylingConfig.Style(
|
||||
button = b.fontStyleItalic,
|
||||
spanClass = ItalicSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_italic,
|
||||
hint = R.string.hint_style_italic,
|
||||
),
|
||||
StylingConfig.Style(
|
||||
button = b.fontStyleUnderline,
|
||||
// a custom span is used to prevent issues with keyboards which underline words
|
||||
spanClass = UnderlineCustomSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_underline,
|
||||
hint = R.string.hint_style_underline,
|
||||
),
|
||||
StylingConfig.Style(
|
||||
button = b.fontStyleStrike,
|
||||
spanClass = StrikethroughSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_strikethrough,
|
||||
hint = R.string.hint_style_strike,
|
||||
),
|
||||
StylingConfig.Style(
|
||||
button = b.fontStyleSubscript,
|
||||
spanClass = SubscriptSizeSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_subscript,
|
||||
hint = R.string.hint_style_subscript,
|
||||
),
|
||||
StylingConfig.Style(
|
||||
button = b.fontStyleSuperscript,
|
||||
spanClass = SuperscriptSizeSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_superscript,
|
||||
hint = R.string.hint_style_superscript,
|
||||
),
|
||||
)
|
||||
val styles = DefaultTextStyles.getAsList(b.fontStyle)
|
||||
|
||||
uiConfig = UIConfig(
|
||||
context = activity,
|
||||
@ -285,28 +250,24 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
||||
)
|
||||
stylingConfig = StylingConfig(
|
||||
editText = b.text,
|
||||
fontStyleGroup = b.fontStyle,
|
||||
fontStyleClear = b.fontStyleClear,
|
||||
fontStyleGroup = b.fontStyle.styles,
|
||||
fontStyleClear = b.fontStyle.clear,
|
||||
styles = styles,
|
||||
textHtml = if (App.devMode) b.textHtml else null,
|
||||
htmlCompatibleMode = app.profile.loginStoreType == LOGIN_TYPE_MOBIDZIENNIK,
|
||||
htmlMode = when (app.profile.loginStoreType) {
|
||||
LOGIN_TYPE_MOBIDZIENNIK -> COMPATIBLE
|
||||
else -> ORIGINAL
|
||||
},
|
||||
)
|
||||
|
||||
b.fontStyleLayout.isVisible = enableTextStyling
|
||||
b.fontStyle.root.isVisible = enableTextStyling
|
||||
if (enableTextStyling) {
|
||||
textStylingManager.attach(stylingConfig)
|
||||
b.fontStyle.addOnButtonCheckedListener { _, _, _ ->
|
||||
b.fontStyle.styles.addOnButtonCheckedListener { _, _, _ ->
|
||||
changedBody = true
|
||||
}
|
||||
}
|
||||
|
||||
if (App.devMode) {
|
||||
b.textHtml.isVisible = true
|
||||
b.text.addTextChangedListener {
|
||||
b.textHtml.text = getMessageBody()
|
||||
}
|
||||
}
|
||||
|
||||
activity.navView.bottomBar.apply {
|
||||
fabEnable = true
|
||||
fabExtendedText = getString(R.string.messages_compose_send)
|
||||
|
@ -5,7 +5,6 @@
|
||||
package pl.szczodrzynski.edziennik.ui.modules.messages.single
|
||||
|
||||
import android.os.Bundle
|
||||
import android.text.Html
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -32,6 +31,7 @@ import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesUtils
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.list.MessagesFragment
|
||||
import pl.szczodrzynski.edziennik.utils.Anim
|
||||
import pl.szczodrzynski.edziennik.utils.BetterLink
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
|
||||
@ -255,7 +255,7 @@ class MessageFragment : Fragment(), CoroutineScope {
|
||||
}
|
||||
}
|
||||
messageRecipients.append("</ul>")
|
||||
b.recipients.text = Html.fromHtml(messageRecipients.toString())
|
||||
b.recipients.text = BetterHtml.fromHtml(activity, messageRecipients)
|
||||
|
||||
showAttachments()
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.widgets.timetable;
|
||||
|
||||
import static android.util.TypedValue.COMPLEX_UNIT_SP;
|
||||
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@ -16,7 +18,6 @@ import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Html;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
@ -32,14 +33,13 @@ import com.mikepenz.iconics.utils.IconicsDrawableExtensionsKt;
|
||||
import java.util.List;
|
||||
|
||||
import kotlin.Unit;
|
||||
import pl.szczodrzynski.edziennik.ExtensionsKt;
|
||||
import pl.szczodrzynski.edziennik.R;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||
import pl.szczodrzynski.edziennik.utils.models.ItemWidgetTimetableModel;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week;
|
||||
|
||||
import static android.util.TypedValue.COMPLEX_UNIT_SP;
|
||||
|
||||
public class WidgetTimetableFactory implements RemoteViewsService.RemoteViewsFactory {
|
||||
|
||||
private static final String TAG = "WidgetTimetableProvider";
|
||||
@ -309,17 +309,17 @@ public class WidgetTimetableFactory implements RemoteViewsService.RemoteViewsFac
|
||||
|
||||
views.setViewVisibility(R.id.widgetTimetableOldSubjectName, View.GONE);
|
||||
if (lesson.lessonChange) {
|
||||
views.setTextViewText(R.id.widgetTimetableSubjectName, Html.fromHtml("<i>"+lesson.subjectName+"</i>"));
|
||||
views.setTextViewText(R.id.widgetTimetableSubjectName, ExtensionsKt.asItalicSpannable(lesson.subjectName));
|
||||
if (lesson.lessonChangeNoClassroom) {
|
||||
views.setTextViewText(R.id.widgetTimetableClassroomName, Html.fromHtml("<del>"+lesson.classroomName+"</del>"));
|
||||
views.setTextViewText(R.id.widgetTimetableClassroomName, ExtensionsKt.asStrikethroughSpannable(lesson.classroomName));
|
||||
}
|
||||
else {
|
||||
views.setTextViewText(R.id.widgetTimetableClassroomName, Html.fromHtml("<i>" + lesson.classroomName + "</i>"));
|
||||
views.setTextViewText(R.id.widgetTimetableClassroomName, ExtensionsKt.asItalicSpannable(lesson.classroomName));
|
||||
}
|
||||
}
|
||||
else if (lesson.lessonCancelled) {
|
||||
views.setTextViewText(R.id.widgetTimetableSubjectName, Html.fromHtml("<del>"+lesson.subjectName+"</del>"));
|
||||
views.setTextViewText(R.id.widgetTimetableClassroomName, Html.fromHtml("<del>"+lesson.classroomName+"</del>"));
|
||||
views.setTextViewText(R.id.widgetTimetableSubjectName, ExtensionsKt.asStrikethroughSpannable(lesson.subjectName));
|
||||
views.setTextViewText(R.id.widgetTimetableClassroomName, ExtensionsKt.asStrikethroughSpannable(lesson.classroomName));
|
||||
}
|
||||
else {
|
||||
views.setTextViewText(R.id.widgetTimetableSubjectName, lesson.subjectName);
|
||||
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2021-10-11.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.utils
|
||||
|
||||
import android.text.style.StrikethroughSpan
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.StyledTextButtonsBinding
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.StylingConfig
|
||||
import pl.szczodrzynski.edziennik.utils.span.*
|
||||
|
||||
object DefaultTextStyles {
|
||||
|
||||
fun getAsList(b: StyledTextButtonsBinding) = listOf(
|
||||
StylingConfig.Style(
|
||||
button = b.bold,
|
||||
spanClass = BoldSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_bold,
|
||||
hint = R.string.hint_style_bold,
|
||||
),
|
||||
StylingConfig.Style(
|
||||
button = b.italic,
|
||||
spanClass = ItalicSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_italic,
|
||||
hint = R.string.hint_style_italic,
|
||||
),
|
||||
StylingConfig.Style(
|
||||
button = b.underline,
|
||||
// a custom span is used to prevent issues with keyboards which underline words
|
||||
spanClass = UnderlineCustomSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_underline,
|
||||
hint = R.string.hint_style_underline,
|
||||
),
|
||||
StylingConfig.Style(
|
||||
button = b.strike,
|
||||
spanClass = StrikethroughSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_strikethrough,
|
||||
hint = R.string.hint_style_strike,
|
||||
),
|
||||
StylingConfig.Style(
|
||||
button = b.subscript,
|
||||
spanClass = SubscriptSizeSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_subscript,
|
||||
hint = R.string.hint_style_subscript,
|
||||
),
|
||||
StylingConfig.Style(
|
||||
button = b.superscript,
|
||||
spanClass = SuperscriptSizeSpan::class.java,
|
||||
icon = CommunityMaterial.Icon2.cmd_format_superscript,
|
||||
hint = R.string.hint_style_superscript,
|
||||
),
|
||||
)
|
||||
}
|
@ -32,8 +32,14 @@ object BetterHtml {
|
||||
SuperscriptSizeSpan::class.java,
|
||||
)
|
||||
|
||||
fun fromHtml(context: Context, stringRes: Int) = fromHtml(
|
||||
context,
|
||||
context.getString(stringRes),
|
||||
nl2br = true,
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
fun fromHtml(context: Context, html: String): Spanned {
|
||||
fun fromHtml(context: Context?, html: CharSequence, nl2br: Boolean = false): Spanned {
|
||||
val hexPattern = "(#[a-fA-F0-9]{6})"
|
||||
val colorRegex = "(?:color=\"$hexPattern\")|(?:style=\"color: ?${hexPattern})"
|
||||
.toRegex(RegexOption.IGNORE_CASE)
|
||||
@ -42,29 +48,35 @@ object BetterHtml {
|
||||
.replace("\\[META:[A-z0-9]+;[0-9-]+]".toRegex(), "")
|
||||
.replace("background-color: ?$hexPattern;".toRegex(), "")
|
||||
|
||||
val colorBackground = android.R.attr.colorBackground.resolveAttr(context)
|
||||
val textColorPrimary = android.R.attr.textColorPrimary.resolveAttr(context) and 0xffffff
|
||||
if (nl2br) {
|
||||
text = text.replace("\n", "<br>")
|
||||
}
|
||||
|
||||
colorRegex.findAll(text).forEach { result ->
|
||||
val group = result.groups.drop(1).firstOrNull { it != null } ?: return@forEach
|
||||
if (context != null) {
|
||||
val colorBackground = android.R.attr.colorBackground.resolveAttr(context)
|
||||
val textColorPrimary = android.R.attr.textColorPrimary.resolveAttr(context) and 0xffffff
|
||||
|
||||
val color = Color.parseColor(group.value)
|
||||
var newColor = 0xff000000.toInt() or color
|
||||
colorRegex.findAll(text).forEach { result ->
|
||||
val group = result.groups.drop(1).firstOrNull { it != null } ?: return@forEach
|
||||
|
||||
var blendAmount = 1
|
||||
var numIterations = 0
|
||||
val color = Color.parseColor(group.value)
|
||||
var newColor = 0xff000000.toInt() or color
|
||||
|
||||
while (numIterations < 100 && ColorUtils.calculateContrast(
|
||||
colorBackground,
|
||||
newColor
|
||||
) < 4.5f
|
||||
) {
|
||||
blendAmount += 2
|
||||
newColor = blendColors(color, blendAmount shl 24 or textColorPrimary)
|
||||
numIterations++
|
||||
var blendAmount = 1
|
||||
var numIterations = 0
|
||||
|
||||
while (numIterations < 100 && ColorUtils.calculateContrast(
|
||||
colorBackground,
|
||||
newColor
|
||||
) < 4.5f
|
||||
) {
|
||||
blendAmount += 2
|
||||
newColor = blendColors(color, blendAmount shl 24 or textColorPrimary)
|
||||
numIterations++
|
||||
}
|
||||
|
||||
text = text.replaceRange(group.range, "#" + (newColor and 0xffffff).toString(16))
|
||||
}
|
||||
|
||||
text = text.replaceRange(group.range, "#" + (newColor and 0xffffff).toString(16))
|
||||
}
|
||||
|
||||
/*val olRegex = """<ol>(.+?)</\s*?ol>"""
|
||||
|
@ -45,16 +45,13 @@ class EventManager(val app: App) : CoroutineScope {
|
||||
showType: Boolean = true,
|
||||
doneIconColor: Int? = null
|
||||
) {
|
||||
var eventTopic = if (showType)
|
||||
"${event.typeName ?: "wydarzenie"} - ${event.topic}"
|
||||
else
|
||||
event.topic
|
||||
val topicSpan = event.topicHtml
|
||||
|
||||
if (event.addedManually) {
|
||||
eventTopic = "{cmd-clipboard-edit-outline} $eventTopic"
|
||||
}
|
||||
|
||||
title.text = eventTopic
|
||||
title.text = listOfNotNull(
|
||||
if (event.addedManually) "{cmd-clipboard-edit-outline} " else null,
|
||||
if (showType) "${event.typeName ?: "wydarzenie"} - " else null,
|
||||
topicSpan,
|
||||
).concat()
|
||||
|
||||
title.setCompoundDrawables(
|
||||
null,
|
||||
|
@ -25,6 +25,7 @@ import pl.szczodrzynski.edziennik.data.db.full.MessageFull
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesUtils
|
||||
import pl.szczodrzynski.edziennik.utils.TextInputKeyboardEdit
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode.ORIGINAL
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.StylingConfig
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
@ -148,7 +149,7 @@ class MessageManager(private val app: App) {
|
||||
suspend fun saveAsDraft(config: UIConfig, stylingConfig: StylingConfig, profileId: Int, messageId: Long?) {
|
||||
val teachers = config.recipients.allChips.mapNotNull { it.data as? Teacher }
|
||||
val subject = config.subject.text?.toString() ?: ""
|
||||
val body = textStylingManager.getHtmlText(stylingConfig, enableHtmlCompatible = false)
|
||||
val body = textStylingManager.getHtmlText(stylingConfig, htmlMode = ORIGINAL)
|
||||
|
||||
withContext(Dispatchers.Default) {
|
||||
if (messageId != null) {
|
||||
|
@ -6,18 +6,25 @@ package pl.szczodrzynski.edziennik.utils.managers
|
||||
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.style.StrikethroughSpan
|
||||
import android.text.style.SubscriptSpan
|
||||
import android.text.style.SuperscriptSpan
|
||||
import android.text.style.UnderlineSpan
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.button.MaterialButtonToggleGroup
|
||||
import com.mikepenz.iconics.typeface.IIcon
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.attachToastHint
|
||||
import pl.szczodrzynski.edziennik.hasSet
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.utils.TextInputKeyboardEdit
|
||||
import pl.szczodrzynski.edziennik.utils.html.BetterHtml
|
||||
import pl.szczodrzynski.edziennik.utils.managers.TextStylingManager.HtmlMode.*
|
||||
import pl.szczodrzynski.edziennik.utils.span.BoldSpan
|
||||
import pl.szczodrzynski.edziennik.utils.span.ItalicSpan
|
||||
|
||||
class TextStylingManager(private val app: App) {
|
||||
companion object {
|
||||
@ -28,14 +35,45 @@ class TextStylingManager(private val app: App) {
|
||||
"((?:<br>)+)</p>".toRegex()
|
||||
}
|
||||
|
||||
data class StylingConfig(
|
||||
enum class HtmlMode {
|
||||
/**
|
||||
* The default mode, suitable for fromHtml conversion.
|
||||
*/
|
||||
ORIGINAL,
|
||||
|
||||
/**
|
||||
* A more browser-compatible mode.
|
||||
*/
|
||||
COMPATIBLE,
|
||||
|
||||
/**
|
||||
* A simple, paragraph-stripped mode with \n instead of <br>.
|
||||
* The converted text has no HTML tags when no spans in source.
|
||||
*/
|
||||
SIMPLE,
|
||||
|
||||
/**
|
||||
* Markdown-compatible text mode.
|
||||
*/
|
||||
MARKDOWN,
|
||||
}
|
||||
|
||||
open class StylingConfigBase(
|
||||
val editText: TextInputKeyboardEdit,
|
||||
val htmlMode: HtmlMode = ORIGINAL,
|
||||
) {
|
||||
var watchStyleChecked = true
|
||||
var watchSelectionChanged = true
|
||||
}
|
||||
|
||||
class StylingConfig(
|
||||
editText: TextInputKeyboardEdit,
|
||||
val fontStyleGroup: MaterialButtonToggleGroup,
|
||||
val fontStyleClear: Button,
|
||||
val styles: List<Style>,
|
||||
val textHtml: TextView? = null,
|
||||
val htmlCompatibleMode: Boolean = false,
|
||||
) {
|
||||
htmlMode: HtmlMode = ORIGINAL,
|
||||
) : StylingConfigBase(editText, htmlMode) {
|
||||
data class Style(
|
||||
val button: MaterialButton,
|
||||
val spanClass: Class<*>,
|
||||
@ -45,9 +83,6 @@ class TextStylingManager(private val app: App) {
|
||||
) {
|
||||
fun newInstance(): Any = spanClass.newInstance()
|
||||
}
|
||||
|
||||
var watchStyleChecked = true
|
||||
var watchSelectionChanged = true
|
||||
}
|
||||
|
||||
fun attach(config: StylingConfig) {
|
||||
@ -76,6 +111,14 @@ class TextStylingManager(private val app: App) {
|
||||
onSelectionChanged(config, selectionStart, selectionEnd)
|
||||
}
|
||||
|
||||
if (config.textHtml != null) {
|
||||
config.editText.addTextChangedListener {
|
||||
config.textHtml.text = getHtmlText(config)
|
||||
}
|
||||
config.textHtml.isVisible = true
|
||||
config.textHtml.text = getHtmlText(config)
|
||||
}
|
||||
|
||||
/*b.fontStyleBold.shapeAppearanceModel = b.fontStyleBold.shapeAppearanceModel
|
||||
.toBuilder()
|
||||
.setBottomLeftCornerSize(0f)
|
||||
@ -91,15 +134,14 @@ class TextStylingManager(private val app: App) {
|
||||
.build()*/
|
||||
}
|
||||
|
||||
fun getHtmlText(config: StylingConfig, enableHtmlCompatible: Boolean = true): String {
|
||||
fun getHtmlText(config: StylingConfigBase, htmlMode: HtmlMode = config.htmlMode): String {
|
||||
val text = config.editText.text?.trimEnd() ?: return ""
|
||||
val spanned = SpannableStringBuilder(text)
|
||||
|
||||
val htmlCompatibleMode = config.htmlCompatibleMode && enableHtmlCompatible
|
||||
val toHtmlFlag = if (htmlCompatibleMode)
|
||||
HtmlCompat.TO_HTML_PARAGRAPH_LINES_INDIVIDUAL
|
||||
else
|
||||
HtmlCompat.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE
|
||||
val toHtmlFlag = when (htmlMode) {
|
||||
COMPATIBLE -> HtmlCompat.TO_HTML_PARAGRAPH_LINES_INDIVIDUAL
|
||||
else -> HtmlCompat.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE
|
||||
}
|
||||
|
||||
// apparently setting the spans to a different Spannable calls the original EditText's
|
||||
// onSelectionChanged with selectionStart=-1, which in effect unchecks the format toggles
|
||||
@ -113,24 +155,41 @@ class TextStylingManager(private val app: App) {
|
||||
if (spanStart == spanEnd && it::class.java in BetterHtml.customSpanClasses)
|
||||
spanned.removeSpan(it)
|
||||
}
|
||||
var textHtml = HtmlCompat.toHtml(spanned, toHtmlFlag)
|
||||
.replace("\n", "")
|
||||
.replace(" dir=\"ltr\"", "")
|
||||
.replace("</b><b>", "")
|
||||
.replace("</i><i>", "")
|
||||
.replace("</u><u>", "")
|
||||
.replace("</sub><sub>", "")
|
||||
.replace("</sup><sup>", "")
|
||||
.replace("p style=\"margin-top:0; margin-bottom:0;\"", "p")
|
||||
.replace("<br></p>", "</p><br>")
|
||||
// replace multiple newlines so they convert fromHtml correctly
|
||||
// this should not be breaking with htmlCompatibleMode == true,
|
||||
// as line breaks cannot occur inside paragraphs with these flags
|
||||
.replace(paragraphBrRegex, "</p>$1")
|
||||
|
||||
var textHtml = when (htmlMode) {
|
||||
SIMPLE -> spanned
|
||||
.replaceSpan(BoldSpan::class.java, "<b>", "</b>")
|
||||
.replaceSpan(ItalicSpan::class.java, "<i>", "</i>")
|
||||
.replaceSpan(UnderlineSpan::class.java, "<u>", "</u>")
|
||||
.replaceSpan(StrikethroughSpan::class.java, "<s>", "</s>")
|
||||
.replaceSpan(SubscriptSpan::class.java, "<sub>", "</sub>")
|
||||
.replaceSpan(SuperscriptSpan::class.java, "<sup>", "</sup>")
|
||||
.toString()
|
||||
MARKDOWN -> spanned
|
||||
.replaceSpan(BoldSpan::class.java, "**", "**")
|
||||
.replaceSpan(ItalicSpan::class.java, "_", "_")
|
||||
.replaceSpan(UnderlineSpan::class.java, "__", "__")
|
||||
.replaceSpan(StrikethroughSpan::class.java, "~~", "~~")
|
||||
.toString()
|
||||
else -> HtmlCompat.toHtml(spanned, toHtmlFlag)
|
||||
.replace("\n", "")
|
||||
.replace(" dir=\"ltr\"", "")
|
||||
.replace("</b><b>", "")
|
||||
.replace("</i><i>", "")
|
||||
.replace("</u><u>", "")
|
||||
.replace("</sub><sub>", "")
|
||||
.replace("</sup><sup>", "")
|
||||
.replace("p style=\"margin-top:0; margin-bottom:0;\"", "p")
|
||||
.replace("<br></p>", "</p><br>")
|
||||
// replace multiple newlines so they convert fromHtml correctly
|
||||
// this should not be breaking with htmlCompatibleMode == true,
|
||||
// as line breaks cannot occur inside paragraphs with these flags
|
||||
.replace(paragraphBrRegex, "</p>$1")
|
||||
}
|
||||
|
||||
config.watchSelectionChanged = true
|
||||
|
||||
if (htmlCompatibleMode) {
|
||||
if (htmlMode == COMPATIBLE) {
|
||||
textHtml = textHtml
|
||||
.replace("<br>", "<p> </p>")
|
||||
.replace("<b>", "<strong>")
|
||||
@ -147,7 +206,7 @@ class TextStylingManager(private val app: App) {
|
||||
private fun onStyleChecked(
|
||||
config: StylingConfig,
|
||||
style: StylingConfig.Style,
|
||||
isChecked: Boolean
|
||||
isChecked: Boolean,
|
||||
) {
|
||||
if (!config.watchStyleChecked)
|
||||
return
|
||||
|
@ -164,7 +164,6 @@
|
||||
android:id="@+id/topic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{event.topic}"
|
||||
android:textAppearance="@style/NavView.TextView.Medium"
|
||||
android:textIsSelectable="true"
|
||||
tools:text="Rozdział II: Panowanie Piastów i Jagiellonów.Przeniesiony z 11 grudnia." />
|
||||
@ -190,7 +189,6 @@
|
||||
android:id="@+id/body"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{event.homeworkBody}"
|
||||
android:textAppearance="@style/NavView.TextView.Medium"
|
||||
android:textIsSelectable="true"
|
||||
tools:text="Rozdział II: Panowanie Piastów i Jagiellonów.Przeniesiony z 11 grudnia." />
|
||||
|
@ -118,11 +118,14 @@
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/topicLayout"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="@string/dialog_event_manual_topic">
|
||||
android:hint="@string/dialog_event_manual_topic"
|
||||
app:endIconMode="custom"
|
||||
tools:endIconDrawable="@android:drawable/ic_menu_crop">
|
||||
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputKeyboardEdit
|
||||
android:id="@+id/topic"
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<import type="androidx.core.text.HtmlCompat" />
|
||||
<import type="pl.szczodrzynski.edziennik.utils.html.BetterHtml" />
|
||||
<variable
|
||||
name="message"
|
||||
type="pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus.Message" />
|
||||
@ -43,7 +43,7 @@
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{HtmlCompat.fromHtml(message.title, HtmlCompat.FROM_HTML_MODE_LEGACY)}"
|
||||
android:text="@{BetterHtml.fromHtml(context, message.title, false)}"
|
||||
android:textAppearance="@style/NavView.TextView.Title"
|
||||
tools:text="Dziennik nie działa" />
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@{HtmlCompat.fromHtml(message.contentLong, HtmlCompat.FROM_HTML_MODE_LEGACY)}"
|
||||
android:text="@{BetterHtml.fromHtml(context, message.contentLong, false)}"
|
||||
tools:text="Dziennik się zepsuł i nie działa, szkoda\n\n\nwiele linijek ma ten tekst" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
|
@ -95,7 +95,7 @@
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
<com.mikepenz.iconics.view.IconicsTextView
|
||||
android:id="@+id/addedBy"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -2,202 +2,106 @@
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2019-12-22.
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<data>
|
||||
|
||||
<import type="com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial" />
|
||||
</data>
|
||||
|
||||
<ScrollView
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="40dp"><!-- half of the FAB's size -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/recipientsLayout"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="40dp"><!-- half of the FAB's size -->
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/recipientsLayout"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
|
||||
app:boxBackgroundColor="@android:color/transparent"
|
||||
app:boxBackgroundMode="filled"
|
||||
app:endIconDrawable="@drawable/dropdown_arrow"
|
||||
app:endIconMode="custom">
|
||||
|
||||
<com.hootsuite.nachos.NachoTextView
|
||||
android:id="@+id/recipients"
|
||||
style="@style/Widget.MaterialComponents.TextInputEditText.FilledBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:boxBackgroundColor="@android:color/transparent"
|
||||
app:boxBackgroundMode="filled"
|
||||
app:endIconDrawable="@drawable/dropdown_arrow"
|
||||
app:endIconMode="custom">
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:focusedByDefault="true"
|
||||
android:hint="@string/messages_compose_to_hint" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.hootsuite.nachos.NachoTextView
|
||||
android:id="@+id/recipients"
|
||||
style="@style/Widget.MaterialComponents.TextInputEditText.FilledBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:focusedByDefault="true"
|
||||
android:hint="@string/messages_compose_to_hint" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/subjectLayout"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:boxBackgroundColor="@android:color/transparent"
|
||||
app:boxBackgroundMode="filled"
|
||||
app:counterEnabled="true"
|
||||
tools:counterMaxLength="180">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/subjectLayout"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox"
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputKeyboardEdit
|
||||
android:id="@+id/subject"
|
||||
style="@style/Widget.MaterialComponents.TextInputEditText.FilledBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:boxBackgroundColor="@android:color/transparent"
|
||||
app:boxBackgroundMode="filled"
|
||||
app:counterEnabled="true"
|
||||
tools:counterMaxLength="180">
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:hint="@string/messages_compose_subject_hint"
|
||||
android:inputType="textCapSentences|textAutoCorrect|textShortMessage|textAutoComplete|textEmailSubject"
|
||||
android:singleLine="true"
|
||||
tools:text="kachoomba" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputKeyboardEdit
|
||||
android:id="@+id/subject"
|
||||
style="@style/Widget.MaterialComponents.TextInputEditText.FilledBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:hint="@string/messages_compose_subject_hint"
|
||||
android:inputType="textCapSentences|textAutoCorrect|textShortMessage|textAutoComplete|textEmailSubject"
|
||||
android:singleLine="true"
|
||||
tools:text="kachoomba" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/textLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:boxBackgroundColor="@android:color/transparent"
|
||||
app:boxBackgroundMode="filled"
|
||||
app:counterEnabled="true"
|
||||
tools:counterMaxLength="1983">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/textLayout"
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputKeyboardEdit
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:boxBackgroundColor="@android:color/transparent"
|
||||
app:boxBackgroundMode="filled"
|
||||
app:counterEnabled="true"
|
||||
tools:counterMaxLength="1983">
|
||||
android:ems="10"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="start|top"
|
||||
android:hint="@string/messages_compose_text_hint"
|
||||
android:inputType="textMultiLine|textAutoCorrect|textLongMessage|textAutoComplete|textCapSentences"
|
||||
android:minLines="3"
|
||||
tools:text="Witam,\n\nchciałem przekazać bardzo ważną wiadomość.\nJest to cytat znanej osoby.\n\n"To jest tak, ale nie. Pamiętaj żeby oczywiście"\n\nCytat ma bardzo duże przesłanie i ogromny wpływ na dzisiejszą kulturę i rozwój współczesnej cywilizacji.\n\nJako zadanie domowe, należy wypisać 5 pierwszych liczb pierwszych. Uzasadnij decyzję, odwołując się do cytatu i 3 innych przykładów z literatury lub filmu.\n\nPozdrawiam,\nJa." />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputKeyboardEdit
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="start|top"
|
||||
android:hint="@string/messages_compose_text_hint"
|
||||
android:inputType="textMultiLine|textAutoCorrect|textLongMessage|textAutoComplete|textCapSentences"
|
||||
android:minLines="3"
|
||||
tools:text="Witam,\n\nchciałem przekazać bardzo ważną wiadomość.\nJest to cytat znanej osoby.\n\n"To jest tak, ale nie. Pamiętaj żeby oczywiście"\n\nCytat ma bardzo duże przesłanie i ogromny wpływ na dzisiejszą kulturę i rozwój współczesnej cywilizacji.\n\nJako zadanie domowe, należy wypisać 5 pierwszych liczb pierwszych. Uzasadnij decyzję, odwołując się do cytatu i 3 innych przykładów z literatury lub filmu.\n\nPozdrawiam,\nJa." />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
<include
|
||||
android:id="@+id/fontStyle"
|
||||
layout="@layout/styled_text_buttons" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/fontStyleLayout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
<Button
|
||||
android:id="@+id/breakpoints"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:text="Breakpoints!"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
android:id="@+id/fontStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fontStyleBold"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf674" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fontStyleItalic"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf691" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fontStyleUnderline"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf6c5" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fontStyleStrike"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf6b1" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fontStyleSubscript"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf6b2" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fontStyleSuperscript"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf6b3" />
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||
|
||||
<!-- TODO 2021-10-05: stack the group and button on top -->
|
||||
<!-- android:layout_marginTop="-13dp" -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/fontStyleClear"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:text="@string/messages_compose_style_clear" />
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/breakpoints"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:text="Breakpoints!"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textHtml"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:fontFamily="monospace"
|
||||
android:visibility="gone"
|
||||
tools:text="<p>Witam,</p>To jest bardzo długi tekst żeby sprawdzić ok działa"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</layout>
|
||||
<TextView
|
||||
android:id="@+id/textHtml"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:fontFamily="monospace"
|
||||
android:visibility="gone"
|
||||
tools:text="<p>Witam,</p>To jest bardzo długi tekst żeby sprawdzić ok działa"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
99
app/src/main/res/layout/styled_text_buttons.xml
Normal file
99
app/src/main/res/layout/styled_text_buttons.xml
Normal file
@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2021-10-11.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
android:id="@+id/styles"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/bold"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf674" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/italic"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf691" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/underline"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf6c5" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/strike"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf6b1" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/subscript"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf6b2" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/superscript"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="@font/community_material_font_v5_8_55"
|
||||
android:minWidth="48dp"
|
||||
android:textSize="20sp"
|
||||
app:iconPadding="0dp"
|
||||
tools:text="\uf6b3" />
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||
</HorizontalScrollView>
|
||||
<!-- TODO 2021-10-05: stack the group and button on top -->
|
||||
<!-- android:layout_marginTop="-13dp" -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/clear"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:text="@string/styled_text_clear_button" />
|
||||
</LinearLayout>
|
46
app/src/main/res/layout/styled_text_dialog.xml
Normal file
46
app/src/main/res/layout/styled_text_dialog.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2021-10-11.
|
||||
-->
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="250dp"
|
||||
app:counterEnabled="true">
|
||||
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputKeyboardEdit
|
||||
android:id="@+id/editText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:inputType="textMultiLine|textAutoCorrect|textLongMessage|textAutoComplete|textCapSentences"
|
||||
android:minLines="10"
|
||||
tools:text="Witam,\n\nchciałem przekazać bardzo ważną wiadomość.\nJest to cytat znanej osoby.\n\n"To jest tak, ale nie. Pamiętaj żeby oczywiście"\n\nCytat ma bardzo duże przesłanie i ogromny wpływ na dzisiejszą kulturę i rozwój współczesnej cywilizacji.\n\nJako zadanie domowe, należy wypisać 5 pierwszych liczb pierwszych. Uzasadnij decyzję, odwołując się do cytatu i 3 innych przykładów z literatury lub filmu.\n\nPozdrawiam,\nJa." />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/fontStyle"
|
||||
layout="@layout/styled_text_buttons" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/htmlText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:fontFamily="monospace"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
@ -1470,7 +1470,7 @@
|
||||
<string name="hint_style_strike">Przekreślenie</string>
|
||||
<string name="hint_style_subscript">Indeks dolny</string>
|
||||
<string name="hint_style_superscript">Indeks górny</string>
|
||||
<string name="messages_compose_style_clear">Wyczyść format</string>
|
||||
<string name="styled_text_clear_button">Wyczyść format</string>
|
||||
<string name="hint_message_star">Oznacz gwiazdką</string>
|
||||
<string name="message_forward">Przekaż dalej</string>
|
||||
<string name="message_delete">Usuń</string>
|
||||
@ -1491,4 +1491,5 @@
|
||||
<string name="messages_compose_discard_draft_text">Czy chcesz odrzucić zapisaną wersję wiadomości? Spowoduje to również anulowanie wprowadzonych zmian i usunięcie wiadomości.</string>
|
||||
<string name="login_mobidziennik_server_prefix">https://</string>
|
||||
<string name="login_mobidziennik_server_suffix">.mobidziennik.pl/</string>
|
||||
<string name="styled_text_dialog_title">Edytuj tekst</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user