From 450ed8529dc97de2b9b1572d1358f3f071e6452d Mon Sep 17 00:00:00 2001 From: tyronetheqt Date: Sat, 13 Jun 2026 09:25:46 +0300 Subject: [PATCH] fix: use sans-serif font family on Linux when Twemoji is enabled When Twemoji is set as a fontFamilyFallback on Linux with no explicit fontFamily (null), the Flutter engine promotes the first fallback to the primary font. This causes Twemoji to render all text glyphs, resulting in missing characters for most UI text. Fix this by setting fontFamily to "sans-serif" (resolved through fontconfig) on Linux when Twemoji is enabled. On other platforms the existing null behavior is preserved, since their font managers handle fontFamilyFallback correctly. As a related improvement, filter out Android-specific fonts (SystemFont, Roboto) from the fallback fonts list on non-Android platforms. Closes https://github.com/ExteraApp/Extera/issues/124 --- lib/config/themes.dart | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/config/themes.dart b/lib/config/themes.dart index ef1380d7b..2bc7226c9 100644 --- a/lib/config/themes.dart +++ b/lib/config/themes.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:extera_next/config/setting_keys.dart'; +import 'package:extera_next/utils/platform_infos.dart'; import 'app_config.dart'; abstract class FluffyThemes { @@ -18,6 +19,15 @@ abstract class FluffyThemes { static bool isThreeColumnMode(BuildContext context) => MediaQuery.sizeOf(context).width > FluffyThemes.columnWidth * 3.5; + static List _filteredFallbackFonts(String fonts) { + if (fonts.isEmpty) return const []; + final list = fonts.split(','); + if (!PlatformInfos.isAndroid) { + list.removeWhere((f) => f == 'SystemFont' || f == 'Roboto'); + } + return list; + } + static LinearGradient backgroundGradient(BuildContext context, int alpha) { final colorScheme = Theme.of(context).colorScheme; return LinearGradient( @@ -81,16 +91,21 @@ abstract class FluffyThemes { brightness: brightness, colorScheme: colorScheme, useSystemColors: true, - fontFamily: AppSettings.systemFont.value + fontFamily: AppSettings.systemFont.value && PlatformInfos.isAndroid ? 'SystemFont' - : AppSettings.uiFont.value.isEmpty - ? null - : AppSettings.uiFont.value, + : AppSettings.uiFont.value.isNotEmpty + ? AppSettings.uiFont.value + : PlatformInfos.isLinux && twemoji == true + ? 'sans-serif' + : null, fontFamilyFallback: twemoji == true - ? ['Twemoji Mozilla', ...AppSettings.fallbackFonts.value.split(',')] + ? [ + 'Twemoji Mozilla', + ..._filteredFallbackFonts(AppSettings.fallbackFonts.value), + ] : AppSettings.fallbackFonts.value.isEmpty ? null - : AppSettings.fallbackFonts.value.split(','), + : _filteredFallbackFonts(AppSettings.fallbackFonts.value), dividerColor: brightness == Brightness.dark ? colorScheme.surfaceContainerHighest : colorScheme.surfaceContainer,