Solo watching and a clearer offline start
Putting anything up offline starts a solo session: an in-app server bound to 127.0.0.1 only, joined like hosting, so tracking, next episode and the player all work. Invite friends re-hosts on the Host card's port and password with the same media and position; Stop needs no confirmation. Offline, the Library opens with a welcome band (Join a friend, Host, Watch solo); without a Jellyfin account it leads with Files and Link, Jellyfin is an optional card. Play buttons work offline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8186fbb5d3
commit
e0db5cc655
28 files changed
+1013
-345
No files matched your search
@@ -13,8 +13,8 @@ enum CardAction {
|
||||
none,
|
||||
putUp,
|
||||
|
||||
/// Available, but not in a server: shown disabled with a hint.
|
||||
playOffline,
|
||||
/// Available, nobody else watching (offline or solo): plays it here.
|
||||
play,
|
||||
request,
|
||||
requestSeries,
|
||||
requested,
|
||||
@@ -162,15 +162,10 @@ class AiringCard extends StatelessWidget {
|
||||
final spinner = const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2));
|
||||
Widget? b = switch (action) {
|
||||
CardAction.none => null,
|
||||
CardAction.putUp => FilledButton.tonalIcon(
|
||||
CardAction.putUp || CardAction.play => FilledButton.tonalIcon(
|
||||
onPressed: enabled ? onAction : null,
|
||||
icon: busy ? spinner : const Icon(Icons.play_arrow, size: 18),
|
||||
label: const Text('Put it up'),
|
||||
),
|
||||
CardAction.playOffline => FilledButton.tonalIcon(
|
||||
onPressed: null,
|
||||
icon: const Icon(Icons.play_arrow, size: 18),
|
||||
label: const Text('Play'),
|
||||
label: Text(action == CardAction.play ? 'Play' : 'Put it up'),
|
||||
),
|
||||
CardAction.request || CardAction.requestSeries => OutlinedButton.icon(
|
||||
onPressed: enabled ? onAction : null,
|
||||
@@ -216,7 +211,7 @@ class AiringCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
);
|
||||
final tap = action == CardAction.putUp && disabledHint == null && !busy ? onAction : null;
|
||||
final tap = (action == CardAction.putUp || action == CardAction.play) && disabledHint == null && !busy ? onAction : null;
|
||||
if (compact) {
|
||||
final requestable = action == CardAction.request || action == CardAction.requestSeries;
|
||||
return Material(
|
||||
|
||||
@@ -21,8 +21,9 @@ import 'schedule_card.dart';
|
||||
enum ScheduleFilter { jellyfin, following, all }
|
||||
|
||||
class SchedulePage extends StatefulWidget {
|
||||
/// In a server: available episodes can be put up.
|
||||
final bool online;
|
||||
/// Nobody else watches (offline or solo): available episodes say Play
|
||||
/// (offline that starts a solo session).
|
||||
final bool solo;
|
||||
|
||||
/// Puts a Jellyfin episode up in the server; returns an error to show.
|
||||
final Future<String?> Function(JellyfinMedia pick) onPutUp;
|
||||
@@ -36,7 +37,7 @@ class SchedulePage extends StatefulWidget {
|
||||
|
||||
const SchedulePage({
|
||||
super.key,
|
||||
required this.online,
|
||||
this.solo = false,
|
||||
required this.onPutUp,
|
||||
required this.onToast,
|
||||
this.repository,
|
||||
@@ -215,9 +216,9 @@ class _SchedulePageState extends State<SchedulePage> {
|
||||
|
||||
(CardAction, String?) _actionFor(ScheduleEntry e) {
|
||||
if (e.status == ScheduleStatus.available || e.status == ScheduleStatus.inLibrary) {
|
||||
if (!widget.online) return (CardAction.playOffline, 'Join or host a server to put it up');
|
||||
if (e.jellyfinSeriesId == null) return (CardAction.putUp, 'Not linked to a Jellyfin series yet');
|
||||
return (CardAction.putUp, null);
|
||||
final put = widget.solo ? CardAction.play : CardAction.putUp;
|
||||
if (e.jellyfinSeriesId == null) return (put, 'Not linked to a Jellyfin series yet');
|
||||
return (put, null);
|
||||
}
|
||||
final me = _me;
|
||||
final CardAction kind;
|
||||
@@ -242,6 +243,7 @@ class _SchedulePageState extends State<SchedulePage> {
|
||||
Future<void> _onAction(ScheduleEntry e, CardAction action) async {
|
||||
switch (action) {
|
||||
case CardAction.putUp:
|
||||
case CardAction.play:
|
||||
return _putUp(e);
|
||||
case CardAction.request:
|
||||
case CardAction.requestSeries:
|
||||
@@ -530,7 +532,7 @@ class _SchedulePageState extends State<SchedulePage> {
|
||||
|
||||
Widget _card(ScheduleEntry e, DateTime now) {
|
||||
final (action, hint) = _actionFor(e);
|
||||
final busy = _busy.contains(action == CardAction.putUp ? 'play:${_key(e)}' : _key(e));
|
||||
final busy = _busy.contains(action == CardAction.putUp || action == CardAction.play ? 'play:${_key(e)}' : _key(e));
|
||||
return AiringCard(
|
||||
entry: e,
|
||||
now: now,
|
||||
|
||||
Reference in new issue
Block a user