anchor.diff:              child: InkWell(
                 onTap: () {
                   globalNavigatorKey.currentState.push(
  +                  // TODO prevent opening multiple instances
                     MaterialPageRoute(builder: (context) => QueuePage()),
                   );
                 },
  
positive.code:   final backgroundColor = theme.colorScheme.surface;
    final foregroundColor = theme.colorScheme.onSurface;
    return Container(
      color: backgroundColor,
      child: Row(
        children: [
          Padding(
            padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
            child: ListThumbnail(song.artwork),
          ),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  song.title,
                  style: theme.textTheme.subtitle2.copyWith(color: foregroundColor),
                  overflow: TextOverflow.ellipsis,
                  maxLines: 1,
                ),
                Text(
                  song.artist,
                  style: theme.textTheme.caption.copyWith(color: foregroundColor.withOpacity(0.75)),
                  overflow: TextOverflow.ellipsis,
                  maxLines: 1,
                ),
              ],
            ),
          ),
          StreamBuilder<PlaybackState>(
            stream: AudioService.playbackStateStream,
            builder: (context, snapshot) {
              bool playing = false;
              if (snapshot.hasData) {
                playing = snapshot.data.playing && snapshot.data.processingState != AudioProcessingState.completed;
              }
              return Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  // TODO add previous button
                  if (playing) pauseButton(foregroundColor) else playButton(foregroundColor),
                  nextButton(foregroundColor), // TODO grey out when cannot skip next
                ],
              );
            },
          ),
          // TODO Buffering indicator
          // TODO Progress bar
        ],
      ),
    );
  }
  
  IconButton pauseButton(Color color) => IconButton(
        icon: Icon(Icons.pause),
        onPressed: AudioService.pause,
        iconSize: 24.0,
        color: color,
      );
  
  IconButton playButton(Color color) => IconButton(
        icon: Icon(Icons.play_arrow),
        onPressed: AudioService.play,
        iconSize: 24.0,
        color: color,
      );
  
  IconButton nextButton(Color color) => IconButton(
        icon: Icon(Icons.skip_next),
        onPressed: AudioService.skipToNext,
        iconSize: 24.0,
        color: color,
      );
  
negative.code: import 'package:polaris/foreground/ui/utils/thumbnail.dart';
  import 'package:polaris/shared/dto.dart';
  import 'package:polaris/shared/media_item.dart';
  import 'package:rxdart/rxdart.dart';
  
  final getIt = GetIt.instance;
  
  class MediaState {
    final MediaItem mediaItem;
    final Duration position;
    MediaState(this.mediaItem, this.position);
  }
  
  Stream<MediaState> get _mediaStateStream => Rx.combineLatest2<MediaItem, Duration, MediaState>(
      AudioService.currentMediaItemStream,
      AudioService.positionStream,
      (mediaItem, position) => MediaState(mediaItem, position));
  
  class Player extends StatelessWidget {
    @override
  