Refactor HomePage layout to separate title and audio player bar, enhancing clarity and organization
This commit is contained in:
@@ -405,7 +405,7 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
backgroundColor: AppTheme.primaryBackground,
|
backgroundColor: AppTheme.primaryBackground,
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
// Top bar: title, audio bar (if visible), nav buttons, all in a centered row
|
// Top bar: title and nav buttons
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
@@ -417,51 +417,25 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
children: [
|
children: [
|
||||||
// Left spacer
|
// Left spacer
|
||||||
const Expanded(child: SizedBox()),
|
const Expanded(child: SizedBox()),
|
||||||
// Center: title and audio bar
|
// Center: title only
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: Row(
|
child: Builder(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
builder: (context) {
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
final screenWidth = MediaQuery.of(context).size.width;
|
||||||
children: [
|
final fontSize = screenWidth < 600 ? 24.0 : 48.0;
|
||||||
Builder(
|
return Text(
|
||||||
builder: (context) {
|
'b0esche.cloud',
|
||||||
final screenWidth = MediaQuery.of(
|
style: TextStyle(
|
||||||
context,
|
fontFamily: 'PixelatedElegance',
|
||||||
).size.width;
|
fontSize: fontSize,
|
||||||
final fontSize = screenWidth < 600 ? 24.0 : 48.0;
|
color: AppTheme.primaryText,
|
||||||
return Text(
|
decoration: TextDecoration.underline,
|
||||||
'b0esche.cloud',
|
decorationColor: AppTheme.primaryText,
|
||||||
style: TextStyle(
|
fontFeatures: const [FontFeature.slashedZero()],
|
||||||
fontFamily: 'PixelatedElegance',
|
|
||||||
fontSize: fontSize,
|
|
||||||
color: AppTheme.primaryText,
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
decorationColor: AppTheme.primaryText,
|
|
||||||
fontFeatures: const [
|
|
||||||
FontFeature.slashedZero(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (_showAudioBar &&
|
|
||||||
_audioFileName != null &&
|
|
||||||
_audioFileUrl != null) ...[
|
|
||||||
const SizedBox(width: 24),
|
|
||||||
SlideTransition(
|
|
||||||
position: _audioBarOffset,
|
|
||||||
child: AudioPlayerBar(
|
|
||||||
fileName: _audioFileName!,
|
|
||||||
fileUrl: _audioFileUrl!,
|
|
||||||
onClose: () {
|
|
||||||
_audioBarController.reverse();
|
|
||||||
setState(() => _showAudioBar = false);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
],
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Right: nav buttons
|
// Right: nav buttons
|
||||||
@@ -498,6 +472,28 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// Audio player bar (absolute, below title)
|
||||||
|
if (_showAudioBar &&
|
||||||
|
_audioFileName != null &&
|
||||||
|
_audioFileUrl != null)
|
||||||
|
Positioned(
|
||||||
|
top: 56, // adjust as needed for spacing below top bar
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: SlideTransition(
|
||||||
|
position: _audioBarOffset,
|
||||||
|
child: Center(
|
||||||
|
child: AudioPlayerBar(
|
||||||
|
fileName: _audioFileName!,
|
||||||
|
fileUrl: _audioFileUrl!,
|
||||||
|
onClose: () {
|
||||||
|
_audioBarController.reverse();
|
||||||
|
setState(() => _showAudioBar = false);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
Center(
|
Center(
|
||||||
child: BlocBuilder<AuthBloc, AuthState>(
|
child: BlocBuilder<AuthBloc, AuthState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
|
|||||||
@@ -50,11 +50,16 @@ class _AudioPlayerBarState extends State<AudioPlayerBar>
|
|||||||
Future<void> _initAudio() async {
|
Future<void> _initAudio() async {
|
||||||
try {
|
try {
|
||||||
await _audioPlayer.setUrl(widget.fileUrl);
|
await _audioPlayer.setUrl(widget.fileUrl);
|
||||||
setState(() {
|
// Wait until duration is available
|
||||||
_duration = _audioPlayer.duration ?? Duration.zero;
|
_audioPlayer.durationStream.firstWhere((d) => d != null).then((d) async {
|
||||||
_isLoading = false;
|
setState(() {
|
||||||
|
_duration = d ?? Duration.zero;
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
await _audioPlayer.play(); // Start playback automatically
|
||||||
|
// Animate play icon
|
||||||
|
if (mounted) _iconController.forward();
|
||||||
});
|
});
|
||||||
_audioPlayer.play(); // Start playback automatically
|
|
||||||
_audioPlayer.positionStream.listen((pos) {
|
_audioPlayer.positionStream.listen((pos) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_position = pos;
|
_position = pos;
|
||||||
|
|||||||
Reference in New Issue
Block a user