add apibuilder widget to make api callsmore straightforward and data updateable from everywhere through providers

This commit is contained in:
2023-12-30 22:23:42 +01:00
parent 6ca462e2d2
commit fca5df4c70
28 changed files with 812 additions and 341 deletions

View File

@ -0,0 +1,67 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'BaseProvider.dart';
class APIBuilder<T extends BaseProvider, K, DTO> extends StatefulWidget {
const APIBuilder(
{super.key,
required this.onLoad,
required this.onData,
this.interval,
this.dto});
final DTO? dto;
final Duration? interval;
final Widget Function() onLoad;
final Widget Function(K t) onData;
@override
State<APIBuilder<T, K, DTO>> createState() => _APIBuilderState<T, K, DTO>();
}
class _APIBuilderState<T extends BaseProvider, K, DTO>
extends State<APIBuilder<T, K, DTO>> {
Timer? timer;
@override
void initState() {
super.initState();
Provider.of<T>(context, listen: false).loadFuture(context, dto: widget.dto);
if (widget.interval != null) {
timer = Timer.periodic(widget.interval!, (Timer t) {
final RenderObject? box = context.findRenderObject();
print(box);
print(context.mounted);
Provider.of<T>(context, listen: false)
.refresh(context, dto: widget.dto);
});
}
}
@override
void dispose() {
super.dispose();
timer?.cancel();
}
@override
Widget build(BuildContext context) {
final Future<K> fut = Provider.of<T>(context).data as Future<K>;
return FutureBuilder<K>(
future: fut,
builder: (context, snapshot) {
if (snapshot.hasData) {
return widget.onData(snapshot.data!);
} else {
return widget.onLoad();
}
},
);
}
}

View File

@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
abstract class BaseProvider<T, DTO> with ChangeNotifier {
late Future<T> data;
loadFuture(context, {DTO? dto});
refresh(context, {DTO? dto}) {
loadFuture(context, dto: dto);
notifyListeners();
}
}

View File

@ -0,0 +1,19 @@
import 'package:aurcache/api/builds.dart';
import '../api/API.dart';
import '../models/build.dart';
import 'BaseProvider.dart';
class BuildDTO {
final int buildID;
BuildDTO({required this.buildID});
}
class BuildProvider extends BaseProvider<Build, BuildDTO> {
@override
loadFuture(context, {dto}) {
// todo search solution to force an exising dto
data = API.getBuild(dto!.buildID);
}
}

View File

@ -0,0 +1,23 @@
import 'package:aurcache/api/builds.dart';
import '../api/API.dart';
import '../models/build.dart';
import 'BaseProvider.dart';
class BuildsDTO {
final int? pkgID;
final int? limit;
BuildsDTO({this.pkgID, this.limit});
}
class BuildsProvider extends BaseProvider<List<Build>, BuildsDTO> {
@override
loadFuture(context, {dto}) {
if (dto != null) {
data = API.listAllBuilds(pkgID: dto.pkgID, limit: dto.limit);
} else {
data = API.listAllBuilds();
}
}
}

View File

@ -1 +0,0 @@

View File

@ -0,0 +1,19 @@
import 'package:aurcache/api/packages.dart';
import '../api/API.dart';
import '../models/package.dart';
import 'BaseProvider.dart';
class PackageDTO {
final int pkgID;
PackageDTO({required this.pkgID});
}
class PackageProvider extends BaseProvider<Package, PackageDTO> {
@override
loadFuture(context, {dto}) {
// todo search solution to force an exising dto
data = API.getPackage(dto!.pkgID);
}
}

View File

@ -0,0 +1,11 @@
import 'package:aurcache/api/packages.dart';
import 'package:aurcache/providers/BaseProvider.dart';
import '../api/API.dart';
class PackagesProvider extends BaseProvider {
@override
loadFuture(context, {dto}) {
data = API.listPackages();
}
}

View File

@ -0,0 +1,11 @@
import 'package:aurcache/api/statistics.dart';
import '../api/API.dart';
import 'BaseProvider.dart';
class StatsProvider extends BaseProvider {
@override
loadFuture(context, {dto}) {
data = API.listStats();
}
}