mirror of
https://github.com/Ujwal223/FocusGram.git
synced 2026-04-03 18:02:20 +02:00
improvement/;
bugfixes added word libraby (~500 words)
This commit is contained in:
@@ -94,9 +94,12 @@ class AboutPage extends StatelessWidget {
|
||||
}
|
||||
|
||||
Future<void> _launchURL(String url) async {
|
||||
final uri = Uri.parse(url);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
final uri = Uri.tryParse(url);
|
||||
if (uri == null) return;
|
||||
try {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
} catch (_) {
|
||||
// Ignore if cannot launch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,6 +209,12 @@ class _FrictionSliderTileState extends State<_FrictionSliderTile> {
|
||||
_draftValue = widget.value;
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(_FrictionSliderTile old) {
|
||||
super.didUpdateWidget(old);
|
||||
if (!_pendingConfirm) _draftValue = widget.value;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final divisions = ((widget.max - widget.min) / widget.divisor).round();
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
import '../services/session_manager.dart';
|
||||
import '../services/settings_service.dart';
|
||||
@@ -29,6 +30,7 @@ class _MainWebViewPageState extends State<MainWebViewPage>
|
||||
// Watchdog for app-session expiry
|
||||
Timer? _watchdog;
|
||||
bool _extensionDialogShown = false;
|
||||
bool _lastSessionActive = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -36,12 +38,28 @@ class _MainWebViewPageState extends State<MainWebViewPage>
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
_initWebView();
|
||||
_startWatchdog();
|
||||
|
||||
// Listen to session changes to update JS context immediately
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.read<SessionManager>().addListener(_onSessionChanged);
|
||||
_lastSessionActive = context.read<SessionManager>().isSessionActive;
|
||||
});
|
||||
}
|
||||
|
||||
void _onSessionChanged() {
|
||||
if (!mounted) return;
|
||||
final sm = context.read<SessionManager>();
|
||||
if (_lastSessionActive != sm.isSessionActive) {
|
||||
_lastSessionActive = sm.isSessionActive;
|
||||
_applyInjections();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
_watchdog?.cancel();
|
||||
context.read<SessionManager>().removeListener(_onSessionChanged);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -154,6 +172,15 @@ class _MainWebViewPageState extends State<MainWebViewPage>
|
||||
);
|
||||
},
|
||||
onNavigationRequest: (request) {
|
||||
// Handle external links (non-Instagram/Facebook)
|
||||
final uri = Uri.tryParse(request.url);
|
||||
if (uri != null &&
|
||||
!uri.host.contains('instagram.com') &&
|
||||
!uri.host.contains('facebook.com')) {
|
||||
launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
return NavigationDecision.prevent;
|
||||
}
|
||||
|
||||
final decision = NavigationGuard.evaluate(url: request.url);
|
||||
|
||||
if (decision.blocked) {
|
||||
@@ -255,7 +282,11 @@ class _MainWebViewPageState extends State<MainWebViewPage>
|
||||
await _navigateTo('/explore/');
|
||||
break;
|
||||
case 2:
|
||||
_openSessionModal();
|
||||
if (context.read<SessionManager>().isSessionActive) {
|
||||
await _navigateTo('/reels/');
|
||||
} else {
|
||||
_openSessionModal();
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
await _navigateTo('/direct/inbox/');
|
||||
@@ -393,11 +424,21 @@ class _EdgePanelState extends State<_EdgePanel> {
|
||||
// Hits will pass through the Stack to the WebView except on our children.
|
||||
return Stack(
|
||||
children: [
|
||||
// ── Tap-to-close Backdrop (only when expanded) ──
|
||||
if (_isExpanded)
|
||||
Positioned.fill(
|
||||
child: GestureDetector(
|
||||
onTap: _toggleExpansion,
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Container(color: Colors.black.withValues(alpha: 0.15)),
|
||||
),
|
||||
),
|
||||
|
||||
// ── The Handle (Minimized State) ──
|
||||
if (!_isExpanded)
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: MediaQuery.of(context).size.height * 0.35,
|
||||
top: MediaQuery.of(context).size.height * 0.35 + 30, // Added margin
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: Column(
|
||||
@@ -480,7 +521,7 @@ class _EdgePanelState extends State<_EdgePanel> {
|
||||
duration: const Duration(milliseconds: 350),
|
||||
curve: Curves.easeOutQuart,
|
||||
left: _isExpanded ? 0 : -220,
|
||||
top: MediaQuery.of(context).size.height * 0.25,
|
||||
top: MediaQuery.of(context).size.height * 0.25 + 30, // Added margin
|
||||
child: GestureDetector(
|
||||
onHorizontalDragUpdate: (details) {
|
||||
if (details.delta.dx < -10) _toggleExpansion();
|
||||
|
||||
@@ -10,7 +10,7 @@ class SettingsPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settings = context.watch<SettingsService>();
|
||||
// Watching services ensures the UI rebuilds when settings or session state change.
|
||||
final sm = context.watch<SessionManager>();
|
||||
|
||||
return Scaffold(
|
||||
@@ -45,7 +45,7 @@ class SettingsPage extends StatelessWidget {
|
||||
title: 'Distraction Management',
|
||||
subtitle: 'Blur explore and reel controls',
|
||||
icon: Icons.visibility_off_outlined,
|
||||
destination: _DistractionSettingsPage(settings: settings),
|
||||
destination: const _DistractionSettingsPage(),
|
||||
),
|
||||
_buildSettingsTile(
|
||||
context: context,
|
||||
@@ -149,11 +149,11 @@ class SettingsPage extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _DistractionSettingsPage extends StatelessWidget {
|
||||
final SettingsService settings;
|
||||
const _DistractionSettingsPage({required this.settings});
|
||||
const _DistractionSettingsPage();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settings = context.watch<SettingsService>();
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.black,
|
||||
appBar: AppBar(
|
||||
|
||||
@@ -278,6 +278,10 @@ class InjectionController {
|
||||
(function() {
|
||||
function lockReelScroll(reelContainer) {
|
||||
if (reelContainer.dataset.scrollLocked) return;
|
||||
|
||||
// If session is active, don't lock
|
||||
if (window.__focusgramSessionActive === true) return;
|
||||
|
||||
reelContainer.dataset.scrollLocked = 'true';
|
||||
|
||||
let startY = 0;
|
||||
@@ -321,6 +325,7 @@ class InjectionController {
|
||||
/// JS to disable swipe-to-next behavior inside the isolated Reel player.
|
||||
static const String disableReelSwipeJS = '''
|
||||
(function disableSwipeNavigation() {
|
||||
if (window.__focusgramSessionActive === true) return;
|
||||
let startX = 0;
|
||||
document.addEventListener('touchstart', e => { startX = e.touches[0].clientX; }, {passive: true});
|
||||
document.addEventListener('touchmove', e => {
|
||||
@@ -330,6 +335,10 @@ class InjectionController {
|
||||
})();
|
||||
''';
|
||||
|
||||
/// JS to update the session state variable in the page context.
|
||||
static String buildSessionStateJS(bool active) =>
|
||||
'window.__focusgramSessionActive = $active;';
|
||||
|
||||
// ── Public API ──────────────────────────────────────────────────────────────
|
||||
|
||||
/// Full injection JS to run on every page load.
|
||||
@@ -345,9 +354,11 @@ class InjectionController {
|
||||
if (blurExplore) css.write(_blurExploreCSS);
|
||||
|
||||
return '''
|
||||
${buildSessionStateJS(sessionActive)}
|
||||
${_buildMutationObserver(css.toString())}
|
||||
$_periodicNavRemoverJS
|
||||
$_dismissAppBannerJS
|
||||
$reelsMutationObserverJS
|
||||
''';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,499 @@ class DisciplineChallenge {
|
||||
'patience',
|
||||
'intent',
|
||||
'choice',
|
||||
'calm',
|
||||
'peace',
|
||||
'truth',
|
||||
'grit',
|
||||
'work',
|
||||
'time',
|
||||
'life',
|
||||
'soul',
|
||||
'mind',
|
||||
'body',
|
||||
'heart',
|
||||
'will',
|
||||
'hope',
|
||||
'love',
|
||||
'kind',
|
||||
'help',
|
||||
'give',
|
||||
'take',
|
||||
'stay',
|
||||
'move',
|
||||
'jump',
|
||||
'run',
|
||||
'walk',
|
||||
'talk',
|
||||
'sing',
|
||||
'play',
|
||||
'read',
|
||||
'write',
|
||||
'draw',
|
||||
'cook',
|
||||
'bake',
|
||||
'farm',
|
||||
'fish',
|
||||
'hunt',
|
||||
'grow',
|
||||
'learn',
|
||||
'teach',
|
||||
'lead',
|
||||
'follow',
|
||||
'build',
|
||||
'fix',
|
||||
'save',
|
||||
'spend',
|
||||
'win',
|
||||
'lose',
|
||||
'try',
|
||||
'fail',
|
||||
'rise',
|
||||
'fall',
|
||||
'start',
|
||||
'stop',
|
||||
'wait',
|
||||
'now',
|
||||
'here',
|
||||
'slow',
|
||||
'fast',
|
||||
'high',
|
||||
'low',
|
||||
'deep',
|
||||
'wide',
|
||||
'long',
|
||||
'short',
|
||||
'big',
|
||||
'small',
|
||||
'old',
|
||||
'new',
|
||||
'good',
|
||||
'bad',
|
||||
'real',
|
||||
'fake',
|
||||
'pure',
|
||||
'dark',
|
||||
'light',
|
||||
'fire',
|
||||
'water',
|
||||
'earth',
|
||||
'air',
|
||||
'wind',
|
||||
'storm',
|
||||
'sun',
|
||||
'moon',
|
||||
'star',
|
||||
'sky',
|
||||
'road',
|
||||
'path',
|
||||
'gate',
|
||||
'door',
|
||||
'room',
|
||||
'house',
|
||||
'home',
|
||||
'city',
|
||||
'town',
|
||||
'land',
|
||||
'sea',
|
||||
'ocean',
|
||||
'lake',
|
||||
'river',
|
||||
'wood',
|
||||
'tree',
|
||||
'leaf',
|
||||
'root',
|
||||
'seed',
|
||||
'fruit',
|
||||
'food',
|
||||
'bread',
|
||||
'cake',
|
||||
'milk',
|
||||
'wine',
|
||||
'beer',
|
||||
'salt',
|
||||
'gold',
|
||||
'iron',
|
||||
'rock',
|
||||
'sand',
|
||||
'dust',
|
||||
'bone',
|
||||
'blood',
|
||||
'skin',
|
||||
'hair',
|
||||
'eyes',
|
||||
'ears',
|
||||
'nose',
|
||||
'mouth',
|
||||
'hand',
|
||||
'foot',
|
||||
'wing',
|
||||
'tail',
|
||||
'bird',
|
||||
'cat',
|
||||
'dog',
|
||||
'bear',
|
||||
'wolf',
|
||||
'lion',
|
||||
'deer',
|
||||
'horse',
|
||||
'cow',
|
||||
'pig',
|
||||
'sheep',
|
||||
'goat',
|
||||
'bee',
|
||||
'ant',
|
||||
'fly',
|
||||
'worm',
|
||||
'snake',
|
||||
'frog',
|
||||
'turtle',
|
||||
'crab',
|
||||
'whale',
|
||||
'shark',
|
||||
'dolphin',
|
||||
'eagle',
|
||||
'hawk',
|
||||
'owl',
|
||||
'swan',
|
||||
'duck',
|
||||
'goose',
|
||||
'rose',
|
||||
'lily',
|
||||
'pine',
|
||||
'oak',
|
||||
'fern',
|
||||
'moss',
|
||||
'weed',
|
||||
'grass',
|
||||
'corn',
|
||||
'rice',
|
||||
'bean',
|
||||
'pea',
|
||||
'nut',
|
||||
'oil',
|
||||
'honey',
|
||||
'wax',
|
||||
'silk',
|
||||
'wool',
|
||||
'flax',
|
||||
'hemp',
|
||||
'paper',
|
||||
'ink',
|
||||
'pen',
|
||||
'book',
|
||||
'lamp',
|
||||
'bed',
|
||||
'chair',
|
||||
'desk',
|
||||
'wall',
|
||||
'roof',
|
||||
'step',
|
||||
'mile',
|
||||
'inch',
|
||||
'yard',
|
||||
'hour',
|
||||
'day',
|
||||
'week',
|
||||
'month',
|
||||
'year',
|
||||
'age',
|
||||
'past',
|
||||
'next',
|
||||
'death',
|
||||
'birth',
|
||||
'name',
|
||||
'word',
|
||||
'song',
|
||||
'poem',
|
||||
'story',
|
||||
'myth',
|
||||
'fact',
|
||||
'law',
|
||||
'rule',
|
||||
'king',
|
||||
'queen',
|
||||
'lord',
|
||||
'lady',
|
||||
'man',
|
||||
'woman',
|
||||
'child',
|
||||
'youth',
|
||||
'elder',
|
||||
'friend',
|
||||
'foe',
|
||||
'guest',
|
||||
'host',
|
||||
'war',
|
||||
'fight',
|
||||
'deal',
|
||||
'buy',
|
||||
'sell',
|
||||
'pay',
|
||||
'debt',
|
||||
'cost',
|
||||
'coin',
|
||||
'cash',
|
||||
'bank',
|
||||
'shop',
|
||||
'mall',
|
||||
'mill',
|
||||
'port',
|
||||
'ship',
|
||||
'boat',
|
||||
'car',
|
||||
'bus',
|
||||
'bike',
|
||||
'train',
|
||||
'plane',
|
||||
'street',
|
||||
'hill',
|
||||
'peak',
|
||||
'cave',
|
||||
'well',
|
||||
'bridge',
|
||||
'tower',
|
||||
'fort',
|
||||
'camp',
|
||||
'tent',
|
||||
'ash',
|
||||
'smoke',
|
||||
'coal',
|
||||
'log',
|
||||
'branch',
|
||||
'stick',
|
||||
'tool',
|
||||
'hammer',
|
||||
'nail',
|
||||
'saw',
|
||||
'knife',
|
||||
'fork',
|
||||
'spoon',
|
||||
'bowl',
|
||||
'cup',
|
||||
'plate',
|
||||
'pot',
|
||||
'pan',
|
||||
'stove',
|
||||
'oven',
|
||||
'sink',
|
||||
'bath',
|
||||
'soap',
|
||||
'towel',
|
||||
'comb',
|
||||
'brush',
|
||||
'mirror',
|
||||
'clock',
|
||||
'watch',
|
||||
'ring',
|
||||
'belt',
|
||||
'boot',
|
||||
'shoe',
|
||||
'sock',
|
||||
'hat',
|
||||
'coat',
|
||||
'shirt',
|
||||
'pant',
|
||||
'dress',
|
||||
'skirt',
|
||||
'bag',
|
||||
'box',
|
||||
'case',
|
||||
'lock',
|
||||
'key',
|
||||
'bell',
|
||||
'horn',
|
||||
'drum',
|
||||
'pipe',
|
||||
'lute',
|
||||
'harp',
|
||||
'flute',
|
||||
'reed',
|
||||
'cord',
|
||||
'rope',
|
||||
'knot',
|
||||
'net',
|
||||
'hook',
|
||||
'line',
|
||||
'bait',
|
||||
'trap',
|
||||
'plow',
|
||||
'hoe',
|
||||
'rake',
|
||||
'spade',
|
||||
'crop',
|
||||
'wheat',
|
||||
'oats',
|
||||
'rye',
|
||||
'zinc',
|
||||
'lead',
|
||||
'copper',
|
||||
'tin',
|
||||
'silver',
|
||||
'stone',
|
||||
'clay',
|
||||
'mud',
|
||||
'rain',
|
||||
'snow',
|
||||
'hail',
|
||||
'mist',
|
||||
'fog',
|
||||
'cloud',
|
||||
'dawn',
|
||||
'dusk',
|
||||
'noon',
|
||||
'night',
|
||||
'ghost',
|
||||
'angel',
|
||||
'devil',
|
||||
'god',
|
||||
'fate',
|
||||
'doom',
|
||||
'fear',
|
||||
'joy',
|
||||
'woe',
|
||||
'pain',
|
||||
'care',
|
||||
'hate',
|
||||
'rage',
|
||||
'lust',
|
||||
'greed',
|
||||
'pride',
|
||||
'envy',
|
||||
'sloth',
|
||||
'wrath',
|
||||
'holy',
|
||||
'sin',
|
||||
'hell',
|
||||
'heaven',
|
||||
'void',
|
||||
'space',
|
||||
'form',
|
||||
'idea',
|
||||
'thought',
|
||||
'dot',
|
||||
'circle',
|
||||
'square',
|
||||
'point',
|
||||
'edge',
|
||||
'flow',
|
||||
'wave',
|
||||
'tide',
|
||||
'shore',
|
||||
'bank',
|
||||
'cliff',
|
||||
'vale',
|
||||
'meadow',
|
||||
'field',
|
||||
'plain',
|
||||
'desert',
|
||||
'forest',
|
||||
'jungle',
|
||||
'swamp',
|
||||
'marsh',
|
||||
'glade',
|
||||
'grove',
|
||||
'peak',
|
||||
'ridge',
|
||||
'slope',
|
||||
'track',
|
||||
'trail',
|
||||
'lane',
|
||||
'path',
|
||||
'alley',
|
||||
'court',
|
||||
'plaza',
|
||||
'park',
|
||||
'bridge',
|
||||
'tunnel',
|
||||
'arch',
|
||||
'dome',
|
||||
'spire',
|
||||
'tower',
|
||||
'wall',
|
||||
'fence',
|
||||
'gate',
|
||||
'stair',
|
||||
'floor',
|
||||
'beam',
|
||||
'pole',
|
||||
'mast',
|
||||
'sail',
|
||||
'deck',
|
||||
'hull',
|
||||
'keel',
|
||||
'oar',
|
||||
'helm',
|
||||
'anchor',
|
||||
'net',
|
||||
'rope',
|
||||
'knot',
|
||||
'line',
|
||||
'hook',
|
||||
'bait',
|
||||
'trap',
|
||||
'net',
|
||||
'spear',
|
||||
'bow',
|
||||
'arrow',
|
||||
'sword',
|
||||
'shield',
|
||||
'armor',
|
||||
'helm',
|
||||
'boot',
|
||||
'glove',
|
||||
'cloak',
|
||||
'scarf',
|
||||
'belt',
|
||||
'ujwal',
|
||||
'ring',
|
||||
'gem',
|
||||
'jewel',
|
||||
'pearl',
|
||||
'gold',
|
||||
'silver',
|
||||
'bronze',
|
||||
'iron',
|
||||
'steel',
|
||||
'brass',
|
||||
'glass',
|
||||
'stone',
|
||||
'brick',
|
||||
'tile',
|
||||
'wood',
|
||||
'clay',
|
||||
'wax',
|
||||
'ink',
|
||||
'paint',
|
||||
'dye',
|
||||
'glue',
|
||||
'oil',
|
||||
'coal',
|
||||
'gas',
|
||||
'steam',
|
||||
'heat',
|
||||
'cold',
|
||||
'ice',
|
||||
'frost',
|
||||
'thaw',
|
||||
'melt',
|
||||
'burn',
|
||||
'glow',
|
||||
'shine',
|
||||
'beam',
|
||||
'ray',
|
||||
'spark',
|
||||
'flash',
|
||||
'flare',
|
||||
'blast',
|
||||
'shock',
|
||||
'wave',
|
||||
'pulse',
|
||||
'beat',
|
||||
'rhythm',
|
||||
'tone',
|
||||
'note',
|
||||
'tune',
|
||||
'song',
|
||||
];
|
||||
|
||||
/// Shows the word challenge dialog. Returns true if successful.
|
||||
|
||||
Reference in New Issue
Block a user