feat: font scaler added

This commit is contained in:
2026-06-14 15:59:48 +03:30
parent 1971708b3f
commit f266f4d142
5 changed files with 83 additions and 2 deletions
@@ -12,8 +12,11 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import com.approagency.pharmacy.data.local.SessionManager
@@ -52,8 +55,19 @@ class MainActivity : ComponentActivity(), OtpAutofillController {
enableEdgeToEdge()
setContent {
val themeMode by session.themeMode.collectAsState()
val fontScale by session.fontScale.collectAsState()
DrugTheme(themeMode = themeMode) {
AppNavGraph()
// مقیاسِ متنِ انتخابیِ کاربر روی fontScaleِ سیستم اعمال می‌شود
// تا کلِ متن‌های اپ یک‌جا بزرگ/کوچک شوند.
val density = LocalDensity.current
CompositionLocalProvider(
LocalDensity provides Density(
density = density.density,
fontScale = density.fontScale * fontScale.scale
)
) {
AppNavGraph()
}
}
}
}
@@ -2,6 +2,7 @@ package com.approagency.pharmacy.data.local
import android.content.Context
import android.content.SharedPreferences
import com.approagency.pharmacy.domain.model.FontScale
import com.approagency.pharmacy.domain.model.ThemeMode
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -128,6 +129,20 @@ class SessionManager(context: Context) {
runCatching { ThemeMode.valueOf(prefs.getString(KEY_THEME_MODE, null) ?: ThemeMode.SYSTEM.name) }
.getOrDefault(ThemeMode.SYSTEM)
// ---------- اندازهٔ متن ----------
private val _fontScale = MutableStateFlow(readFontScale())
val fontScale: StateFlow<FontScale> = _fontScale.asStateFlow()
fun setFontScale(scale: FontScale) {
prefs.edit().putString(KEY_FONT_SCALE, scale.name).apply()
_fontScale.value = scale
}
private fun readFontScale(): FontScale =
runCatching { FontScale.valueOf(prefs.getString(KEY_FONT_SCALE, null) ?: FontScale.NORMAL.name) }
.getOrDefault(FontScale.NORMAL)
private fun readAccount() = AccountState(
isLoggedIn = !token.isNullOrBlank(),
mobile = prefs.getString(KEY_MOBILE, null),
@@ -147,5 +162,6 @@ class SessionManager(context: Context) {
const val KEY_SUB_TITLE = "subscription_title"
const val KEY_SUB_EXPIRE = "subscription_expire_at"
const val KEY_THEME_MODE = "theme_mode"
const val KEY_FONT_SCALE = "font_scale"
}
}
@@ -0,0 +1,11 @@
package com.approagency.pharmacy.domain.model
/**
* اندازهٔ متنِ انتخابیِ کاربر (به‌ویژه برای کاربرانِ مسن‌تر).
* [scale] ضریبی است که روی fontScaleِ دستگاه اعمال می‌شود.
*/
enum class FontScale(val scale: Float, val label: String) {
NORMAL(1.0f, "معمولی"),
LARGE(1.2f, "بزرگ"),
XLARGE(1.45f, "خیلی بزرگ")
}
@@ -39,6 +39,7 @@ fun MainContainer(
val account by session.account.collectAsState()
val sheetVisible by sheetController.visible.collectAsState()
val themeMode by session.themeMode.collectAsState()
val fontScale by session.fontScale.collectAsState()
val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()
@@ -59,6 +60,8 @@ fun MainContainer(
appVersion = appVersion,
themeMode = themeMode,
onThemeModeChange = { session.setThemeMode(it) },
fontScale = fontScale,
onFontScaleChange = { session.setFontScale(it) },
onLogout = { showLogoutConfirm = true }
)
}
@@ -1,6 +1,8 @@
package com.approagency.pharmacy.presentation.account
import androidx.compose.foundation.background
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -43,6 +45,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import com.approagency.pharmacy.data.local.AccountState
import com.approagency.pharmacy.domain.model.FontScale
import com.approagency.pharmacy.domain.model.ThemeMode
import com.vada.caller.ui.theme.dime
@@ -60,6 +63,8 @@ fun AccountDrawer(
appVersion: String,
themeMode: ThemeMode,
onThemeModeChange: (ThemeMode) -> Unit,
fontScale: FontScale,
onFontScaleChange: (FontScale) -> Unit,
onLogout: () -> Unit
) {
ModalDrawerSheet(
@@ -71,6 +76,7 @@ fun AccountDrawer(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
.verticalScroll(rememberScrollState())
.padding(horizontal = MaterialTheme.dime.lg, vertical = MaterialTheme.dime.xl)
) {
Header(account)
@@ -121,7 +127,18 @@ fun AccountDrawer(
Spacer(Modifier.height(MaterialTheme.dime.sm))
ThemeModeSelector(selected = themeMode, onSelect = onThemeModeChange)
Spacer(Modifier.weight(1f))
Spacer(Modifier.height(MaterialTheme.dime.lg))
// اندازهٔ متن (برای کاربرانِ مسن‌تر)
Text(
text = "اندازهٔ متن",
style = MaterialTheme.typography.titleSmall,
fontWeight = FontWeight.Bold
)
Spacer(Modifier.height(MaterialTheme.dime.sm))
FontScaleSelector(selected = fontScale, onSelect = onFontScaleChange)
Spacer(Modifier.height(MaterialTheme.dime.xl))
if (account.isLoggedIn) {
OutlinedButton(
@@ -267,3 +284,23 @@ private fun ThemeModeSelector(
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun FontScaleSelector(
selected: FontScale,
onSelect: (FontScale) -> Unit
) {
val options = FontScale.entries
SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) {
options.forEachIndexed { index, option ->
SegmentedButton(
selected = selected == option,
onClick = { onSelect(option) },
shape = SegmentedButtonDefaults.itemShape(index, options.size),
icon = {},
label = { Text(option.label, style = MaterialTheme.typography.labelSmall) }
)
}
}
}