Skip to content

Instantly share code, notes, and snippets.

@jezell
Created December 6, 2024 07:20
Show Gist options
  • Save jezell/a40a879bd984aadd8ea9d6b705a859f0 to your computer and use it in GitHub Desktop.
Save jezell/a40a879bd984aadd8ea9d6b705a859f0 to your computer and use it in GitHub Desktop.
o1 pro slides from json test
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
class TextSlide {
/// Hex color for the text. Defaults to white (#ffffff) if missing or empty.
final String textColor;
/// Title of the slide. Defaults to empty string if missing.
final String title;
/// Bulleted text content. Defaults to empty string if missing.
final String text;
/// Background image URL. Defaults to empty string if missing.
final String background;
/// Voiceover text. Defaults to empty string if missing.
/// (Not displayed, but may be used for other logic if needed.)
final String voiceover;
/// Voiceover audio URL or asset path. Defaults to empty if missing.
final String voiceoverAudio;
TextSlide({
required this.textColor,
required this.title,
required this.text,
required this.background,
required this.voiceover,
required this.voiceoverAudio,
});
factory TextSlide.fromJson(Map<String, dynamic> json) {
return TextSlide(
textColor: (json['textColor'] as String?)?.isNotEmpty == true
? json['textColor'] as String
: '#ffffff',
title: (json['title'] as String?) ?? '',
text: (json['text'] as String?) ?? '',
background: (json['background'] as String?) ?? '',
voiceover: (json['voiceover'] as String?) ?? '',
voiceoverAudio: (json['voiceover_audio'] as String?) ?? '',
);
}
Map<String, dynamic> toJson() {
return {
'textColor': textColor,
'title': title,
'text': text,
'background': background,
'voiceover': voiceover,
'voiceover_audio': voiceoverAudio,
};
}
}
class SlideData {
final TextSlide textSlide;
SlideData({required this.textSlide});
factory SlideData.fromJson(Map<String, dynamic> json) {
return SlideData(
textSlide: TextSlide.fromJson(json['text_slide'] as Map<String, dynamic>),
);
}
Map<String, dynamic> toJson() {
return {
'text_slide': textSlide.toJson(),
};
}
}
class TextSlideWidget extends StatefulWidget {
final SlideData slideData;
const TextSlideWidget({Key? key, required this.slideData}) : super(key: key);
@override
State<TextSlideWidget> createState() => _TextSlideWidgetState();
}
class _TextSlideWidgetState extends State<TextSlideWidget> {
final AudioPlayer _audioPlayer = AudioPlayer();
@override
void initState() {
super.initState();
_playVoiceoverIfAvailable();
}
Future<void> _playVoiceoverIfAvailable() async {
final voiceoverAudio = widget.slideData.textSlide.voiceoverAudio;
if (voiceoverAudio.isNotEmpty) {
await _audioPlayer.play(UrlSource(voiceoverAudio));
}
}
@override
void dispose() {
_audioPlayer.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final ts = widget.slideData.textSlide;
final textColor = _fromHex(ts.textColor);
return Stack(
fit: StackFit.expand,
children: [
// Background image or fallback
if (ts.background.isNotEmpty)
Image.network(
ts.background,
fit: BoxFit.cover,
)
else
Container(color: Colors.black),
// Optional gradient overlay for readability
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.black.withOpacity(0.3), Colors.black.withOpacity(0.7)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
),
// Slide content
SafeArea(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (ts.title.isNotEmpty)
Text(
ts.title,
style: TextStyle(
color: textColor,
fontSize: 28,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
if (ts.text.isNotEmpty)
_buildBulletList(ts.text, textColor),
],
),
),
),
),
],
);
}
Widget _buildBulletList(String text, Color textColor) {
final lines = text.split('\n').where((line) => line.trim().isNotEmpty);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: lines.map((line) {
final trimmedLine = line.trim().replaceFirst(RegExp(r'^- '), '');
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'• ',
style: TextStyle(color: textColor, fontSize: 18, fontWeight: FontWeight.bold),
),
Expanded(
child: Text(
trimmedLine,
style: TextStyle(color: textColor, fontSize: 16),
),
),
],
),
);
}).toList(),
);
}
Color _fromHex(String hexCode) {
final buffer = StringBuffer();
if (hexCode.length == 7) buffer.write('ff');
buffer.write(hexCode.replaceFirst('#', ''));
return Color(int.parse(buffer.toString(), radix: 16));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment