package com.vgmlr.wedge
import android.content.Context
import android.content.Intent
import android.os.Build
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.graphics.Typeface
import android.util.TypedValue
import android.widget.RemoteViews
import android.widget.RemoteViewsService
import androidx.core.graphics.toColorInt
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import android.graphics.Color as AndroidColor
import android.text.style.UnderlineSpan
import android.text.style.StrikethroughSpan
class WedgeWidgetService : RemoteViewsService() {
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
return WedgeWidgetFactory(applicationContext)
}
}
class WedgeWidgetFactory(private val context: Context) : RemoteViewsService.RemoteViewsFactory {
private var noteContent: String = ""
private var textColor: String = WedgeConfig.WIDGET_TEXT_COLOR_DEFAULT
private var fontSize: Float = WedgeConfig.WIDGET_FONT_SIZE_DEFAULT
private var lineHeight: Float = WedgeConfig.LINE_HEIGHT_DEFAULT
private var boldColor: String = WedgeConfig.BOLD_COLOR_DEFAULT
override fun onCreate() {}
override fun onDataSetChanged() {
runBlocking {
val db = AppDatabase.getInstance(context)
val prefs = PreferenceManager(context)
noteContent = db.noteDao().getNoteSync()?.content ?: ""
textColor = prefs.widgetTextColor.first()
fontSize = prefs.widgetFontSize.first()
lineHeight = prefs.lineHeight.first()
boldColor = prefs.boldColor.first()
}
}
override fun onDestroy() {}
override fun getCount(): Int = 1
override fun getLoadingView(): RemoteViews? = null
override fun getViewTypeCount(): Int = 1
override fun getItemId(position: Int): Long = position.toLong()
override fun hasStableIds(): Boolean = true
override fun getViewAt(position: Int): RemoteViews {
onDataSetChanged()
val views = RemoteViews(context.packageName, R.layout.widget_item)
val spannable = SpannableStringBuilder(noteContent)
WedgeRegex.BOLD_LINE.findAll(noteContent).forEach { match ->
spannable.setSpan(StyleSpan(Typeface.BOLD), match.range.first, match.range.last + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
try {
spannable.setSpan(ForegroundColorSpan(boldColor.toColorInt()), match.range.first, match.range.last + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
} catch (_: Exception) {}
}
WedgeRegex.ITALIC_LINE.findAll(noteContent).forEach { match ->
spannable.setSpan(StyleSpan(Typeface.ITALIC), match.range.first, match.range.last + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
WedgeRegex.UNDERLINE_LINE.findAll(noteContent).forEach { match ->
val contentGroup = match.groups[1]
if (contentGroup != null) {
try {
spannable.setSpan(
UnderlineSpan(),
contentGroup.range.first,
contentGroup.range.last + 1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
} catch (_: Exception) {}
}
}
WedgeRegex.STRIKE_LINE.findAll(noteContent).forEach { match ->
val contentGroup = match.groups[1]
if (contentGroup != null) {
try {
spannable.setSpan(
StrikethroughSpan(),
contentGroup.range.first,
contentGroup.range.last + 1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
} catch (_: Exception) {}
}
}
views.setTextViewText(R.id.item_text, spannable)
views.setOnClickFillInIntent(R.id.item_text, Intent())
try {
views.setTextColor(R.id.item_text, textColor.toColorInt())
} catch (_: Exception) {
views.setTextColor(R.id.item_text, AndroidColor.WHITE)
}
views.setTextViewTextSize(R.id.item_text, TypedValue.COMPLEX_UNIT_SP, fontSize)
if (Build.VERSION.SDK_INT >= 31) {
try {
val method = RemoteViews::class.java.getMethod(
"setLineSpacing",
Int::class.javaPrimitiveType,
Float::class.javaPrimitiveType,
Float::class.javaPrimitiveType
)
method.invoke(views, R.id.item_text, 0f, lineHeight)
} catch (_: Exception) {}
}
return views
}
}