feat: implement search api

This commit is contained in:
Matyáš Caras 2023-03-18 16:55:08 +01:00
parent 7b7f6fb3a9
commit bb2524b2ba
11 changed files with 627 additions and 110 deletions

21
lib/api/classes.dart Normal file
View file

@ -0,0 +1,21 @@
import 'package:json_annotation/json_annotation.dart';
part 'classes.g.dart';
@JsonSerializable()
class SearchResponse {
final int id;
final String key;
final String title;
final String excerpt;
final String description;
const SearchResponse(
this.id, this.key, this.title, this.excerpt, this.description);
/// Connect the generated function to the `fromJson`
/// factory.
factory SearchResponse.fromJson(Map<String, dynamic> json) =>
_$SearchResponseFromJson(json);
/// Connect the generated function to the `toJson` method.
Map<String, dynamic> toJson() => _$SearchResponseToJson(this);
}

25
lib/api/classes.g.dart Normal file
View file

@ -0,0 +1,25 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'classes.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
SearchResponse _$SearchResponseFromJson(Map<String, dynamic> json) =>
SearchResponse(
json['id'] as int,
json['key'] as String,
json['title'] as String,
json['excerpt'] as String,
json['description'] as String,
);
Map<String, dynamic> _$SearchResponseToJson(SearchResponse instance) =>
<String, dynamic>{
'id': instance.id,
'key': instance.key,
'title': instance.title,
'excerpt': instance.excerpt,
'description': instance.description,
};

View file

@ -1,15 +1,26 @@
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:voyagehandbook/api/classes.dart';
final dio = Dio(
BaseOptions(baseUrl: "https://api.wikimedia.org/core/v1/wikivoyage/en"));
class WikiApi {
static final _dio = Dio(
BaseOptions(baseUrl: "https://api.wikimedia.org/core/v1/wikivoyage/en/"));
Future<Response> _getRequest(String endpoint) async {
return await dio.get(endpoint,
options: Options(headers: {"User-Agent": "VoyageHandbook/1.0.0"}));
}
Future<String> search(String q, {int limit = 5}) async {
var r = await _getRequest("search/title?q=$q&limit=$limit");
if (r.statusCode! > 399) return Future.error("API error ${r.statusCode}");
return r.data.toString();
static Future<Response> _getRequest(String endpoint) async {
return await _dio.get(endpoint,
options: Options(
headers: {"User-Agent": "VoyageHandbook/1.0.0"},
validateStatus: (_) => true,
responseType: ResponseType.plain));
}
/// Searches for pages using the WikiMedia API
static Future<List<SearchResponse>> search(String q, {int limit = 5}) async {
var r = await _getRequest("search/page?q=$q&limit=$limit");
if (r.statusCode! > 399) return Future.error("API error ${r.statusCode}");
var json = jsonDecode(r.data)["pages"];
return List<SearchResponse>.generate(
json.length, (index) => SearchResponse.fromJson(json[index]));
}
}

View file

@ -1,4 +1,7 @@
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';
import 'package:voyagehandbook/util/color_schemes.g.dart';
import 'package:voyagehandbook/views/home.dart';
void main() {
runApp(const MyApp());
@ -10,106 +13,20 @@ class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
return DynamicColorBuilder(
builder: (lightDynamic, darkDynamic) => MaterialApp(
title: 'Voyage Handbook',
theme: ThemeData(
useMaterial3: true,
colorScheme: lightDynamic ?? lightColorScheme
),
darkTheme: ThemeData(
useMaterial3: true,
colorScheme: darkDynamic ?? darkColorScheme
),
home: const HomeView(),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

View file

@ -0,0 +1,69 @@
import 'package:flutter/material.dart';
const lightColorScheme = ColorScheme(
brightness: Brightness.light,
primary: Color(0xFF9C432E),
onPrimary: Color(0xFFFFFFFF),
primaryContainer: Color(0xFFFFDAD2),
onPrimaryContainer: Color(0xFF3D0700),
secondary: Color(0xFF815500),
onSecondary: Color(0xFFFFFFFF),
secondaryContainer: Color(0xFFFFDDB2),
onSecondaryContainer: Color(0xFF291800),
tertiary: Color(0xFF855300),
onTertiary: Color(0xFFFFFFFF),
tertiaryContainer: Color(0xFFFFDDB8),
onTertiaryContainer: Color(0xFF2A1700),
error: Color(0xFFBA1A1A),
errorContainer: Color(0xFFFFDAD6),
onError: Color(0xFFFFFFFF),
onErrorContainer: Color(0xFF410002),
background: Color(0xFFFFFBFF),
onBackground: Color(0xFF201A19),
surface: Color(0xFFFFFBFF),
onSurface: Color(0xFF201A19),
surfaceVariant: Color(0xFFF5DDD8),
onSurfaceVariant: Color(0xFF534340),
outline: Color(0xFF85736F),
onInverseSurface: Color(0xFFFBEEEB),
inverseSurface: Color(0xFF362F2D),
inversePrimary: Color(0xFFFFB4A3),
shadow: Color(0xFF000000),
surfaceTint: Color(0xFF9C432E),
outlineVariant: Color(0xFFD8C2BD),
scrim: Color(0xFF000000),
);
const darkColorScheme = ColorScheme(
brightness: Brightness.dark,
primary: Color(0xFFFFB4A3),
onPrimary: Color(0xFF5E1606),
primaryContainer: Color(0xFF7D2C19),
onPrimaryContainer: Color(0xFFFFDAD2),
secondary: Color(0xFFFFB94D),
onSecondary: Color(0xFF442B00),
secondaryContainer: Color(0xFF624000),
onSecondaryContainer: Color(0xFFFFDDB2),
tertiary: Color(0xFFFFB960),
onTertiary: Color(0xFF472A00),
tertiaryContainer: Color(0xFF653E00),
onTertiaryContainer: Color(0xFFFFDDB8),
error: Color(0xFFFFB4AB),
errorContainer: Color(0xFF93000A),
onError: Color(0xFF690005),
onErrorContainer: Color(0xFFFFDAD6),
background: Color(0xFF201A19),
onBackground: Color(0xFFEDE0DD),
surface: Color(0xFF201A19),
onSurface: Color(0xFFEDE0DD),
surfaceVariant: Color(0xFF534340),
onSurfaceVariant: Color(0xFFD8C2BD),
outline: Color(0xFFA08C88),
onInverseSurface: Color(0xFF201A19),
inverseSurface: Color(0xFFEDE0DD),
inversePrimary: Color(0xFF9C432E),
shadow: Color(0xFF000000),
surfaceTint: Color(0xFFFFB4A3),
outlineVariant: Color(0xFF534340),
scrim: Color(0xFF000000),
);

42
lib/util/drawer.dart Normal file
View file

@ -0,0 +1,42 @@
import 'package:flutter/material.dart';
import 'package:voyagehandbook/views/home.dart';
import '../views/search.dart';
Drawer genDrawer(int page, BuildContext context) => Drawer(
child: ListView(
children: [
DrawerHeader(
child: Column(
children: const [
Text("Voyage Handbook"),
Text("Created by Matyáš Caras")
],
)),
ListTile(
selected: page == 1,
title: const Text("Home"),
leading: const Icon(Icons.home),
onTap: () => page == 1
? Navigator.of(context).pop()
: Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const HomeView(),
),
),
),
ListTile(
selected: page == 2,
title: const Text("Search"),
leading: const Icon(Icons.search),
onTap: () => page == 2
? Navigator.of(context).pop()
: Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const SearchView(),
),
),
),
],
),
);

14
lib/util/storage.dart Normal file
View file

@ -0,0 +1,14 @@
import 'dart:io';
import 'package:path_provider/path_provider.dart';
/// Used to ease up accessing local files
class StorageAccess {
/// Get files in `recent` folder, which contains recently opened pages
static Future<List<File>> get recent async {
var files =
Directory("${(await getApplicationDocumentsDirectory()).path}/recent");
if (!files.existsSync()) files.createSync();
return files.listSync().whereType<File>().toList();
}
}

View file

@ -0,0 +1,49 @@
import 'package:flutter/material.dart';
import 'package:voyagehandbook/util/drawer.dart';
import 'package:voyagehandbook/util/storage.dart';
class HomeView extends StatefulWidget {
const HomeView({super.key});
@override
State<HomeView> createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
var _recents = [];
@override
void initState() {
super.initState();
load();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Home")),
drawer: genDrawer(1, context),
body: Center(
child: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width * 0.9,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
(_recents.isEmpty)
? const Flexible(
child: Text(
"You haven't opened anything recently, swipe right and start searching."),
)
: const CircularProgressIndicator()
],
),
),
),
);
}
void load() async {
_recents = await StorageAccess.recent;
setState(() {});
}
}

45
lib/views/search.dart Normal file
View file

@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter/src/widgets/placeholder.dart';
import 'package:voyagehandbook/api/wikimedia.dart';
import '../util/drawer.dart';
class SearchView extends StatefulWidget {
const SearchView({super.key});
@override
State<SearchView> createState() => _SearchViewState();
}
class _SearchViewState extends State<SearchView> {
final _searchController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Search WikiVoyage")),
drawer: genDrawer(2, context),
body: Center(
child: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width * 0.9,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: _searchController,
),
TextButton(
onPressed: () async {
if (_searchController.text == "") return;
var r = await WikiApi.search(_searchController.text);
print(r[0].excerpt);
},
child: const Text("Search"))
],
),
),
),
);
}
}

View file

@ -1,6 +1,30 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: "503361166f4a100e0d7eb7fb5a62c6f0322512f2bcb48d6922caf98f24b0ab90"
url: "https://pub.dev"
source: hosted
version: "56.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "93fcd81a6716e69864516750590cf1e699420615046bda19100238aa7b429785"
url: "https://pub.dev"
source: hosted
version: "5.8.0"
args:
dependency: transitive
description:
name: args
sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
async:
dependency: transitive
description:
@ -17,6 +41,70 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.1"
build:
dependency: transitive
description:
name: build
sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777"
url: "https://pub.dev"
source: hosted
version: "2.3.1"
build_config:
dependency: transitive
description:
name: build_config
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
url: "https://pub.dev"
source: hosted
version: "1.1.1"
build_daemon:
dependency: transitive
description:
name: build_daemon
sha256: "757153e5d9cd88253cb13f28c2fb55a537dc31fefd98137549895b5beb7c6169"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
sha256: db49b8609ef8c81cca2b310618c3017c00f03a92af44c04d310b907b2d692d95
url: "https://pub.dev"
source: hosted
version: "2.2.0"
build_runner:
dependency: "direct dev"
description:
name: build_runner
sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727
url: "https://pub.dev"
source: hosted
version: "2.3.3"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292"
url: "https://pub.dev"
source: hosted
version: "7.2.7"
built_collection:
dependency: transitive
description:
name: built_collection
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
url: "https://pub.dev"
source: hosted
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
sha256: "31b7c748fd4b9adf8d25d72a4c4a59ef119f12876cf414f94f8af5131d5fa2b0"
url: "https://pub.dev"
source: hosted
version: "8.4.4"
characters:
dependency: transitive
description:
@ -25,6 +113,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.1"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
clock:
dependency: transitive
description:
@ -33,6 +129,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.1"
code_builder:
dependency: transitive
description:
name: code_builder
sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe"
url: "https://pub.dev"
source: hosted
version: "4.4.0"
collection:
dependency: transitive
description:
@ -41,6 +145,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.17.0"
convert:
dependency: transitive
description:
name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
crypto:
dependency: transitive
description:
name: crypto
sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67
url: "https://pub.dev"
source: hosted
version: "3.0.2"
cupertino_icons:
dependency: "direct main"
description:
@ -49,6 +169,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.5"
dart_style:
dependency: transitive
description:
name: dart_style
sha256: "6d691edde054969f0e0f26abb1b30834b5138b963793e56f69d3a9a4435e6352"
url: "https://pub.dev"
source: hosted
version: "2.3.0"
dio:
dependency: "direct main"
description:
@ -57,6 +185,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.0.2"
dynamic_color:
dependency: "direct main"
description:
name: dynamic_color
sha256: c4a508284b14ec4dda5adba2c28b2cdd34fbae1afead7e8c52cad87d51c5405b
url: "https://pub.dev"
source: hosted
version: "1.6.2"
fake_async:
dependency: transitive
description:
@ -81,6 +217,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.1.4"
fixnum:
dependency: transitive
description:
name: fixnum
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
flutter:
dependency: "direct main"
description: flutter
@ -104,6 +248,38 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
url: "https://pub.dev"
source: hosted
version: "3.2.0"
glob:
dependency: transitive
description:
name: glob
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
graphs:
dependency: transitive
description:
name: graphs
sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2
url: "https://pub.dev"
source: hosted
version: "2.2.0"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
url: "https://pub.dev"
source: hosted
version: "3.2.1"
http_parser:
dependency: transitive
description:
@ -112,6 +288,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
io:
dependency: transitive
description:
name: io
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
js:
dependency: transitive
description:
@ -120,6 +304,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.5"
json_annotation:
dependency: "direct main"
description:
name: json_annotation
sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317
url: "https://pub.dev"
source: hosted
version: "4.8.0"
json_serializable:
dependency: "direct main"
description:
name: json_serializable
sha256: dadc08bd61f72559f938dd08ec20dbfec6c709bba83515085ea943d2078d187a
url: "https://pub.dev"
source: hosted
version: "6.6.1"
lints:
dependency: transitive
description:
@ -128,6 +328,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
logging:
dependency: transitive
description:
name: logging
sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
matcher:
dependency: transitive
description:
@ -152,6 +360,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.0"
mime:
dependency: transitive
description:
name: mime
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
url: "https://pub.dev"
source: hosted
version: "1.0.4"
package_config:
dependency: transitive
description:
name: package_config
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
path:
dependency: transitive
description:
@ -224,6 +448,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
pool:
dependency: transitive
description:
name: pool
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
url: "https://pub.dev"
source: hosted
version: "1.5.1"
process:
dependency: transitive
description:
@ -232,6 +464,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.2.4"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17"
url: "https://pub.dev"
source: hosted
version: "2.1.3"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
sha256: ec85d7d55339d85f44ec2b682a82fea340071e8978257e5a43e69f79e98ef50c
url: "https://pub.dev"
source: hosted
version: "1.2.2"
shared_preferences:
dependency: "direct main"
description:
@ -288,11 +536,43 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.5"
shelf:
dependency: transitive
description:
name: shelf
sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c
url: "https://pub.dev"
source: hosted
version: "1.4.0"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8
url: "https://pub.dev"
source: hosted
version: "1.0.3"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_gen:
dependency: transitive
description:
name: source_gen
sha256: c2bea18c95cfa0276a366270afaa2850b09b4a76db95d546f3d003dcc7011298
url: "https://pub.dev"
source: hosted
version: "1.2.7"
source_helper:
dependency: transitive
description:
name: source_helper
sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f"
url: "https://pub.dev"
source: hosted
version: "1.3.3"
source_span:
dependency: transitive
description:
@ -317,6 +597,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.1"
stream_transform:
dependency: transitive
description:
name: stream_transform
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
@ -341,6 +629,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.4.16"
timing:
dependency: transitive
description:
name: timing
sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
typed_data:
dependency: transitive
description:
@ -357,6 +653,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
watcher:
dependency: transitive
description:
name: watcher
sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b
url: "https://pub.dev"
source: hosted
version: "2.3.0"
win32:
dependency: transitive
description:
@ -373,6 +685,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
yaml:
dependency: transitive
description:
name: yaml
sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
sdks:
dart: ">=2.19.4 <3.0.0"
flutter: ">=3.0.0"
flutter: ">=3.4.0-17.0.pre"

View file

@ -38,6 +38,9 @@ dependencies:
shared_preferences: ^2.0.18
path_provider: ^2.0.13
dio: ^5.0.2
json_serializable: ^6.6.1
json_annotation: ^4.8.0
dynamic_color: ^1.6.2
dev_dependencies:
flutter_test:
@ -49,6 +52,7 @@ dev_dependencies:
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^2.0.0
build_runner: ^2.3.3
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec