diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a09a0acc..bd6b245cc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
+### Added
+
+- Accessibility: apply bold font system setting
+
## [v1.7.4] - 2022-11-11
### Added
diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AccessibilityHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AccessibilityHandler.kt
index eaf3e0bfa..d44a5ed29 100644
--- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AccessibilityHandler.kt
+++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AccessibilityHandler.kt
@@ -3,6 +3,7 @@ package deckers.thibault.aves.channel.calls
import android.annotation.SuppressLint
import android.content.Context
import android.content.ContextWrapper
+import android.content.res.Configuration
import android.os.Build
import android.provider.Settings
import android.util.Log
@@ -19,6 +20,7 @@ class AccessibilityHandler(private val contextWrapper: ContextWrapper) : MethodC
"areAnimationsRemoved" -> safe(call, result, ::areAnimationsRemoved)
"hasRecommendedTimeouts" -> safe(call, result, ::hasRecommendedTimeouts)
"getRecommendedTimeoutMillis" -> safe(call, result, ::getRecommendedTimeoutMillis)
+ "shouldUseBoldFont" -> safe(call, result, ::shouldUseBoldFont)
else -> result.notImplemented()
}
}
@@ -76,8 +78,28 @@ class AccessibilityHandler(private val contextWrapper: ContextWrapper) : MethodC
result.success(millis)
}
+ // Flutter v3.4 already checks the system `Configuration.fontWeightAdjustment` to update `MediaQuery`
+ // but we need to also check the non-standard Samsung field `bf` representing the bold font toggle
+ private fun shouldUseBoldFont(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
+ var shouldBold = false
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ val config = contextWrapper.resources.configuration
+ val fontWeightAdjustment = config.fontWeightAdjustment
+ shouldBold = if (fontWeightAdjustment != Configuration.FONT_WEIGHT_ADJUSTMENT_UNDEFINED && fontWeightAdjustment != 0) {
+ fontWeightAdjustment >= BOLD_TEXT_WEIGHT_ADJUSTMENT
+ } else {
+ // fallback to Samsung non-standard field
+ Regex(" bf=([01]) ").find(config.toString())?.groups?.get(1)?.value == "1"
+ }
+ }
+ result.success(shouldBold)
+ }
+
companion object {
private val LOG_TAG = LogUtils.createTag()
const val CHANNEL = "deckers.thibault/aves/accessibility"
+
+ // match Flutter way: https://github.com/flutter/engine/blob/main/shell/platform/android/io/flutter/view/AccessibilityBridge.java#L125
+ const val BOLD_TEXT_WEIGHT_ADJUSTMENT = 300
}
}
\ No newline at end of file
diff --git a/lib/services/accessibility_service.dart b/lib/services/accessibility_service.dart
index eb442ee7d..61ac1bb34 100644
--- a/lib/services/accessibility_service.dart
+++ b/lib/services/accessibility_service.dart
@@ -4,6 +4,16 @@ import 'package:flutter/services.dart';
class AccessibilityService {
static const _platform = MethodChannel('deckers.thibault/aves/accessibility');
+ static Future shouldUseBoldFont() async {
+ try {
+ final result = await _platform.invokeMethod('shouldUseBoldFont');
+ if (result != null) return result as bool;
+ } on PlatformException catch (e, stack) {
+ await reportService.recordError(e, stack);
+ }
+ return false;
+ }
+
static Future areAnimationsRemoved() async {
try {
final result = await _platform.invokeMethod('areAnimationsRemoved');
diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart
index 915dc4160..811cebf8d 100644
--- a/lib/widgets/aves_app.dart
+++ b/lib/widgets/aves_app.dart
@@ -108,6 +108,7 @@ class AvesApp extends StatefulWidget {
class _AvesAppState extends State with WidgetsBindingObserver {
final ValueNotifier appModeNotifier = ValueNotifier(AppMode.main);
late final Future _appSetup;
+ late final Future _shouldUseBoldFontLoader;
late final Future _dynamicColorPaletteLoader;
final CollectionSource _mediaStoreSource = MediaStoreSource();
final Debouncer _mediaStoreChangeDebouncer = Debouncer(delay: Durations.mediaContentChangeDebounceDelay);
@@ -129,6 +130,7 @@ class _AvesAppState extends State with WidgetsBindingObserver {
_appSetup = _setup();
// remember screen size to use it later, when `context` and `window` are no longer reliable
_screenSize = _getScreenSize();
+ _shouldUseBoldFontLoader = AccessibilityService.shouldUseBoldFont();
_dynamicColorPaletteLoader = DynamicColorPlugin.getCorePalette();
_mediaStoreChangeChannel.receiveBroadcastStream().listen((event) => _onMediaStoreChange(event as String?));
_newIntentChannel.receiveBroadcastStream().listen((event) => _onNewIntent(event as Map?));
@@ -205,32 +207,43 @@ class _AvesAppState extends State with WidgetsBindingObserver {
lightAccent = Color(tonalPalette?.get(60) ?? defaultAccent.value);
darkAccent = Color(tonalPalette?.get(70) ?? defaultAccent.value);
}
- return MaterialApp(
- navigatorKey: AvesApp.navigatorKey,
- home: home,
- navigatorObservers: _navigatorObservers,
- builder: (context, child) {
- if (initialized) {
- WidgetsBinding.instance.addPostFrameCallback((_) => AvesApp.setSystemUIStyle(context));
- }
- return AvesColorsProvider(
- child: Theme(
- data: Theme.of(context).copyWith(
- pageTransitionsTheme: pageTransitionsTheme,
- ),
- child: child!,
- ),
+ return FutureBuilder(
+ future: _shouldUseBoldFontLoader,
+ builder: (context, snapshot) {
+ // Flutter v3.4 already checks the system `Configuration.fontWeightAdjustment` to update `MediaQuery`
+ // but we need to also check the non-standard Samsung field `bf` representing the bold font toggle
+ final shouldUseBoldFont = snapshot.data ?? false;
+ return MaterialApp(
+ navigatorKey: AvesApp.navigatorKey,
+ home: home,
+ navigatorObservers: _navigatorObservers,
+ builder: (context, child) {
+ if (initialized) {
+ WidgetsBinding.instance.addPostFrameCallback((_) => AvesApp.setSystemUIStyle(context));
+ }
+ return MediaQuery(
+ data: MediaQuery.of(context).copyWith(boldText: shouldUseBoldFont),
+ child: AvesColorsProvider(
+ child: Theme(
+ data: Theme.of(context).copyWith(
+ pageTransitionsTheme: pageTransitionsTheme,
+ ),
+ child: child!,
+ ),
+ ),
+ );
+ },
+ onGenerateTitle: (context) => context.l10n.appName,
+ theme: Themes.lightTheme(lightAccent, initialized),
+ darkTheme: themeBrightness == AvesThemeBrightness.black ? Themes.blackTheme(darkAccent, initialized) : Themes.darkTheme(darkAccent, initialized),
+ themeMode: themeBrightness.appThemeMode,
+ locale: settingsLocale,
+ localizationsDelegates: AppLocalizations.localizationsDelegates,
+ supportedLocales: AvesApp.supportedLocales,
+ // TODO TLAD remove custom scroll behavior when this is fixed: https://github.com/flutter/flutter/issues/82906
+ scrollBehavior: StretchMaterialScrollBehavior(),
);
},
- onGenerateTitle: (context) => context.l10n.appName,
- theme: Themes.lightTheme(lightAccent, initialized),
- darkTheme: themeBrightness == AvesThemeBrightness.black ? Themes.blackTheme(darkAccent, initialized) : Themes.darkTheme(darkAccent, initialized),
- themeMode: themeBrightness.appThemeMode,
- locale: settingsLocale,
- localizationsDelegates: AppLocalizations.localizationsDelegates,
- supportedLocales: AvesApp.supportedLocales,
- // TODO TLAD remove custom scroll behavior when this is fixed: https://github.com/flutter/flutter/issues/82906
- scrollBehavior: StretchMaterialScrollBehavior(),
);
},
);