MediaQueue: QueueList in Example
This commit is contained in:
parent
90ae50dd28
commit
3351e5e5ab
7 changed files with 175 additions and 4 deletions
|
|
@ -223,7 +223,17 @@ class _MyAppState extends State<MyApp> {
|
|||
padding: const EdgeInsets.all(8.0),
|
||||
child: ElevatedButton(
|
||||
child: Text("Append to Queue"),
|
||||
onPressed: _hasSession ? _appendToQueue : null,
|
||||
/**
|
||||
* From the documentation:
|
||||
* The Receiver SDK maintains the queue and responds to operations
|
||||
* on the queue as long as the queue has at least one item
|
||||
* currently active (playing or paused).
|
||||
*/
|
||||
onPressed: _hasSession &&
|
||||
![PlayerState.idle, PlayerState.unknown]
|
||||
.contains(_playerState)
|
||||
? _appendToQueue
|
||||
: null,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_cast_framework/cast.dart';
|
||||
import 'package:flutter_cast_framework/widgets.dart';
|
||||
import 'package:flutter_cast_framework_example/widgets/QueueListItem.dart';
|
||||
|
||||
class QueueRoute extends StatelessWidget {
|
||||
final FlutterCastFramework castFramework;
|
||||
|
|
@ -9,23 +11,66 @@ class QueueRoute extends StatelessWidget {
|
|||
required this.castFramework,
|
||||
}) : super(key: key);
|
||||
|
||||
Widget _getEmptyQueueMessage(BuildContext context) {
|
||||
Widget _getEmptyQueueMessage(BuildContext context, String text) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
"Queue is empty!",
|
||||
text,
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _getEmptyItemMessage(BuildContext context, String text) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
text,
|
||||
style: Theme.of(context).textTheme.bodyText1,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Queue'),
|
||||
),
|
||||
body: _getEmptyQueueMessage(context),
|
||||
body: QueueList(
|
||||
castFramework: castFramework,
|
||||
listItemBuilder: (BuildContext context, MediaQueueItem item) {
|
||||
return QueueListItem(item: item);
|
||||
},
|
||||
emptyListStateBuilder: (context, isLoading, error) {
|
||||
if (isLoading) {
|
||||
return _getEmptyQueueMessage(context, "Loading...");
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
debugPrint(
|
||||
"MediaQueue - error while retrieving items count $error",
|
||||
);
|
||||
return _getEmptyQueueMessage(context, "An error occurred");
|
||||
}
|
||||
|
||||
return _getEmptyQueueMessage(context, "Queue is empty!");
|
||||
},
|
||||
emptyItemStateBuilder: (context, isLoading, error) {
|
||||
if (isLoading) {
|
||||
return _getEmptyItemMessage(context, "Loading...");
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
debugPrint(
|
||||
"MediaQueue - error while retrieving items count $error",
|
||||
);
|
||||
return _getEmptyItemMessage(context, "An error occurred");
|
||||
}
|
||||
|
||||
return _getEmptyItemMessage(context, "Item is empty!");
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
36
example/lib/widgets/QueueItemHeading.dart
Normal file
36
example/lib/widgets/QueueItemHeading.dart
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_cast_framework/cast.dart';
|
||||
|
||||
class QueueItemHeading extends StatelessWidget {
|
||||
final MediaInfo? mediaInfo;
|
||||
|
||||
const QueueItemHeading({
|
||||
Key? key,
|
||||
required this.mediaInfo,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// final titleText = mediaInfo?.mediaMetadata?.strings[MediaMetadataKey.title]
|
||||
// final subtitleText = mediaInfo?.mediaMetadata?.strings[MediaMetadataKey.subtitle]
|
||||
final titleText = "";
|
||||
final subtitleText = "";
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
titleText,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
Container(height: 2),
|
||||
Text(
|
||||
subtitleText,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
45
example/lib/widgets/QueueListItem.dart
Normal file
45
example/lib/widgets/QueueListItem.dart
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_cast_framework/cast.dart';
|
||||
import 'package:flutter_cast_framework_example/widgets/QueueItemHeading.dart';
|
||||
import 'package:flutter_cast_framework_example/widgets/Thumbnail.dart';
|
||||
|
||||
class QueueListItem extends StatelessWidget {
|
||||
final MediaQueueItem item;
|
||||
|
||||
const QueueListItem({
|
||||
Key? key,
|
||||
required this.item,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final webImage = item.media?.mediaMetadata?.webImages?.first;
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
width: 1,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Thumbnail(image: webImage),
|
||||
),
|
||||
Container(width: 10), // this is a spacer
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: QueueItemHeading(
|
||||
mediaInfo: item.media,
|
||||
),
|
||||
),
|
||||
// isCastConnected ? moreMenuButton : SizedBox.shrink(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
27
example/lib/widgets/Thumbnail.dart
Normal file
27
example/lib/widgets/Thumbnail.dart
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_cast_framework/cast.dart';
|
||||
import 'package:transparent_image/transparent_image.dart';
|
||||
|
||||
class Thumbnail extends StatelessWidget {
|
||||
final WebImage? image;
|
||||
|
||||
const Thumbnail({
|
||||
Key? key,
|
||||
required this.image,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final imageUrl = image?.url;
|
||||
|
||||
return AspectRatio(
|
||||
aspectRatio: 480.0 / 270.0,
|
||||
child: imageUrl == null
|
||||
? SizedBox.shrink()
|
||||
: FadeInImage.memoryNetwork(
|
||||
placeholder: kTransparentImage,
|
||||
image: imageUrl,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -170,6 +170,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.2"
|
||||
transparent_image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: transparent_image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ dependencies:
|
|||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^0.1.2
|
||||
transparent_image: ^2.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Reference in a new issue