add horizontal-list support + ui improvements
This commit is contained in:
parent
55e7a5e7e3
commit
f7283a6633
|
@ -990,17 +990,17 @@ class HomePageSection {
|
|||
'grid-preview-two': HomePageSectionLayout.row,
|
||||
'grid': HomePageSectionLayout.grid,
|
||||
'slideshow': HomePageSectionLayout.slideshow,
|
||||
'horizontal-list': HomePageSectionLayout.horizontalList
|
||||
}[json['layout'] ?? ''];
|
||||
if (layout == null) {
|
||||
_logger.warning('UNKNOWN LAYOUT: ${json['layout']}');
|
||||
return null;
|
||||
}
|
||||
_logger.fine('LAYOUT: $layout');
|
||||
final items = <HomePageItem>[];
|
||||
for (var i in (json['items'] ?? [])) {
|
||||
HomePageItem? hpi = HomePageItem.fromPrivateJson(i);
|
||||
if (hpi != null) items.add(hpi);
|
||||
}
|
||||
_logger.fine(json['title']);
|
||||
final items = ((json['items'] ?? []) as List)
|
||||
.map((e) => HomePageItem.fromPrivateJson(e as Map))
|
||||
.whereNotNull()
|
||||
.toList(growable: false);
|
||||
return HomePageSection(
|
||||
title: json['title'],
|
||||
items: items,
|
||||
|
@ -1044,10 +1044,6 @@ class HomePageItem {
|
|||
return HomePageItem(
|
||||
type: HomePageItemType.ARTIST,
|
||||
value: Artist.fromPrivateJson(json['data']));
|
||||
case 'channel':
|
||||
return HomePageItem(
|
||||
type: HomePageItemType.CHANNEL,
|
||||
value: DeezerChannel.fromPrivateJson(json, false));
|
||||
case 'album':
|
||||
return HomePageItem(
|
||||
type: HomePageItemType.ALBUM,
|
||||
|
@ -1056,10 +1052,18 @@ class HomePageItem {
|
|||
return HomePageItem(
|
||||
type: HomePageItemType.SHOW,
|
||||
value: Show.fromPrivateJson(json['data']));
|
||||
case 'channel':
|
||||
return HomePageItem(
|
||||
type: HomePageItemType.CHANNEL,
|
||||
value: DeezerChannel.fromPrivateJson(json, false));
|
||||
case 'external-link':
|
||||
return HomePageItem(
|
||||
type: HomePageItemType.EXTERNAL_LINK,
|
||||
value: DeezerChannel.fromPrivateJson(json, true));
|
||||
case 'track':
|
||||
return HomePageItem(
|
||||
type: HomePageItemType.TRACK,
|
||||
value: Track.fromPrivateJson(json['data']));
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -1101,9 +1105,13 @@ class HomePageItem {
|
|||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
String type = describeEnum(this.type);
|
||||
String type = this.type.name;
|
||||
return {'type': type, 'value': value.toJson()};
|
||||
}
|
||||
|
||||
String toString() {
|
||||
return type.name;
|
||||
}
|
||||
}
|
||||
|
||||
@HiveType(typeId: 14)
|
||||
|
@ -1181,6 +1189,9 @@ enum HomePageItemType {
|
|||
|
||||
@HiveField(6)
|
||||
EXTERNAL_LINK,
|
||||
|
||||
@HiveField(7)
|
||||
TRACK, // for track mixes
|
||||
}
|
||||
|
||||
@HiveType(typeId: 3)
|
||||
|
@ -1193,6 +1204,10 @@ enum HomePageSectionLayout {
|
|||
/// ROW but bigger
|
||||
@HiveField(2)
|
||||
slideshow,
|
||||
|
||||
/// Homepage song radios
|
||||
@HiveField(3)
|
||||
horizontalList,
|
||||
}
|
||||
|
||||
enum RepeatType { NONE, LIST, TRACK }
|
||||
|
|
|
@ -255,7 +255,7 @@ class AudioPlayerTask extends BaseAudioHandler {
|
|||
// listen for connectivity changes
|
||||
_subscriptions.add(Connectivity()
|
||||
.onConnectivityChanged
|
||||
.listen(_determineAudioQualityByResult));
|
||||
.listen(_determineAudioQualityByResults));
|
||||
}
|
||||
|
||||
if (shouldLoadQueue) {
|
||||
|
@ -271,7 +271,7 @@ class AudioPlayerTask extends BaseAudioHandler {
|
|||
try {
|
||||
await Connectivity()
|
||||
.checkConnectivity()
|
||||
.then(_determineAudioQualityByResult);
|
||||
.then(_determineAudioQualityByResults);
|
||||
return true;
|
||||
} catch (e) {
|
||||
_isConnectivityPluginAvailable = false;
|
||||
|
@ -282,12 +282,13 @@ class AudioPlayerTask extends BaseAudioHandler {
|
|||
_logger.warning(
|
||||
'Couldn\'t determine connection! Falling back to other (which may use wifi quality)');
|
||||
// on error, return dummy value -- error can happen on linux if not using NetworkManager, for example
|
||||
_determineAudioQualityByResult(ConnectivityResult.other);
|
||||
_determineAudioQualityByResults([ConnectivityResult.other]);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Determines the [AudioQuality] to use according to [result]
|
||||
void _determineAudioQualityByResult(ConnectivityResult result) {
|
||||
void _determineAudioQualityByResults(List<ConnectivityResult> results) {
|
||||
final result = results[0];
|
||||
switch (result) {
|
||||
case ConnectivityResult.mobile:
|
||||
case ConnectivityResult.bluetooth:
|
||||
|
|
|
@ -31,7 +31,7 @@ import 'package:freezer/ui/search.dart';
|
|||
import 'package:freezer/ui/settings_screen.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:i18n_extension/i18n_widget.dart';
|
||||
import 'package:i18n_extension/i18n_extension.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:freezer/translations.i18n.dart';
|
||||
import 'package:quick_actions/quick_actions.dart';
|
||||
|
@ -287,14 +287,15 @@ class _LoginMainWrapperState extends State<LoginMainWrapper> {
|
|||
super.initState();
|
||||
}
|
||||
|
||||
Future _logOut() async {
|
||||
Future<void> _logOut() async {
|
||||
await GetIt.instance<DeezerAPI>().logout();
|
||||
setState(() {
|
||||
settings.arl = null;
|
||||
settings.offlineMode = false;
|
||||
});
|
||||
|
||||
settings.arl = null;
|
||||
settings.offlineMode = false;
|
||||
await settings.save();
|
||||
await Cache.wipe();
|
||||
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
@ -210,7 +211,7 @@ class _HomePageWidgetState extends State<HomePageWidget> {
|
|||
return HomePageGridSection(section);
|
||||
case HomePageSectionLayout.slideshow:
|
||||
case HomePageSectionLayout.row:
|
||||
default:
|
||||
case HomePageSectionLayout.horizontalList:
|
||||
return HomepageRowSection(section);
|
||||
}
|
||||
}
|
||||
|
@ -243,72 +244,70 @@ class _HomePageWidgetState extends State<HomePageWidget> {
|
|||
}
|
||||
}
|
||||
|
||||
class HomepageRowSection extends StatefulWidget {
|
||||
class HomepageRowSection extends StatelessWidget {
|
||||
final HomePageSection section;
|
||||
const HomepageRowSection(this.section, {super.key});
|
||||
|
||||
@override
|
||||
State<HomepageRowSection> createState() => _HomepageRowSectionState();
|
||||
}
|
||||
Widget buildChild(BuildContext context, List<HomePageItem> items) {
|
||||
return Row(
|
||||
children: items
|
||||
.map((item) => Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6.0),
|
||||
child: HomePageItemWidget(item),
|
||||
))
|
||||
.toList(growable: false));
|
||||
}
|
||||
|
||||
class _HomepageRowSectionState extends State<HomepageRowSection> {
|
||||
final _controller = ScrollController();
|
||||
List<List<T>> _sliceInNLists<T>(List<T> source, int n) {
|
||||
final List<List<T>> dest = List.generate(n, (_) => [], growable: false);
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
int i = 0;
|
||||
for (var item in source) {
|
||||
dest[i].add(item);
|
||||
if (++i == n) i = 0;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Widget child = switch (section.layout) {
|
||||
HomePageSectionLayout.horizontalList => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: _sliceInNLists(section.items!, 3)
|
||||
.map((e) => buildChild(context, e))
|
||||
.toList(growable: false)),
|
||||
_ => buildChild(context, section.items!)
|
||||
};
|
||||
return ListTile(
|
||||
title: Text(
|
||||
widget.section.title ?? '',
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w900),
|
||||
title: Text(
|
||||
section.title ?? '',
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w900),
|
||||
),
|
||||
subtitle: Scrollbar(
|
||||
thickness: MainScreen.of(context).isDesktop ? null : 1.0,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: child,
|
||||
),
|
||||
subtitle: Scrollbar(
|
||||
controller: _controller,
|
||||
thickness: MainScreen.of(context).isDesktop ? null : 1.0,
|
||||
child: SingleChildScrollView(
|
||||
controller: _controller,
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: List.generate(widget.section.items!.length + 1, (j) {
|
||||
//Has more items
|
||||
if (j == widget.section.items!.length) {
|
||||
if (widget.section.hasMore ?? false) {
|
||||
return TextButton(
|
||||
child: Text(
|
||||
'Show more'.i18n,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(fontSize: 20.0),
|
||||
),
|
||||
onPressed: () => Navigator.of(context).pushRoute(
|
||||
builder: (context) => HomePageScreen(
|
||||
title: widget.section.title!,
|
||||
channel:
|
||||
DeezerChannel(target: widget.section.pagePath),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
//Show item
|
||||
HomePageItem item = widget.section.items![j];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6.0),
|
||||
child: HomePageItemWidget(item),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
));
|
||||
),
|
||||
trailing: section.hasMore == true
|
||||
? const Icon(Icons.keyboard_arrow_right)
|
||||
: null,
|
||||
onTap: section.hasMore == true
|
||||
? () => Navigator.of(context).pushRoute(
|
||||
builder: (context) => HomePageScreen(
|
||||
title: section.title!,
|
||||
channel: DeezerChannel(target: section.pagePath),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,6 +367,7 @@ class HomePageItemWidget extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mediaQuery = MediaQuery.of(context);
|
||||
switch (item.type) {
|
||||
case HomePageItemType.SMARTTRACKLIST:
|
||||
return SmartTrackListTile(
|
||||
|
@ -444,6 +444,16 @@ class HomePageItemWidget extends StatelessWidget {
|
|||
.pushRoute(builder: (context) => ShowScreen(item.value));
|
||||
},
|
||||
);
|
||||
case HomePageItemType.TRACK:
|
||||
final track = item.value as Track;
|
||||
return TrackCardTile.fromTrack(
|
||||
track,
|
||||
onTap: () => playerHelper.playSearchMixDeferred(track),
|
||||
onSecondary: (details) =>
|
||||
MenuSheet(context).defaultTrackMenu(track, details: details),
|
||||
width:
|
||||
mediaQuery.size.width > 530 ? null : mediaQuery.size.width * 0.75,
|
||||
);
|
||||
default:
|
||||
return const SizedBox(height: 0, width: 0);
|
||||
}
|
||||
|
|
|
@ -293,7 +293,8 @@ class _LibraryTracksState extends State<LibraryTracks> {
|
|||
return;
|
||||
}
|
||||
|
||||
ConnectivityResult connectivity = await Connectivity().checkConnectivity();
|
||||
ConnectivityResult connectivity =
|
||||
(await Connectivity().checkConnectivity())[0];
|
||||
if (connectivity != ConnectivityResult.none) {
|
||||
setState(() => _loading = true);
|
||||
int pos = tracks.length;
|
||||
|
|
|
@ -96,7 +96,6 @@ class _LoginOnOtherDeviceState extends State<LoginOnOtherDevice> {
|
|||
}
|
||||
}
|
||||
|
||||
print(res);
|
||||
final data = res.data as Map;
|
||||
if (!data['ok']) {
|
||||
setState(() {
|
||||
|
|
|
@ -20,68 +20,71 @@ import 'package:url_launcher/url_launcher.dart';
|
|||
|
||||
class SliverTrackPersistentHeader extends SliverPersistentHeaderDelegate {
|
||||
final Track track;
|
||||
final double extent;
|
||||
const SliverTrackPersistentHeader(this.track, {required this.extent});
|
||||
static const kExtent = 84.0 + 16.0 * 2 + 2.0;
|
||||
const SliverTrackPersistentHeader(this.track);
|
||||
|
||||
@override
|
||||
bool shouldRebuild(oldDelegate) => false;
|
||||
|
||||
@override
|
||||
double get maxExtent => extent;
|
||||
double get maxExtent => kExtent;
|
||||
@override
|
||||
double get minExtent => extent;
|
||||
double get minExtent => kExtent;
|
||||
|
||||
@override
|
||||
Widget build(
|
||||
BuildContext context, double shrinkOffset, bool overlapsContent) {
|
||||
return DecoratedBox(
|
||||
decoration: BoxDecoration(color: Theme.of(context).cardColor),
|
||||
decoration:
|
||||
BoxDecoration(color: Theme.of(context).colorScheme.background),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 16.0),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
const SizedBox(width: 16.0),
|
||||
Semantics(
|
||||
label: "Album art".i18n,
|
||||
image: true,
|
||||
child: CachedImage(
|
||||
url: track.albumArt!.full,
|
||||
height: 128,
|
||||
width: 128,
|
||||
height: 86.0,
|
||||
width: 86.0,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 240.0,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
track.title!,
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 22.0, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
track.artistString,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
style: const TextStyle(fontSize: 20.0),
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Text(
|
||||
track.album!.title!,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
Text(track.durationString)
|
||||
],
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
track.title!,
|
||||
maxLines: 1,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
track.album!.title!,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
Text(
|
||||
track.artistString,
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -202,6 +205,7 @@ class MenuSheet {
|
|||
builder: (context, scrollController) => Material(
|
||||
type: MaterialType.card,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
borderRadius:
|
||||
const BorderRadius.vertical(top: Radius.circular(20.0)),
|
||||
child: SafeArea(
|
||||
|
@ -210,8 +214,7 @@ class MenuSheet {
|
|||
slivers: [
|
||||
SliverPersistentHeader(
|
||||
pinned: true,
|
||||
delegate: SliverTrackPersistentHeader(track,
|
||||
extent: 128.0 + 16.0 + 16.0)),
|
||||
delegate: SliverTrackPersistentHeader(track)),
|
||||
SliverList(
|
||||
delegate: SliverChildListDelegate.fixed(options
|
||||
.map((option) => ListTile(
|
||||
|
|
|
@ -369,10 +369,7 @@ class PlayerScreenDesktop extends StatelessWidget {
|
|||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||
child: PlayerScreenTopRow(
|
||||
textSize: 12.h,
|
||||
iconSize: 21.h,
|
||||
showQueueButton: false,
|
||||
),
|
||||
textSize: 12.h, iconSize: 21.h, desktopMode: true),
|
||||
),
|
||||
Flexible(
|
||||
child: ConstrainedBox(
|
||||
|
@ -1049,7 +1046,7 @@ class _BigAlbumArtState extends State<BigAlbumArt> with WidgetsBindingObserver {
|
|||
right: 16.0,
|
||||
child: LyricsButton(
|
||||
onTap: _pushLyrics,
|
||||
size: constraints.maxHeight / 20,
|
||||
size: 20.spMax,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -1121,14 +1118,15 @@ class PlayerScreenTopRow extends StatelessWidget {
|
|||
final double? iconSize;
|
||||
final double? textWidth;
|
||||
final bool short;
|
||||
final bool showQueueButton; // not needed on desktop
|
||||
const PlayerScreenTopRow(
|
||||
{super.key,
|
||||
this.textSize,
|
||||
this.iconSize,
|
||||
this.textWidth,
|
||||
this.short = false,
|
||||
this.showQueueButton = true});
|
||||
final bool desktopMode;
|
||||
const PlayerScreenTopRow({
|
||||
super.key,
|
||||
this.textSize,
|
||||
this.iconSize,
|
||||
this.textWidth,
|
||||
this.short = false,
|
||||
this.desktopMode = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -1175,20 +1173,9 @@ class PlayerScreenTopRow extends StatelessWidget {
|
|||
.copyWith(fontSize: textSize ?? 38.sp)));
|
||||
}),
|
||||
),
|
||||
showQueueButton
|
||||
? IconButton(
|
||||
icon: Icon(
|
||||
Icons.menu,
|
||||
semanticLabel: "Queue".i18n,
|
||||
),
|
||||
iconSize: size,
|
||||
splashRadius: size * 1.5,
|
||||
onPressed: () => Navigator.of(context).pushRoute(
|
||||
builder: (ctx) => QueueScreen(
|
||||
closePlayer: FancyScaffold.of(context)!.closePanel,
|
||||
)),
|
||||
)
|
||||
: SizedBox.square(dimension: size + 16.0),
|
||||
desktopMode
|
||||
? PlayerMenuButtonDesktop(size: size)
|
||||
: PlayerMenuButton(size: size)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -1329,7 +1316,19 @@ class BottomBarControls extends StatelessWidget {
|
|||
textSize: size * 0.75,
|
||||
),
|
||||
const Expanded(child: SizedBox()),
|
||||
PlayerMenuButton(size: size),
|
||||
if (!desktopMode)
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.playlist_play,
|
||||
semanticLabel: "Queue".i18n,
|
||||
),
|
||||
iconSize: size,
|
||||
splashRadius: size * 1.5,
|
||||
onPressed: () => Navigator.of(context).pushRoute(
|
||||
builder: (ctx) => QueueScreen(
|
||||
closePlayer: FancyScaffold.of(context)!.closePanel,
|
||||
)),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -1371,9 +1370,19 @@ class BottomBarControls extends StatelessWidget {
|
|||
// toastLength: Toast.LENGTH_SHORT);
|
||||
// },
|
||||
// ),
|
||||
desktopMode
|
||||
? PlayerMenuButtonDesktop(size: iconSize)
|
||||
: PlayerMenuButton(size: iconSize)
|
||||
if (!desktopMode)
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.playlist_play,
|
||||
semanticLabel: "Queue".i18n,
|
||||
),
|
||||
iconSize: size,
|
||||
splashRadius: size * 1.5,
|
||||
onPressed: () => Navigator.of(context).pushRoute(
|
||||
builder: (ctx) => QueueScreen(
|
||||
closePlayer: FancyScaffold.of(context)!.closePanel,
|
||||
)),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,102 @@ VoidCallback? normalizeSecondary(SecondaryTapCallback? callback) {
|
|||
return () => callback.call(null);
|
||||
}
|
||||
|
||||
class TrackCardTile extends StatelessWidget {
|
||||
static const _kDefaultWidth = 424.0;
|
||||
final VoidCallback onTap;
|
||||
|
||||
/// Hold or Right Click
|
||||
final SecondaryTapCallback? onSecondary;
|
||||
final Widget? trailing;
|
||||
final String trackId;
|
||||
final String title;
|
||||
final String artist;
|
||||
final String artUri;
|
||||
final bool explicit;
|
||||
|
||||
final double? width;
|
||||
|
||||
const TrackCardTile({
|
||||
required this.trackId,
|
||||
required this.title,
|
||||
required this.artist,
|
||||
required this.artUri,
|
||||
required this.explicit,
|
||||
required this.onTap,
|
||||
this.onSecondary,
|
||||
this.trailing,
|
||||
this.width,
|
||||
super.key,
|
||||
});
|
||||
|
||||
factory TrackCardTile.fromTrack(
|
||||
Track track, {
|
||||
required VoidCallback onTap,
|
||||
SecondaryTapCallback? onSecondary,
|
||||
Widget? trailing,
|
||||
double? width,
|
||||
}) =>
|
||||
TrackCardTile(
|
||||
trackId: track.id,
|
||||
title: track.title!,
|
||||
artist: track.artistString,
|
||||
artUri: track.albumArt!.thumb,
|
||||
explicit: track.explicit ?? false,
|
||||
onSecondary: onSecondary,
|
||||
onTap: onTap,
|
||||
width: width,
|
||||
trailing: trailing,
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: width ?? _kDefaultWidth,
|
||||
height: 64.0,
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
onLongPress: normalizeSecondary(onSecondary),
|
||||
onSecondaryTapUp: onSecondary,
|
||||
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
CachedImage(url: artUri),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(title, overflow: TextOverflow.ellipsis, maxLines: 1),
|
||||
Text(
|
||||
artist,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
?.copyWith(color: Theme.of(context).disabledColor),
|
||||
)
|
||||
]),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
);
|
||||
ListTile(
|
||||
title: Text(title),
|
||||
subtitle: Text(artist),
|
||||
leading: Stack(
|
||||
children: [CachedImage(url: artUri), PlayItemButton(onTap: onTap)],
|
||||
),
|
||||
contentPadding: const EdgeInsets.only(left: 16.0, right: 124.0),
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TrackTile extends StatelessWidget {
|
||||
final VoidCallback? onTap;
|
||||
|
||||
|
@ -399,21 +495,34 @@ class PlaylistCardTile extends StatelessWidget {
|
|||
class PlayItemButton extends StatelessWidget {
|
||||
final FutureOr<void> Function() onTap;
|
||||
final double size;
|
||||
const PlayItemButton({required this.onTap, this.size = 32.0, super.key});
|
||||
final bool filled;
|
||||
const PlayItemButton({
|
||||
required this.onTap,
|
||||
this.size = 32.0,
|
||||
this.filled = true,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox.square(
|
||||
dimension: size,
|
||||
child: DecoratedBox(
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle, color: Colors.white),
|
||||
decoration: filled
|
||||
? const BoxDecoration(
|
||||
shape: BoxShape.circle, color: Colors.white)
|
||||
: const BoxDecoration(),
|
||||
child: Center(
|
||||
child: AwaitingButton(
|
||||
onTap: onTap,
|
||||
child: Icon(
|
||||
Icons.play_arrow,
|
||||
color: Colors.black,
|
||||
color: filled ? Colors.black : Colors.white,
|
||||
shadows: filled
|
||||
? null
|
||||
: const [
|
||||
Shadow(blurRadius: 2.0, color: Colors.black)
|
||||
],
|
||||
size: size / 1.5,
|
||||
)))));
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import window_manager
|
|||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
AudioServicePlugin.register(with: registry.registrar(forPlugin: "AudioServicePlugin"))
|
||||
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
||||
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
|
||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||
DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
|
||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
||||
IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin"))
|
||||
|
|
122
pubspec.lock
122
pubspec.lock
|
@ -5,26 +5,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
|
||||
sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "61.0.0"
|
||||
version: "67.0.0"
|
||||
analyzer:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
|
||||
sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.13.0"
|
||||
version: "6.4.1"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
|
||||
sha256: "0763b45fa9294197a2885c8567927e2830ade852e5c896fd4ab7e0e348d0f373"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.10"
|
||||
version: "3.5.0"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -229,18 +229,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: connectivity_plus
|
||||
sha256: "224a77051d52a11fbad53dd57827594d3bd24f945af28bd70bab376d68d437f0"
|
||||
sha256: db7a4e143dc72cc3cb2044ef9b052a7ebfe729513e6a82943bc3526f784365b8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.2"
|
||||
version: "6.0.3"
|
||||
connectivity_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: connectivity_plus_platform_interface
|
||||
sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a
|
||||
sha256: b6a56efe1e6675be240de39107281d4034b64ac23438026355b4234042a35adb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.4"
|
||||
version: "2.0.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -269,10 +269,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: cross_file
|
||||
sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e
|
||||
sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.3+8"
|
||||
version: "0.3.4+1"
|
||||
crypto:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -475,10 +475,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_cache_manager
|
||||
sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba"
|
||||
sha256: "395d6b7831f21f3b989ebedbb785545932adb9afe2622c1ffacf7f4b53a7e544"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.1"
|
||||
version: "3.3.2"
|
||||
flutter_cache_manager_hive:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -508,10 +508,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
sha256: "55b9b229307a10974b26296ff29f2e132256ba4bd74266939118eaefa941cb00"
|
||||
sha256: "8cdc719114ab1c86c64bb7a86d3a679674c3637edd229e3a994797d4a1504ce4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "16.3.3"
|
||||
version: "17.1.0"
|
||||
flutter_local_notifications_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -683,10 +683,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba
|
||||
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.1"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -707,10 +707,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: i18n_extension
|
||||
sha256: "813da89a434e617e3065a5d729f148a4d2d93d227e4d1ed4e77660eda6fa58c2"
|
||||
sha256: "514fca4f34e8eb73cd29d2938225bf139b1ff3cede462c0b2875f60f470e64b2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.3"
|
||||
version: "11.0.12"
|
||||
i18n_extension_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: i18n_extension_core
|
||||
sha256: f45157bcd04d4fd88811e8e7c104a66ffbf77d16a6cf8526197c30cb78cbf1c4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.6"
|
||||
i18n_extension_importer:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -755,26 +763,26 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: isar
|
||||
sha256: "99165dadb2cf2329d3140198363a7e7bff9bbd441871898a87e26914d25cf1ea"
|
||||
url: "https://pub.dev"
|
||||
sha256: "01de08cdea6e2060987e75bdedea46f244d9657fcd0e73b4372d6309b0e60f73"
|
||||
url: "https://pub.isar-community.dev"
|
||||
source: hosted
|
||||
version: "3.1.0+1"
|
||||
version: "3.1.6"
|
||||
isar_flutter_libs:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: isar_flutter_libs
|
||||
sha256: bc6768cc4b9c61aabff77152e7f33b4b17d2fc93134f7af1c3dd51500fe8d5e8
|
||||
url: "https://pub.dev"
|
||||
sha256: "268ef3fa93f213096f34e8f7f91ad16d920b33631fbdae317f3eb29f90e95b85"
|
||||
url: "https://pub.isar-community.dev"
|
||||
source: hosted
|
||||
version: "3.1.0+1"
|
||||
version: "3.1.6"
|
||||
isar_generator:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: isar_generator
|
||||
sha256: "76c121e1295a30423604f2f819bc255bc79f852f3bc8743a24017df6068ad133"
|
||||
url: "https://pub.dev"
|
||||
sha256: d2bbd77573c60ae1eddc323a20020223ba161e5a06e84143ea659411fb73b574
|
||||
url: "https://pub.isar-community.dev"
|
||||
source: hosted
|
||||
version: "3.1.0+1"
|
||||
version: "3.1.6"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -943,6 +951,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
mini_music_visualizer:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: mini_music_visualizer
|
||||
sha256: "095b3c5e12f4c045544432829a044a7fe1c5a7789a6d0003347c73d9bf3170cc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
move_to_background:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -963,18 +979,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: network_info_plus
|
||||
sha256: "4601b815b1c6a46d84839f65cd774a7d999738471d910fae00d813e9e98b04e1"
|
||||
sha256: "5bd4b86e28fed5ed4e6ac7764133c031dfb7d3f46aa2a81b46f55038aa78ecc0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.0+1"
|
||||
version: "5.0.3"
|
||||
network_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: network_info_plus_platform_interface
|
||||
sha256: "881f5029c5edaf19c616c201d3d8b366c5b1384afd5c1da5a49e4345de82fb8b"
|
||||
sha256: "2e193d61d3072ac17824638793d3b89c6d581ce90c11604f4ca87311b42f2706"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
version: "2.0.0"
|
||||
nm:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1027,18 +1043,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79"
|
||||
sha256: "2c582551839386fa7ddbc7770658be7c0f87f388a4bff72066478f597c34d17f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.1"
|
||||
version: "7.0.0"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
|
||||
sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "3.0.0"
|
||||
palette_generator:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1171,10 +1187,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: photo_view
|
||||
sha256: "8036802a00bae2a78fc197af8a158e3e2f7b500561ed23b4c458107685e645bb"
|
||||
sha256: "1fc3d970a91295fbd1364296575f854c9863f225505c28c46e0a03e48960c75e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.14.0"
|
||||
version: "0.15.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1308,18 +1324,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: share_plus
|
||||
sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900"
|
||||
sha256: ef3489a969683c4f3d0239010cc8b7a2a46543a8d139e111c06c558875083544
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.2.2"
|
||||
version: "9.0.0"
|
||||
share_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: share_plus_platform_interface
|
||||
sha256: "251eb156a8b5fa9ce033747d73535bf53911071f8d3b6f4f0b578505ce0d4496"
|
||||
sha256: "0f9e4418835d1b2c3ae78fdb918251959106cefdbc4dd43526e182f80e82f6d4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.0"
|
||||
version: "4.0.0"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1377,10 +1393,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: spotify
|
||||
sha256: "50bd5a07b580ee441d0b4d81227185ada768332c353671aa7555ea47cc68eb9e"
|
||||
sha256: d8effb9fa14731fe98fc5d111e0e1a0aac27b34366b5dcb8db79e6dd2219c000
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.5"
|
||||
version: "0.13.6+1"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1601,10 +1617,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b
|
||||
sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
version: "2.3.1"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1649,10 +1665,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: wakelock_plus
|
||||
sha256: f268ca2116db22e57577fb99d52515a24bdc1d570f12ac18bb762361d43b043d
|
||||
sha256: c8b7cc80f045533b40a0e6c9109905494e3cf32c0fbd5c62616998e0de44003f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.4"
|
||||
version: "1.2.4"
|
||||
wakelock_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1673,18 +1689,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05"
|
||||
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.2"
|
||||
version: "0.5.1"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: "939ab60734a4f8fa95feacb55804fa278de28bdeef38e616dc08e44a84adea23"
|
||||
sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
version: "2.4.5"
|
||||
webview_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
35
pubspec.yaml
35
pubspec.yaml
|
@ -35,45 +35,45 @@ dependencies:
|
|||
path: ^1.6.4
|
||||
sqflite: ^2.0.0+3
|
||||
permission_handler: ^11.2.0
|
||||
intl: ^0.18.0
|
||||
intl: ^0.18.1
|
||||
filesize: ^2.0.1
|
||||
fluttertoast: ^8.0.8
|
||||
palette_generator: ^0.3.0
|
||||
flutter_material_color_picker: ^1.0.5
|
||||
country_pickers: ^2.0.0
|
||||
move_to_background: ^1.0.1
|
||||
flutter_local_notifications: ^16.3.2
|
||||
flutter_local_notifications: ^17.1.0
|
||||
collection: ^1.17.1
|
||||
random_string: ^2.0.1
|
||||
async: ^2.6.1
|
||||
html: ^0.15.0
|
||||
flutter_screenutil: ^5.0.0+2
|
||||
marquee: ^2.2.0
|
||||
flutter_cache_manager: ^3.0.0
|
||||
flutter_cache_manager: ^3.3.2
|
||||
cached_network_image: ^3.1.0
|
||||
i18n_extension: ^10.0.3
|
||||
i18n_extension: ^11.0.12
|
||||
url_launcher: ^6.0.5
|
||||
uni_links: ^0.5.1
|
||||
numberpicker: ^2.1.1
|
||||
quick_actions: ^1.0.5
|
||||
photo_view: ^0.14.0
|
||||
photo_view: ^0.15.0
|
||||
scrobblenaut:
|
||||
git:
|
||||
url: https://github.com/Pato05/Scrobblenaut.git
|
||||
ref: main
|
||||
open_file: ^3.0.3
|
||||
version: ^3.0.2
|
||||
wakelock_plus: ^1.1.1
|
||||
wakelock_plus: ^1.2.4
|
||||
google_fonts: ^6.1.0
|
||||
audio_session: ^0.1.6
|
||||
audio_service: ^0.18.1
|
||||
provider: ^6.0.0
|
||||
hive_flutter: ^1.1.0
|
||||
connectivity_plus: ^5.0.2
|
||||
share_plus: ^7.0.2
|
||||
connectivity_plus: ^6.0.3
|
||||
share_plus: ^9.0.0
|
||||
disk_space_plus: ^0.2.3
|
||||
dynamic_color: ^1.6.6
|
||||
package_info_plus: ^5.0.1
|
||||
package_info_plus: ^7.0.0
|
||||
encrypt: ^5.0.1
|
||||
dart_blowfish:
|
||||
git:
|
||||
|
@ -93,8 +93,12 @@ dependencies:
|
|||
audio_service_mpris: ^0.1.3
|
||||
|
||||
rxdart: ^0.27.7
|
||||
isar: ^3.1.0+1
|
||||
isar_flutter_libs: ^3.1.0+1
|
||||
isar:
|
||||
hosted: https://pub.isar-community.dev
|
||||
version: ^3.1.6
|
||||
isar_flutter_libs:
|
||||
hosted: https://pub.isar-community.dev
|
||||
version: ^3.1.6
|
||||
flutter_background_service: ^5.0.1
|
||||
dio: ^5.3.3
|
||||
dio_cookie_manager: ^3.1.1
|
||||
|
@ -102,7 +106,7 @@ dependencies:
|
|||
git: https://github.com/Pato05/flutter_cache_manager_hive.git
|
||||
flex_color_picker: ^3.3.0
|
||||
webview_flutter: ^4.4.4
|
||||
network_info_plus: ^4.1.0+1
|
||||
network_info_plus: ^5.0.3
|
||||
pointycastle: ^3.7.4
|
||||
i18n_extension_importer: ^0.0.6
|
||||
tray_manager: ^0.2.1
|
||||
|
@ -110,18 +114,21 @@ dependencies:
|
|||
get_it: ^7.6.7
|
||||
freezed_annotation:
|
||||
^2.4.1
|
||||
mini_music_visualizer: ^1.1.0
|
||||
#deezcryptor:
|
||||
#path: deezcryptor/
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
analyzer: ^5.13.0
|
||||
analyzer: ^6.4.1
|
||||
json_serializable: ^6.0.1
|
||||
build_runner: ^2.4.6
|
||||
hive_generator: ^2.0.0
|
||||
flutter_lints: ^3.0.1
|
||||
isar_generator: ^3.1.0+1
|
||||
isar_generator:
|
||||
hosted: https://pub.isar-community.dev
|
||||
version: ^3.1.0
|
||||
freezed: ^2.4.7
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
|
|
Loading…
Reference in New Issue