Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,22 @@ import android.provider.DocumentsContract
import android.provider.MediaStore
import android.provider.Settings
import android.telecom.TelecomManager
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.EditText
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.addCallback
import androidx.annotation.RequiresApi
import androidx.core.app.ActivityCompat
import androidx.core.net.toUri
import androidx.core.util.Pair
import androidx.core.view.LayoutInflaterCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.get
Expand All @@ -44,6 +48,7 @@ import org.fossify.commons.dialogs.WritePermissionDialog
import org.fossify.commons.dialogs.WritePermissionDialog.WritePermissionDialogMode
import org.fossify.commons.extensions.adjustAlpha
import org.fossify.commons.extensions.applyColorFilter
import org.fossify.commons.extensions.applyFontToTextView
import org.fossify.commons.extensions.baseConfig
import org.fossify.commons.extensions.buildDocumentUriSdk30
import org.fossify.commons.extensions.canManageMedia
Expand Down Expand Up @@ -183,6 +188,7 @@ abstract class BaseSimpleActivity : EdgeToEdgeActivity() {
setTheme(getThemeId(showTransparentTop = true))
}

installFontInflaterFactory()
super.onCreate(savedInstanceState)
WindowCompat.enableEdgeToEdge(window)
registerBackPressedCallback()
Expand All @@ -194,6 +200,25 @@ abstract class BaseSimpleActivity : EdgeToEdgeActivity() {
}
}

private fun installFontInflaterFactory() {
val inflater = layoutInflater
if (inflater.factory2 != null) return

val appCompatDelegate = delegate
LayoutInflaterCompat.setFactory2(inflater, object : LayoutInflater.Factory2 {
override fun onCreateView(parent: View?, name: String, context: Context, attrs: AttributeSet): View? {
val view = appCompatDelegate.createView(parent, name, context, attrs)
val textView = view as? TextView ?: return view
applyFontToTextView(textView)
return view
}

override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
return onCreateView(null, name, context, attrs)
}
})
}

override fun onResume() {
super.onResume()
if (useDynamicTheme) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package org.fossify.commons.activities

import android.content.ContentValues
import android.graphics.Color
import android.graphics.Typeface
import android.net.Uri
import android.os.Bundle
import androidx.activity.result.contract.ActivityResultContracts
import org.fossify.commons.R
import org.fossify.commons.databinding.ActivityCustomizationBinding
import org.fossify.commons.dialogs.ColorPickerDialog
Expand All @@ -11,16 +14,19 @@ import org.fossify.commons.dialogs.ConfirmationDialog
import org.fossify.commons.dialogs.LineColorPickerDialog
import org.fossify.commons.dialogs.PurchaseThankYouDialog
import org.fossify.commons.dialogs.RadioGroupDialog
import org.fossify.commons.extensions.applyFontToViewRecursively
import org.fossify.commons.extensions.baseConfig
import org.fossify.commons.extensions.beVisibleIf
import org.fossify.commons.extensions.canAccessGlobalConfig
import org.fossify.commons.extensions.checkAppIconColor
import org.fossify.commons.extensions.getColoredMaterialStatusBarColor
import org.fossify.commons.extensions.getContrastColor
import org.fossify.commons.extensions.getFilenameFromUri
import org.fossify.commons.extensions.getProperPrimaryColor
import org.fossify.commons.extensions.getProperTextColor
import org.fossify.commons.extensions.getThemeId
import org.fossify.commons.extensions.isDynamicTheme
import org.fossify.commons.extensions.isFontFile
import org.fossify.commons.extensions.isSystemInDarkMode
import org.fossify.commons.extensions.isThankYouInstalled
import org.fossify.commons.extensions.setFillWithStroke
Expand All @@ -32,9 +38,16 @@ import org.fossify.commons.extensions.withGlobalConfig
import org.fossify.commons.helpers.APP_ICON_IDS
import org.fossify.commons.helpers.APP_LAUNCHER_NAME
import org.fossify.commons.helpers.DARK_GREY
import org.fossify.commons.helpers.FONT_TYPE_CUSTOM
import org.fossify.commons.helpers.FONT_TYPE_MONOSPACE
import org.fossify.commons.helpers.FONT_TYPE_SYSTEM_DEFAULT
import org.fossify.commons.helpers.FontHelper
import org.fossify.commons.helpers.MyContentProvider.COL_ACCENT_COLOR
import org.fossify.commons.helpers.MyContentProvider.COL_APP_ICON_COLOR
import org.fossify.commons.helpers.MyContentProvider.COL_BACKGROUND_COLOR
import org.fossify.commons.helpers.MyContentProvider.COL_FONT_DATA
import org.fossify.commons.helpers.MyContentProvider.COL_FONT_NAME
import org.fossify.commons.helpers.MyContentProvider.COL_FONT_TYPE
import org.fossify.commons.helpers.MyContentProvider.COL_PRIMARY_COLOR
import org.fossify.commons.helpers.MyContentProvider.COL_TEXT_COLOR
import org.fossify.commons.helpers.MyContentProvider.COL_THEME_TYPE
Expand All @@ -48,6 +61,7 @@ import org.fossify.commons.models.GlobalConfig
import org.fossify.commons.models.MyTheme
import org.fossify.commons.models.RadioItem
import org.fossify.commons.models.isGlobalThemingEnabled
import java.io.File
import kotlin.math.abs

class CustomizationActivity : BaseSimpleActivity() {
Expand All @@ -69,12 +83,19 @@ class CustomizationActivity : BaseSimpleActivity() {
private var curAppIconColor = 0
private var curSelectedThemeId = 0
private var originalAppIconColor = 0
private var curFontType = 0
private var curFontFileName = ""
private var lastSavePromptTS = 0L
private var hasUnsavedChanges = false
private val predefinedThemes = LinkedHashMap<Int, MyTheme>()
private var curPrimaryLineColorPicker: LineColorPickerDialog? = null
private var globalConfig: GlobalConfig? = null

private val fontFilePicker =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
uri?.let { handleFontFileSelected(it) }
}

override fun getAppIconIDs() = intent.getIntegerArrayListExtra(APP_ICON_IDS) ?: ArrayList()

override fun getAppLauncherName() = intent.getStringExtra(APP_LAUNCHER_NAME) ?: ""
Expand Down Expand Up @@ -437,12 +458,16 @@ class CustomizationActivity : BaseSimpleActivity() {
primaryColor = curPrimaryColor
accentColor = curAccentColor
appIconColor = curAppIconColor
fontType = curFontType
fontName = curFontFileName
}

if (didAppIconColorChange) {
checkAppIconColor()
}

FontHelper.clearCache()

baseConfig.isGlobalThemeEnabled = binding.applyToAllSwitch.isChecked
baseConfig.isSystemThemeEnabled = curSelectedThemeId == THEME_SYSTEM

Expand All @@ -461,6 +486,13 @@ class CustomizationActivity : BaseSimpleActivity() {
put(COL_PRIMARY_COLOR, curPrimaryColor)
put(COL_ACCENT_COLOR, curAccentColor)
put(COL_APP_ICON_COLOR, curAppIconColor)
put(COL_FONT_TYPE, curFontType)
put(COL_FONT_NAME, curFontFileName)
if (curFontType == FONT_TYPE_CUSTOM && curFontFileName.isNotEmpty()) {
FontHelper.getFontData(this@CustomizationActivity, curFontFileName)?.let {
put(COL_FONT_DATA, it)
}
}
}
)
}
Expand Down Expand Up @@ -490,6 +522,8 @@ class CustomizationActivity : BaseSimpleActivity() {
curPrimaryColor = baseConfig.primaryColor
curAccentColor = baseConfig.accentColor
curAppIconColor = baseConfig.appIconColor
curFontType = baseConfig.fontType
curFontFileName = baseConfig.fontName
}

private fun setupColorsPickers() {
Expand Down Expand Up @@ -526,6 +560,8 @@ class CustomizationActivity : BaseSimpleActivity() {
}
}
}

setupFontPicker()
}

private fun hasColorChanged(old: Int, new: Int) = abs(old - new) > 1
Expand All @@ -536,6 +572,100 @@ class CustomizationActivity : BaseSimpleActivity() {
refreshMenuItems()
}

private fun setupFontPicker() {
updateFontDisplay()
binding.customizationFontHolder.setOnClickListener {
fontPickerClicked()
}
}

private fun updateFontDisplay() {
binding.customizationFont.text = when (curFontType) {
FONT_TYPE_MONOSPACE -> getString(R.string.font_monospace)
FONT_TYPE_CUSTOM -> curFontFileName.ifEmpty { getString(R.string.select_font_file) }
else -> getString(R.string.font_system_default)
}
}

private fun fontPickerClicked() {
val items = arrayListOf(
RadioItem(FONT_TYPE_SYSTEM_DEFAULT, getString(R.string.font_system_default)),
RadioItem(FONT_TYPE_MONOSPACE, getString(R.string.font_monospace)),
RadioItem(FONT_TYPE_CUSTOM, getString(R.string.select_font_file))
)

RadioGroupDialog(this, items, curFontType) { selected ->
val selectedType = selected as Int
if (selectedType == FONT_TYPE_CUSTOM) {
openFontFilePicker()
} else {
curFontType = selectedType
curFontFileName = ""
fontChanged()
}
}
}

private fun openFontFilePicker() {
try {
fontFilePicker.launch(
arrayOf(
"font/ttf",
"font/otf",
"application/x-font-ttf",
"application/x-font-otf",
"*/*"
)
)
} catch (e: Exception) {
toast(R.string.system_service_disabled)
}
}

private fun handleFontFileSelected(uri: Uri) {
try {
val fileName = getFilenameFromUri(uri)
if (fileName.isEmpty() || !fileName.isFontFile()) {
toast(R.string.invalid_font_file)
return
}

val fontData = contentResolver.openInputStream(uri)?.use { it.readBytes() }
if (fontData == null) {
toast(R.string.invalid_font_file)
return
}

val tempFile = File(cacheDir, fileName)
tempFile.writeBytes(fontData)
try {
Typeface.createFromFile(tempFile)
} catch (_: Exception) {
tempFile.delete()
toast(R.string.invalid_font_file)
return
}
tempFile.delete()

if (FontHelper.saveFontData(this, fontData, fileName)) {
curFontType = FONT_TYPE_CUSTOM
curFontFileName = fileName
fontChanged()
} else {
toast(R.string.invalid_font_file)
}
} catch (_: Exception) {
toast(R.string.invalid_font_file)
}
}

private fun fontChanged() {
hasUnsavedChanges = true
updateFontDisplay()
applyFontToViewRecursively(window.decorView)
refreshMenuItems()
}

private fun setCurrentTextColor(color: Int) {
curTextColor = color
updateLabelColors(color)
Expand Down Expand Up @@ -707,6 +837,8 @@ class CustomizationActivity : BaseSimpleActivity() {
binding.customizationPrimaryColorLabel,
binding.customizationAccentColorLabel,
binding.customizationAppIconColorLabel,
binding.customizationFontLabel,
binding.customizationFont,
binding.applyToAllLabel,
binding.applyToAllNote
).forEach {
Expand All @@ -717,6 +849,7 @@ class CustomizationActivity : BaseSimpleActivity() {
private fun updateHeaderColors(primaryColor: Int = getProperPrimaryColor()) {
arrayListOf(
binding.settingsThemeAndColorsLabel,
binding.settingsFontLabel,
binding.settingsAllFossifyAppsLabel
).forEach {
it.setTextColor(primaryColor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.fossify.commons.R
import org.fossify.commons.compose.extensions.MyDevices
import org.fossify.commons.compose.theme.AppThemeSurface
import org.fossify.commons.compose.theme.SimpleTheme
import org.fossify.commons.extensions.applyFontToTextView
import org.fossify.commons.extensions.fromHtml
import org.fossify.commons.extensions.removeUnderlines

Expand All @@ -40,6 +41,8 @@ fun LinkifyTextComponent(
textView.textAlignment = textAlignment
textView.textSize = fontSize.value
textView.movementMethod = LinkMovementMethod.getInstance()
context.applyFontToTextView(textView)

if (removeUnderlines) {
customLinkifyTextView.removeUnderlines()
}
Expand Down
Loading
Loading