feat: Add mobile playlist screen for managing IPTV configurations, including creation, editing, and auto-login.

This commit is contained in:
Michael committed 2025-12-27 10:37:25 +01:00
1 parent 5dd83019d3
commit aaa0e9624d
3 files changed
+40 -6

No files matched your search

@@ -134,6 +134,7 @@ class _MobilePlaylistScreenState extends ConsumerState<MobilePlaylistScreen> {
onSubmitted: () =>
FocusScope.of(context).requestFocus(dnsFocus),
focusNode: nameFocus,
nextFocus: dnsFocus,
),
const SizedBox(height: 16),
@@ -147,6 +148,8 @@ class _MobilePlaylistScreenState extends ConsumerState<MobilePlaylistScreen> {
onSubmitted: () =>
FocusScope.of(context).requestFocus(usernameFocus),
focusNode: dnsFocus,
nextFocus: usernameFocus,
prevFocus: nameFocus,
),
const SizedBox(height: 16),
@@ -159,6 +162,8 @@ class _MobilePlaylistScreenState extends ConsumerState<MobilePlaylistScreen> {
onSubmitted: () =>
FocusScope.of(context).requestFocus(passwordFocus),
focusNode: usernameFocus,
nextFocus: passwordFocus,
prevFocus: dnsFocus,
),
const SizedBox(height: 16),
@@ -172,6 +177,8 @@ class _MobilePlaylistScreenState extends ConsumerState<MobilePlaylistScreen> {
onSubmitted: () =>
FocusScope.of(context).requestFocus(buttonFocus),
focusNode: passwordFocus,
nextFocus: buttonFocus,
prevFocus: usernameFocus,
),
const SizedBox(height: 32),
@@ -262,6 +269,8 @@ class _MobilePlaylistScreenState extends ConsumerState<MobilePlaylistScreen> {
TextInputAction? textAction,
VoidCallback? onSubmitted,
FocusNode? focusNode, // This is now the "navigation" focus
FocusNode? nextFocus,
FocusNode? prevFocus,
}) {
// Create a dedicated internal focus node for the actual TextField
// We don't expose this, allowing us to control when the keyboard opens
@@ -280,6 +289,8 @@ class _MobilePlaylistScreenState extends ConsumerState<MobilePlaylistScreen> {
textAction: textAction,
onSubmitted: onSubmitted,
navigationFocus: focusNode,
nextFocus: nextFocus,
prevFocus: prevFocus,
);
}
@@ -599,6 +610,8 @@ class _TVTextField extends StatefulWidget {
final TextInputAction? textAction;
final VoidCallback? onSubmitted;
final FocusNode? navigationFocus;
final FocusNode? nextFocus;
final FocusNode? prevFocus;
const _TVTextField({
required this.controller,
@@ -610,6 +623,8 @@ class _TVTextField extends StatefulWidget {
this.textAction,
this.onSubmitted,
this.navigationFocus,
this.nextFocus,
this.prevFocus,
});
@override
@@ -667,6 +682,14 @@ class _TVTextFieldState extends State<_TVTextField> {
_activateInput();
return KeyEventResult.handled;
}
if (key == LogicalKeyboardKey.arrowDown && widget.nextFocus != null) {
widget.nextFocus!.requestFocus();
return KeyEventResult.handled;
}
if (key == LogicalKeyboardKey.arrowUp && widget.prevFocus != null) {
widget.prevFocus!.requestFocus();
return KeyEventResult.handled;
}
}
return KeyEventResult.ignored;
},
@@ -102,7 +102,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
),
),
Text(
'Version 1.5.0',
'Version 1.5.1',
style: GoogleFonts.inter(
fontSize: 13,
color: AppColors.textSecondary,
@@ -173,6 +173,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
label: 'TV en Direct',
hint: 'Ex: FR, HD, SPORT',
icon: Icons.live_tv,
currentKeywords: settings.liveTvKeywords,
controller: _liveTvController,
onChanged: (val) {
ref
@@ -185,6 +186,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
label: 'Films',
hint: 'Ex: FR, VF, 4K',
icon: Icons.movie,
currentKeywords: settings.moviesKeywords,
controller: _moviesController,
onChanged: (val) {
ref
@@ -197,6 +199,7 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
label: 'Séries',
hint: 'Ex: FR, VF',
icon: Icons.tv,
currentKeywords: settings.seriesKeywords,
controller: _seriesController,
onChanged: (val) {
ref
@@ -393,9 +396,15 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
required String label,
required String hint,
required IconData icon,
required List<String> currentKeywords,
required TextEditingController controller,
required ValueChanged<String> onChanged,
}) {
final hasFilters = currentKeywords.isNotEmpty;
final subtitle = hasFilters
? currentKeywords.join(', ')
: 'Aucun filtre (Tout afficher)';
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: TVFocusable(
@@ -427,12 +436,14 @@ class _MobileSettingsTabState extends ConsumerState<MobileSettingsTab> {
),
),
Text(
controller.text.isEmpty ? hint : controller.text,
subtitle,
style: TextStyle(
color: controller.text.isEmpty
? AppColors.textSecondary
: AppColors.textPrimary,
color: hasFilters
? AppColors.primary
: AppColors.textSecondary,
fontSize: 12,
fontWeight:
hasFilters ? FontWeight.w600 : FontWeight.normal,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
+1 -1
View File
@@ -1,7 +1,7 @@
name: xtremflow
description: High-performance IPTV Web Application with Xtream Codes API
publish_to: 'none'
version: 1.5.0+10
version: 1.5.1+11
environment:
sdk: '>=3.0.0 <4.0.0'