mirror of
https://github.com/Ujwal223/FocusGram.git
synced 2026-06-03 04:17:59 +02:00
improvement: improved UI Elements and some optimizations
This commit is contained in:
@@ -71,6 +71,13 @@ class InjectionController {
|
||||
}
|
||||
''';
|
||||
|
||||
/// CSS that adds bottom padding so feed content doesn't hide behind our bar.
|
||||
static const String _bottomPaddingCSS = '''
|
||||
body, #react-root > div {
|
||||
padding-bottom: 64px !important;
|
||||
}
|
||||
''';
|
||||
|
||||
/// CSS to blur Explore feed posts/reels (keeps stories visible).
|
||||
static const String _blurExploreCSS = '''
|
||||
/* Blur Explore grid posts and reel cards (not stories row) */
|
||||
@@ -250,6 +257,27 @@ class InjectionController {
|
||||
})();
|
||||
''';
|
||||
|
||||
/// JS to disable vertical swipe gestures that drive reel-to-reel transition.
|
||||
static const String reelSwipeBlockerJS = '''
|
||||
(function() {
|
||||
let _touchStartY = 0;
|
||||
document.addEventListener('touchstart', function(e) {
|
||||
_touchStartY = e.touches[0].clientY;
|
||||
}, { passive: true });
|
||||
|
||||
document.addEventListener('touchmove', function(e) {
|
||||
const deltaY = e.touches[0].clientY - _touchStartY;
|
||||
// If swiping UP (negative delta), block it to prevent next reel load
|
||||
if (deltaY < -10) {
|
||||
if (e.cancelable) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
}, { passive: false });
|
||||
})();
|
||||
''';
|
||||
|
||||
// ── Reel scroll-lock ────────────────────────────────────────────────────────
|
||||
|
||||
/// JS that prevents the user from scrolling to a different reel.
|
||||
@@ -329,6 +357,7 @@ class InjectionController {
|
||||
}) {
|
||||
final StringBuffer css = StringBuffer();
|
||||
css.write(_hideInstagramNavCSS);
|
||||
css.write(_bottomPaddingCSS); // Ensure content isn't behind our bar
|
||||
if (!sessionActive) css.write(_hideReelsCSS);
|
||||
if (blurExplore) css.write(_blurExploreCSS);
|
||||
|
||||
|
||||
@@ -1,34 +1,40 @@
|
||||
/// Determines whether a navigation request should be blocked.
|
||||
///
|
||||
/// Rules:
|
||||
/// - /reels/* and /reel/* are blocked unless [sessionActive] is true OR
|
||||
/// [isDmReelException] is true (single DM reel open).
|
||||
/// - /explore/ is allowed (but explore content is blurred via CSS).
|
||||
/// - Only instagram.com domains are allowed (blocks external redirects).
|
||||
/// - instagram.com/reels (and /reels/) = BLOCKED — this is the mindless feed tab
|
||||
/// - instagram.com/reel/SHORTCODE/ = ALLOWED — a specific reel (e.g. from a DM)
|
||||
/// - /explore/ is allowed (explore content is blurred via CSS instead)
|
||||
/// - Only instagram.com domains are allowed (blocks external redirects)
|
||||
class NavigationGuard {
|
||||
static const _allowedHosts = ['instagram.com', 'www.instagram.com'];
|
||||
|
||||
static const _blockedPathPrefixes = ['/reels', '/reel/'];
|
||||
/// Regex matching the Reels FEED root — NOT individual reels.
|
||||
static final _reelsFeedRegex = RegExp(
|
||||
r'instagram\.com/reels/?$',
|
||||
caseSensitive: false,
|
||||
);
|
||||
|
||||
/// Regex matching a specific reel (e.g. /reel/ABC123/).
|
||||
static final _specificReelRegex = RegExp(
|
||||
r'instagram\.com/reel/[^/?#]+',
|
||||
caseSensitive: false,
|
||||
);
|
||||
|
||||
/// Returns a [BlockDecision] for the given [url].
|
||||
static BlockDecision evaluate({
|
||||
required String url,
|
||||
required bool sessionActive,
|
||||
required bool isDmReelException,
|
||||
}) {
|
||||
static BlockDecision evaluate({required String url}) {
|
||||
Uri uri;
|
||||
try {
|
||||
uri = Uri.parse(url);
|
||||
} catch (_) {
|
||||
return BlockDecision(blocked: false, reason: null);
|
||||
return const BlockDecision(blocked: false, reason: null);
|
||||
}
|
||||
|
||||
// Allow non-HTTP schemes (about:blank, data:, etc.)
|
||||
if (!uri.scheme.startsWith('http')) {
|
||||
return BlockDecision(blocked: false, reason: null);
|
||||
return const BlockDecision(blocked: false, reason: null);
|
||||
}
|
||||
|
||||
// Block non-Instagram domains (prevents phishing redirects)
|
||||
// Block non-Instagram domains (prevents phishing/external redirects)
|
||||
final host = uri.host.toLowerCase();
|
||||
if (!_allowedHosts.any((h) => host == h || host.endsWith('.$h'))) {
|
||||
return BlockDecision(
|
||||
@@ -37,49 +43,21 @@ class NavigationGuard {
|
||||
);
|
||||
}
|
||||
|
||||
// Check reel/reels path
|
||||
final path = uri.path.toLowerCase();
|
||||
final isReelUrl = _blockedPathPrefixes.any((p) => path.startsWith(p));
|
||||
|
||||
if (isReelUrl) {
|
||||
if (sessionActive || isDmReelException) {
|
||||
return BlockDecision(blocked: false, reason: null);
|
||||
}
|
||||
return BlockDecision(
|
||||
// Block ONLY the Reels feed tab root (/reels, /reels/)
|
||||
// but allow specific reels (/reel/SHORTCODE/) opened from DMs
|
||||
if (_reelsFeedRegex.hasMatch(url)) {
|
||||
return const BlockDecision(
|
||||
blocked: true,
|
||||
reason: 'Reel navigation blocked — no active session',
|
||||
reason:
|
||||
'Reels feed is disabled — open a specific reel from DMs instead',
|
||||
);
|
||||
}
|
||||
|
||||
return BlockDecision(blocked: false, reason: null);
|
||||
return const BlockDecision(blocked: false, reason: null);
|
||||
}
|
||||
|
||||
/// Returns true if the URL looks like a Reel link from a DM.
|
||||
static bool isDmReelLink(String url) {
|
||||
try {
|
||||
final uri = Uri.parse(url);
|
||||
final path = uri.path.toLowerCase();
|
||||
return path.startsWith('/reel/') || path.startsWith('/reels/');
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts a canonical single-reel URL from a DM reel link.
|
||||
/// Strips query params that might trigger Reels feed.
|
||||
static String? canonicalizeDmReelUrl(String url) {
|
||||
try {
|
||||
final uri = Uri.parse(url);
|
||||
// Keep only the reel path, strip all query parameters
|
||||
return Uri(
|
||||
scheme: 'https',
|
||||
host: 'www.instagram.com',
|
||||
path: uri.path,
|
||||
).toString();
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/// True if the URL is a specific individual reel (from a DM share).
|
||||
static bool isSpecificReel(String url) => _specificReelRegex.hasMatch(url);
|
||||
}
|
||||
|
||||
class BlockDecision {
|
||||
|
||||
Reference in New Issue
Block a user