Player controls: one model, two skins (Standard, Minimal); conventional layout; controls settings

PlayerControlsModel holds the controls' state and actions once; the
Standard skin (our own, no more media_kit controls or private-state
reach-ins) and Minimal (the former uosc design, made the app's own and
credited) only draw it. One layout spec for both: play first, then
previous/next, volume, time; subtitles, audio, settings, chat,
fullscreen last; everything else in the settings menu. Settings ->
Player -> Controls: time display, size, hide delay, optional buttons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
foxyzandClaude Opus 5.5 committed 2026-10-15 17:03:15 +03:00
1 parent 959eed38a4
commit fd8064611a
40 files changed
+3820 -3975

No files matched your search

+27 -11
View File
@@ -3,9 +3,9 @@ import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:sync_relay_core/core.dart';
import 'package:watch_together/src/controls/uosc/buttons.dart';
import 'package:watch_together/src/controls/uosc/controls.dart';
import 'package:watch_together/src/controls/uosc/timeline.dart';
import 'package:watch_together/src/controls/frame.dart';
import 'package:watch_together/src/controls/minimal/style.dart';
import 'package:watch_together/src/controls/minimal/timeline.dart';
import 'package:watch_together/src/session/health.dart';
import 'package:watch_together/src/session/now_playing.dart';
import 'package:watch_together/src/shell/now_playing_title.dart';
@@ -248,21 +248,37 @@ void main() {
expect(find.textContaining('Waiting for Someone With A Long Name 0'), findsOneWidget);
});
testWidgets('uosc top bar and start card: ${size.width.toInt()}', (tester) async {
testWidgets('minimal top bar and start card: ${size.width.toInt()}', (tester) async {
debugArtBytes = (hash) => png;
await sized(
tester,
size,
Stack(fit: StackFit.expand, children: [
StartCard(now: long),
UoscControls(
topLeft: NowPlayingBlock(now: long),
top: Row(mainAxisSize: MainAxisSize.min, children: [
for (final i in [Icons.chat_bubble_outline, Icons.fullscreen, Icons.close])
UoscButton(icon: i, tooltip: '', onPressed: () {}),
ControlsFrame(
builder: (context, visible) => Stack(children: [
Positioned(
left: 16,
right: 10,
top: 0,
height: 72,
child: Row(children: [
Expanded(child: NowPlayingBlock(now: long)),
for (final i in [Icons.fullscreen, Icons.close])
MinimalButton(icon: i, tooltip: '', onPressed: () {}),
]),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: MinimalTimeline(
position: Duration.zero,
duration: const Duration(minutes: 24),
expanded: visible,
onSeek: (_) {}),
),
]),
timeline: (context, expanded) =>
UoscTimeline(position: Duration.zero, duration: const Duration(minutes: 24), expanded: expanded, onSeek: (_) {}),
),
]),
);