diff --git a/backend/src/api/remove.rs b/backend/src/api/remove.rs index 21c52a2..96344e2 100644 --- a/backend/src/api/remove.rs +++ b/backend/src/api/remove.rs @@ -1,9 +1,6 @@ use crate::repo::repo::{remove_pkg, remove_version}; -use rocket::serde::json::Json; -use rocket::serde::Deserialize; use rocket::{post, State}; -use rocket_okapi::okapi::schemars; -use rocket_okapi::{openapi, JsonSchema}; +use rocket_okapi::openapi; use sea_orm::DatabaseConnection; #[openapi(tag = "test")] diff --git a/backend/src/repo/repo.rs b/backend/src/repo/repo.rs index b1fec64..0a607e9 100644 --- a/backend/src/repo/repo.rs +++ b/backend/src/repo/repo.rs @@ -1,7 +1,7 @@ use crate::aur::aur::download_pkgbuild; -use crate::db::prelude::Packages; use crate::db::prelude::Versions; -use crate::db::versions; +use crate::db::prelude::{Builds, Packages}; +use crate::db::{builds, versions}; use crate::pkgbuild::build::build_pkgbuild; use anyhow::anyhow; use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, ModelTrait, QueryFilter}; @@ -39,6 +39,49 @@ pub async fn add_pkg( Ok(pkg_file_name) } +pub async fn remove_pkg(db: &DatabaseConnection, pkg_id: i32) -> anyhow::Result<()> { + let pkg = Packages::find_by_id(pkg_id) + .one(db) + .await? + .ok_or(anyhow!("id not found"))?; + + fs::remove_dir_all(format!("./builds/{}", pkg.name))?; + + let versions = Versions::find() + .filter(versions::Column::PackageId.eq(pkg.id)) + .all(db) + .await?; + + for v in versions { + rem_ver(db, v).await?; + } + + // remove corresponding builds + let builds = Builds::find() + .filter(builds::Column::PkgId.eq(pkg.id)) + .all(db) + .await?; + for b in builds { + b.delete(db).await?; + } + + // remove package db entry + pkg.delete(db).await?; + + Ok(()) +} + +pub async fn remove_version(db: &DatabaseConnection, version_id: i32) -> anyhow::Result<()> { + let version = Versions::find() + .filter(versions::Column::PackageId.eq(version_id)) + .one(db) + .await?; + if let Some(version) = version { + rem_ver(db, version).await?; + } + Ok(()) +} + fn repo_add(pkg_file_name: String) -> anyhow::Result<()> { let db_file = format!("{REPO_NAME}.db.tar.gz"); @@ -79,40 +122,6 @@ fn repo_remove(pkg_file_name: String) -> anyhow::Result<()> { Ok(()) } -pub async fn remove_pkg(db: &DatabaseConnection, pkg_id: i32) -> anyhow::Result<()> { - let pkg = Packages::find_by_id(pkg_id) - .one(db) - .await? - .ok_or(anyhow!("id not found"))?; - - fs::remove_dir_all(format!("./builds/{}", pkg.name))?; - - let versions = Versions::find() - .filter(versions::Column::PackageId.eq(pkg.id)) - .all(db) - .await?; - - for v in versions { - rem_ver(db, v).await?; - } - - // remove package db entry - pkg.delete(db).await?; - - Ok(()) -} - -pub async fn remove_version(db: &DatabaseConnection, version_id: i32) -> anyhow::Result<()> { - let version = Versions::find() - .filter(versions::Column::PackageId.eq(version_id)) - .one(db) - .await?; - if let Some(version) = version { - rem_ver(db, version).await?; - } - Ok(()) -} - async fn rem_ver(db: &DatabaseConnection, version: versions::Model) -> anyhow::Result<()> { if let Some(filename) = version.file_name.clone() { // so repo-remove only supports passing a package name and removing the whole package diff --git a/frontend/lib/providers/APIBuilder.dart b/frontend/lib/components/api/APIBuilder.dart similarity index 54% rename from frontend/lib/providers/APIBuilder.dart rename to frontend/lib/components/api/APIBuilder.dart index 12ca755..7841135 100644 --- a/frontend/lib/providers/APIBuilder.dart +++ b/frontend/lib/components/api/APIBuilder.dart @@ -2,8 +2,9 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:visibility_detector/visibility_detector.dart'; -import 'BaseProvider.dart'; +import '../../providers/BaseProvider.dart'; class APIBuilder extends StatefulWidget { const APIBuilder( @@ -25,6 +26,7 @@ class APIBuilder extends StatefulWidget { class _APIBuilderState extends State> { Timer? timer; + bool visible = true; @override void initState() { @@ -33,12 +35,10 @@ class _APIBuilderState if (widget.interval != null) { timer = Timer.periodic(widget.interval!, (Timer t) { - final RenderObject? box = context.findRenderObject(); - print(box); - print(context.mounted); - - Provider.of(context, listen: false) - .refresh(context, dto: widget.dto); + if (visible) { + Provider.of(context, listen: false) + .refresh(context, dto: widget.dto); + } }); } } @@ -53,15 +53,30 @@ class _APIBuilderState Widget build(BuildContext context) { final Future fut = Provider.of(context).data as Future; - return FutureBuilder( - future: fut, - builder: (context, snapshot) { - if (snapshot.hasData) { - return widget.onData(snapshot.data!); - } else { - return widget.onLoad(); + return VisibilityDetector( + key: widget.key ?? const Key("APIBuilder"), + onVisibilityChanged: (visibilityInfo) { + var visiblePercentage = visibilityInfo.visibleFraction * 100; + + if (mounted) { + setState(() { + visible = visiblePercentage != 0; + }); } + + debugPrint( + 'Widget ${visibilityInfo.key} is ${visiblePercentage}% visible'); }, + child: FutureBuilder( + future: fut, + builder: (context, snapshot) { + if (snapshot.hasData) { + return widget.onData(snapshot.data!); + } else { + return widget.onLoad(); + } + }, + ), ); } } diff --git a/frontend/lib/components/dashboard/recent_builds.dart b/frontend/lib/components/dashboard/recent_builds.dart index b1346f3..fbd55a0 100644 --- a/frontend/lib/components/dashboard/recent_builds.dart +++ b/frontend/lib/components/dashboard/recent_builds.dart @@ -4,7 +4,7 @@ import 'package:aurcache/api/builds.dart'; import 'package:aurcache/components/builds_table.dart'; import 'package:aurcache/models/build.dart'; import 'package:aurcache/components/dashboard/your_packages.dart'; -import 'package:aurcache/providers/APIBuilder.dart'; +import 'package:aurcache/components/api/APIBuilder.dart'; import 'package:aurcache/providers/builds_provider.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; @@ -41,6 +41,7 @@ class _RecentBuildsState extends State { SizedBox( width: double.infinity, child: APIBuilder, BuildsDTO>( + key: const Key("Builds on dashboard"), dto: BuildsDTO(limit: 10), interval: const Duration(seconds: 10), onLoad: () => const Text("no data"), diff --git a/frontend/lib/components/dashboard/your_packages.dart b/frontend/lib/components/dashboard/your_packages.dart index b3d8167..14d5408 100644 --- a/frontend/lib/components/dashboard/your_packages.dart +++ b/frontend/lib/components/dashboard/your_packages.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:aurcache/api/packages.dart'; -import 'package:aurcache/providers/APIBuilder.dart'; +import 'package:aurcache/components/api/APIBuilder.dart'; import 'package:aurcache/providers/packages_provider.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; @@ -44,7 +44,7 @@ class _YourPackagesState extends State { child: SizedBox( width: double.infinity, child: APIBuilder, Object>( - key: GlobalKey(), + key: Key("Packages on dashboard"), interval: const Duration(seconds: 10), onData: (data) { return DataTable( diff --git a/frontend/lib/components/menu_shell.dart b/frontend/lib/components/routing/menu_shell.dart similarity index 91% rename from frontend/lib/components/menu_shell.dart rename to frontend/lib/components/routing/menu_shell.dart index d589d0f..2dcba36 100644 --- a/frontend/lib/components/menu_shell.dart +++ b/frontend/lib/components/routing/menu_shell.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import '../utils/responsive.dart'; -import '../screens/dashboard_screen.dart'; +import '../../utils/responsive.dart'; +import '../../screens/dashboard_screen.dart'; import 'side_menu.dart'; class MenuShell extends StatelessWidget { diff --git a/frontend/lib/components/router.dart b/frontend/lib/components/routing/router.dart similarity index 95% rename from frontend/lib/components/router.dart rename to frontend/lib/components/routing/router.dart index 6789c66..752b534 100644 --- a/frontend/lib/components/router.dart +++ b/frontend/lib/components/routing/router.dart @@ -1,7 +1,7 @@ import 'package:aurcache/screens/build_screen.dart'; import 'package:aurcache/screens/builds_screen.dart'; import 'package:aurcache/screens/dashboard_screen.dart'; -import 'package:aurcache/components/menu_shell.dart'; +import 'package:aurcache/components/routing/menu_shell.dart'; import 'package:aurcache/screens/package_screen.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; diff --git a/frontend/lib/components/side_menu.dart b/frontend/lib/components/routing/side_menu.dart similarity index 95% rename from frontend/lib/components/side_menu.dart rename to frontend/lib/components/routing/side_menu.dart index 3316175..fbdbb32 100644 --- a/frontend/lib/components/side_menu.dart +++ b/frontend/lib/components/routing/side_menu.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:go_router/go_router.dart'; -import '../constants/color_constants.dart'; +import '../../constants/color_constants.dart'; class SideMenu extends StatelessWidget { const SideMenu({ @@ -86,7 +86,7 @@ class DrawerListTile extends StatelessWidget { ), title: Text( title, - style: TextStyle(color: Colors.white54), + style: const TextStyle(color: Colors.white54), ), ); } diff --git a/frontend/lib/main.dart b/frontend/lib/main.dart index 30e2e80..57ef57e 100644 --- a/frontend/lib/main.dart +++ b/frontend/lib/main.dart @@ -1,4 +1,4 @@ -import 'package:aurcache/components/router.dart'; +import 'package:aurcache/components/routing/router.dart'; import 'package:aurcache/providers/build_provider.dart'; import 'package:aurcache/providers/builds_provider.dart'; import 'package:aurcache/providers/package_provider.dart'; diff --git a/frontend/lib/screens/build_screen.dart b/frontend/lib/screens/build_screen.dart index 9d022e6..03d6242 100644 --- a/frontend/lib/screens/build_screen.dart +++ b/frontend/lib/screens/build_screen.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:aurcache/api/builds.dart'; import 'package:aurcache/components/build_output.dart'; import 'package:aurcache/models/build.dart'; -import 'package:aurcache/providers/APIBuilder.dart'; +import 'package:aurcache/components/api/APIBuilder.dart'; import 'package:aurcache/providers/build_provider.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; diff --git a/frontend/lib/screens/builds_screen.dart b/frontend/lib/screens/builds_screen.dart index 3315556..368e39a 100644 --- a/frontend/lib/screens/builds_screen.dart +++ b/frontend/lib/screens/builds_screen.dart @@ -1,5 +1,5 @@ import 'package:aurcache/components/builds_table.dart'; -import 'package:aurcache/providers/APIBuilder.dart'; +import 'package:aurcache/components/api/APIBuilder.dart'; import 'package:aurcache/providers/builds_provider.dart'; import 'package:flutter/material.dart'; import '../constants/color_constants.dart'; diff --git a/frontend/lib/screens/dashboard_screen.dart b/frontend/lib/screens/dashboard_screen.dart index a727f84..4a467cc 100644 --- a/frontend/lib/screens/dashboard_screen.dart +++ b/frontend/lib/screens/dashboard_screen.dart @@ -1,5 +1,5 @@ import 'package:aurcache/api/statistics.dart'; -import 'package:aurcache/providers/APIBuilder.dart'; +import 'package:aurcache/components/api/APIBuilder.dart'; import 'package:aurcache/providers/stats_provider.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; diff --git a/frontend/lib/screens/package_screen.dart b/frontend/lib/screens/package_screen.dart index 3cd8468..a15762e 100644 --- a/frontend/lib/screens/package_screen.dart +++ b/frontend/lib/screens/package_screen.dart @@ -2,10 +2,11 @@ import 'dart:async'; import 'package:aurcache/api/builds.dart'; import 'package:aurcache/api/packages.dart'; -import 'package:aurcache/providers/APIBuilder.dart'; +import 'package:aurcache/components/api/APIBuilder.dart'; import 'package:aurcache/providers/builds_provider.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; import '../api/API.dart'; import '../components/builds_table.dart'; @@ -15,6 +16,7 @@ import '../models/build.dart'; import '../models/package.dart'; import '../providers/package_provider.dart'; import '../providers/packages_provider.dart'; +import '../providers/stats_provider.dart'; class PackageScreen extends StatefulWidget { const PackageScreen({super.key, required this.pkgID}); @@ -61,6 +63,15 @@ class _PackageScreenState extends State { final succ = await API.deletePackage(pkg.id); if (succ) { context.pop(); + + Provider.of(context, + listen: false) + .refresh(context); + Provider.of(context, + listen: false) + .refresh(context); + Provider.of(context, listen: false) + .refresh(context); } }, child: const Text( @@ -92,7 +103,7 @@ class _PackageScreenState extends State { width: double.infinity, child: APIBuilder, BuildsDTO>( - key: GlobalKey(), + key: const Key("Builds on Package info"), dto: BuildsDTO(pkgID: pkg.id), interval: const Duration(seconds: 5), onData: (data) { diff --git a/frontend/pubspec.lock b/frontend/pubspec.lock index 09b5909..45c1ad8 100644 --- a/frontend/pubspec.lock +++ b/frontend/pubspec.lock @@ -405,6 +405,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + visibility_detector: + dependency: "direct main" + description: + name: visibility_detector + sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 + url: "https://pub.dev" + source: hosted + version: "0.4.0+2" web: dependency: transitive description: diff --git a/frontend/pubspec.yaml b/frontend/pubspec.yaml index 73ae70b..26db5c2 100644 --- a/frontend/pubspec.yaml +++ b/frontend/pubspec.yaml @@ -41,6 +41,7 @@ dependencies: dio: ^5.3.3 go_router: ^13.0.0 provider: ^6.1.1 + visibility_detector: ^0.4.0+2 dev_dependencies: flutter_test: