Created
September 28, 2021 18:54
-
-
Save diegoveloper/aef7e2fcdc45e6e272e42b42a53331fb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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