Phase 3.5: Implemented adaptive navigation (BottomBar/Rail) and My Stream console
This commit is contained in:
125
frontend/lib/pages/my_stream_page.dart
Normal file
125
frontend/lib/pages/my_stream_page.dart
Normal file
@@ -0,0 +1,125 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import '../providers/auth_provider.dart';
|
||||
import '../providers/settings_provider.dart';
|
||||
import '../services/api_service.dart';
|
||||
|
||||
class MyStreamPage extends StatefulWidget {
|
||||
@override
|
||||
_MyStreamPageState createState() => _MyStreamPageState();
|
||||
}
|
||||
|
||||
class _MyStreamPageState extends State<MyStreamPage> {
|
||||
Map<String, dynamic>? _roomInfo;
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_fetchMyRoom();
|
||||
}
|
||||
|
||||
Future<void> _fetchMyRoom() async {
|
||||
setState(() => _isLoading = true);
|
||||
final settings = context.read<SettingsProvider>();
|
||||
final auth = context.read<AuthProvider>();
|
||||
final api = ApiService(settings, auth.token);
|
||||
|
||||
try {
|
||||
final response = await api.getMyRoom();
|
||||
if (response.statusCode == 200) {
|
||||
setState(() => _roomInfo = jsonDecode(response.body));
|
||||
}
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Failed to fetch room info")));
|
||||
} finally {
|
||||
setState(() => _isLoading = false);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final settings = context.watch<SettingsProvider>();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text("My Stream Console")),
|
||||
body: _isLoading
|
||||
? Center(child: CircularProgressIndicator())
|
||||
: _roomInfo == null
|
||||
? Center(child: Text("No room info found."))
|
||||
: SingleChildScrollView(
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildInfoCard(
|
||||
title: "Room Title",
|
||||
value: _roomInfo!['title'],
|
||||
icon: Icons.edit,
|
||||
onTap: () {
|
||||
// TODO: Implement title update API later
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Title editing coming soon!")));
|
||||
},
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
_buildInfoCard(
|
||||
title: "RTMP Server URL",
|
||||
value: settings.rtmpUrl,
|
||||
icon: Icons.copy,
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: settings.rtmpUrl));
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Server URL copied to clipboard")));
|
||||
},
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
_buildInfoCard(
|
||||
title: "Stream Key (Keep Secret!)",
|
||||
value: _roomInfo!['stream_key'],
|
||||
icon: Icons.copy,
|
||||
isSecret: true,
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: _roomInfo!['stream_key']));
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Stream Key copied to clipboard")));
|
||||
},
|
||||
),
|
||||
SizedBox(height: 30),
|
||||
Center(
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(Icons.info_outline, color: Colors.grey),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
"Use OBS or other tools to stream to this address.",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Colors.grey, fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildInfoCard({
|
||||
required String title,
|
||||
required String value,
|
||||
required IconData icon,
|
||||
bool isSecret = false,
|
||||
VoidCallback? onTap,
|
||||
}) {
|
||||
return Card(
|
||||
child: ListTile(
|
||||
title: Text(title, style: TextStyle(fontSize: 12, color: Colors.grey)),
|
||||
subtitle: Text(
|
||||
isSecret ? "••••••••••••••••" : value,
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
|
||||
),
|
||||
trailing: IconButton(icon: Icon(icon), onPressed: onTap),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user