Blogging App using the Blogger API using Flutter.
Published in
4 min readOct 21, 2023
Install a Package of Blogger
flutter pub add blogger
Step 1: Create a project
import 'package:flutter/material.dart';
import 'views/home_view.dart';
void main() {
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: HomeView(title: 'Blogs'),
);
}
}
Step 2: Creating Views For blogging
views/home_view.dart
import 'package:flutter/material.dart';
import 'package:blogger/blogger.dart';
import 'page_view.dart';
import 'post_view.dart';
class HomeView extends StatefulWidget {
const HomeView({super.key, required this.title});
final String title;
@override
State<HomeView> createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
String key = const String.fromEnvironment('API_KEY');
List<String> blogIds = const String.fromEnvironment('BLOG_IDS').split(',');
Future<List<BlogsModel>> getAllBlogs() async {
final res = await Blogger(apiKey: key, blogId: blogIds[0])
.getBlogs(blogIds: blogIds);
return res;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: FutureBuilder<List<BlogsModel>>(
future: getAllBlogs(),
builder: ((context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.hasError) {
return const Center(
child: Text('Try Again'),
);
} else {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text(
'Blog ${index + 1} - ${snapshot.data![index].name}'),
subtitle: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton.icon(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PagesView(
blogId: blogIds[index],
apiKey: key,
)),
);
},
icon: const Icon(Icons.pages),
label: const Padding(
padding: EdgeInsets.all(8.0),
child: Text('Pages'),
)),
const SizedBox(
height: 20,
),
ElevatedButton.icon(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PostView(
blogId: blogIds[index],
apiKey: key,
)),
);
},
icon: const Icon(Icons.post_add),
label: const Padding(
padding: EdgeInsets.all(8.0),
child: Text('Posts'),
)),
],
),
),
);
});
}
}),
),
),
);
}
}
views/page_view.dart
import 'package:blogger/blogger.dart';
import 'package:flutter/material.dart';
import 'html_view.dart';
class PagesView extends StatefulWidget {
final String blogId;
final String apiKey;
const PagesView({super.key, required this.blogId, required this.apiKey});
@override
State<PagesView> createState() => _PageViewState();
}
class _PageViewState extends State<PagesView> {
Future<PageModel> getPages() async {
final res =
await Blogger(apiKey: widget.apiKey, blogId: widget.blogId).getPages();
return res;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Posts'),
),
body: FutureBuilder(
future: getPages(),
builder: ((context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.hasError) {
return const Center(
child: Text('Try Again'),
);
} else {
return ListView.builder(
itemCount: snapshot.data!.items!.length,
itemBuilder: (ctx, index) {
return Center(
child: Card(
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HTMLView(
data: snapshot.data!.items![index],
)),
);
},
child: Container(
height: 100,
width: double.infinity,
padding: const EdgeInsets.all(8.0),
child: Center(
child:
Text(snapshot.data!.items![index].title!))),
)),
);
});
}
})),
);
}
}
views/post_view.dart
import 'package:blogger/blogger.dart';
import 'package:flutter/material.dart';
import 'html_view.dart';
class PostView extends StatefulWidget {
final String blogId;
final String apiKey;
const PostView({super.key, required this.blogId, required this.apiKey});
@override
State<PostView> createState() => _PostViewState();
}
class _PostViewState extends State<PostView> {
Future<PostModel> getAllpost() async {
final res =
await Blogger(apiKey: widget.apiKey, blogId: widget.blogId).getPosts(
includeComment: true,
);
return res;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Posts'),
),
body: FutureBuilder(
future: getAllpost(),
builder: ((context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.hasError) {
return const Center(
child: Text('Try Again'),
);
} else {
return ListView.builder(
itemCount: snapshot.data?.items?.length ?? 0,
itemBuilder: (ctx, index) {
return Center(
child: Card(
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HTMLView(
data: snapshot.data!.items![index],
)),
);
},
child: Container(
height: 100,
width: double.infinity,
padding: const EdgeInsets.all(8.0),
child: Center(
child:
Text(snapshot.data!.items![index].title!))),
)),
);
});
}
})),
);
}
}
views/html_view.dart
import 'package:blogger/blogger.dart';
import 'show_comments.dart';
import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
import 'package:url_launcher/url_launcher.dart';
class HTMLView extends StatefulWidget {
final PostItemModel data;
const HTMLView({super.key, required this.data});
@override
State<HTMLView> createState() => _HTMLViewState();
}
class _HTMLViewState extends State<HTMLView> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.data.title!),
actions: [
InkWell(
onTap: () {
print(widget.data.replies!.postComments!);
ShowComments().displayshowModalBottomSheet(
context,
widget.data.replies!.postComments!,
);
},
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.comment),
),
)
],
),
body: SingleChildScrollView(
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: HtmlWidget(
widget.data.content!,
customStylesBuilder: (element) {
if (element.classes.contains('foo')) {
return {'color': 'red'};
}
return null;
},
//customWidgetBuilder: (element) {},
onTapUrl: (url) async {
if (!await launchUrl(Uri.parse(url))) {
throw 'Could not launch $url';
}
return true;
},
onErrorBuilder: (context, element, error) =>
Text('$element error: $error'),
onLoadingBuilder: (context, element, loadingProgress) =>
const CircularProgressIndicator(),
renderMode: RenderMode.column,
textStyle: const TextStyle(
fontSize: 14,
),
),
),
),
),
);
}
}
Sponor This Package Link Below