Skip to content

Commit

Permalink
#282 Add Search Bar in Example Gallery App
Browse files Browse the repository at this point in the history
  • Loading branch information
vkmaxcooldude committed Mar 26, 2024
1 parent e900ec2 commit e692a2a
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 27 deletions.
28 changes: 2 additions & 26 deletions examples/mirai_gallery/assets/json/home_screen.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,4 @@
{
"type": "scaffold",
"appBar": {
"type": "appBar",
"title": {
"type": "text",
"data": "Mirai Gallery"
},
"elevation": 0
},
"body": {
"type": "padding",
"padding": {
"bottom": 24
},
"child": {
"type": "listView",
"shrinkWrap": true,
"separator": {
"type": "container",
"height": 10
},
"children": [
[
{
"type": "listTile",
"leading": {
Expand Down Expand Up @@ -1215,6 +1193,4 @@
}
}
]
}
}
}

75 changes: 75 additions & 0 deletions examples/mirai_gallery/lib/app/home/bloc/home_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

part 'home_event.dart';
part 'home_state.dart';

class HomeBloc extends Bloc<HomeEvent, HomeState> {
HomeBloc() : super(const HomeLoading()) {
on<_Initialize>(_onInitializeEvent);
on<UserInputEvent>(_onUserInputEvent);
controller = TextEditingController()
..addListener(_textEditingControllerListener);
add(const _Initialize());
}

late final TextEditingController controller;

final List<Map<String, dynamic>> _allItems = [];

void _onInitializeEvent(_Initialize event, Emitter<HomeState> emit) async {
final items = await _loadAndParseJsonFromAsset();
if (items.isNotEmpty) {
_allItems.addAll(items);
}
emit(HomeLoaded(items: items));
}

void _onUserInputEvent(UserInputEvent event, Emitter<HomeState> emit) {
if (event.keyword.isNotEmpty) {
List<Map<String, dynamic>> matchedItems = [];

final String keyword = event.keyword.toLowerCase();
for (final Map<String, dynamic> item in _allItems) {
var text = item["title"]?["data"];
if (text != null && text is String) {
if (text.toLowerCase().contains(keyword)) {
matchedItems.add(item);
}
}
}
emit(HomeLoaded(items: matchedItems));
} else {
emit(HomeLoaded(items: _allItems));
}
}

Future<List<Map<String, dynamic>>> _loadAndParseJsonFromAsset() async {
try {
final String json =
await rootBundle.loadString("assets/json/home_screen.json");
final List<dynamic> decodedJson = jsonDecode(json);
final List<Map<String, dynamic>> castedJson =
decodedJson.cast<Map<String, dynamic>>();
return castedJson;
} catch (_) {
return const [];
}
}

// Add `UserInputEvent` with the latest keyword
void _textEditingControllerListener() {
add(UserInputEvent(keyword: controller.text));
}

@override
Future<void> close() {
controller
..removeListener(_textEditingControllerListener)
..dispose();
return super.close();
}
}
17 changes: 17 additions & 0 deletions examples/mirai_gallery/lib/app/home/bloc/home_event.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
part of 'home_bloc.dart';

@immutable
sealed class HomeEvent {
const HomeEvent();
}

// Event used to perform the initializations of the HomeBloc
class _Initialize extends HomeEvent {
const _Initialize();
}

class UserInputEvent extends HomeEvent {
final String keyword;

const UserInputEvent({required this.keyword});
}
16 changes: 16 additions & 0 deletions examples/mirai_gallery/lib/app/home/bloc/home_state.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
part of 'home_bloc.dart';

@immutable
sealed class HomeState {
final List<Map<String, dynamic>> items;

const HomeState({required this.items});
}

class HomeLoading extends HomeState {
const HomeLoading({super.items = const []});
}

class HomeLoaded extends HomeState {
const HomeLoaded({required super.items});
}
59 changes: 58 additions & 1 deletion examples/mirai_gallery/lib/app/home/home_screen.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,68 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:mirai/mirai.dart';

import 'bloc/home_bloc.dart';

class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});

@override
Widget build(BuildContext context) {
return Mirai.fromAssets('assets/json/home_screen.json') ?? const SizedBox();
return BlocProvider<HomeBloc>(
create: (context) => HomeBloc(),
child: Builder(
builder: (context) {
return Scaffold(
appBar: AppBar(
title: const Text("Mirai Gallery"),
),
body: Column(
children: [
TextField(
controller: BlocProvider.of<HomeBloc>(context).controller,
decoration: InputDecoration(
hintText: "Search",
prefixIcon: const Icon(Icons.search),
suffixIcon: IconButton(
onPressed:
BlocProvider.of<HomeBloc>(context).controller.clear,
icon: const Icon(Icons.clear),
),
),
),
const SizedBox(height: 10.0),
Expanded(
child: BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
if (state is HomeLoaded) {
return Mirai.fromJson(
{
"type": "listView",
"shrinkWrap": false,
"separator": {
"type": "container",
"height": 10
},
"children": state.items,
},
context,
) ??
const SizedBox();
}
if (state is HomeLoading) {
return const CircularProgressIndicator();
}
return const SizedBox();
},
),
),
SizedBox(height: 24.0 + MediaQuery.of(context).padding.bottom)
],
),
);
},
),
);
}
}

0 comments on commit e692a2a

Please sign in to comment.