mirror of
https://github.com/Ujwal223/FocusGram.git
synced 2026-07-02 17:35:46 +02:00
Feature Pack with bug fixes for V2
This commit is contained in:
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user