Files
Hightube/frontend/lib/pages/home_page.dart

121 lines
4.0 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/auth_provider.dart';
import '../providers/settings_provider.dart';
import '../services/api_service.dart';
import 'settings_page.dart';
import 'player_page.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<dynamic> _activeRooms = [];
bool _isLoading = false;
Timer? _refreshTimer;
@override
void initState() {
super.initState();
_refreshRooms();
// 启动自动刷新定时器 (每 10 秒自动更新列表)
_refreshTimer = Timer.periodic(Duration(seconds: 10), (timer) {
if (mounted) _refreshRooms(isAuto: true);
});
}
@override
void dispose() {
_refreshTimer?.cancel();
super.dispose();
}
Future<void> _refreshRooms({bool isAuto = false}) async {
if (!isAuto) setState(() => _isLoading = true);
final settings = context.read<SettingsProvider>();
final auth = context.read<AuthProvider>();
final api = ApiService(settings, auth.token);
try {
final response = await api.getActiveRooms();
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
if (mounted) {
setState(() => _activeRooms = data['active_rooms'] ?? []);
}
}
} catch (e) {
if (!isAuto && mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Failed to load rooms")));
}
} finally {
if (!isAuto && mounted) setState(() => _isLoading = false);
}
}
@override
Widget build(BuildContext context) {
final settings = context.watch<SettingsProvider>();
return Scaffold(
appBar: AppBar(
title: Text("Hightube Live"),
actions: [
IconButton(
icon: Icon(Icons.refresh),
tooltip: "Manual Refresh",
onPressed: () => _refreshRooms(),
),
IconButton(
icon: Icon(Icons.settings),
tooltip: "Settings",
onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (_) => SettingsPage())),
),
IconButton(
icon: Icon(Icons.logout),
tooltip: "Logout",
onPressed: () => context.read<AuthProvider>().logout(),
),
],
),
body: RefreshIndicator(
onRefresh: _refreshRooms,
child: _isLoading && _activeRooms.isEmpty
? Center(child: CircularProgressIndicator())
: _activeRooms.isEmpty
? ListView(children: [Padding(padding: EdgeInsets.only(top: 50), child: Center(child: Text("No active rooms. Be the first!")))])
: ListView.builder(
itemCount: _activeRooms.length,
itemBuilder: (context, index) {
final room = _activeRooms[index];
return ListTile(
leading: CircleAvatar(child: Icon(Icons.live_tv)),
title: Text(room['title']),
subtitle: Text("User ID: ${room['user_id']} (Streaming now)"),
trailing: Icon(Icons.play_circle_filled, color: Colors.blue),
onTap: () {
// 动态构建播放链接rtmp://{host}:1935/live/{room_id}
final rtmpUrl = "${settings.rtmpUrl}/${room['room_id']}";
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => PlayerPage(
title: room['title'],
rtmpUrl: rtmpUrl,
),
),
);
},
);
},
),
),
);
}
}