Skip to content

Instantly share code, notes, and snippets.

@diegoveloper
Created September 28, 2021 18:54
Show Gist options
  • Save diegoveloper/aef7e2fcdc45e6e272e42b42a53331fb to your computer and use it in GitHub Desktop.
Save diegoveloper/aef7e2fcdc45e6e272e42b42a53331fb to your computer and use it in GitHub Desktop.
// We need to access the HttpRequest object to make requests in DartPad
//
// ignore: avoid_web_libraries_in_flutter
import 'dart:html';
import 'dart:async';
import 'package:flutter/material.dart';
import 'dart:convert';
// Simple Reddit Feed
// What we provide:
// - Web client for making requests
// - Some Flutter boilerplate code
// What we want to see:
// 1. Parse the response from the web client
// 2. Build a simple widget to display the contents of the "t3" kind of data
// a. Title of the post
// b. Subreddit that the post submitted in
// c. Author of the post
// d. Grey square (if the post has a thumbnail preview, otherwise nothing)
// 3. Display the contents of the front page in a scrollable view
// 4. Browse other subreddits
// What you can do:
// - Look up Flutter documentation
// - Import packages (where available on DartPad)
// - Replace the boilerplate code with whatever you like
// - Use Stack Overflow as a resource
// Sample Solution Video: https://www.youtube.com/watch?v=K3okIxB57S4
class WebClient {
/* General response from Reddit.
*
* Expect data to be well-formed in the following scheme:
{
"kind":"Listing",
"data":{
"children":[
{
"kind":"t3",
"data":{
"title":"Wholesome homewrecking",
"subreddit":"AnimalsBeingDerps",
"author":"lastingeffect29",
"preview": {}
}
}
]
}
}
* A kind of "Listing" will contain a ["data"]["children"] array.
* A kind of "t3" will contain the following keys in the ["data"] field:
* - "title": Title of the post
* - "subreddit": Subreddit that the post was submitted in
* - "author": User that submitted the post
* - "preview": Thumbnails of the post (if present). If this is null, then there are
* no thumbnails for this post.
*
*/
static Future<String> fetch([String? subreddit]) => HttpRequest.getString(
subreddit == null
? 'https://www.reddit.com/.json'
: 'https://www.reddit.com/r/$subreddit/.json',
);
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Reddit Feed',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'My Reddit'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final debouncer = Debouncer();
final textController = TextEditingController();
List _items = [];
void _fetch() async {
final search = textController.text.trim();
final response = await WebClient.fetch(search.isEmpty ? null : search);
final data = jsonDecode(response);
final children = data['data']['children'];
setState(() {
_items = children.map((e) => RedditItem.fromJson(e)).toList();
});
}
void _onSearch(String search) {
// TODO
}
@override
void dispose() {
textController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
backgroundColor: const Color(0xFFF3F5F1),
body: Padding(
padding: const EdgeInsets.all(5.0),
child: Column(
children: [
TextField(
controller: textController,
decoration: const InputDecoration(
label: Text('Subreddit'),
),
),
Expanded(
child: ListView.builder(
itemCount: _items.length,
itemBuilder: (context, index) {
final item = _items[index];
return _RedditItemWidget(item: item);
},
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _fetch,
tooltip: 'Go',
child: const Icon(Icons.play_arrow),
),
);
}
}
class Debouncer {
Debouncer({
this.delay = const Duration(milliseconds: 500),
});
late Timer? _timer;
final Duration delay;
void debounce(void Function() callback) {
_timer?.cancel();
_timer = Timer(delay, callback);
}
void dispose() {
_timer?.cancel();
}
}
class _RedditItemWidget extends StatelessWidget {
const _RedditItemWidget({required this.item, Key? key}) : super(key: key);
final RedditItem item;
Widget build(BuildContext context) {
return SizedBox(
height: 100,
child: Card(
elevation: 5,
child: Row(
children: [
Expanded(
child: item.preview != null
? const Placeholder()
: const SizedBox.shrink(),
),
Expanded(
flex: 3,
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Column(
children: [
Expanded(
child: Text(item.title),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(item.subreddit),
Text(item.author),
],
),
),
],
),
),
),
],
),
),
);
}
}
class RedditItem {
RedditItem({
required this.title,
required this.subreddit,
required this.author,
this.preview,
});
final String title;
final String subreddit;
final String author;
final Map<String, dynamic>? preview;
static RedditItem fromJson(Map<String, dynamic> json) {
final data = json['data'];
return RedditItem(
title: data['title'],
subreddit: data['subreddit'],
author: data['author'],
preview: data['preview'],
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment