Restructure step 3: your server, Invite, version gate, AppGraph
- One server per app run (loopback, no password); Invite attaches an all-interfaces listener to the same server and Stop sharing detaches it (guests told with 4016); members, media and Up next never reset. No solo mode: you're home on your own server unless in a friend's. - Navigation: none / yours / friend; a join passes a version gate on /health first (clear "they/you need to update", update offer). - Invite as a value (host, port, name, password flag, version, fp reserved); addresses filtered (loopback, link-local, 198.18/15, bridges) and ranked; Sharing chip, Copy invite, Stop sharing. - Alone looks like a plain player (alone replaces solo). - AppGraph builds and disposes systems; widgets use AppScope; SessionState deleted; a test caps the remaining singletons. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
629be0d9ed
commit
4d00b7455e
86 files changed
+2993
-2071
No files matched your search
@@ -6,8 +6,9 @@ import 'package:sync_relay_core/core.dart' show JellyfinStreamType;
|
||||
|
||||
import '../jellyfin/track_prefs.dart' show MpvTrack;
|
||||
import '../playback/playback_controller.dart' show PlaybackController, RenderMode;
|
||||
import '../session/session_coordinator.dart' show SessionCoordinator;
|
||||
import '../shaders/shader_presets.dart';
|
||||
import '../state/session_state.dart';
|
||||
import '../app/app_graph.dart';
|
||||
import '../shell/mark_problem.dart';
|
||||
import '../shell/motion.dart';
|
||||
import '../state/settings.dart';
|
||||
@@ -200,11 +201,10 @@ class ProgressLineSetting extends StatelessWidget {
|
||||
|
||||
/// Saves a shader choice (also used on the next join) and puts it on the
|
||||
/// running player, if any; the player announces the result.
|
||||
void applyShaderChoice(ShaderPreset preset, ShaderQuality? quality) {
|
||||
void applyShaderChoice(SessionCoordinator coord, ShaderPreset preset, ShaderQuality? quality) {
|
||||
final s = AppSettings.instance;
|
||||
if (quality != null) s.setShaderQuality(quality);
|
||||
s.setShaderPreset(preset);
|
||||
final coord = SessionState.instance.coordinator;
|
||||
coord.markInput();
|
||||
coord.playback.applyShaders(announce: true);
|
||||
}
|
||||
@@ -242,7 +242,7 @@ class ShaderPresetSetting extends StatelessWidget {
|
||||
for (final p in ShaderPreset.values)
|
||||
if (p != ShaderPreset.custom || hasCustom || preset == p) (p, p.label),
|
||||
],
|
||||
onChanged: (p) => applyShaderChoice(p, null),
|
||||
onChanged: (p) => applyShaderChoice(AppScope.of(context).coordinator, p, null),
|
||||
),
|
||||
if (preset.isAnime4k) ...[
|
||||
const SizedBox(width: 8),
|
||||
@@ -250,7 +250,7 @@ class ShaderPresetSetting extends StatelessWidget {
|
||||
key: const ValueKey('shader-quality'),
|
||||
value: quality,
|
||||
items: [for (final q in ShaderQuality.values) (q, q.label)],
|
||||
onChanged: (q) => applyShaderChoice(preset, q),
|
||||
onChanged: (q) => applyShaderChoice(AppScope.of(context).coordinator, preset, q),
|
||||
),
|
||||
],
|
||||
],
|
||||
@@ -265,9 +265,8 @@ class ShaderPresetSetting extends StatelessWidget {
|
||||
|
||||
/// Puts the hwdec setting on the running player (mpv switches decoders
|
||||
/// on the fly). `SYNC_RELAY_HWDEC` wins, as at player start.
|
||||
Future<void> applyHwdecLive() async {
|
||||
Future<void> applyHwdecLive(PlaybackController playback) async {
|
||||
if ((Platform.environment['SYNC_RELAY_HWDEC'] ?? '').isNotEmpty) return;
|
||||
final playback = SessionState.instance.coordinator.playback;
|
||||
if (!playback.alive.peek()) return;
|
||||
try {
|
||||
final dynamic platform = playback.player.platform;
|
||||
@@ -308,7 +307,7 @@ class _HwdecSettingState extends State<HwdecSetting> {
|
||||
items: const [(HwdecMode.auto, 'Auto'), (HwdecMode.off, 'Off'), (HwdecMode.custom, 'Custom')],
|
||||
onChanged: (m) {
|
||||
_s.setHwdecMode(m);
|
||||
applyHwdecLive();
|
||||
applyHwdecLive(AppScope.of(context).coordinator.playback);
|
||||
},
|
||||
),
|
||||
below: mode != HwdecMode.custom
|
||||
@@ -324,7 +323,7 @@ class _HwdecSettingState extends State<HwdecSetting> {
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: _s.setHwdecCustom,
|
||||
onSubmitted: (_) => applyHwdecLive(),
|
||||
onSubmitted: (_) => applyHwdecLive(AppScope.of(context).coordinator.playback),
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -342,7 +341,7 @@ class TrackSetting extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final coord = SessionState.instance.coordinator;
|
||||
final coord = AppScope.of(context).coordinator;
|
||||
return SignalBuilder(builder: (context) {
|
||||
final list = [
|
||||
for (final t in coord.playback.tracks.value)
|
||||
|
||||
Reference in new issue
Block a user