Skip to content

Commit

Permalink
Bug fixes and UI work
Browse files Browse the repository at this point in the history
  • Loading branch information
WindingMotor committed Sep 22, 2024
1 parent 3908c85 commit 1779180
Show file tree
Hide file tree
Showing 18 changed files with 425 additions and 210 deletions.
6 changes: 6 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ PODS:
- DKImagePickerController/PhotoGallery
- Flutter
- Flutter (1.0.0)
- image_picker_ios (0.0.1):
- Flutter
- metadata_god (0.0.1)
- network_info_plus (0.0.1):
- Flutter
Expand Down Expand Up @@ -69,6 +71,7 @@ DEPENDENCIES:
- audioplayers_darwin (from `.symlinks/plugins/audioplayers_darwin/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- metadata_god (from `.symlinks/plugins/metadata_god/ios`)
- network_info_plus (from `.symlinks/plugins/network_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
Expand Down Expand Up @@ -96,6 +99,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/file_picker/ios"
Flutter:
:path: Flutter
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
metadata_god:
:path: ".symlinks/plugins/metadata_god/ios"
network_info_plus:
Expand All @@ -121,6 +126,7 @@ SPEC CHECKSUMS:
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
metadata_god: eceae399d0020475069a5cebc35943ce8562b5d7
network_info_plus: 9d930145451916919786087c4173226363616071
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
Expand Down
11 changes: 11 additions & 0 deletions lib/audio/nplayer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class NPlayer extends ChangeNotifier {

List<String> get playlists => PlaylistManager.playlistNames;


NServer? _server;
NServer? get server => _server;

Expand Down Expand Up @@ -521,6 +522,16 @@ class NPlayer extends ChangeNotifier {
}

// SECTION: Song Loading and Management

Future<void> setPlaylistImage(String playlistName, File imageFile) async {
await PlaylistManager.setPlaylistImage(playlistName, imageFile);
notifyListeners();
}

String? getPlaylistImagePath(String playlistName) {
return PlaylistManager.getPlaylistImagePath(playlistName);
}

Future<void> reloadSongs() async {
_log("Reloading songs");
_allSongs.clear();
Expand Down
118 changes: 71 additions & 47 deletions lib/audio/nplayer_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class NPlayerWidget extends StatefulWidget {

class _NPlayerWidgetState extends State<NPlayerWidget> {
bool _isPlayerExpanded = false;
double _swipeOffset = 0.0;

Widget _buildMarqueeText(String text) {
return LayoutBuilder(
Expand Down Expand Up @@ -253,56 +254,79 @@ IconButton(
return const SizedBox.shrink();
}

@override
Widget build(BuildContext context) {
return Consumer<NPlayer>(
builder: (context, player, child) {
final currentSong = player.getCurrentSong();
if (currentSong == null) {
return const SizedBox.shrink();
}
@override
Widget build(BuildContext context) {
return Consumer<NPlayer>(
builder: (context, player, child) {
final currentSong = player.getCurrentSong();
if (currentSong == null) {
return const SizedBox.shrink();
}

return GestureDetector(
onVerticalDragEnd: (details) {
if (details.primaryVelocity! < 0) {
// Swipe up
setState(() => _isPlayerExpanded = true);
} else if (details.primaryVelocity! > 0) {
// Swipe down
setState(() => _isPlayerExpanded = false);
return GestureDetector(
onVerticalDragEnd: (details) {
if (details.primaryVelocity! < 0) {
// Swipe up
setState(() => _isPlayerExpanded = true);
} else if (details.primaryVelocity! > 0) {
// Swipe down
setState(() => _isPlayerExpanded = false);
}
},
onHorizontalDragUpdate: (details) {
setState(() {
_swipeOffset += details.delta.dx;
_swipeOffset = _swipeOffset.clamp(-100.0, 100.0);
});
},
onHorizontalDragEnd: (details) {
if (_swipeOffset.abs() > 50) {
if (_swipeOffset > 0) {
player.previousSong();
} else {
player.nextSong();
}
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 250),
height: _isPlayerExpanded ? MediaQuery.of(context).size.height * 0.55 : 70,
margin: const EdgeInsets.symmetric(horizontal: 16.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.0),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 10,
offset: const Offset(0, 5),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Stack(
children: [
_buildBackgroundImage(player),
_isPlayerExpanded
? _buildExpandedView(player)
: Container(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: _buildSongInfo(player),
),
],
}
setState(() {
_swipeOffset = 0;
});
},
onLongPress: () {
player.togglePlayPause();
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 250),
curve: Curves.easeOutCubic,
transform: Matrix4.translationValues(_swipeOffset, 0, 0),
height: _isPlayerExpanded ? MediaQuery.of(context).size.height * 0.55 : 70,
margin: const EdgeInsets.symmetric(horizontal: 16.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.0),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 10,
offset: const Offset(0, 5),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Stack(
children: [
_buildBackgroundImage(player),
_isPlayerExpanded
? _buildExpandedView(player)
: Container(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: _buildSongInfo(player),
),
],
),
),
);
},
);
}
),
);
},
);
}
}
36 changes: 28 additions & 8 deletions lib/audio/nplaylist.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@ import 'package:blossom/tools/settings.dart';

class PlaylistManager {
static const String _playlistFileName = 'playlists.json';
static Map<String, List<String>> _playlists = {};
static Map<String, Map<String, dynamic>> _playlists = {};
static late String _playlistArtDir;

static Future<void> load() async {
final songDir = await Settings.getSongDir();
final file = File(path.join(songDir, _playlistFileName));
_playlistArtDir = path.join(songDir, 'playlistArt');

// Create playlistArt directory if it doesn't exist
await Directory(_playlistArtDir).create(recursive: true);

if (await file.exists()) {
final content = await file.readAsString();
final json = jsonDecode(content) as Map<String, dynamic>;
_playlists = json.map((key, value) => MapEntry(key, List<String>.from(value)));
_playlists = json.map((key, value) => MapEntry(key, Map<String, dynamic>.from(value)));
}
}

Expand All @@ -27,17 +32,25 @@ class PlaylistManager {
static List<String> get playlistNames => _playlists.keys.toList();

static List<String> getPlaylistSongs(String playlistName) {
return _playlists[playlistName] ?? [];
return List<String>.from(_playlists[playlistName]?['songs'] ?? []);
}

static String? getPlaylistImagePath(String playlistName) {
return _playlists[playlistName]?['imagePath'];
}

static Future<void> createPlaylist(String name) async {
static Future<void> createPlaylist(String name, {String? imagePath}) async {
if (!_playlists.containsKey(name)) {
_playlists[name] = [];
_playlists[name] = {'songs': [], 'imagePath': imagePath};
await save();
}
}

static Future<void> deletePlaylist(String name) async {
String? imagePath = _playlists[name]?['imagePath'];
if (imagePath != null) {
await File(imagePath).delete();
}
_playlists.remove(name);
await save();
}
Expand All @@ -46,16 +59,23 @@ class PlaylistManager {
if (!_playlists.containsKey(playlistName)) {
await createPlaylist(playlistName);
}
if (!_playlists[playlistName]!.contains(songName)) {
_playlists[playlistName]!.add(songName);
if (!_playlists[playlistName]!['songs'].contains(songName)) {
_playlists[playlistName]!['songs'].add(songName);
await save();
}
}

static Future<void> removeSongFromPlaylist(String playlistName, String songName) async {
if (_playlists.containsKey(playlistName)) {
_playlists[playlistName]!.remove(songName);
_playlists[playlistName]!['songs'].remove(songName);
await save();
}
}

static Future<void> setPlaylistImage(String playlistName, File imageFile) async {
String newImagePath = path.join(_playlistArtDir, '$playlistName${path.extension(imageFile.path)}');
await imageFile.copy(newImagePath);
_playlists[playlistName]!['imagePath'] = newImagePath;
await save();
}
}
Loading

0 comments on commit 1779180

Please sign in to comment.