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
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
// 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(),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user