💄 Adjust UI
This commit is contained in:
@@ -23,6 +23,11 @@ class MyApp extends StatelessWidget {
|
|||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
),
|
),
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
darkTheme: ThemeData(
|
darkTheme: ThemeData(
|
||||||
colorScheme: ColorScheme.fromSeed(
|
colorScheme: ColorScheme.fromSeed(
|
||||||
@@ -30,6 +35,11 @@ class MyApp extends StatelessWidget {
|
|||||||
brightness: Brightness.dark,
|
brightness: Brightness.dark,
|
||||||
),
|
),
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
themeMode: ThemeMode.system,
|
themeMode: ThemeMode.system,
|
||||||
home: const Shell(),
|
home: const Shell(),
|
||||||
|
|||||||
@@ -458,6 +458,7 @@ class LibraryScreen extends HookConsumerWidget {
|
|||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: const Text('Edit Track'),
|
title: const Text('Edit Track'),
|
||||||
content: Column(
|
content: Column(
|
||||||
|
spacing: 16,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
TextField(
|
TextField(
|
||||||
|
|||||||
@@ -23,25 +23,25 @@ class PlayerScreen extends HookConsumerWidget {
|
|||||||
final tabController = useTabController(initialLength: 2);
|
final tabController = useTabController(initialLength: 2);
|
||||||
final isMobile = MediaQuery.sizeOf(context).width <= 640;
|
final isMobile = MediaQuery.sizeOf(context).width <= 640;
|
||||||
|
|
||||||
return Scaffold(
|
return StreamBuilder<Playlist>(
|
||||||
body: Stack(
|
stream: player.stream.playlist,
|
||||||
children: [
|
initialData: player.state.playlist,
|
||||||
// Main content (StreamBuilder)
|
builder: (context, snapshot) {
|
||||||
StreamBuilder<Playlist>(
|
final index = snapshot.data?.index ?? 0;
|
||||||
stream: player.stream.playlist,
|
final medias = snapshot.data?.medias ?? [];
|
||||||
initialData: player.state.playlist,
|
if (medias.isEmpty || index < 0 || index >= medias.length) {
|
||||||
builder: (context, snapshot) {
|
return const Center(child: Text('No media selected'));
|
||||||
final index = snapshot.data?.index ?? 0;
|
}
|
||||||
final medias = snapshot.data?.medias ?? [];
|
final media = medias[index];
|
||||||
if (medias.isEmpty || index < 0 || index >= medias.length) {
|
|
||||||
return const Center(child: Text('No media selected'));
|
|
||||||
}
|
|
||||||
final media = medias[index];
|
|
||||||
final path = Uri.decodeFull(Uri.parse(media.uri).path);
|
|
||||||
|
|
||||||
final metadataAsync = ref.watch(trackMetadataProvider(path));
|
final path = Uri.decodeFull(Uri.parse(media.uri).path);
|
||||||
|
final metadataAsync = ref.watch(trackMetadataProvider(path));
|
||||||
|
|
||||||
return Builder(
|
return Scaffold(
|
||||||
|
body: Stack(
|
||||||
|
children: [
|
||||||
|
// Main content (StreamBuilder)
|
||||||
|
Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
return Padding(
|
return Padding(
|
||||||
@@ -65,41 +65,45 @@ class PlayerScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
// IconButton
|
|
||||||
Positioned(
|
|
||||||
top: MediaQuery.of(context).padding.top + 16,
|
|
||||||
left: 16,
|
|
||||||
child: IconButton(
|
|
||||||
icon: const Icon(Icons.keyboard_arrow_down),
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
iconSize: 24,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// TabBar (if mobile)
|
|
||||||
if (isMobile)
|
|
||||||
Positioned(
|
|
||||||
top: MediaQuery.of(context).padding.top + 14,
|
|
||||||
left: 54,
|
|
||||||
right: 54,
|
|
||||||
child: TabBar(
|
|
||||||
controller: tabController,
|
|
||||||
tabAlignment: TabAlignment.fill,
|
|
||||||
tabs: const [
|
|
||||||
Tab(text: 'Cover'),
|
|
||||||
Tab(text: 'Lyrics'),
|
|
||||||
],
|
|
||||||
dividerHeight: 0,
|
|
||||||
indicatorColor: Colors.transparent,
|
|
||||||
overlayColor: WidgetStatePropertyAll(Colors.transparent),
|
|
||||||
splashFactory: NoSplash.splashFactory,
|
|
||||||
),
|
),
|
||||||
),
|
// IconButton
|
||||||
],
|
Positioned(
|
||||||
),
|
top: MediaQuery.of(context).padding.top + 16,
|
||||||
|
left: 16,
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(Icons.keyboard_arrow_down),
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
iconSize: 24,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// TabBar (if mobile)
|
||||||
|
if (isMobile)
|
||||||
|
Positioned(
|
||||||
|
top: MediaQuery.of(context).padding.top + 14,
|
||||||
|
left: 54,
|
||||||
|
right: 54,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
child: TabBar(
|
||||||
|
controller: tabController,
|
||||||
|
tabAlignment: TabAlignment.fill,
|
||||||
|
tabs: const [
|
||||||
|
Tab(text: 'Cover'),
|
||||||
|
Tab(text: 'Lyrics'),
|
||||||
|
],
|
||||||
|
dividerHeight: 0,
|
||||||
|
indicatorColor: Colors.transparent,
|
||||||
|
overlayColor: WidgetStatePropertyAll(Colors.transparent),
|
||||||
|
splashFactory: NoSplash.splashFactory,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_LyricsRefreshButton(trackPath: path),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -370,36 +374,26 @@ class _PlayerLyrics extends HookConsumerWidget {
|
|||||||
final lyricsData = LyricsData.fromJsonString(track.lyrics!);
|
final lyricsData = LyricsData.fromJsonString(track.lyrics!);
|
||||||
|
|
||||||
if (lyricsData.type == 'timed') {
|
if (lyricsData.type == 'timed') {
|
||||||
return Stack(
|
return _TimedLyricsView(
|
||||||
children: [
|
lyrics: lyricsData,
|
||||||
_TimedLyricsView(
|
player: player,
|
||||||
lyrics: lyricsData,
|
trackPath: trackPath!,
|
||||||
player: player,
|
|
||||||
trackPath: trackPath!,
|
|
||||||
),
|
|
||||||
_LyricsRefreshButton(trackPath: trackPath!),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Plain text lyrics
|
// Plain text lyrics
|
||||||
return Stack(
|
return ListView.builder(
|
||||||
children: [
|
padding: const EdgeInsets.all(16),
|
||||||
ListView.builder(
|
itemCount: lyricsData.lines.length,
|
||||||
padding: const EdgeInsets.all(16),
|
itemBuilder: (context, index) {
|
||||||
itemCount: lyricsData.lines.length,
|
return Padding(
|
||||||
itemBuilder: (context, index) {
|
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||||
return Padding(
|
child: Text(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
lyricsData.lines[index].text,
|
||||||
child: Text(
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
lyricsData.lines[index].text,
|
textAlign: TextAlign.center,
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
),
|
||||||
textAlign: TextAlign.center,
|
);
|
||||||
),
|
},
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_LyricsRefreshButton(trackPath: trackPath!),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user