mirror of
https://github.com/R0m1k3/xtremobile.git
synced 2026-10-22 14:48:16 +02:00
feat: Add Xtream API service with DNS resolution and caching, and new IPTV player screens.
This commit is contained in:
1 parent
18dc184388
commit
915f75661f
3 files changed
+110
-66
No files matched your search
@@ -769,33 +769,50 @@ class _LitePlayerScreenState extends ConsumerState<LitePlayerScreen>
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
Expanded(
|
||||
child: Shortcuts(
|
||||
shortcuts: <LogicalKeySet, Intent>{
|
||||
LogicalKeySet(LogicalKeyboardKey.arrowUp):
|
||||
const DirectionalFocusIntent(TraversalDirection.up),
|
||||
LogicalKeySet(LogicalKeyboardKey.arrowDown):
|
||||
const DirectionalFocusIntent(
|
||||
TraversalDirection.down),
|
||||
child: Actions(
|
||||
actions: <Type, Action<Intent>>{
|
||||
DirectionalFocusIntent:
|
||||
CallbackAction<DirectionalFocusIntent>(
|
||||
onInvoke: (intent) {
|
||||
if (intent.direction == TraversalDirection.up ||
|
||||
intent.direction == TraversalDirection.down) {
|
||||
FocusScope.of(context)
|
||||
.focusInDirection(intent.direction);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
},
|
||||
child: Slider(
|
||||
value: _position.inSeconds
|
||||
.toDouble()
|
||||
.clamp(0, _duration.inSeconds.toDouble()),
|
||||
min: 0,
|
||||
max: _duration.inSeconds.toDouble(),
|
||||
activeColor: AppColors.primary,
|
||||
inactiveColor: Colors.white24,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
_position = Duration(seconds: val.toInt());
|
||||
_isSeeking = true;
|
||||
});
|
||||
},
|
||||
onChangeEnd: (val) {
|
||||
_controller?.seekTo(Duration(seconds: val.toInt()));
|
||||
_isSeeking = false;
|
||||
_onUserInteraction();
|
||||
child: Shortcuts(
|
||||
shortcuts: <LogicalKeySet, Intent>{
|
||||
LogicalKeySet(LogicalKeyboardKey.arrowUp):
|
||||
const DirectionalFocusIntent(
|
||||
TraversalDirection.up),
|
||||
LogicalKeySet(LogicalKeyboardKey.arrowDown):
|
||||
const DirectionalFocusIntent(
|
||||
TraversalDirection.down),
|
||||
},
|
||||
child: Slider(
|
||||
value: _position.inSeconds
|
||||
.toDouble()
|
||||
.clamp(0, _duration.inSeconds.toDouble()),
|
||||
min: 0,
|
||||
max: _duration.inSeconds.toDouble(),
|
||||
activeColor: AppColors.primary,
|
||||
inactiveColor: Colors.white24,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
_position = Duration(seconds: val.toInt());
|
||||
_isSeeking = true;
|
||||
});
|
||||
},
|
||||
onChangeEnd: (val) {
|
||||
_controller?.seekTo(Duration(seconds: val.toInt()));
|
||||
_isSeeking = false;
|
||||
_onUserInteraction();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1343,39 +1343,59 @@ class _NativePlayerScreenState extends ConsumerState<NativePlayerScreen>
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Shortcuts(
|
||||
shortcuts: <LogicalKeySet, Intent>{
|
||||
LogicalKeySet(LogicalKeyboardKey.arrowUp):
|
||||
const DirectionalFocusIntent(
|
||||
TraversalDirection.up),
|
||||
LogicalKeySet(LogicalKeyboardKey.arrowDown):
|
||||
const DirectionalFocusIntent(
|
||||
TraversalDirection.down),
|
||||
child: Actions(
|
||||
actions: <Type, Action<Intent>>{
|
||||
// Override directional focus intents for Up/Down
|
||||
DirectionalFocusIntent:
|
||||
CallbackAction<DirectionalFocusIntent>(
|
||||
onInvoke: (intent) {
|
||||
if (intent.direction ==
|
||||
TraversalDirection.up ||
|
||||
intent.direction ==
|
||||
TraversalDirection.down) {
|
||||
// Manually move focus in the requested direction
|
||||
FocusScope.of(context)
|
||||
.focusInDirection(intent.direction);
|
||||
return null;
|
||||
}
|
||||
// For left/right, don't handle (let Slider do seeking)
|
||||
return null;
|
||||
},
|
||||
),
|
||||
},
|
||||
child: Slider(
|
||||
value: _position.inSeconds
|
||||
.toDouble()
|
||||
.clamp(0, _duration.inSeconds.toDouble()),
|
||||
min: 0,
|
||||
max: _duration.inSeconds.toDouble(),
|
||||
// Add divisions for precise seeking (1 step = 10 seconds)
|
||||
divisions: _duration.inSeconds > 0
|
||||
? (_duration.inSeconds / 10).ceil()
|
||||
: null,
|
||||
activeColor: AppColors.primary,
|
||||
inactiveColor: Colors.white24,
|
||||
onChangeStart: (_) => _isSeeking = true,
|
||||
onChangeEnd: (value) async {
|
||||
await _player
|
||||
.seek(Duration(seconds: value.toInt()));
|
||||
_isSeeking = false;
|
||||
},
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_position =
|
||||
Duration(seconds: value.toInt());
|
||||
});
|
||||
child: Shortcuts(
|
||||
shortcuts: <LogicalKeySet, Intent>{
|
||||
LogicalKeySet(LogicalKeyboardKey.arrowUp):
|
||||
const DirectionalFocusIntent(
|
||||
TraversalDirection.up),
|
||||
LogicalKeySet(LogicalKeyboardKey.arrowDown):
|
||||
const DirectionalFocusIntent(
|
||||
TraversalDirection.down),
|
||||
},
|
||||
child: Slider(
|
||||
value: _position.inSeconds
|
||||
.toDouble()
|
||||
.clamp(0, _duration.inSeconds.toDouble()),
|
||||
min: 0,
|
||||
max: _duration.inSeconds.toDouble(),
|
||||
divisions: _duration.inSeconds > 0
|
||||
? (_duration.inSeconds / 10).ceil()
|
||||
: null,
|
||||
activeColor: AppColors.primary,
|
||||
inactiveColor: Colors.white24,
|
||||
onChangeStart: (_) => _isSeeking = true,
|
||||
onChangeEnd: (value) async {
|
||||
await _player
|
||||
.seek(Duration(seconds: value.toInt()));
|
||||
_isSeeking = false;
|
||||
},
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_position =
|
||||
Duration(seconds: value.toInt());
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user