Files
FocusGram-Android/lib/services/injection_controller.dart
Ujwal 7bb472d212 What's new
- Reordered Settings Page.
- Added "Click to Unblur" for posts.
- Added Persistent Notification
- Improved Grayscale Scheduling.
and more.
2026-03-04 10:48:14 +05:45

110 lines
4.1 KiB
Dart

// ============================================================================
// FocusGram — InjectionController
// ============================================================================
import '../scripts/core_injection.dart' as scripts;
import '../scripts/ui_hider.dart' as ui_hider;
class InjectionController {
static const String iOSUserAgent =
'Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) '
'AppleWebKit/605.1.15 (KHTML, like Gecko) '
'Version/26.0 Mobile/15E148 Safari/604.1';
static const String reelsMutationObserverJS =
scripts.kReelsMutationObserverJS;
static const String linkSanitizationJS = scripts.kLinkSanitizationJS;
static String get notificationBridgeJS => scripts.kNotificationBridgeJS;
static String _buildMutationObserver(String cssContent) =>
'''
(function fgApplyStyles() {
const ID = 'focusgram-style';
function inject() {
let el = document.getElementById(ID);
if (!el) {
el = document.createElement('style');
el.id = ID;
(document.head || document.documentElement).appendChild(el);
}
el.textContent = ${_escapeJsString(cssContent)};
}
inject();
new MutationObserver(() => { if (!document.getElementById(ID)) inject(); })
.observe(document.documentElement, { childList: true, subtree: true });
})();
''';
static String _escapeJsString(String s) {
final escaped = s.replaceAll(r'\', r'\\').replaceAll('`', r'\`');
return '`$escaped`';
}
static String softNavigateJS(String path) =>
'''
(function() {
const t = ${_escapeJsString(path)};
if (window.location.pathname !== t) window.location.href = t;
})();
''';
static String buildSessionStateJS(bool active) =>
'window.__focusgramSessionActive = $active;';
static String buildInjectionJS({
required bool sessionActive,
required bool blurExplore,
required bool blurReels,
required bool tapToUnblur,
required bool enableTextSelection,
required bool hideSuggestedPosts, // JS-only, handled by InjectionManager
required bool hideSponsoredPosts, // JS-only, handled by InjectionManager
required bool hideLikeCounts,
required bool hideFollowerCounts,
// hideStoriesBar parameter removed per user request
required bool hideExploreTab,
required bool hideReelsTab,
required bool hideShopTab,
required bool disableReelsEntirely,
}) {
final css = StringBuffer()..writeln(scripts.kGlobalUIFixesCSS);
if (!enableTextSelection) css.writeln(scripts.kDisableSelectionCSS);
if (!sessionActive) {
// Hide reel feed content when no session active
css.writeln(scripts.kHideReelsFeedContentCSS);
}
// FIX: blurReels moved OUTSIDE `if (!sessionActive)`.
// Previously it was inside that block alongside display:none on the parent —
// you cannot blur children of a display:none element, making it dead code.
// Now: when sessionActive=true, reel thumbnails are blurred as friction.
// when sessionActive=false, reels are hidden anyway (blur harmless).
if (blurReels) css.writeln(scripts.kBlurReelsCSS);
if (blurExplore) css.writeln(scripts.kBlurHomeFeedAndExploreCSS);
if (hideLikeCounts) css.writeln(ui_hider.kHideLikeCountsCSS);
if (hideFollowerCounts) css.writeln(ui_hider.kHideFollowerCountsCSS);
// Stories hiding removed per user request
if (hideExploreTab) css.writeln(ui_hider.kHideExploreTabCSS);
if (hideReelsTab) css.writeln(ui_hider.kHideReelsTabCSS);
if (hideShopTab) css.writeln(ui_hider.kHideShopTabCSS);
return '''
${buildSessionStateJS(sessionActive)}
window.__fgDisableReelsEntirely = $disableReelsEntirely;
window.__fgTapToUnblur = $tapToUnblur;
${scripts.kTrackPathJS}
${_buildMutationObserver(css.toString())}
${scripts.kDismissAppBannerJS}
${!sessionActive ? scripts.kStrictReelsBlockJS : ''}
${scripts.kReelsMutationObserverJS}
${tapToUnblur ? scripts.kTapToUnblurJS : ''}
${scripts.kLinkSanitizationJS}
${scripts.kThemeDetectorJS}
${scripts.kBadgeMonitorJS}
''';
}
}