PSDK-978 - Экран настроек
This commit is contained in:
committed by
Николай Коротков
parent
909f35c1b9
commit
885d75a18e
@@ -7,6 +7,7 @@ import 'package:nut_player_example/src/features/main_screen/presentation/buttons
|
||||
import 'package:nut_player_example/src/features/main_screen/presentation/json_view.dart';
|
||||
import 'package:nut_player_example/src/features/main_screen/presentation/url_view.dart';
|
||||
import 'package:nut_player_example/src/features/player_screen/presentation/player_view.dart';
|
||||
import 'package:nut_player_example/src/features/settings_screen/domain/settings_bloc.dart';
|
||||
import '../../player_screen/domain/bloc/playerview_bloc.dart';
|
||||
import '../../settings_screen/presentation/settings_view.dart';
|
||||
|
||||
@@ -92,7 +93,19 @@ class Home extends StatelessWidget {
|
||||
);
|
||||
}));
|
||||
} else if (state is SettingState) {
|
||||
Navigator.push(context, CupertinoPageRoute(builder: (_) { return const SettingsView(); }));
|
||||
Navigator.push(context, CupertinoPageRoute(builder: (_) {
|
||||
return BlocProvider(
|
||||
create: (context) => SettingsBloc(),
|
||||
child: BlocListener<SettingsBloc, SettingsState>(
|
||||
listener: (context, state) {
|
||||
if (state is SettingsDismiss) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
child: const SettingsView(),
|
||||
)
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
context.read<UrlBloc>().add(UrlResetEvent());
|
||||
|
||||
@@ -82,11 +82,11 @@ class _PlayerViewState extends State<PlayerView> {
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w400)),
|
||||
),
|
||||
children: _buildOptionsWidgets(context, bloc)),
|
||||
children: _buildOptionsWidgets(bloc)),
|
||||
CupertinoListSection.insetGrouped(
|
||||
margin: const EdgeInsets.symmetric(vertical: 0, horizontal: 20),
|
||||
hasLeading: false,
|
||||
children: _buildStartPositionWidget(context, bloc)
|
||||
children: _buildStartPositionWidget(bloc)
|
||||
),
|
||||
CupertinoListSection.insetGrouped(
|
||||
hasLeading: false,
|
||||
@@ -147,7 +147,7 @@ class _PlayerViewState extends State<PlayerView> {
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
List<Widget> _buildOptionsWidgets(BuildContext context, PlayerViewBloc bloc) {
|
||||
List<Widget> _buildOptionsWidgets(PlayerViewBloc bloc) {
|
||||
return PlayerViewController.playbackSettings.map((setting) {
|
||||
final selectedIndex = bloc.selectedIndex(setting);
|
||||
return OptionsView(
|
||||
@@ -166,7 +166,7 @@ class _PlayerViewState extends State<PlayerView> {
|
||||
}).toList();
|
||||
}
|
||||
|
||||
List<Widget> _buildStartPositionWidget(BuildContext context, PlayerViewBloc bloc) {
|
||||
List<Widget> _buildStartPositionWidget(PlayerViewBloc bloc) {
|
||||
return [InputView(
|
||||
NumericOptionData(
|
||||
key: PlayerViewController.startPosition.key,
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:nut_player_example/src/common/models/option_data.dart';
|
||||
|
||||
part 'settings_event.dart';
|
||||
part 'settings_state.dart';
|
||||
|
||||
class SettingsBloc extends Bloc<SettingsEvent, SettingsState> {
|
||||
SettingsBloc() : super(SettingsInitialState.create()) {
|
||||
on<DismissEvent>(_onDismissEvent);
|
||||
on<SpeedChangedEvent>(_onSpeedChangedEvent);
|
||||
on<VolumeChangedEvent>(_onVolumeChangedEvent);
|
||||
on<BrightnessChangedEvent>(_onBrightnessChangedEvent);
|
||||
on<AutostartChangedEvent>(_onAutostartChangedEvent);
|
||||
on<FullscreenChangedEvent>(_onFullscreenChangedEvent);
|
||||
on<PipChangedEvent>(_onPipChangedEvent);
|
||||
on<SettingsChangedEvent>(_onSettingsChangedEvent);
|
||||
on<ColorChangedEvent>(_onColorChangedEvent);
|
||||
on<QualityChangedEvent>(_onQualityChangedEvent);
|
||||
on<QualityNamingChangedEvent>(_onQualityNamingChangedEvent);
|
||||
on<SubsChangedEvent>(_onSubsChangedEvent);
|
||||
on<StartPositionChangedEvent>(_onStartPositionChangedEvent);
|
||||
on<LoopChangedEvent>(_onLoopChangedEvent);
|
||||
}
|
||||
|
||||
_onDismissEvent(DismissEvent event, Emitter<SettingsState> emit) {
|
||||
emit(SettingsDismiss());
|
||||
}
|
||||
|
||||
_onSpeedChangedEvent(SpeedChangedEvent event, Emitter<SettingsState> emit) {
|
||||
final settingsState = state;
|
||||
if (settingsState is! SettingsInitialState) { return; }
|
||||
|
||||
final speedWithoutX = event.option.title.replaceAll(RegExp('x'), '');
|
||||
final speed = double.tryParse(speedWithoutX) ?? 1;
|
||||
|
||||
emit(settingsState.copy(speed: speed));
|
||||
}
|
||||
|
||||
_onVolumeChangedEvent(VolumeChangedEvent event, Emitter<SettingsState> emit) {
|
||||
final settingsState = state;
|
||||
if (settingsState is! SettingsInitialState) { return; }
|
||||
|
||||
final volume = double.parse(event.option.title);
|
||||
|
||||
emit(settingsState.copy(volume: volume));
|
||||
}
|
||||
|
||||
_onBrightnessChangedEvent(BrightnessChangedEvent event, Emitter<SettingsState> emit) {
|
||||
final settingsState = state;
|
||||
if (settingsState is! SettingsInitialState) { return; }
|
||||
|
||||
final brightness = double.parse(event.option.title);
|
||||
|
||||
emit(settingsState.copy(brightness: brightness));
|
||||
}
|
||||
|
||||
_onStartPositionChangedEvent(StartPositionChangedEvent event, Emitter<SettingsState> emit) {}
|
||||
_onQualityChangedEvent(QualityChangedEvent event, Emitter<SettingsState> emit) {}
|
||||
_onSubsChangedEvent(SubsChangedEvent event, Emitter<SettingsState> emit) {}
|
||||
_onQualityNamingChangedEvent(QualityNamingChangedEvent event, Emitter<SettingsState> emit) {}
|
||||
_onAutostartChangedEvent(AutostartChangedEvent event, Emitter<SettingsState> emit) {}
|
||||
_onLoopChangedEvent(LoopChangedEvent event, Emitter<SettingsState> emit) {}
|
||||
_onPipChangedEvent(PipChangedEvent event, Emitter<SettingsState> emit) {}
|
||||
_onSettingsChangedEvent(SettingsChangedEvent event, Emitter<SettingsState> emit) {}
|
||||
_onFullscreenChangedEvent(FullscreenChangedEvent event, Emitter<SettingsState> emit) {}
|
||||
_onColorChangedEvent(ColorChangedEvent event, Emitter<SettingsState> emit) {}
|
||||
|
||||
int selectedIndex(OptionDataContainer setting) {
|
||||
if (setting.key == const Key('PlaybackOptionSpeedID')) {
|
||||
return _selectedIndexForSpeed(setting.options);
|
||||
} else if (setting.key == const Key('PlaybackOptionVolumeID')) {
|
||||
return _selectedIndexForVolume(setting.options);
|
||||
} else if (setting.key == const Key('PlaybackOptionBrightnessID')) {
|
||||
return _selectedIndexForBrightness(setting.options);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int _selectedIndexForSpeed(List<OptionData> settings) {
|
||||
final settingsState = state;
|
||||
if (settingsState is! SettingsInitialState) { return 3; }
|
||||
|
||||
return settings.indexWhere((element) => element.value == settingsState.speed.toString());
|
||||
}
|
||||
|
||||
int _selectedIndexForVolume(List<OptionData> settings) {
|
||||
final settingsState = state;
|
||||
if (settingsState is! SettingsInitialState) { return 5; }
|
||||
|
||||
return settings.indexWhere((element) => element.value == settingsState.volume.toString());
|
||||
}
|
||||
|
||||
int _selectedIndexForBrightness(List<OptionData> settings) {
|
||||
final settingsState = state;
|
||||
if (settingsState is! SettingsInitialState) { return 5; }
|
||||
|
||||
return settings.indexWhere((element) => element.value == settingsState.brightness.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
part of 'settings_bloc.dart';
|
||||
|
||||
@immutable
|
||||
abstract class SettingsEvent {}
|
||||
|
||||
class DismissEvent extends SettingsEvent {}
|
||||
|
||||
class SpeedChangedEvent extends SettingsEvent {
|
||||
final OptionData option;
|
||||
SpeedChangedEvent(this.option);
|
||||
}
|
||||
|
||||
class VolumeChangedEvent extends SettingsEvent {
|
||||
final OptionData option;
|
||||
VolumeChangedEvent(this.option);
|
||||
}
|
||||
|
||||
class BrightnessChangedEvent extends SettingsEvent {
|
||||
final OptionData option;
|
||||
BrightnessChangedEvent(this.option);
|
||||
}
|
||||
|
||||
class QualityChangedEvent extends SettingsEvent {
|
||||
final OptionData option;
|
||||
QualityChangedEvent(this.option);
|
||||
}
|
||||
|
||||
class QualityNamingChangedEvent extends SettingsEvent {
|
||||
final OptionData option;
|
||||
QualityNamingChangedEvent(this.option);
|
||||
}
|
||||
|
||||
class FullscreenChangedEvent extends SettingsEvent {
|
||||
final OptionData option;
|
||||
FullscreenChangedEvent(this.option);
|
||||
}
|
||||
|
||||
class ColorChangedEvent extends SettingsEvent {
|
||||
final OptionData option;
|
||||
ColorChangedEvent(this.option);
|
||||
}
|
||||
|
||||
class SubsChangedEvent extends SettingsEvent {
|
||||
final bool isOn;
|
||||
SubsChangedEvent(this.isOn);
|
||||
}
|
||||
|
||||
class PipChangedEvent extends SettingsEvent {
|
||||
final bool isOn;
|
||||
PipChangedEvent(this.isOn);
|
||||
}
|
||||
|
||||
class SettingsChangedEvent extends SettingsEvent {
|
||||
final bool isOn;
|
||||
SettingsChangedEvent(this.isOn);
|
||||
}
|
||||
|
||||
class AutostartChangedEvent extends SettingsEvent {
|
||||
final bool isOn;
|
||||
AutostartChangedEvent(this.isOn);
|
||||
}
|
||||
|
||||
class LoopChangedEvent extends SettingsEvent {
|
||||
final bool isOn;
|
||||
LoopChangedEvent(this.isOn);
|
||||
}
|
||||
|
||||
class StartPositionChangedEvent extends SettingsEvent {
|
||||
final int value;
|
||||
StartPositionChangedEvent(this.value);
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
part of 'settings_bloc.dart';
|
||||
|
||||
enum FullscreenSettings { landscape, flexible, off }
|
||||
enum SkinColor { white }
|
||||
enum VideoQuality { auto, p2160, p1440, p1080, p720, p480, p360, p240, p144 }
|
||||
enum VideoQualityNaming { common, rus, eng, resolution }
|
||||
enum LogType { off, info, debug }
|
||||
|
||||
sealed class SettingsState {}
|
||||
|
||||
class SettingsDismiss extends SettingsState {}
|
||||
|
||||
@immutable
|
||||
class SettingsInitialState extends SettingsState {
|
||||
final bool isSkinByDefault;
|
||||
|
||||
final FullscreenSettings fullscreenSettings;
|
||||
final bool isPipAvailable;
|
||||
final bool isSettingsAvailable;
|
||||
final SkinColor skinColor;
|
||||
|
||||
final bool isAutostart;
|
||||
final double volume;
|
||||
final double brightness;
|
||||
final double speed;
|
||||
final VideoQualityNaming qualityNaming;
|
||||
final VideoQuality quality;
|
||||
final bool isSubtitlesAvailable;
|
||||
final int start;
|
||||
|
||||
final bool isLoop;
|
||||
|
||||
final int manifest;
|
||||
final int track;
|
||||
final int chunk;
|
||||
|
||||
final LogType log;
|
||||
|
||||
SettingsInitialState({
|
||||
required this.isSkinByDefault,
|
||||
required this.fullscreenSettings,
|
||||
required this.isPipAvailable,
|
||||
required this.isSettingsAvailable,
|
||||
required this.skinColor,
|
||||
required this.isAutostart,
|
||||
required this.brightness,
|
||||
required this.volume,
|
||||
required this.speed,
|
||||
required this.qualityNaming,
|
||||
required this.quality,
|
||||
required this.isSubtitlesAvailable,
|
||||
required this.start,
|
||||
required this.isLoop,
|
||||
required this.manifest,
|
||||
required this.track,
|
||||
required this.chunk,
|
||||
required this.log
|
||||
});
|
||||
|
||||
SettingsInitialState copy({
|
||||
bool? isSkinByDefault,
|
||||
|
||||
FullscreenSettings? fullscreenSettings,
|
||||
bool? isPipAvailable,
|
||||
bool? isSettingsAvailable,
|
||||
SkinColor? skinColor,
|
||||
|
||||
bool? isAutostart,
|
||||
double? volume,
|
||||
double? brightness,
|
||||
double? speed,
|
||||
VideoQualityNaming? qualityNaming,
|
||||
VideoQuality? quality,
|
||||
bool? isSubtitlesAvailable,
|
||||
int? start,
|
||||
|
||||
bool? isLoop,
|
||||
|
||||
int? manifest,
|
||||
int? track,
|
||||
int? chunk,
|
||||
|
||||
LogType? log
|
||||
}) {
|
||||
return SettingsInitialState(
|
||||
isSkinByDefault: isSkinByDefault ?? this.isSkinByDefault,
|
||||
fullscreenSettings: fullscreenSettings ?? this.fullscreenSettings,
|
||||
isPipAvailable: isPipAvailable ?? this.isPipAvailable,
|
||||
isSettingsAvailable: isSettingsAvailable ?? this.isSettingsAvailable,
|
||||
skinColor: skinColor ?? this.skinColor,
|
||||
isAutostart: isAutostart ?? this.isAutostart,
|
||||
volume: volume ?? this.volume,
|
||||
brightness: brightness ?? this.brightness,
|
||||
speed: speed ?? this.speed,
|
||||
qualityNaming: qualityNaming ?? this.qualityNaming,
|
||||
quality: quality ?? this.quality,
|
||||
isSubtitlesAvailable: isSubtitlesAvailable ?? this.isSubtitlesAvailable,
|
||||
start: start ?? this.start,
|
||||
isLoop: isLoop ?? this.isLoop,
|
||||
manifest: manifest ?? this.manifest,
|
||||
track: track ?? this.track,
|
||||
chunk: chunk ?? this.chunk,
|
||||
log: log ?? this.log
|
||||
);
|
||||
}
|
||||
|
||||
factory SettingsInitialState.create() {
|
||||
return SettingsInitialState(
|
||||
isSkinByDefault: true,
|
||||
fullscreenSettings: FullscreenSettings.landscape,
|
||||
isPipAvailable: false,
|
||||
isSettingsAvailable: true,
|
||||
skinColor: SkinColor.white,
|
||||
isAutostart: false,
|
||||
brightness: 0.5,
|
||||
volume: 0.5,
|
||||
speed: 1,
|
||||
qualityNaming: VideoQualityNaming.common,
|
||||
quality: VideoQuality.auto,
|
||||
isSubtitlesAvailable: true,
|
||||
start: 0,
|
||||
isLoop: false,
|
||||
manifest: 5000,
|
||||
track: 3000,
|
||||
chunk: 3000,
|
||||
log: LogType.info);
|
||||
}
|
||||
|
||||
|
||||
static const skinSettings = [
|
||||
OptionData(key: Key('SkinOptionDefaultID'), title: 'По умолчанию', isSelected: true),
|
||||
OptionData(key: Key('SkinOptionByUserID'), title: 'Свой')
|
||||
];
|
||||
|
||||
static final standardSkinSettings = [
|
||||
OptionDataContainer(
|
||||
key: const Key('FullscreenID'),
|
||||
title: 'Полноэкранный режим',
|
||||
options: const [
|
||||
OptionData(key: Key('SkinStandardFullscreenAlbumID'), title: 'Альбомный'),
|
||||
OptionData(key: Key('SkinStandardFullscreenFlexID'), title: 'Гибкий'),
|
||||
OptionData(key: Key('SkinStandardFullscreenOffID'), title: 'Выкл.')
|
||||
]
|
||||
),
|
||||
const OptionData(key: Key(''), title: 'Картинка в картинке'),
|
||||
const OptionData(key: Key(''), title: 'Настройки', isSelected: true),
|
||||
OptionDataContainer(
|
||||
key: const Key('ColorID'),
|
||||
title: 'Цвет',
|
||||
options: const [
|
||||
OptionData(key: Key('SkinStandardColor1ID'), title: '#0D70D1'),
|
||||
OptionData(key: Key('SkinStandardColor2ID'), title: '#000000'),
|
||||
OptionData(key: Key('SkinStandardColor3ID'), title: '#FFFFFF')
|
||||
]
|
||||
)
|
||||
];
|
||||
|
||||
static final playbackOptions = [
|
||||
const OptionData(key: Key('PlaybackOptionAutostartID'), title: 'Автостарт'),
|
||||
OptionDataContainer(
|
||||
key: const Key('PlaybackOptionVolumeID'),
|
||||
title: 'Громкость',
|
||||
options: const [
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume00ID'), '0.0'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume01ID'), '0.1'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume02ID'), '0.2'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume03ID'), '0.3'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume04ID'), '0.4'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume05ID'), '0.5'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume06ID'), '0.6'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume07ID'), '0.7'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume08ID'), '0.8'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume09ID'), '0.9'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume10ID'), '1.0')
|
||||
],
|
||||
onSelectedOption: (option) => VolumeChangedEvent(option)
|
||||
),
|
||||
OptionDataContainer(
|
||||
key: const Key('PlaybackOptionBrightnessID'),
|
||||
title: 'Яркость',
|
||||
options: const [
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume00ID'), '0.0'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume01ID'), '0.1'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume02ID'), '0.2'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume03ID'), '0.3'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume04ID'), '0.4'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume05ID'), '0.5'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume06ID'), '0.6'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume07ID'), '0.7'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume08ID'), '0.8'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume09ID'), '0.9'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionVolume10ID'), '1.0')
|
||||
],
|
||||
onSelectedOption: (option) => BrightnessChangedEvent(option)
|
||||
),
|
||||
OptionDataContainer(
|
||||
key: const Key('PlaybackOptionSpeedID'),
|
||||
title: 'Скорость',
|
||||
options: const [
|
||||
OptionData(key: Key('PlaybackOptionSpeed025xID'), title: '0.25x', value: '0.25'),
|
||||
OptionData(key: Key('PlaybackOptionSpeed05xID'), title: '0.5x', value: '0.5'),
|
||||
OptionData(key: Key('PlaybackOptionSpeed075xID'), title: '0.75x', value: '0.75'),
|
||||
OptionData(key: Key('PlaybackOptionSpeedNormalID'), title: 'Обычная', value: '1.0'),
|
||||
OptionData(key: Key('PlaybackOptionSpeed125xID'), title: '1.25x', value: '1.25'),
|
||||
OptionData(key: Key('PlaybackOptionSpeed15xID'), title: '1.5x', value: '1.5'),
|
||||
OptionData(key: Key('PlaybackOptionSpeed175xID'), title: '1.75x', value: '1.75'),
|
||||
OptionData(key: Key('PlaybackOptionSpeed2xID'), title: '2x', value: '2.0')
|
||||
],
|
||||
onSelectedOption: (option) => SpeedChangedEvent(option)
|
||||
),
|
||||
OptionDataContainer(
|
||||
key: const Key('PlaybackOptionQualityID'),
|
||||
title: 'Качество',
|
||||
options: const [
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionQualityAutoID'), 'Авто'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionQuality4kID'), '4K'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionQuality1440pID'), '1440p Ultra HD'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionQuality1080pID'), '1080p FHD'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionQuality720pID'), '720p HD'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionQuality480pID'), '480p'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionQuality360pID'), '360p'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionQuality240pID'), '240p'),
|
||||
OptionData.withValueEqualTitle(Key('PlaybackOptionQuality144pID'), '144p')
|
||||
]
|
||||
),
|
||||
OptionDataContainer(
|
||||
key: const Key('PlaybackOptionQualityNamingID'),
|
||||
title: 'Название качества',
|
||||
options: const [
|
||||
OptionData(key: Key('PlaybackOptionQualityNameCommonID'), title: 'Common'),
|
||||
OptionData(key: Key('PlaybackOptionQualityNameRusID'), title: 'Russian'),
|
||||
OptionData(key: Key('PlaybackOptionQualityNameEngID'), title: 'English'),
|
||||
OptionData(key: Key('PlaybackOptionQualityNameResolutionID'), title: 'Resolution')
|
||||
]
|
||||
),
|
||||
const OptionData(key: Key('PlaybackOptionSubtitlesID'), title: 'Субтитры', isSelected: true),
|
||||
const NumericOptionData(key: Key('PlaybackOptionStartPositionID'), title: 'Стартовая позиция', value: 0)
|
||||
];
|
||||
|
||||
static const extraOption = OptionData(key: Key('ExtraOptionLoopID'), title: 'Зацикленность');
|
||||
|
||||
static const timeoutsOptions = [
|
||||
NumericOptionData(key: Key('TimeoutsOptionManifestID'), title: 'Манифест (мс)', value: 5000),
|
||||
NumericOptionData(key: Key('TimeoutsOptionTrackID'), title: 'Трек (мс)', value: 3000),
|
||||
NumericOptionData(key: Key('TimeoutsOptionChunkID'), title: 'Сегмент (мс)', value: 3000)
|
||||
];
|
||||
|
||||
static const logOptions = {
|
||||
"LogType.off": OptionData(key: Key('LogOptionOffId'), title: 'Выкл.'),
|
||||
"LogType.info": OptionData(key: Key('LogOptionInfoID'), title: 'Инфо.'),
|
||||
"LogType.debug": OptionData(key: Key('LogOptionDebugID'), title: 'Отладка')
|
||||
};
|
||||
}
|
||||
|
||||
+93
-200
@@ -1,124 +1,18 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:nut_player_example/src/common/models/option_data.dart';
|
||||
import 'package:nut_player_example/src/common/views/checkmark_list_option.dart';
|
||||
//import 'package:nut_player_example/src/common/views/checkmark_list_option.dart';
|
||||
import 'package:nut_player_example/src/common/views/input_view.dart';
|
||||
//import 'package:nut_player_example/src/common/views/options_view.dart';
|
||||
import 'package:nut_player_example/src/features/settings_screen/domain/settings_bloc.dart';
|
||||
import 'package:nut_player_example/src/common/views/options_view.dart';
|
||||
import 'package:nut_player_example/src/features/settings_screen/presentation/toggle_view.dart';
|
||||
//import 'package:nut_player_example/src/features/settings_screen/presentation/toggle_view.dart';
|
||||
|
||||
enum LogType { off, info, debug }
|
||||
class SettingsView extends StatelessWidget {
|
||||
|
||||
class SettingsView extends StatefulWidget {
|
||||
const SettingsView({super.key});
|
||||
|
||||
@override
|
||||
State<SettingsView> createState() => _SettingsViewState();
|
||||
}
|
||||
|
||||
class _SettingsViewState extends State<SettingsView> {
|
||||
// final List<OptionData> _skinOptions = const [
|
||||
// OptionData(key: Key('SkinOptionDefaultID'), title: 'По умолчанию', isSelected: true),
|
||||
// OptionData(key: Key('SkinOptionByUserID'), title: 'Свой')
|
||||
// ];
|
||||
//
|
||||
// final List<OptionData> _standardSkinOptions = const [
|
||||
// OptionData(key: Key('SkinStandardOptionFullscreenID'), title: 'Полноэкранный режим'),
|
||||
// OptionData(key: Key('SkinStandardOptionPipID'), title: 'Картинка в картинке', isSelected: true),
|
||||
// OptionData(key: Key('SkinStandardOptionSettingsID'), title: 'Настройки', isSelected: true),
|
||||
// OptionData(key: Key('SkinStandardOptionColorID'), title: 'Цвет')
|
||||
// ];
|
||||
|
||||
// final List<OptionData> _fullscreen = const [
|
||||
// OptionData(key: Key('SkinStandardFullscreenAlbumID'), title: 'Альбомный', isSelected: true),
|
||||
// OptionData(key: Key('SkinStandardFullscreenFlexID'), title: 'Гибкий'),
|
||||
// OptionData(key: Key('SkinStandardFullscreenOffID'), title: 'Выкл.')
|
||||
// ];
|
||||
//
|
||||
// final List<OptionData> _colors = const [
|
||||
// OptionData(key: Key('SkinStandardColor1ID'), title: '#0D70D1', isSelected: true),
|
||||
// OptionData(key: Key('SkinStandardColor2ID'), title: '#000000'),
|
||||
// OptionData(key: Key('SkinStandardColor3ID'), title: '#FFFFFF')
|
||||
// ];
|
||||
|
||||
// final List<OptionData> _playbackOptions = const [
|
||||
// OptionData(key: Key('PlaybackOptionAutostartID'), title: 'Автостарт'),
|
||||
// OptionData(key: Key('PlaybackOptionVolumeID'), title: 'Громкость'),
|
||||
// OptionData(key: Key('PlaybackOptionBrightnessID'), title: 'Яркость'),
|
||||
// OptionData(key: Key('PlaybackOptionSpeedID'), title: 'Скорость'),
|
||||
// OptionData(key: Key('PlaybackOptionQualityNamingID'), title: 'Название качества'),
|
||||
// OptionData(key: Key('PlaybackOptionQualityID'), title: 'Качество'),
|
||||
// OptionData(key: Key('PlaybackOptionSubtitlesID'), title: 'Субтитры', isSelected: true)
|
||||
// ];
|
||||
|
||||
//final NumericOptionData _startPositionOption = const NumericOptionData(key: Key('PlaybackOptionStartPositionID'), title: 'Стартовая позиция', value: 0);
|
||||
|
||||
//final OptionData _extraOption = const OptionData(key: Key('ExtraOptionLoopID'), title: 'Зацикленность');
|
||||
|
||||
LogType _currentLogType = LogType.info;
|
||||
|
||||
// final List<OptionData> _volumeOptions = const [
|
||||
// OptionData(key: Key('PlaybackOptionVolume00ID'), title: '0.0'),
|
||||
// OptionData(key: Key('PlaybackOptionVolume01ID'), title: '0.1'),
|
||||
// OptionData(key: Key('PlaybackOptionVolume02ID'), title: '0.2'),
|
||||
// OptionData(key: Key('PlaybackOptionVolume03ID'), title: '0.3'),
|
||||
// OptionData(key: Key('PlaybackOptionVolume04ID'), title: '0.4'),
|
||||
// OptionData(key: Key('PlaybackOptionVolume05ID'), title: '0.5', isSelected: true),
|
||||
// OptionData(key: Key('PlaybackOptionVolume06ID'), title: '0.6'),
|
||||
// OptionData(key: Key('PlaybackOptionVolume07ID'), title: '0.7'),
|
||||
// OptionData(key: Key('PlaybackOptionVolume08ID'), title: '0.8'),
|
||||
// OptionData(key: Key('PlaybackOptionVolume09ID'), title: '0.9'),
|
||||
// OptionData(key: Key('PlaybackOptionVolume10ID'), title: '1.0')
|
||||
// ];
|
||||
|
||||
// final List<OptionData> _brightnessOptions = const [
|
||||
// OptionData(key: Key('PlaybackOptionBrightness00ID'), title: '0.0'),
|
||||
// OptionData(key: Key('PlaybackOptionBrightness01ID'), title: '0.1'),
|
||||
// OptionData(key: Key('PlaybackOptionBrightness02ID'), title: '0.2'),
|
||||
// OptionData(key: Key('PlaybackOptionBrightness03ID'), title: '0.3'),
|
||||
// OptionData(key: Key('PlaybackOptionBrightness04ID'), title: '0.4'),
|
||||
// OptionData(key: Key('PlaybackOptionBrightness05ID'), title: '0.5', isSelected: true),
|
||||
// OptionData(key: Key('PlaybackOptionBrightness06ID'), title: '0.6'),
|
||||
// OptionData(key: Key('PlaybackOptionBrightness07ID'), title: '0.7'),
|
||||
// OptionData(key: Key('PlaybackOptionBrightness08ID'), title: '0.8'),
|
||||
// OptionData(key: Key('PlaybackOptionBrightness09ID'), title: '0.9'),
|
||||
// OptionData(key: Key('PlaybackOptionBrightness10ID'), title: '1.0')
|
||||
// ];
|
||||
|
||||
// final List<OptionData> _speedOptions = const [
|
||||
// OptionData(key: Key('PlaybackOptionSpeed025xID'), title: '0.25x'),
|
||||
// OptionData(key: Key('PlaybackOptionSpeed05xID'), title: '0.5x'),
|
||||
// OptionData(key: Key('PlaybackOptionSpeed075xID'), title: '0.75x'),
|
||||
// OptionData(key: Key('PlaybackOptionSpeedNormalID'), title: 'Обычная', isSelected: true),
|
||||
// OptionData(key: Key('PlaybackOptionSpeed125xID'), title: '1.25x'),
|
||||
// OptionData(key: Key('PlaybackOptionSpeed15xID'), title: '1.5x'),
|
||||
// OptionData(key: Key('PlaybackOptionSpeed175xID'), title: '1.75x'),
|
||||
// OptionData(key: Key('PlaybackOptionSpeed2xID'), title: '2x'),
|
||||
// ];
|
||||
|
||||
// final List<OptionData> _qualityOptions = const [
|
||||
// OptionData(key: Key('PlaybackOptionQualityAutoID'), title: 'Авто', isSelected: true),
|
||||
// OptionData(key: Key('PlaybackOptionQuality4kID'), title: '4K'),
|
||||
// OptionData(key: Key('PlaybackOptionQuality1440pID'), title: '1440p Ultra HD'),
|
||||
// OptionData(key: Key('PlaybackOptionQuality1080pID'), title: '1080p FHD'),
|
||||
// OptionData(key: Key('PlaybackOptionQuality720pID'), title: '720p HD'),
|
||||
// OptionData(key: Key('PlaybackOptionQuality480pID'), title: '480p'),
|
||||
// OptionData(key: Key('PlaybackOptionQuality360pID'), title: '360p'),
|
||||
// OptionData(key: Key('PlaybackOptionQuality240pID'), title: '240p'),
|
||||
// OptionData(key: Key('PlaybackOptionQuality144pID'), title: '144p')
|
||||
// ];
|
||||
|
||||
// final List<OptionData> _qualityNamingOptions = const [
|
||||
// OptionData(key: Key('PlaybackOptionQualityNameCommonID'), title: 'Common', isSelected: true),
|
||||
// OptionData(key: Key('PlaybackOptionQualityNameRusID'), title: 'Russian'),
|
||||
// OptionData(key: Key('PlaybackOptionQualityNameEngID'), title: 'English'),
|
||||
// OptionData(key: Key('PlaybackOptionQualityNameResolutionID'), title: 'Resolution')
|
||||
// ];
|
||||
|
||||
final List<NumericOptionData> _timeoutsOptions = const [
|
||||
NumericOptionData(key: Key('TimeoutsOptionManifestID'), title: 'Манифест (мс)', value: 5000),
|
||||
NumericOptionData(key: Key('TimeoutsOptionTrackID'), title: 'Трек (мс)', value: 3000),
|
||||
NumericOptionData(key: Key('TimeoutsOptionChunkID'), title: 'Сегмент (мс)', value: 3000)
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CupertinoPageScaffold(
|
||||
@@ -128,14 +22,20 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
middle: const Text('Настройки', style: TextStyle(decoration: TextDecoration.none, color: CupertinoColors.black, fontWeight: FontWeight.w600)),
|
||||
leading: CupertinoNavigationBarBackButton(
|
||||
previousPageTitle: 'Назад',
|
||||
onPressed: () { Navigator.of(context).pop(); }
|
||||
onPressed: () {
|
||||
final bloc = context.read<SettingsBloc>();
|
||||
bloc.add(DismissEvent());
|
||||
}
|
||||
),
|
||||
padding: const EdgeInsetsDirectional.all(0),
|
||||
backgroundColor: CupertinoColors.white,
|
||||
),
|
||||
child: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
child: BlocBuilder<SettingsBloc, SettingsState>(
|
||||
builder: (context, state) {
|
||||
final bloc = context.read<SettingsBloc>();
|
||||
return Column(
|
||||
children: [
|
||||
// НАСТРОЙКИ СКИНА
|
||||
CupertinoListSection.insetGrouped(
|
||||
@@ -146,12 +46,11 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
style: const TextStyle(decoration: TextDecoration.none, color: CupertinoColors.systemGrey, fontSize: 13, fontWeight: FontWeight.w400)
|
||||
),
|
||||
),
|
||||
children: const []
|
||||
// <Widget>[..._skinOptions.map((value) {
|
||||
// return CheckmarkListOption(
|
||||
// value, false, () {},
|
||||
// );
|
||||
// }).toList()]
|
||||
children: <Widget>[...SettingsInitialState.skinSettings.map((value) {
|
||||
return CheckmarkListOption(
|
||||
value, value.isSelected, () {},
|
||||
);
|
||||
}).toList()]
|
||||
),
|
||||
|
||||
// НАСТРОЙКИ СТАНДАРТНОГО СКИНА
|
||||
@@ -163,16 +62,7 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
style: const TextStyle(decoration: TextDecoration.none, color: CupertinoColors.systemGrey, fontSize: 13, fontWeight: FontWeight.w400)
|
||||
),
|
||||
),
|
||||
children: const []
|
||||
//<Widget>[..._standardSkinOptions.map((value) {
|
||||
// if (value.key == const Key('SkinStandardOptionFullscreenID')) {
|
||||
// return OptionsView(value.title, _fullscreen);
|
||||
// } else if (value.key == const Key('SkinStandardOptionColorID')) {
|
||||
// return OptionsView(value.title, _colors);
|
||||
// } else {
|
||||
//return ToggleView(value);
|
||||
// }
|
||||
//}).toList()]
|
||||
children: _buildSettingsWidgets(SettingsInitialState.standardSkinSettings, bloc)
|
||||
),
|
||||
|
||||
// ВОСПРОИЗВЕДЕНИЕ
|
||||
@@ -184,26 +74,7 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
style: const TextStyle(decoration: TextDecoration.none, color: CupertinoColors.systemGrey, fontSize: 13, fontWeight: FontWeight.w400)
|
||||
),
|
||||
),
|
||||
children: const []
|
||||
//<Widget>[..._playbackOptions.map((value) {
|
||||
// if (value.key == const Key('PlaybackOptionVolumeID')) {
|
||||
// return OptionsView(value.title, _volumeOptions);
|
||||
// } else if (value.key == const Key('PlaybackOptionBrightnessID')) {
|
||||
// return OptionsView(value.title, _brightnessOptions);
|
||||
// } else if (value.key == const Key('PlaybackOptionSpeedID')) {
|
||||
// return OptionsView(value.title, _speedOptions);
|
||||
// } else if (value.key == const Key('PlaybackOptionQualityID')) {
|
||||
// return OptionsView(value.title, _qualityOptions);
|
||||
// } else if (value.key == const Key('PlaybackOptionQualityNamingID')) {
|
||||
// return OptionsView(value.title, _qualityNamingOptions);
|
||||
// } else if (value.key == const Key('PlaybackOptionStartPositionID')) {
|
||||
// return ToggleView(value);
|
||||
// } else {
|
||||
//return ToggleView(value);
|
||||
// }
|
||||
//}).toList()
|
||||
//+ [InputView(_startPositionOption)]
|
||||
//]
|
||||
children: _buildSettingsWidgets(SettingsInitialState.playbackOptions, bloc)
|
||||
),
|
||||
|
||||
// ДОПОЛНИТЕЛЬНО
|
||||
@@ -221,7 +92,7 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
style: TextStyle(decoration: TextDecoration.none, color: CupertinoColors.systemGrey, fontSize: 12, fontWeight: FontWeight.w400)
|
||||
),
|
||||
),
|
||||
children: const []//[ToggleView(_extraOption)]
|
||||
children: const [ToggleView(SettingsInitialState.extraOption)]
|
||||
),
|
||||
|
||||
// ЗАДЕРЖКИ
|
||||
@@ -233,7 +104,7 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
style: const TextStyle(decoration: TextDecoration.none, color: CupertinoColors.systemGrey, fontSize: 13, fontWeight: FontWeight.w400)
|
||||
),
|
||||
),
|
||||
children: <Widget>[..._timeoutsOptions.map((value) {
|
||||
children: <Widget>[...SettingsInitialState.timeoutsOptions.map((value) {
|
||||
return InputView(value);
|
||||
}).toList()]
|
||||
),
|
||||
@@ -254,52 +125,7 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
color: CupertinoColors.systemGrey3,
|
||||
border: Border.all(color: CupertinoColors.systemGrey3)
|
||||
),
|
||||
child: CupertinoSlidingSegmentedControl<LogType>(
|
||||
backgroundColor: CupertinoColors.extraLightBackgroundGray,
|
||||
groupValue: _currentLogType,
|
||||
onValueChanged: (LogType? value) {
|
||||
if (value != null) {
|
||||
setState(() {
|
||||
_currentLogType = value;
|
||||
});
|
||||
}
|
||||
},
|
||||
children: const <LogType, Widget>{
|
||||
LogType.off: Padding(
|
||||
key: Key('LogOffSegmentElementID'),
|
||||
padding: EdgeInsets.symmetric(vertical: 6),
|
||||
child: Text('Выкл.',
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.none,
|
||||
fontSize: 16,
|
||||
color: CupertinoColors.black,
|
||||
fontWeight: FontWeight.normal)
|
||||
),
|
||||
),
|
||||
LogType.info: Padding(
|
||||
key: Key('LogInfoSegmentElementID'),
|
||||
padding: EdgeInsets.symmetric(vertical: 6),
|
||||
child: Text('Инфо',
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.none,
|
||||
fontSize: 16,
|
||||
color: CupertinoColors.black,
|
||||
fontWeight: FontWeight.normal)
|
||||
),
|
||||
),
|
||||
LogType.debug: Padding(
|
||||
key: Key('LogDebugSegmentElementID'),
|
||||
padding: EdgeInsets.symmetric(vertical: 6),
|
||||
child: Text('Отладка',
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.none,
|
||||
fontSize: 16,
|
||||
color: CupertinoColors.black,
|
||||
fontWeight: FontWeight.normal)
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
child: _buildLog(context)
|
||||
),
|
||||
]
|
||||
),
|
||||
@@ -322,7 +148,10 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
||||
child: const Text('Проверка падения приложения',
|
||||
style: TextStyle(decoration: TextDecoration.none, color: CupertinoColors.black, fontSize: 17, fontWeight: FontWeight.w400)),
|
||||
onPressed: (){ final value = const []; print(value[7]); }
|
||||
onPressed: () {
|
||||
const value = [];
|
||||
value[7];
|
||||
}
|
||||
)
|
||||
)
|
||||
]
|
||||
@@ -335,9 +164,73 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
style: TextStyle(decoration: TextDecoration.none, color: CupertinoColors.systemGrey, fontSize: 13, fontWeight: FontWeight.w400))
|
||||
)
|
||||
]
|
||||
)
|
||||
);
|
||||
},
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _buildSettingsWidgets(List<Object> objects, SettingsBloc bloc) {
|
||||
return <Widget>[...objects.map((setting) {
|
||||
if (setting is OptionDataContainer) {
|
||||
final selectedIndex = bloc.selectedIndex(setting);
|
||||
return OptionsView(
|
||||
setting.title,
|
||||
setting.options,
|
||||
selectedIndex,
|
||||
(selectedIndex) {
|
||||
final selectedOption = setting.options[selectedIndex];
|
||||
final event = setting.onSelectedOption?.call(selectedOption);
|
||||
if (event != null) {
|
||||
bloc.add(event);
|
||||
}
|
||||
},
|
||||
key: setting.key,
|
||||
);
|
||||
} else if (setting is OptionData) {
|
||||
return ToggleView(setting);
|
||||
} else if (setting is NumericOptionData) {
|
||||
return InputView(setting);
|
||||
} else {
|
||||
return const Text('not implemented');
|
||||
}
|
||||
}).toList()];
|
||||
}
|
||||
|
||||
Widget? _buildLog(BuildContext context) {
|
||||
final bloc = context.read<SettingsBloc>();
|
||||
final settingsState = bloc.state;
|
||||
if (settingsState is! SettingsInitialState) { return null; }
|
||||
|
||||
return CupertinoSlidingSegmentedControl<LogType>(
|
||||
backgroundColor: CupertinoColors.extraLightBackgroundGray,
|
||||
groupValue: settingsState.log,
|
||||
onValueChanged: (LogType? value) {
|
||||
if (value != null) {
|
||||
// менять состояние
|
||||
}
|
||||
},
|
||||
children: <LogType, Widget>{
|
||||
LogType.off: _buildLogSegment(SettingsInitialState.logOptions[LogType.off.toString()]!),
|
||||
LogType.info: _buildLogSegment(SettingsInitialState.logOptions[LogType.info.toString()]!),
|
||||
LogType.debug: _buildLogSegment(SettingsInitialState.logOptions[LogType.debug.toString()]!),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Padding _buildLogSegment(OptionData data) {
|
||||
return Padding(
|
||||
key: data.key,
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
child: Text(data.title,
|
||||
style: const TextStyle(
|
||||
decoration: TextDecoration.none,
|
||||
fontSize: 16,
|
||||
color: CupertinoColors.black,
|
||||
fontWeight: FontWeight.normal)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user