diff --git a/examples/mirai_gallery/assets/json/home_screen.json b/examples/mirai_gallery/assets/json/home_screen.json index 6f5f6ccd..5aa7d780 100644 --- a/examples/mirai_gallery/assets/json/home_screen.json +++ b/examples/mirai_gallery/assets/json/home_screen.json @@ -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": { @@ -1244,8 +1222,10 @@ "assetPath": "assets/json/filled_button_example.json" } } + }, + { + "type": "sizedBox", + "height": 24.0 } ] - } - } -} \ No newline at end of file + \ No newline at end of file diff --git a/examples/mirai_gallery/lib/app/home/cubit/home_cubit.dart b/examples/mirai_gallery/lib/app/home/cubit/home_cubit.dart new file mode 100644 index 00000000..3e901c2e --- /dev/null +++ b/examples/mirai_gallery/lib/app/home/cubit/home_cubit.dart @@ -0,0 +1,72 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'home_state.dart'; + +class HomeBloc extends Cubit { + HomeBloc() : super(const HomeLoading()) { + controller = TextEditingController() + ..addListener(_textEditingControllerListener); + _initialize(); + } + + late final TextEditingController controller; + + final List> _allItems = []; + + void _initialize() async { + final items = await _loadAndParseJsonFromAsset(); + if (items.isNotEmpty) { + _allItems.addAll(items); + } + emit(HomeLoaded(items: items)); + } + + void _onUserInput({required String keyword}) { + if (keyword.isNotEmpty) { + List> matchedItems = []; + + keyword = keyword.toLowerCase(); + for (final Map 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>> _loadAndParseJsonFromAsset() async { + try { + final String json = + await rootBundle.loadString("assets/json/home_screen.json"); + final List decodedJson = jsonDecode(json); + final List> castedJson = + decodedJson.cast>(); + return castedJson; + } catch (_) { + return const []; + } + } + + // Listen to text editing controller for the latest keyword + void _textEditingControllerListener() { + _onUserInput(keyword: controller.text); + } + + @override + Future close() { + controller + ..removeListener(_textEditingControllerListener) + ..dispose(); + return super.close(); + } +} diff --git a/examples/mirai_gallery/lib/app/home/cubit/home_state.dart b/examples/mirai_gallery/lib/app/home/cubit/home_state.dart new file mode 100644 index 00000000..a0cfc1e0 --- /dev/null +++ b/examples/mirai_gallery/lib/app/home/cubit/home_state.dart @@ -0,0 +1,16 @@ +part of 'home_cubit.dart'; + +@immutable +sealed class HomeState { + final List> items; + + const HomeState({required this.items}); +} + +class HomeLoading extends HomeState { + const HomeLoading({super.items = const []}); +} + +class HomeLoaded extends HomeState { + const HomeLoaded({required super.items}); +} diff --git a/examples/mirai_gallery/lib/app/home/home_screen.dart b/examples/mirai_gallery/lib/app/home/home_screen.dart index 48f6206d..98bd3396 100644 --- a/examples/mirai_gallery/lib/app/home/home_screen.dart +++ b/examples/mirai_gallery/lib/app/home/home_screen.dart @@ -1,11 +1,67 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:mirai/mirai.dart'; +import 'cubit/home_cubit.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( + create: (context) => HomeBloc(), + child: Builder( + builder: (context) { + return Scaffold( + appBar: AppBar( + title: const Text("Mirai Gallery"), + ), + body: Column( + children: [ + TextField( + controller: BlocProvider.of(context).controller, + decoration: InputDecoration( + hintText: "Search", + prefixIcon: const Icon(Icons.search), + suffixIcon: IconButton( + onPressed: + BlocProvider.of(context).controller.clear, + icon: const Icon(Icons.clear), + ), + ), + ), + const SizedBox(height: 10.0), + Expanded( + child: BlocBuilder( + 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(); + }, + ), + ), + ], + ), + ); + }, + ), + ); } }