121 lines
4.0 KiB
Dart
121 lines
4.0 KiB
Dart
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,
|
||
),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
},
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|