Skip to content

Commit

Permalink
fix: notification thumbnail & media id nullability
Browse files Browse the repository at this point in the history
  • Loading branch information
alexmercerind committed Oct 6, 2022
1 parent 823820a commit d4522d4
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 160 deletions.
57 changes: 31 additions & 26 deletions lib/api/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,33 +129,38 @@ class API {
);
final parser = Xml2Json();
parser.parse(response.body);
return jsonDecode(parser.toGData())['feed']['entry']
.map(
(e) => Event(
server,
int.parse(e['id']['raw']),
int.parse(e['category']['term'].split('/').first),
e['title']['\$t'],
e['published'] == null || e['published']['\$t'] == null
? DateTime.now()
: DateTime.parse(e['published']['\$t']),
e['updated'] == null || e['updated']['\$t'] == null
? DateTime.now()
: DateTime.parse(e['updated']['\$t']),
e['category']['term'],
int.parse(e['content']['media_id']),
Duration(
milliseconds: int.tryParse(e['content']['media_size']) ?? 0,
),
Uri.parse(
e['content']['\$t'].replaceAll(
'https://',
'https://${Uri.encodeComponent(server.login)}:${Uri.encodeComponent(server.password)}@',
return jsonDecode(parser.toGData())['feed']['entry'].map((e) {
debugPrint(e.toString());
return Event(
server,
int.parse(e['id']['raw']),
int.parse(e['category']['term'].split('/').first),
e['title']['\$t'],
e['published'] == null || e['published']['\$t'] == null
? DateTime.now()
: DateTime.parse(e['published']['\$t']),
e['updated'] == null || e['updated']['\$t'] == null
? DateTime.now()
: DateTime.parse(e['updated']['\$t']),
e['category']['term'],
!e.containsKey('content')
? null
: int.parse(e['content']['media_id']),
!e.containsKey('content')
? null
: Duration(
milliseconds: int.tryParse(e['content']['media_size']) ?? 0,
),
),
),
)
.cast<Event>();
!e.containsKey('content')
? null
: Uri.parse(
e['content']['\$t'].replaceAll(
'https://',
'https://${Uri.encodeComponent(server.login)}:${Uri.encodeComponent(server.password)}@',
),
),
);
}).cast<Event>();
} catch (exception, stacktrace) {
debugPrint(exception.toString());
debugPrint(stacktrace.toString());
Expand Down
8 changes: 5 additions & 3 deletions lib/api/api_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,11 @@ abstract class APIHelpers {
final list = events.toList();
list.removeWhere((element) => element.deviceID.toString() != deviceID);
for (int i = 0; i < list.length; i++) {
final thumbnail = await getThumbnailForMediaID(list[i].mediaID);
if (thumbnail != null) {
return thumbnail;
if (list[i].mediaID != null) {
final thumbnail = await getThumbnailForMediaID(list[i].mediaID!);
if (thumbnail != null) {
return thumbnail;
}
}
}
return null;
Expand Down
12 changes: 0 additions & 12 deletions lib/utils/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,3 @@ const kDeviceTileHeight = 360.0;

/// Margin between & around a [DeviceTile]. Only relevant on desktop.
const kDeviceTileMargin = 16.0;

/// Default libVLC flags used while rendering the video output. Only relevant on desktop.
const kLibVLCFlags = [
'--no-audio',
'--rtsp-tcp',
'--network-caching=0',
'--rtsp-caching=150',
'--no-stats',
'--tcp-caching=150',
'--rtsp-frame-buffer-size=500000',
'--realrtsp-caching=150',
];
115 changes: 3 additions & 112 deletions lib/widgets/device_grid.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,13 @@

import 'dart:io';
import 'dart:math';

import 'package:animations/animations.dart';
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'package:dart_vlc/dart_vlc.dart' hide Device;
import 'package:provider/provider.dart';
import 'package:animations/animations.dart';
import 'package:reorderable_grid_view/reorderable_grid_view.dart';

import 'package:bluecherry_client/models/server.dart';
import 'package:bluecherry_client/models/device.dart';
import 'package:bluecherry_client/utils/constants.dart';
import 'package:bluecherry_client/widgets/misc.dart';
import 'package:bluecherry_client/widgets/device_tile.dart';
import 'package:bluecherry_client/widgets/device_tile_selector.dart';
import 'package:bluecherry_client/providers/mobile_view_provider.dart';

Expand All @@ -40,111 +34,8 @@ class DeviceGrid extends StatelessWidget {

@override
Widget build(BuildContext context) {
if (isDesktop) {
// TODO: missing implementation.
// WIP: [DesktopDeviceGrid].
throw Exception('[DeviceGrid] is not supported on desktop.');
} else {
return const MobileDeviceGrid();
}
}
}

/// A draggable grid view showing [DeviceTile]s to the user.
class DesktopDeviceGrid extends StatefulWidget {
final Server server;
final double width;
final double height;
const DesktopDeviceGrid({
Key? key,
required this.server,
this.width = double.infinity,
this.height = double.infinity,
}) : super(key: key);

@override
State<DesktopDeviceGrid> createState() => _DesktopDeviceGridState();
}

class _DesktopDeviceGridState extends State<DesktopDeviceGrid> {
final List<Player> players = <Player>[];
final List<DeviceTile> tiles = <DeviceTile>[];

@override
void initState() {
super.initState();
if (isDesktop) {
for (final device in widget.server.devices) {
players.add(Player(
id: Random().nextInt((pow(2, 16)) ~/ 1 - 1),
// Clamp to reasonable [VideoDimensions], if [widget.width] and
// [widget.height] is passed. Avoids redundant CPU load caused by libvlc
// 3.0 pixel buffer based video callbacks.
videoDimensions: const VideoDimensions(
kDeviceTileWidth ~/ 1,
kDeviceTileHeight ~/ 1,
),
commandlineArguments: kLibVLCFlags +
[
'--rtsp-user=${widget.server.login}',
'--rtsp-pwd=${widget.server.password}',
],
)..open(
Media.network(device.streamURL),
));
tiles.add(
DeviceTile(
key: ValueKey(device.hashCode),
device: device,
libvlcPlayer: players.last,
width: kDeviceTileWidth,
height: kDeviceTileHeight,
tab: -1,
index: -1,
),
);
}
}
}

@override
void dispose() {
// Dispose [Player] instance if the [VideoView] is removed from the [Widget]
// tree.
for (final element in players) {
element.dispose();
}
super.dispose();
}

@override
Widget build(BuildContext context) {
return SizedBox(
width: widget.width,
height: widget.height,
child: PageStorage(
bucket: PageStorageBucket(),
child: ReorderableGridView.count(
shrinkWrap: true,
crossAxisCount: 2,
childAspectRatio: kDeviceTileWidth / kDeviceTileHeight,
mainAxisSpacing: kDeviceTileMargin,
crossAxisSpacing: kDeviceTileMargin,
padding: const EdgeInsets.all(kDeviceTileMargin),
onReorder: (int oldIndex, int newIndex) {
setState(() {
final e = players.removeAt(oldIndex);
players.insert(newIndex, e);
final f = tiles.removeAt(oldIndex);
tiles.insert(newIndex, f);
});
},
children: tiles,
dragStartBehavior: DragStartBehavior.start,
dragWidgetBuilder: (i, c) => tiles[i],
),
),
);
return const MobileDeviceGrid();
// TODO: Missing desktop implementation.
}
}

Expand Down
14 changes: 7 additions & 7 deletions lib/widgets/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -431,16 +431,16 @@ class _ServerTileState extends State<ServerTile> {
widget.server.name,
overflow: TextOverflow.ellipsis,
),
subtitle: fetched
? Text(
[
subtitle: Text(
fetched
? [
if (widget.server.name != widget.server.ip) widget.server.ip,
AppLocalizations.of(context)
.nDevices(widget.server.devices.length),
].join(' • '),
overflow: TextOverflow.ellipsis,
)
: null,
].join(' • ')
: AppLocalizations.of(context).gettingDevices,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
icon: const Icon(
Icons.delete,
Expand Down

0 comments on commit d4522d4

Please sign in to comment.