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),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
child: Text("Append to Queue"),
|
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(
|
Padding(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_cast_framework/cast.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 {
|
class QueueRoute extends StatelessWidget {
|
||||||
final FlutterCastFramework castFramework;
|
final FlutterCastFramework castFramework;
|
||||||
|
|
@ -9,23 +11,66 @@ class QueueRoute extends StatelessWidget {
|
||||||
required this.castFramework,
|
required this.castFramework,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
Widget _getEmptyQueueMessage(BuildContext context) {
|
Widget _getEmptyQueueMessage(BuildContext context, String text) {
|
||||||
return Container(
|
return Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Text(
|
child: Text(
|
||||||
"Queue is empty!",
|
text,
|
||||||
style: Theme.of(context).textTheme.headline6,
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Queue'),
|
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"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.2"
|
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:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ dependencies:
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
cupertino_icons: ^0.1.2
|
cupertino_icons: ^0.1.2
|
||||||
|
transparent_image: ^2.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue