Pith - wedge_android
wedge_android/app/src/main/java/com/vgmlr/wedge/WedgeWidgetService.kt [5.5 kb]
Modified: 22:37:13 74 026 (01 Jun 026)
22 Days Ago
package com.vgmlr.wedge

import android.content.Context
import android.content.Intent
import android.graphics.Color as AndroidColor
import android.graphics.Typeface
import android.os.Build
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StrikethroughSpan
import android.text.style.StyleSpan
import android.text.style.UnderlineSpan
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

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
    private var widgetNextTimeBg: String = WedgeConfig.WIDGET_CALENDAR_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.widgetBoldColor.first()
            widgetNextTimeBg = prefs.widgetNextTimeBg.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) {}
            }
        }

        val nextTimeOffset = WedgeEditorEngine.findNextTimeHighlight(noteContent)
        if (nextTimeOffset != null && nextTimeOffset >= 0 && nextTimeOffset < noteContent.length) {
            val endLine = noteContent.indexOf('\n', nextTimeOffset)
            val endOffset = if (endLine == -1) noteContent.length else endLine
            try {
                spannable.setSpan(
                    BackgroundColorSpan(widgetNextTimeBg.toColorInt()),
                    nextTimeOffset,
                    endOffset,
                    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
    }
}
Updates
OTC Applet - Linux 93.026.1
Wedge - Linux 90.026.1
Wedge - Android 90.026.1
Shim - Android 86.026.1
Kerf - Android 86.026.4
Dev
TVShow (227) 'CSA'
TVShow (228) 'APT'
TVProgram (83) 'BXT'
Miter Update(s)
Peen (Messaging)

Menu
Calendar
Project Tin (024/029)
Miter
RSS Feed
User Avatar
@vgmlr
=SUM(parts)