remove builds from db if pkg is deleted
fix apibuilder interval refreshes refreshing widgets not visible
This commit is contained in:
		| @@ -1,9 +1,6 @@ | |||||||
| use crate::repo::repo::{remove_pkg, remove_version}; | use crate::repo::repo::{remove_pkg, remove_version}; | ||||||
| use rocket::serde::json::Json; |  | ||||||
| use rocket::serde::Deserialize; |  | ||||||
| use rocket::{post, State}; | use rocket::{post, State}; | ||||||
| use rocket_okapi::okapi::schemars; | use rocket_okapi::openapi; | ||||||
| use rocket_okapi::{openapi, JsonSchema}; |  | ||||||
| use sea_orm::DatabaseConnection; | use sea_orm::DatabaseConnection; | ||||||
|  |  | ||||||
| #[openapi(tag = "test")] | #[openapi(tag = "test")] | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| use crate::aur::aur::download_pkgbuild; | use crate::aur::aur::download_pkgbuild; | ||||||
| use crate::db::prelude::Packages; |  | ||||||
| use crate::db::prelude::Versions; | 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 crate::pkgbuild::build::build_pkgbuild; | ||||||
| use anyhow::anyhow; | use anyhow::anyhow; | ||||||
| use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, ModelTrait, QueryFilter}; | use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, ModelTrait, QueryFilter}; | ||||||
| @@ -39,6 +39,49 @@ pub async fn add_pkg( | |||||||
|     Ok(pkg_file_name) |     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<()> { | fn repo_add(pkg_file_name: String) -> anyhow::Result<()> { | ||||||
|     let db_file = format!("{REPO_NAME}.db.tar.gz"); |     let db_file = format!("{REPO_NAME}.db.tar.gz"); | ||||||
|  |  | ||||||
| @@ -79,40 +122,6 @@ fn repo_remove(pkg_file_name: String) -> anyhow::Result<()> { | |||||||
|     Ok(()) |     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<()> { | async fn rem_ver(db: &DatabaseConnection, version: versions::Model) -> anyhow::Result<()> { | ||||||
|     if let Some(filename) = version.file_name.clone() { |     if let Some(filename) = version.file_name.clone() { | ||||||
|         // so repo-remove only supports passing a package name and removing the whole package |         // so repo-remove only supports passing a package name and removing the whole package | ||||||
|   | |||||||
| @@ -2,8 +2,9 @@ import 'dart:async'; | |||||||
| 
 | 
 | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
|  | import 'package:visibility_detector/visibility_detector.dart'; | ||||||
| 
 | 
 | ||||||
| import 'BaseProvider.dart'; | import '../../providers/BaseProvider.dart'; | ||||||
| 
 | 
 | ||||||
| class APIBuilder<T extends BaseProvider, K, DTO> extends StatefulWidget { | class APIBuilder<T extends BaseProvider, K, DTO> extends StatefulWidget { | ||||||
|   const APIBuilder( |   const APIBuilder( | ||||||
| @@ -25,6 +26,7 @@ class APIBuilder<T extends BaseProvider, K, DTO> extends StatefulWidget { | |||||||
| class _APIBuilderState<T extends BaseProvider, K, DTO> | class _APIBuilderState<T extends BaseProvider, K, DTO> | ||||||
|     extends State<APIBuilder<T, K, DTO>> { |     extends State<APIBuilder<T, K, DTO>> { | ||||||
|   Timer? timer; |   Timer? timer; | ||||||
|  |   bool visible = true; | ||||||
| 
 | 
 | ||||||
|   @override |   @override | ||||||
|   void initState() { |   void initState() { | ||||||
| @@ -33,12 +35,10 @@ class _APIBuilderState<T extends BaseProvider, K, DTO> | |||||||
| 
 | 
 | ||||||
|     if (widget.interval != null) { |     if (widget.interval != null) { | ||||||
|       timer = Timer.periodic(widget.interval!, (Timer t) { |       timer = Timer.periodic(widget.interval!, (Timer t) { | ||||||
|         final RenderObject? box = context.findRenderObject(); |         if (visible) { | ||||||
|         print(box); |  | ||||||
|         print(context.mounted); |  | ||||||
| 
 |  | ||||||
|           Provider.of<T>(context, listen: false) |           Provider.of<T>(context, listen: false) | ||||||
|               .refresh(context, dto: widget.dto); |               .refresh(context, dto: widget.dto); | ||||||
|  |         } | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -53,7 +53,21 @@ class _APIBuilderState<T extends BaseProvider, K, DTO> | |||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     final Future<K> fut = Provider.of<T>(context).data as Future<K>; |     final Future<K> fut = Provider.of<T>(context).data as Future<K>; | ||||||
| 
 | 
 | ||||||
|     return FutureBuilder<K>( |     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<K>( | ||||||
|         future: fut, |         future: fut, | ||||||
|         builder: (context, snapshot) { |         builder: (context, snapshot) { | ||||||
|           if (snapshot.hasData) { |           if (snapshot.hasData) { | ||||||
| @@ -62,6 +76,7 @@ class _APIBuilderState<T extends BaseProvider, K, DTO> | |||||||
|             return widget.onLoad(); |             return widget.onLoad(); | ||||||
|           } |           } | ||||||
|         }, |         }, | ||||||
|  |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -4,7 +4,7 @@ import 'package:aurcache/api/builds.dart'; | |||||||
| import 'package:aurcache/components/builds_table.dart'; | import 'package:aurcache/components/builds_table.dart'; | ||||||
| import 'package:aurcache/models/build.dart'; | import 'package:aurcache/models/build.dart'; | ||||||
| import 'package:aurcache/components/dashboard/your_packages.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:aurcache/providers/builds_provider.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:go_router/go_router.dart'; | import 'package:go_router/go_router.dart'; | ||||||
| @@ -41,6 +41,7 @@ class _RecentBuildsState extends State<RecentBuilds> { | |||||||
|           SizedBox( |           SizedBox( | ||||||
|             width: double.infinity, |             width: double.infinity, | ||||||
|             child: APIBuilder<BuildsProvider, List<Build>, BuildsDTO>( |             child: APIBuilder<BuildsProvider, List<Build>, BuildsDTO>( | ||||||
|  |               key: const Key("Builds on dashboard"), | ||||||
|               dto: BuildsDTO(limit: 10), |               dto: BuildsDTO(limit: 10), | ||||||
|               interval: const Duration(seconds: 10), |               interval: const Duration(seconds: 10), | ||||||
|               onLoad: () => const Text("no data"), |               onLoad: () => const Text("no data"), | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import 'dart:async'; | import 'dart:async'; | ||||||
|  |  | ||||||
| import 'package:aurcache/api/packages.dart'; | 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:aurcache/providers/packages_provider.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:go_router/go_router.dart'; | import 'package:go_router/go_router.dart'; | ||||||
| @@ -44,7 +44,7 @@ class _YourPackagesState extends State<YourPackages> { | |||||||
|             child: SizedBox( |             child: SizedBox( | ||||||
|               width: double.infinity, |               width: double.infinity, | ||||||
|               child: APIBuilder<PackagesProvider, List<Package>, Object>( |               child: APIBuilder<PackagesProvider, List<Package>, Object>( | ||||||
|                 key: GlobalKey(), |                 key: Key("Packages on dashboard"), | ||||||
|                 interval: const Duration(seconds: 10), |                 interval: const Duration(seconds: 10), | ||||||
|                 onData: (data) { |                 onData: (data) { | ||||||
|                   return DataTable( |                   return DataTable( | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| 
 | 
 | ||||||
| import '../utils/responsive.dart'; | import '../../utils/responsive.dart'; | ||||||
| import '../screens/dashboard_screen.dart'; | import '../../screens/dashboard_screen.dart'; | ||||||
| import 'side_menu.dart'; | import 'side_menu.dart'; | ||||||
| 
 | 
 | ||||||
| class MenuShell extends StatelessWidget { | class MenuShell extends StatelessWidget { | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| import 'package:aurcache/screens/build_screen.dart'; | import 'package:aurcache/screens/build_screen.dart'; | ||||||
| import 'package:aurcache/screens/builds_screen.dart'; | import 'package:aurcache/screens/builds_screen.dart'; | ||||||
| import 'package:aurcache/screens/dashboard_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:aurcache/screens/package_screen.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:go_router/go_router.dart'; | import 'package:go_router/go_router.dart'; | ||||||
| @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; | |||||||
| import 'package:flutter_svg/flutter_svg.dart'; | import 'package:flutter_svg/flutter_svg.dart'; | ||||||
| import 'package:go_router/go_router.dart'; | import 'package:go_router/go_router.dart'; | ||||||
| 
 | 
 | ||||||
| import '../constants/color_constants.dart'; | import '../../constants/color_constants.dart'; | ||||||
| 
 | 
 | ||||||
| class SideMenu extends StatelessWidget { | class SideMenu extends StatelessWidget { | ||||||
|   const SideMenu({ |   const SideMenu({ | ||||||
| @@ -86,7 +86,7 @@ class DrawerListTile extends StatelessWidget { | |||||||
|       ), |       ), | ||||||
|       title: Text( |       title: Text( | ||||||
|         title, |         title, | ||||||
|         style: TextStyle(color: Colors.white54), |         style: const TextStyle(color: Colors.white54), | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| @@ -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/build_provider.dart'; | ||||||
| import 'package:aurcache/providers/builds_provider.dart'; | import 'package:aurcache/providers/builds_provider.dart'; | ||||||
| import 'package:aurcache/providers/package_provider.dart'; | import 'package:aurcache/providers/package_provider.dart'; | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import 'dart:async'; | |||||||
| import 'package:aurcache/api/builds.dart'; | import 'package:aurcache/api/builds.dart'; | ||||||
| import 'package:aurcache/components/build_output.dart'; | import 'package:aurcache/components/build_output.dart'; | ||||||
| import 'package:aurcache/models/build.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:aurcache/providers/build_provider.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:go_router/go_router.dart'; | import 'package:go_router/go_router.dart'; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import 'package:aurcache/components/builds_table.dart'; | 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:aurcache/providers/builds_provider.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import '../constants/color_constants.dart'; | import '../constants/color_constants.dart'; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import 'package:aurcache/api/statistics.dart'; | 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:aurcache/providers/stats_provider.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:provider/provider.dart'; | import 'package:provider/provider.dart'; | ||||||
|   | |||||||
| @@ -2,10 +2,11 @@ import 'dart:async'; | |||||||
|  |  | ||||||
| import 'package:aurcache/api/builds.dart'; | import 'package:aurcache/api/builds.dart'; | ||||||
| import 'package:aurcache/api/packages.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:aurcache/providers/builds_provider.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
| import 'package:go_router/go_router.dart'; | import 'package:go_router/go_router.dart'; | ||||||
|  | import 'package:provider/provider.dart'; | ||||||
|  |  | ||||||
| import '../api/API.dart'; | import '../api/API.dart'; | ||||||
| import '../components/builds_table.dart'; | import '../components/builds_table.dart'; | ||||||
| @@ -15,6 +16,7 @@ import '../models/build.dart'; | |||||||
| import '../models/package.dart'; | import '../models/package.dart'; | ||||||
| import '../providers/package_provider.dart'; | import '../providers/package_provider.dart'; | ||||||
| import '../providers/packages_provider.dart'; | import '../providers/packages_provider.dart'; | ||||||
|  | import '../providers/stats_provider.dart'; | ||||||
|  |  | ||||||
| class PackageScreen extends StatefulWidget { | class PackageScreen extends StatefulWidget { | ||||||
|   const PackageScreen({super.key, required this.pkgID}); |   const PackageScreen({super.key, required this.pkgID}); | ||||||
| @@ -61,6 +63,15 @@ class _PackageScreenState extends State<PackageScreen> { | |||||||
|                             final succ = await API.deletePackage(pkg.id); |                             final succ = await API.deletePackage(pkg.id); | ||||||
|                             if (succ) { |                             if (succ) { | ||||||
|                               context.pop(); |                               context.pop(); | ||||||
|  |  | ||||||
|  |                               Provider.of<PackagesProvider>(context, | ||||||
|  |                                       listen: false) | ||||||
|  |                                   .refresh(context); | ||||||
|  |                               Provider.of<BuildsProvider>(context, | ||||||
|  |                                       listen: false) | ||||||
|  |                                   .refresh(context); | ||||||
|  |                               Provider.of<StatsProvider>(context, listen: false) | ||||||
|  |                                   .refresh(context); | ||||||
|                             } |                             } | ||||||
|                           }, |                           }, | ||||||
|                           child: const Text( |                           child: const Text( | ||||||
| @@ -92,7 +103,7 @@ class _PackageScreenState extends State<PackageScreen> { | |||||||
|                             width: double.infinity, |                             width: double.infinity, | ||||||
|                             child: APIBuilder<BuildsProvider, List<Build>, |                             child: APIBuilder<BuildsProvider, List<Build>, | ||||||
|                                 BuildsDTO>( |                                 BuildsDTO>( | ||||||
|                               key: GlobalKey(), |                               key: const Key("Builds on Package info"), | ||||||
|                               dto: BuildsDTO(pkgID: pkg.id), |                               dto: BuildsDTO(pkgID: pkg.id), | ||||||
|                               interval: const Duration(seconds: 5), |                               interval: const Duration(seconds: 5), | ||||||
|                               onData: (data) { |                               onData: (data) { | ||||||
|   | |||||||
| @@ -405,6 +405,14 @@ packages: | |||||||
|       url: "https://pub.dev" |       url: "https://pub.dev" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "2.1.4" |     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: |   web: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
|   | |||||||
| @@ -41,6 +41,7 @@ dependencies: | |||||||
|   dio: ^5.3.3 |   dio: ^5.3.3 | ||||||
|   go_router: ^13.0.0 |   go_router: ^13.0.0 | ||||||
|   provider: ^6.1.1 |   provider: ^6.1.1 | ||||||
|  |   visibility_detector: ^0.4.0+2 | ||||||
|  |  | ||||||
| dev_dependencies: | dev_dependencies: | ||||||
|   flutter_test: |   flutter_test: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user