Skip to content

Commit

Permalink
[Presentation] Minor ui changes and improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Wolfteam committed Nov 25, 2023
1 parent b21d1a6 commit 27f8bab
Show file tree
Hide file tree
Showing 13 changed files with 176 additions and 163 deletions.
2 changes: 2 additions & 0 deletions CastIt.Client/lib/presentation/app_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,7 @@ class MyCustomScrollBehavior extends MaterialScrollBehavior {
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
PointerDeviceKind.trackpad,
PointerDeviceKind.stylus,
};
}
31 changes: 26 additions & 5 deletions CastIt.Client/lib/presentation/play/play_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class _PlayPageState extends State<PlayPage> with AutomaticKeepAliveClientMixin<
super.build(context);
return Scaffold(
body: BlocBuilder<PlayBloc, PlayState>(
builder: (ctx, state) => Column(
builder: (context, state) => Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expand All @@ -44,12 +44,33 @@ class _PlayPageState extends State<PlayPage> with AutomaticKeepAliveClientMixin<
),
),
),
const Flexible(flex: 8, fit: FlexFit.tight, child: PlayProgressBar()),
const Flexible(flex: 3, fit: FlexFit.tight, child: PlayProgressText()),
Flexible(
flex: 19,
flex: 8,
fit: FlexFit.tight,
child: PlayButtons(areDisabled: !state.maybeMap(playing: (_) => true, orElse: () => false)),
child: state.maybeMap(
playing: (state) => PlayProgressBar(duration: state.duration, currentSeconds: state.currentSeconds),
orElse: () => const PlayProgressBar(),
),
),
state.maybeMap(
playing: (state) => Flexible(
flex: 3,
fit: FlexFit.tight,
child: PlayProgressText(
currentSeconds: state.currentSeconds,
duration: state.duration,
),
),
orElse: () => const SizedBox.shrink(),
),
Flexible(
flex: state.maybeMap(playing: (_) => 19, orElse: () => 22),
fit: FlexFit.tight,
child: state.maybeMap(
fileLoading: (state) => const PlayButtons.loading(),
playing: (state) => PlayButtons.playing(isPaused: state.isPaused ?? false),
orElse: () => const PlayButtons.disabled(),
),
),
],
),
Expand Down
76 changes: 61 additions & 15 deletions CastIt.Client/lib/presentation/play/widgets/play_buttons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,36 @@ class PlayButtons extends StatelessWidget {
static const double _playbackIconSizeOnMobile = 65;
static const double _playbackIconSizeDesktopOrTablet = 85;

final bool isLoading;
final bool isPlaying;
final bool isPaused;
final bool areDisabled;

const PlayButtons({this.areDisabled = false});
const PlayButtons.loading()
: isLoading = true,
isPlaying = false,
isPaused = false,
areDisabled = true;

const PlayButtons.playing({required this.isPaused})
: isLoading = false,
isPlaying = true,
areDisabled = false;

const PlayButtons.disabled()
: isLoading = false,
isPlaying = false,
isPaused = false,
areDisabled = true;

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final isDarkTheme = theme.brightness == Brightness.dark;
final iconColor = isDarkTheme ? Colors.white : Colors.black;
Color iconColor = isDarkTheme ? Colors.white : Colors.black;
if (areDisabled) {
iconColor = iconColor.withOpacity(0.5);
}
return ResponsiveBuilder(
builder: (ctx, sizing) {
final isDesktopOrTable = sizing.isDesktop || sizing.isTablet;
Expand All @@ -42,15 +63,14 @@ class PlayButtons extends StatelessWidget {
),
DecoratedBox(
decoration: BoxDecoration(
color: theme.colorScheme.secondary,
color: isPlaying ? theme.colorScheme.primary : iconColor,
borderRadius: BorderRadius.circular(50.0),
),
child: BlocBuilder<PlayBloc, PlayState>(
builder: (ctx, state) => state.maybeMap(
playing: (state) => _PlayBackButton(iconSize: playBackIconSize, isPaused: state.isPaused!, isDisabled: areDisabled),
orElse: () => _PlayBackButton(iconSize: playBackIconSize, isPaused: false, isDisabled: areDisabled),
),
),
child: isLoading
? _PlayBackButton.loading(iconSize: playBackIconSize)
: isPlaying || isPaused
? _PlayBackButton.playing(iconSize: playBackIconSize, isPaused: isPaused)
: _PlayBackButton.disabled(iconSize: playBackIconSize),
),
IconButton(
iconSize: iconSize,
Expand Down Expand Up @@ -87,20 +107,46 @@ class _PlayBackButton extends StatelessWidget {
final double iconSize;
final bool isDisabled;
final bool isPaused;
final bool isLoading;

const _PlayBackButton.disabled({required this.iconSize})
: isDisabled = true,
isPaused = false,
isLoading = false;

const _PlayBackButton.loading({required this.iconSize})
: isDisabled = false,
isPaused = false,
isLoading = true;

const _PlayBackButton({
required this.iconSize,
required this.isDisabled,
required this.isPaused,
});
const _PlayBackButton.playing({required this.iconSize, required this.isPaused})
: isDisabled = false,
isLoading = false;

@override
Widget build(BuildContext context) {
if (isLoading) {
return IconButton(
iconSize: iconSize,
onPressed: null,
icon: Stack(
alignment: Alignment.center,
children: [
const Icon(Icons.play_arrow),
SizedBox(
height: iconSize,
width: iconSize,
child: const CircularProgressIndicator(),
),
],
),
);
}
return IconButton(
iconSize: iconSize,
onPressed: isDisabled ? null : () => _togglePlayBack(context),
icon: Icon(
isPaused ? Icons.pause : Icons.play_arrow,
!isPaused && !isDisabled ? Icons.pause : Icons.play_arrow,
color: Colors.white,
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ class _Bottom extends StatelessWidget {
children: <Widget>[
IconButton(
tooltip: i18n.shufflePlayList,
icon: Icon(Icons.shuffle, color: shufflePlayList ? theme.colorScheme.secondary : Colors.white),
icon: Icon(Icons.shuffle, color: shufflePlayList ? theme.colorScheme.primary : Colors.white),
onPressed: !playListIsValid ? null : () => _togglePlayListShuffle(context),
),
Flexible(
Expand All @@ -227,7 +227,7 @@ class _Bottom extends StatelessWidget {
),
IconButton(
tooltip: i18n.loopFile,
icon: Icon(Icons.repeat, color: loopFile ? theme.colorScheme.secondary : Colors.white),
icon: Icon(Icons.repeat, color: loopFile ? theme.colorScheme.primary : Colors.white),
onPressed: !fileIdIsValid ? null : () => _toggleFileLoop(context),
),
],
Expand Down
47 changes: 24 additions & 23 deletions CastIt.Client/lib/presentation/play/widgets/play_progress_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,32 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class PlayProgressBar extends StatelessWidget {
const PlayProgressBar();
final double? duration;
final double? currentSeconds;

const PlayProgressBar({
this.duration,
this.currentSeconds,
});

@override
Widget build(BuildContext context) {
return BlocBuilder<PlayBloc, PlayState>(
builder: (ctx, state) => state.maybeMap(
playing: (state) {
if (state.duration! <= 0) {
return const _DummySlider(value: 100);
}
return Slider(
onChanged: (double value) => context.read<PlayBloc>().add(PlayEvent.sliderValueChanged(newValue: value)),
value: state.currentSeconds!,
max: state.duration!,
activeColor: Theme.of(context).colorScheme.secondary,
label: _generateLabel(state.currentSeconds!),
divisions: state.duration!.round(),
onChangeStart: (startValue) => context.read<PlayBloc>().add(PlayEvent.sliderDragChanged(isSliding: true)),
onChangeEnd: (finalValue) =>
context.read<PlayBloc>().add(PlayEvent.sliderValueChanged(newValue: finalValue.roundToDouble(), triggerGoToSeconds: true)),
);
},
orElse: () => const _DummySlider(),
),
if (duration == null) {
return const _DummySlider();
}

if (duration! <= 0) {
return const _DummySlider(value: 100);
}

return Slider(
value: currentSeconds ?? 0,
max: duration!,
label: _generateLabel(currentSeconds ?? 0),
divisions: duration!.round(),
onChangeStart: (value) => context.read<PlayBloc>().add(PlayEvent.sliderDragChanged(isSliding: true)),
onChanged: (value) => context.read<PlayBloc>().add(PlayEvent.sliderValueChanged(newValue: value)),
onChangeEnd: (value) => context.read<PlayBloc>().add(PlayEvent.sliderValueChanged(newValue: value.roundToDouble(), triggerGoToSeconds: true)),
);
}

Expand All @@ -41,7 +43,6 @@ class _DummySlider extends StatelessWidget {

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Slider(onChanged: null, value: value, max: 100, activeColor: theme.colorScheme.secondary);
return Slider(onChanged: null, value: value, max: 100);
}
}
57 changes: 25 additions & 32 deletions CastIt.Client/lib/presentation/play/widgets/play_progress_text.dart
Original file line number Diff line number Diff line change
@@ -1,43 +1,36 @@
import 'package:castit/application/bloc.dart';
import 'package:castit/domain/extensions/duration_extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class PlayProgressText extends StatelessWidget {
const PlayProgressText();
final double? currentSeconds;
final double? duration;

const PlayProgressText({
required this.currentSeconds,
required this.duration,
});

@override
Widget build(BuildContext context) {
return BlocBuilder<PlayBloc, PlayState>(
builder: (ctx, state) {
final theme = Theme.of(context);
final isDarkTheme = theme.brightness == Brightness.dark;
return state.maybeMap(
playing: (state) {
final current = Duration(seconds: (state.currentSeconds ?? 0).round()).formatDuration();
final total = Duration(seconds: state.duration!.round()).formatDuration();
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
current,
style: TextStyle(color: isDarkTheme ? Colors.white : Colors.black),
),
Text(
total,
style: TextStyle(color: isDarkTheme ? Colors.white : Colors.black),
),
],
),
);
},
orElse: () => const Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
final theme = Theme.of(context);
final isDarkTheme = theme.brightness == Brightness.dark;
final current = Duration(seconds: (currentSeconds ?? 0).round()).formatDuration();
final total = Duration(seconds: (duration ?? 0).round()).formatDuration();
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
current,
style: TextStyle(color: isDarkTheme ? Colors.white : Colors.black),
),
Text(
total,
style: TextStyle(color: isDarkTheme ? Colors.white : Colors.black),
),
);
},
],
),
);
}
}
45 changes: 21 additions & 24 deletions CastIt.Client/lib/presentation/playlist/widgets/file_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,12 @@ class _FileItemState extends State<FileItem> {
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container(
color: widget.isBeingPlayed ? theme.colorScheme.secondary.withOpacity(0.5) : null,
color: widget.isBeingPlayed ? theme.colorScheme.secondaryContainer : null,
height: widget.itemHeight,
child: ListTile(
isThreeLine: true,
selected: widget.loop,
selected: widget.isBeingPlayed,
titleAlignment: ListTileTitleAlignment.titleHeight,
leading: ItemCounter(widget.position),
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
title: _Title(name: widget.name, loop: widget.loop),
Expand Down Expand Up @@ -131,7 +132,6 @@ class _Title extends StatelessWidget {
),
const Flexible(
flex: 10,
fit: FlexFit.tight,
child: Icon(Icons.loop, size: 20),
),
],
Expand Down Expand Up @@ -178,28 +178,25 @@ class _Content extends StatelessWidget {
),
],
),
Container(
margin: const EdgeInsets.only(top: 5),
child: SliderTheme(
data: SliderTheme.of(context).copyWith(
trackHeight: 1,
minThumbSeparation: 0,
disabledActiveTrackColor: theme.colorScheme.secondary,
overlayShape: const RoundSliderThumbShape(enabledThumbRadius: .1, disabledThumbRadius: .1),
thumbColor: Colors.transparent,
thumbShape: const RoundSliderThumbShape(enabledThumbRadius: .1, disabledThumbRadius: .1),
),
child: BlocBuilder<PlayedFileItemBloc, PlayedFileItemState>(
builder: (ctx, state) => Slider(
value: state.maybeMap(
playing: (state) => state.id == id && state.playListId == playListId ? state.playedPercentage : playedPercentage,
orElse: () => playedPercentage,
),
max: 100,
activeColor: Colors.black,
inactiveColor: Colors.grey,
onChanged: null,
SliderTheme(
data: SliderTheme.of(context).copyWith(
trackHeight: 1,
minThumbSeparation: 0,
disabledActiveTrackColor: theme.colorScheme.secondary,
overlayShape: const RoundSliderThumbShape(enabledThumbRadius: .1, disabledThumbRadius: .1),
thumbColor: Colors.transparent,
thumbShape: const RoundSliderThumbShape(enabledThumbRadius: .1, disabledThumbRadius: .1),
),
child: BlocBuilder<PlayedFileItemBloc, PlayedFileItemState>(
builder: (ctx, state) => Slider(
value: state.maybeMap(
playing: (state) => state.id == id && state.playListId == playListId ? state.playedPercentage : playedPercentage,
orElse: () => playedPercentage,
),
max: 100,
activeColor: Colors.black,
inactiveColor: Colors.grey,
onChanged: null,
),
),
),
Expand Down
Loading

0 comments on commit 27f8bab

Please sign in to comment.