Skip to content

Instantly share code, notes, and snippets.

@timmaffett
Created September 7, 2025 15:26
Show Gist options
  • Save timmaffett/7e8b9f5c36526279a2d706214181f5e6 to your computer and use it in GitHub Desktop.
Save timmaffett/7e8b9f5c36526279a2d706214181f5e6 to your computer and use it in GitHub Desktop.
FilipsExampleWith_watch_it
import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:watch_it/watch_it.dart';
final sl = GetIt.instance;
void main() {
sl.registerLazySingleton(() => MyAppState());
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Namer App',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
),
home: MyHomePage(),
);
}
}
class MyAppState extends ChangeNotifier {
var current = WordPair.random();
var presses = 0;
var favorites = <WordPair>[];
void getNext() {
current = WordPair.random();
++presses;
notifyListeners();
}
void toggleFavorite() {
if(favorites.contains(current)) {
favorites.remove(current);
} else {
favorites.add(current);
}
notifyListeners();
}
}
class MyHomePage extends StatefulWidget {
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var selectedIndex = 0;
@override
Widget build(BuildContext context) {
Widget page;
switch (selectedIndex) {
case 0:
page = GeneratorPage();
break;
case 1:
page = FavoritesPage();
break;
default:
throw UnimplementedError('no widget for $selectedIndex');
}
return Scaffold(
body: Row(
children: [
SafeArea(
child: NavigationRail(
extended: false,
destinations: [
NavigationRailDestination(
icon: Icon(Icons.home),
label: Text('Home'),
),
NavigationRailDestination(
icon: Icon(Icons.favorite),
label: Text('Favorites'),
),
],
selectedIndex: selectedIndex,
onDestinationSelected: (value) {
setState(() {
selectedIndex = value;
});
},
),
),
Expanded(
child: Container(
color: Theme.of(context).colorScheme.primaryContainer,
child: page,
),
),
],
),
);
}
}
class GeneratorPage extends WatchingWidget {
@override
Widget build(BuildContext context) {
var appState = watchIt<MyAppState>();
var pair = appState.current;
IconData icon;
if (appState.favorites.contains(pair)) {
icon = Icons.favorite;
} else {
icon = Icons.favorite_border;
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
BigCard(pair: pair),
SizedBox(height: 10),
Row(
mainAxisSize: MainAxisSize.min,
children: [
ElevatedButton.icon(
onPressed: () {
appState.toggleFavorite();
},
icon: Icon(icon),
label: Text('Like'),
),
SizedBox(width: 10),
ElevatedButton(
onPressed: () {
appState.getNext();
},
child: Text('Next ${appState.presses}'),
),
],
),
],
),
);
}
}
class BigCard extends StatelessWidget {
const BigCard({
super.key,
required this.pair,
});
final WordPair pair;
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var style = theme.textTheme.displayMedium!.copyWith(
color: theme.colorScheme.onPrimary);
return Card(
color: theme.colorScheme.primary,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Text(
pair.asLowerCase,
style: style,
semanticsLabel: pair.asPascalCase, // aids screen readers
),
),
);
}
}
class FavoritesPage extends WatchingStatefulWidget {
@override
State<FavoritesPage> createState() => _FavoritesPageState();
}
class _FavoritesPageState extends State<FavoritesPage> {
var selectedIndex = null;
List<FavoritesItem> favorites = [];
@override
Widget build(BuildContext context) {
var appState = watchIt<MyAppState>();
var theme = Theme.of(context);
var textTheme = theme.textTheme.headlineMedium;
for(var index = 0; index < appState.favorites.length; ++index) {
var wordPair = appState.favorites[index];
favorites.add(FavoritesItem(parent: this, wordPair: wordPair, textTheme: textTheme, index: index, selected: selectedIndex == index));
}
var listView = ListView(
padding: const EdgeInsets.all(8),
children: favorites
);
return SafeArea(
child: Column(
children: [
Expanded(
child: Container(
child: listView
)
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
print('TODO: delete');
},
child: Text('Delete'),
)
],
)
]
)
);
}
void toggleSelected(int index) {
if(selectedIndex != null) {
favorites[selectedIndex].setSelected(false);
}
if(selectedIndex != index) {
selectedIndex = index;
favorites[selectedIndex].setSelected(true);
} else {
selectedIndex = null;
}
}
}
class FavoritesItem extends StatelessWidget {
FavoritesItem({
super.key,
required this.parent,
required this.wordPair,
required this.textTheme,
required this.index,
required this.selected,
});
final _FavoritesPageState parent;
final WordPair wordPair;
final TextStyle? textTheme;
final int index;
bool selected;
@override
Widget build(BuildContext context) {
var label = '${wordPair.first[0].toUpperCase()}${wordPair.first.substring(1).toLowerCase()} '
'${wordPair.second[0].toUpperCase()}${wordPair.second.substring(1).toLowerCase()}';
return GestureDetector(
child: Text(label, style: textTheme),
onTap: () {
parent.toggleSelected(index);
}
);
}
void setSelected(bool selected)
{
this.selected = selected;
print("index $index selected $selected");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment