Feature Pack with bug fixes for V2

This commit is contained in:
Ujwal223
2026-06-09 23:39:43 +05:45
parent f1bd12f0bd
commit 39b6545e4a
53 changed files with 7314 additions and 328 deletions
@@ -2,9 +2,10 @@ import 'dart:collection';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import '../../scripts/autoplay_blocker.dart';
import '../../scripts/spa_navigation_monitor.dart';
import '../../scripts/native_feel.dart';
import '../../scripts/focus_scripts.dart';
import '../../scripts/reel_metadata_extractor.dart';
class InstagramPreloader {
static HeadlessInAppWebView? _headlessWebView;
@@ -13,7 +14,7 @@ class InstagramPreloader {
static bool isReady = false;
static Future<void> start(String userAgent) async {
if (_headlessWebView != null) return; // don't start twice
if (_headlessWebView != null) return;
_headlessWebView = HeadlessInAppWebView(
keepAlive: keepAlive,
@@ -31,12 +32,10 @@ class InstagramPreloader {
safeBrowsingEnabled: false,
),
initialUserScripts: UnmodifiableListView([
// DM Ghost — comprehensive blocking, gated by window.__fgFullDmGhost flag.
// it should have worked, but sadly it didnt
UserScript(
source: 'window.__fgBlockAutoplay = true;',
injectionTime: UserScriptInjectionTime.AT_DOCUMENT_START,
),
UserScript(
source: kAutoplayBlockerJS,
source: kFullDmGhostJS,
injectionTime: UserScriptInjectionTime.AT_DOCUMENT_START,
),
UserScript(
@@ -47,6 +46,7 @@ class InstagramPreloader {
source: kNativeFeelingScript,
injectionTime: UserScriptInjectionTime.AT_DOCUMENT_START,
),
// ReelMetadataExtractor removed — reel history feature deleted
]),
onWebViewCreated: (c) {
controller = c;
@@ -8,6 +8,8 @@ class ReelsHistoryEntry {
final String title;
final String thumbnailUrl;
final DateTime visitedAt;
final int durationSeconds; // How long the session lasted
final int adsWatchedInSession; // How many ads watched during this session
const ReelsHistoryEntry({
required this.id,
@@ -15,6 +17,8 @@ class ReelsHistoryEntry {
required this.title,
required this.thumbnailUrl,
required this.visitedAt,
this.durationSeconds = 0,
this.adsWatchedInSession = 0,
});
Map<String, dynamic> toJson() => {
@@ -23,6 +27,8 @@ class ReelsHistoryEntry {
'title': title,
'thumbnailUrl': thumbnailUrl,
'visitedAt': visitedAt.toUtc().toIso8601String(),
'durationSeconds': durationSeconds,
'adsWatchedInSession': adsWatchedInSession,
};
static ReelsHistoryEntry fromJson(Map<String, dynamic> json) {
@@ -34,6 +40,8 @@ class ReelsHistoryEntry {
visitedAt:
DateTime.tryParse((json['visitedAt'] as String?) ?? '') ??
DateTime.now().toUtc(),
durationSeconds: (json['durationSeconds'] as num?)?.toInt() ?? 0,
adsWatchedInSession: (json['adsWatchedInSession'] as num?)?.toInt() ?? 0,
);
}
}
@@ -71,6 +79,8 @@ class ReelsHistoryService {
required String url,
required String title,
required String thumbnailUrl,
int durationSeconds = 0,
int adsWatchedInSession = 0,
}) async {
if (url.isEmpty) return;
final now = DateTime.now().toUtc();
@@ -89,6 +99,8 @@ class ReelsHistoryService {
title: title.isEmpty ? 'Instagram Reel' : title,
thumbnailUrl: thumbnailUrl,
visitedAt: now,
durationSeconds: durationSeconds,
adsWatchedInSession: adsWatchedInSession,
);
final updated = [entry, ...entries];
@@ -104,6 +116,44 @@ class ReelsHistoryService {
await _save(entries);
}
/// Get average reels watched per day in the last 7 days.
Future<double> getWeeklyAverageReels() async {
final entries = await getEntries();
if (entries.isEmpty) return 0;
final now = DateTime.now();
final sevenDaysAgo = now.subtract(const Duration(days: 7));
final recent = entries.where((e) => e.visitedAt.isAfter(sevenDaysAgo)).toList();
if (recent.isEmpty) return 0;
return recent.length / 7.0;
}
/// Get reel counts grouped by day (for the level system).
Future<Map<String, int>> getDailyReelCounts({int days = 30}) async {
final entries = await getEntries();
final now = DateTime.now();
final cutoff = now.subtract(Duration(days: days));
final recent = entries.where((e) => e.visitedAt.isAfter(cutoff)).toList();
final Map<String, int> counts = {};
for (final entry in recent) {
final dayKey = '${entry.visitedAt.year}-'
'${entry.visitedAt.month.toString().padLeft(2, '0')}-'
'${entry.visitedAt.day.toString().padLeft(2, '0')}';
counts[dayKey] = (counts[dayKey] ?? 0) + 1;
}
return counts;
}
/// Get total reels watched in the last [days] days.
Future<int> getRecentReelCount({int days = 7}) async {
final entries = await getEntries();
final now = DateTime.now();
final cutoff = now.subtract(Duration(days: days));
return entries.where((e) => e.visitedAt.isAfter(cutoff)).length;
}
Future<void> clearAll() async {
final prefs = await _getPrefs();
await prefs.remove(_prefsKey);
@@ -74,7 +74,7 @@ class UpdateCheckerService extends ChangeNotifier {
_isDismissed = false;
notifyListeners();
} catch (e) {
debugPrint('Update check failed: $e');
// debugPrint('Update check failed: $e');
}
}