Merge pull request #67 from R0m1k3/antigravity

feat: Add IPTV player screen with live stream FFmpeg transcoding, pla…
This commit is contained in:
LogiFlow authored and GitHub committed 2025-12-07 10:03:16 +01:00
commit 8037744de4
4 files changed
+68 -2

No files matched your search

+50
View File
@@ -0,0 +1,50 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
class DigitalClock extends StatefulWidget {
const DigitalClock({super.key});
@override
State<DigitalClock> createState() => _DigitalClockState();
}
class _DigitalClockState extends State<DigitalClock> {
late Stream<DateTime> _clockStream;
late DateFormat _format;
@override
void initState() {
super.initState();
_format = DateFormat('HH:mm');
_clockStream = Stream.periodic(const Duration(seconds: 1), (_) => DateTime.now());
}
@override
Widget build(BuildContext context) {
return StreamBuilder<DateTime>(
stream: _clockStream,
initialData: DateTime.now(),
builder: (context, snapshot) {
final timeString = _format.format(snapshot.data ?? DateTime.now());
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius: BorderRadius.circular(20),
border: Border.all(color: Colors.white.withOpacity(0.05)),
),
child: Text(
timeString,
style: GoogleFonts.inter(
fontWeight: FontWeight.w600,
fontSize: 16,
color: Colors.white,
),
),
);
},
);
}
}
@@ -4,6 +4,7 @@ import 'package:google_fonts/google_fonts.dart';
import '../../../core/models/playlist_config.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/theme/app_theme.dart';
import '../../../core/widgets/digital_clock.dart';
import '../widgets/live_tv_tab.dart';
import '../widgets/movies_tab.dart';
import '../widgets/series_tab.dart';
@@ -132,7 +133,9 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> with SingleTi
// Global search trigger
},
),
const SizedBox(width: 8),
const SizedBox(width: 16),
const DigitalClock(),
const SizedBox(width: 16),
const CircleAvatar(
radius: 16,
backgroundColor: Colors.white24,
+2 -1
View File
@@ -78,8 +78,9 @@ class _PlayerScreenState extends ConsumerState<PlayerScreen> {
_contentId, currentTime, duration
);
} else if (type == 'playback_ended' && _contentId.isNotEmpty) {
// Clear position when video ends
ref.read(playbackPositionsProvider.notifier).clearPosition(_contentId);
} else if (type == 'user_activity') {
_onHover();
}
}
} catch (e) {
+12
View File
@@ -166,6 +166,18 @@
}, '*');
});
// Report user activity (mouse movement) to parent
let lastActivityTime = 0;
document.addEventListener('mousemove', () => {
const now = Date.now();
if (now - lastActivityTime > 100) { // Throttle to 100ms
lastActivityTime = now;
window.parent.postMessage({
type: 'user_activity'
}, '*');
}
});
// Seek to startTime when video is ready
video.addEventListener('loadedmetadata', () => {
if (startTime > 0 && startTime < video.duration) {