diff --git a/lib/dev_tools/app_dev_tools.dart b/lib/dev_tools/app_dev_tools.dart index 919e0128a3..cee604c94e 100644 --- a/lib/dev_tools/app_dev_tools.dart +++ b/lib/dev_tools/app_dev_tools.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'package:ardrive/dev_tools/drives_health_check.dart'; import 'package:ardrive/dev_tools/thumbnail_generator_poc.dart'; import 'package:ardrive/main.dart'; -import 'package:ardrive/pages/drive_detail/components/hover_widget.dart'; import 'package:ardrive/services/config/config.dart'; import 'package:ardrive/turbo/topup/blocs/payment_form/payment_form_bloc.dart'; import 'package:ardrive/utils/logger.dart'; @@ -364,23 +363,6 @@ class AppConfigWindowManagerState extends State { type: ArDriveDevToolOptionType.bool, ); - final ArDriveDevToolOption fakeTurboCredits = ArDriveDevToolOption( - name: 'fakeTurboCredits', - value: config.fakeTurboCredits, - onChange: (value) { - late AppConfig newConfig; - if (value == null) { - newConfig = config.copyWith(unsetFakeTurboCredits: true); - } else { - newConfig = config.copyWith(fakeTurboCredits: value); - } - setState(() { - configService.updateAppConfig(newConfig); - }); - }, - type: ArDriveDevToolOptionType.turboCredits, - ); - final ArDriveDevToolOption topUpDryRun = ArDriveDevToolOption( name: 'topUpDryRun', value: config.topUpDryRun, @@ -412,82 +394,99 @@ class AppConfigWindowManagerState extends State { autoSyncIntervalInSecondsOption, turboSetDefaultData, forceNoFreeThanksToTurbo, - fakeTurboCredits, topUpDryRun, reloadOption, resetOptions, ]; + final typography = ArDriveTypographyNew.of(context); + return DraggableWindow( windowTitle: _windowTitle, child: SingleChildScrollView( primary: true, child: Column( children: [ - const SizedBox(height: 16), + const SizedBox(height: 48), FutureBuilder( future: _readConfigsFromEnv(), builder: (context, snapshot) { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ArDriveButton( - text: 'dev env', - onPressed: () { - setState(() { - _windowTitle.value = 'Reloading...'; - - configService.updateAppConfig( - AppConfig.fromJson(snapshot.data![0]), - ); - }); - - Future.delayed(const Duration(seconds: 1), () { - setState(() { - _windowTitle.value = 'Dev config'; - reloadPage(); - }); - }); - }, - ), - ArDriveButton( - text: 'staging env', - onPressed: () { - setState(() { - _windowTitle.value = 'Reloading...'; - - configService.updateAppConfig( - AppConfig.fromJson(snapshot.data![2]), - ); - }); - - Future.delayed(const Duration(seconds: 1), () { - setState(() { - _windowTitle.value = 'Staging config'; - reloadPage(); - }); - }); - }, - ), - ArDriveButton( - text: 'prod env', - onPressed: () { - setState(() { - _windowTitle.value = 'Reloading...'; - - configService.updateAppConfig( - AppConfig.fromJson(snapshot.data![1]), - ); - }); - - Future.delayed(const Duration(seconds: 1), () { - setState(() { - _windowTitle.value = 'Prod config'; - }); - }); - }, - ) - ], + return Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Flexible( + child: ArDriveButtonNew( + text: 'dev env', + typography: typography, + variant: ButtonVariant.primary, + onPressed: () { + setState(() { + _windowTitle.value = 'Reloading...'; + + configService.updateAppConfig( + AppConfig.fromJson(snapshot.data![0]), + ); + }); + + Future.delayed(const Duration(seconds: 1), () { + setState(() { + _windowTitle.value = 'Dev config'; + reloadPage(); + }); + }); + }, + ), + ), + const SizedBox(width: 16), + Flexible( + child: ArDriveButtonNew( + text: 'staging env', + variant: ButtonVariant.primary, + typography: typography, + onPressed: () { + setState(() { + _windowTitle.value = 'Reloading...'; + + configService.updateAppConfig( + AppConfig.fromJson(snapshot.data![2]), + ); + }); + + Future.delayed(const Duration(seconds: 1), () { + setState(() { + _windowTitle.value = 'Staging config'; + reloadPage(); + }); + }); + }, + ), + ), + const SizedBox(width: 16), + Flexible( + child: ArDriveButtonNew( + text: 'prod env', + variant: ButtonVariant.primary, + typography: typography, + onPressed: () { + setState(() { + _windowTitle.value = 'Reloading...'; + + configService.updateAppConfig( + AppConfig.fromJson(snapshot.data![1]), + ); + }); + + Future.delayed(const Duration(seconds: 1), () { + setState(() { + _windowTitle.value = 'Prod config'; + }); + }); + }, + ), + ) + ], + ), ); }), ListView.separated( @@ -524,7 +523,7 @@ class AppConfigWindowManagerState extends State { Widget buildOption(ArDriveDevToolOption option) { switch (option.type) { case ArDriveDevToolOptionType.text: - return ArDriveTextField( + return ArDriveTextFieldNew( label: option.name, initialValue: option.value, onFieldSubmitted: (value) { @@ -542,7 +541,7 @@ class AppConfigWindowManagerState extends State { }, ); case ArDriveDevToolOptionType.number: - return ArDriveTextField( + return ArDriveTextFieldNew( label: option.name, initialValue: option.value.toString(), onFieldSubmitted: (value) { @@ -553,7 +552,9 @@ class AppConfigWindowManagerState extends State { ); case ArDriveDevToolOptionType.button: - return ArDriveButton( + return ArDriveButtonNew( + variant: ButtonVariant.primary, + typography: ArDriveTypographyNew.of(context), text: option.name, onPressed: () { option.onChange(option.value); @@ -562,8 +563,9 @@ class AppConfigWindowManagerState extends State { ); case ArDriveDevToolOptionType.buttonTertiary: - return ArDriveButton( - style: ArDriveButtonStyle.tertiary, + return ArDriveButtonNew( + variant: ButtonVariant.outline, + typography: ArDriveTypographyNew.of(context), text: option.name, onPressed: () => option.onChange(option.value), ); @@ -695,16 +697,21 @@ class DraggableWindow extends HookWidget { ), Align( alignment: Alignment.topRight, - child: ArDriveIconButton( - icon: ArDriveIcons.closeCircle( - color: ArDriveTheme.of(context) - .themeData - .colors - .themeBgCanvas, + child: Padding( + padding: const EdgeInsets.only(top: 20, right: 8), + child: ArDriveClickArea( + child: GestureDetector( + onTap: () { + ArDriveDevTools().closeDevTools(); + }, + child: ArDriveIcons.x( + color: ArDriveTheme.of(context) + .themeData + .colorTokens + .iconLow, + ), + ), ), - onPressed: () { - ArDriveDevTools().closeDevTools(); - }, ), ), ], diff --git a/lib/dev_tools/drives_health_check.dart b/lib/dev_tools/drives_health_check.dart index bcbb2cf722..00b0eba046 100644 --- a/lib/dev_tools/drives_health_check.dart +++ b/lib/dev_tools/drives_health_check.dart @@ -8,6 +8,7 @@ import 'package:ardrive_ui/ardrive_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:http/http.dart' as http; +import 'package:retry/retry.dart'; class DrivesHealthCheckModal extends StatefulWidget { const DrivesHealthCheckModal({super.key}); @@ -33,11 +34,11 @@ class _DrivesHealthCheckModalState extends State { this.drives = drives; }); - processDrivesInSequency(); + processDrivesSequentially(); }); } - Future processDrivesInSequency() async { + Future processDrivesSequentially() async { final driveDao = context.read(); for (final drive in drives) { @@ -48,10 +49,10 @@ class _DrivesHealthCheckModalState extends State { ); driveStatuses.add(status); - - setState(() {}); } + setState(() {}); + for (final currentStatus in driveStatuses) { final files = await (driveDao.select(driveDao.fileEntries) ..where((tbl) => tbl.driveId.equals(currentStatus.drive.id))) @@ -83,188 +84,188 @@ class _DrivesHealthCheckModalState extends State { Widget build(BuildContext context) { final typography = ArDriveTypographyNew.of(context); - if (driveStatuses.isNotEmpty) { - return SizedBox( - child: ArDriveModalNew( - constraints: BoxConstraints( - maxHeight: MediaQuery.of(context).size.height * 0.9, - maxWidth: MediaQuery.of(context).size.width * 0.8, - minHeight: MediaQuery.of(context).size.height * 0.9, - ), - content: Column( - children: [ - Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Flexible( - flex: 2, - child: SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text('Drives', - style: typography.heading4( - fontWeight: ArFontWeight.bold, - )), - Text('Click on a drive to view details', - style: typography.paragraphNormal( - fontWeight: ArFontWeight.semiBold, - )), - const SizedBox( - height: 8, - ), - SizedBox( - height: MediaQuery.of(context).size.height * 0.72, - child: ListView.separated( - itemCount: driveStatuses.length, - addAutomaticKeepAlives: true, - separatorBuilder: (context, index) => - const Divider(), - shrinkWrap: true, - itemBuilder: (context, index) { - final driveStatus = driveStatuses[index]; - - return ArDriveClickArea( - child: GestureDetector( - onTap: () { - setState(() { - selectedDriveStatus = driveStatus; - }); - }, - child: DriveHealthCheckTile( - status: driveStatus, - key: Key(driveStatus.drive.id), - isSelected: - selectedDriveStatus.drive.id == - driveStatus.drive.id, - ), - ), - ); - }), - ), - ], - ), - ), - ), - const SizedBox(width: 20), - Flexible( - flex: 1, + if (driveStatuses.isEmpty) { + return const Center( + child: CircularProgressIndicator(), + ); + } + + return SizedBox( + child: ArDriveModalNew( + constraints: BoxConstraints( + maxHeight: MediaQuery.of(context).size.height * 0.9, + maxWidth: MediaQuery.of(context).size.width * 0.8, + minHeight: MediaQuery.of(context).size.height * 0.9, + ), + content: Column( + children: [ + Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Flexible( + flex: 2, + child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text('Drives', + style: typography.heading4( + fontWeight: ArFontWeight.bold, + )), + Text('Click on a drive to view details', + style: typography.paragraphNormal( + fontWeight: ArFontWeight.semiBold, + )), const SizedBox( height: 8, ), - Text( - 'Drive: ${selectedDriveStatus.drive.name}', - style: typography.paragraphLarge( - fontWeight: ArFontWeight.bold, - ), + SizedBox( + height: MediaQuery.of(context).size.height * 0.72, + child: ListView.separated( + itemCount: driveStatuses.length, + addAutomaticKeepAlives: true, + separatorBuilder: (context, index) => + const Divider(), + shrinkWrap: true, + itemBuilder: (context, index) { + final driveStatus = driveStatuses[index]; + + return ArDriveClickArea( + child: GestureDetector( + onTap: () { + setState(() { + selectedDriveStatus = driveStatus; + }); + }, + child: DriveHealthCheckTile( + status: driveStatus, + key: Key(driveStatus.drive.id), + isSelected: + selectedDriveStatus.drive.id == + driveStatus.drive.id, + ), + ), + ); + }), ), - Text('Success Files', - style: typography.paragraphLarge()), - const SizedBox( - height: 8, + ], + ), + ), + ), + const SizedBox(width: 20), + Flexible( + flex: 1, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + height: 8, + ), + Text( + 'Selected Drive: ${selectedDriveStatus.drive.name}', + style: typography.paragraphLarge( + fontWeight: ArFontWeight.bold, ), - Flexible( - flex: 1, - child: ArDriveCard( - content: ConstrainedBox( - constraints: BoxConstraints( - maxHeight: - MediaQuery.of(context).size.height * 0.32, - ), - child: Builder(builder: (context) { - final successFiles = selectedDriveStatus.files - .where((element) => element.isSuccess) - .toList(); - if (successFiles.isEmpty) { - return const Center( - child: Text('No files found'), - ); - } - - return ListView.builder( - itemCount: successFiles.length, - addAutomaticKeepAlives: true, - shrinkWrap: true, - itemBuilder: (context, index) { - final status = successFiles[index]; - - return FileHealthCheckTile( - status: status, - onFinish: () async {}, - ); - }); - }), + ), + Text('Success Files - ${selectedDriveStatus.drive.name}', + style: typography.paragraphLarge()), + const SizedBox( + height: 8, + ), + Flexible( + flex: 1, + child: ArDriveCard( + content: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: + MediaQuery.of(context).size.height * 0.32, ), + child: Builder(builder: (context) { + final successFiles = selectedDriveStatus.files + .where((element) => element.isSuccess) + .toList(); + if (successFiles.isEmpty) { + return const Center( + child: Text('No files found'), + ); + } + + return ListView.builder( + itemCount: successFiles.length, + addAutomaticKeepAlives: true, + shrinkWrap: true, + itemBuilder: (context, index) { + final status = successFiles[index]; + + return FileHealthCheckTile( + status: status, + onFinish: () async {}, + ); + }); + }), ), ), - const SizedBox( - height: 20, - ), - Text('Failed Files', - style: typography.paragraphLarge()), - const SizedBox( - height: 8, - ), - Flexible( - flex: 1, - child: ArDriveCard( - content: ConstrainedBox( - constraints: BoxConstraints( - maxHeight: - MediaQuery.of(context).size.height * 0.32, - ), - child: Builder(builder: (context) { - final failedFiles = selectedDriveStatus.files - .where((element) => element.isFailed) - .toList(); - if (failedFiles.isEmpty) { - return const Center( - child: Text('No files found'), - ); - } - return ListView.builder( - itemCount: failedFiles.length, - addAutomaticKeepAlives: true, - shrinkWrap: true, - itemBuilder: (context, index) { - final status = failedFiles[index]; - - return FileHealthCheckTile( - status: status, - onFinish: () async {}, - ); - }); - }), + ), + const SizedBox( + height: 20, + ), + Text('Failed Files - ${selectedDriveStatus.drive.name}', + style: typography.paragraphLarge()), + const SizedBox( + height: 8, + ), + Flexible( + flex: 1, + child: ArDriveCard( + content: ConstrainedBox( + constraints: BoxConstraints( + maxHeight: + MediaQuery.of(context).size.height * 0.32, ), + child: Builder(builder: (context) { + final failedFiles = selectedDriveStatus.files + .where((element) => element.isFailed) + .toList(); + if (failedFiles.isEmpty) { + return const Center( + child: Text('No files found'), + ); + } + return ListView.builder( + itemCount: failedFiles.length, + addAutomaticKeepAlives: true, + shrinkWrap: true, + itemBuilder: (context, index) { + final status = failedFiles[index]; + + return FileHealthCheckTile( + status: status, + onFinish: () async {}, + ); + }); + }), ), ), - ], - ), + ), + ], ), - ], - ), - const SizedBox( - height: 8, - ), - Text( - 'Drives Loaded: ${driveStatuses.where((element) => !element.isLoading).length} of ${driveStatuses.length}', - style: typography.paragraphLarge( - fontWeight: ArFontWeight.bold, ), + ], + ), + const SizedBox( + height: 8, + ), + Text( + 'Drives Loaded: ${driveStatuses.where((element) => !element.isLoading).length} of ${driveStatuses.length}', + style: typography.paragraphLarge( + fontWeight: ArFontWeight.bold, ), - ], - ), + ), + ], ), - ); - } - - return const Center( - child: CircularProgressIndicator(), + ), ); } @@ -278,11 +279,14 @@ class _DrivesHealthCheckModalState extends State { if (files.isNotEmpty) { final file = files.removeAt(0); checkHealth(file, driveStatus).then((_) { + if (files.isEmpty) { + controller.close(); + return; + } + controller.add(null); setState(() {}); }); - } else { - controller.close(); } } @@ -308,7 +312,8 @@ class _DrivesHealthCheckModalState extends State { final url = '${arweave.client.api.gatewayUrl.origin}/raw/${file.dataTxId}'; - final response = await http.head(Uri.parse(url)); + final response = await retry(() async => await http.head(Uri.parse(url)), + maxDelay: const Duration(seconds: 300)); logger.d( 'Checking health of ${file.name}. Response: ${response.statusCode}'); @@ -331,6 +336,7 @@ class _DrivesHealthCheckModalState extends State { setState(() {}); } catch (e) { + logger.d('Error checking health of ${file.name}. Error: $e'); driveStatus.files.add(FileHealthCheckStatus( file: file, isSuccess: false, @@ -341,8 +347,11 @@ class _DrivesHealthCheckModalState extends State { } class DriveHealthCheckTile extends StatefulWidget { - const DriveHealthCheckTile( - {super.key, required this.status, this.isSelected = false}); + const DriveHealthCheckTile({ + super.key, + required this.status, + this.isSelected = false, + }); final DriveHealthCheckStatus status; final bool isSelected; diff --git a/lib/download/ardrive_downloader.dart b/lib/download/ardrive_downloader.dart index e17804a71c..80bd9375e7 100644 --- a/lib/download/ardrive_downloader.dart +++ b/lib/download/ardrive_downloader.dart @@ -25,8 +25,7 @@ abstract class ArDriveDownloader { String? cipher, String? cipherIvString, }); - - Future downloadToMemory({ + Future downloadToMemory({ required TransactionCommonMixin dataTx, required int fileSize, required String fileName, @@ -38,7 +37,6 @@ abstract class ArDriveDownloader { String? cipher, String? cipherIvString, }); - Future abortDownload(); factory ArDriveDownloader({ diff --git a/lib/pages/drive_detail/components/drive_explorer_item_tile.dart b/lib/pages/drive_detail/components/drive_explorer_item_tile.dart index 6693eb0782..19483c5a2f 100644 --- a/lib/pages/drive_detail/components/drive_explorer_item_tile.dart +++ b/lib/pages/drive_detail/components/drive_explorer_item_tile.dart @@ -93,7 +93,6 @@ class DriveExplorerItemTileLeading extends StatelessWidget { Widget _buildFileIcon(BuildContext context) { if (item is FileDataTableItem && FileTypeHelper.isImage(item.contentType)) { final file = item as FileDataTableItem; - // final url = '${Arweave().api.gatewayUrl.origin}/raw/${file.dataTxId}'; return ArDriveCard( width: 30,