Files
Bernd Steckmeister 25ed765a03 wip: Sicherungs-Commit aller Änderungen seit April + Arbeitsstruktur (CLAUDE.md, ROADMAP.md, PROGRESS.md, Autopilot)
6 Wochen uncommittete Arbeit (Voice-Channels, LiveKit-Manager, Settings-Modal u.v.m.)
als ein WIP-Commit gesichert, damit nichts verloren geht und der Pi den aktuellen
Stand klonen kann. Thematische Aufarbeitung: siehe ROADMAP M0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CPrAGBxBT6GfPXzeWQ4AXb
2026-07-03 05:47:18 +02:00

160 lines
6.3 KiB
Dart

// example_app.dart
// Pyramid Players · Showcase / Test-Harness
//
// Zeigt alle Player-Varianten in einem scrollbaren Dark-Layout.
// Drop-in-fähig: füge die drei Pyramid-Dateien (theme + audio + video)
// in dein Projekt und referenziere sie wie unten.
import 'package:flutter/material.dart';
import 'pyramid_theme.dart';
import 'pyramid_audio_player.dart';
import 'pyramid_video_player.dart';
void main() => runApp(const PyramidShowcaseApp());
class PyramidShowcaseApp extends StatelessWidget {
const PyramidShowcaseApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Pyramid · Players',
theme: ThemeData(
scaffoldBackgroundColor: PyramidTheme.bg0,
fontFamily: PyramidTheme.fontSans,
useMaterial3: true,
),
home: const _Showcase(),
);
}
}
class _Showcase extends StatefulWidget {
const _Showcase();
@override
State<_Showcase> createState() => _ShowcaseState();
}
class _ShowcaseState extends State<_Showcase> {
bool _playing = true;
Duration _audioPos = const Duration(minutes: 1, seconds: 11);
final _audioDur = const Duration(minutes: 3, seconds: 24);
Duration _videoPos = const Duration(minutes: 1, seconds: 28);
final _videoDur = const Duration(minutes: 4, seconds: 12);
void _toggle() => setState(() => _playing = !_playing);
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(48, 48, 48, 120),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text('PYRAMID · MEDIA PLAYERS',
style: TextStyle(fontFamily: PyramidTheme.fontMono, fontSize: 10, letterSpacing: 1.4, color: PyramidTheme.fgDim)),
const SizedBox(height: 6),
Text('Audio + Video — Flutter', style: TextStyle(color: PyramidTheme.fg, fontSize: 28, fontWeight: FontWeight.w500)),
const SizedBox(height: 40),
_section('AUDIO'),
_grid([
_frame('01 · Default', 'chunky bars',
PyramidAudioPlayer(
variant: AudioPlayerVariant.defaultBars,
title: 'test track', artist: 'pyramid · demo',
duration: _audioDur, position: _audioPos,
playing: _playing, onTogglePlay: _toggle,
onSeek: (p) => setState(() => _audioPos = p),
)),
_frame('02 · Gracile', 'hairline wave',
PyramidAudioPlayer(
variant: AudioPlayerVariant.gracile,
title: 'test track', artist: 'pyramid · demo',
duration: _audioDur, position: _audioPos,
playing: _playing, onTogglePlay: _toggle,
onSeek: (p) => setState(() => _audioPos = p),
)),
_frame('03 · Compact', 'in-chat',
PyramidAudioPlayer(
variant: AudioPlayerVariant.compact,
title: 'test track', artist: 'pyramid · demo',
duration: _audioDur, position: _audioPos,
playing: _playing, onTogglePlay: _toggle,
onSeek: (p) => setState(() => _audioPos = p),
)),
_frame('04 · Mono', 'terminal',
PyramidAudioPlayer(
variant: AudioPlayerVariant.mono,
title: 'test.wav', artist: 'pyramid · demo',
duration: _audioDur, position: _audioPos,
playing: _playing, onTogglePlay: _toggle,
onSeek: (p) => setState(() => _audioPos = p),
)),
]),
const SizedBox(height: 40),
_section('VIDEO'),
_grid([
_frame('01 · Default', 'hover-chrome',
PyramidVideoPlayer(
variant: VideoPlayerVariant.defaultHover,
title: 'test clip', subtitle: 'pyramid · 1080p',
duration: _videoDur, position: _videoPos, buffered: 0.65,
playing: _playing, onTogglePlay: _toggle,
onSeek: (p) => setState(() => _videoPos = p),
)),
_frame('02 · Minimal', 'always-visible',
PyramidVideoPlayer(
variant: VideoPlayerVariant.minimal,
title: 'test clip', subtitle: 'pyramid · 1080p',
duration: _videoDur, position: _videoPos, buffered: 0.65,
playing: _playing, onTogglePlay: _toggle,
onSeek: (p) => setState(() => _videoPos = p),
)),
_frame('03 · Framed', 'editorial',
PyramidVideoPlayer(
variant: VideoPlayerVariant.framed,
title: 'test clip', subtitle: 'pyramid · 1080p',
duration: _videoDur, position: _videoPos, buffered: 0.65,
playing: _playing, onTogglePlay: _toggle,
onSeek: (p) => setState(() => _videoPos = p),
)),
]),
]),
),
),
);
}
Widget _section(String label) => Padding(
padding: const EdgeInsets.only(bottom: 20),
child: Container(
padding: const EdgeInsets.only(bottom: 8),
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: PyramidTheme.border))),
child: Text(label,
style: TextStyle(fontFamily: PyramidTheme.fontMono, fontSize: 10, letterSpacing: 1.8, color: PyramidTheme.fgDim)),
),
);
Widget _frame(String label, String sub, Widget child) => Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 14),
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(label, style: TextStyle(fontFamily: PyramidTheme.fontMono, fontSize: 10, letterSpacing: 1.4, color: PyramidTheme.fgMuted)),
Text(sub, style: TextStyle(fontFamily: PyramidTheme.fontMono, fontSize: 10, letterSpacing: 1.4, color: PyramidTheme.fgDim)),
]),
),
child,
],
);
Widget _grid(List<Widget> items) => Wrap(
spacing: 28, runSpacing: 28,
children: items.map((i) => SizedBox(width: 420, child: i)).toList(),
);
}