Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement clean up space #119

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Implement clean up space #119

wants to merge 2 commits into from

Conversation

cp-pratik-k
Copy link
Collaborator

@cp-pratik-k cp-pratik-k commented Jan 17, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a new "Clean Up" feature to help users manage and delete media
    • Introduced a dedicated Clean Up screen for media management
    • Added localized tab titles for Home, Transfer, Albums, and Accounts
  • Improvements

    • Enhanced localization support for tab labels
    • Improved media deletion process with better error handling
    • Added new database functionality for tracking media cleanup
  • User Interface

    • Updated main screen with localized tab titles
    • Added a new Clean Up option in account settings
    • Implemented a grid view for selecting media to delete

Copy link

coderabbitai bot commented Jan 17, 2025

Walkthrough

This pull request introduces a comprehensive clean-up feature for media management. The changes span multiple components, including localization, UI screens, state management, routing, and database services. A new "Clean Up" functionality is added, allowing users to view and delete media items across different providers. The implementation includes a dedicated screen, state notifier, route, and database management for tracking media that can be cleaned up.

Changes

File Change Summary
app/assets/locales/app_en.arb Added localization entries for tab titles and clean-up screen
app/lib/ui/flow/accounts/components/settings_action_list.dart Added clean-up media action to settings list
app/lib/ui/flow/clean_up/* Created new clean-up screen, state notifier, and related components
app/lib/ui/navigation/app_route.dart Added new route for clean-up screen
data/lib/domain/config.dart Added cleanUpTable constant
data/lib/models/clean_up/* Created CleanUpMedia model with Freezed and JSON serialization
data/lib/services/local_media_service.dart Added methods for managing clean-up media database

Sequence Diagram

sequenceDiagram
    participant User
    participant SettingsScreen
    participant CleanUpScreen
    participant CleanUpStateNotifier
    participant LocalMediaService
    participant Database

    User->>SettingsScreen: Tap "Clean Up" action
    SettingsScreen->>CleanUpScreen: Navigate
    CleanUpScreen->>CleanUpStateNotifier: Load clean-up medias
    CleanUpStateNotifier->>LocalMediaService: Retrieve media
    LocalMediaService->>Database: Query clean-up media
    Database-->>LocalMediaService: Return media list
    LocalMediaService-->>CleanUpStateNotifier: Return media list
    CleanUpStateNotifier-->>CleanUpScreen: Update UI with media
    User->>CleanUpScreen: Select media to delete
    User->>CleanUpScreen: Tap delete button
    CleanUpScreen->>CleanUpStateNotifier: Delete selected media
    CleanUpStateNotifier->>LocalMediaService: Remove media
    LocalMediaService->>Database: Delete media entries
Loading

Possibly related PRs

Poem

🐰 A Rabbit's Clean-Up Ballad 🧹

In folders dark and cluttered wide,
Where forgotten memories reside,
A clean-up feature now takes flight,
Sweeping pixels left and right!

Tap and clear with bunny might! 🐾


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@cp-pratik-k cp-pratik-k changed the title Delete after upload Implement clean up space screen Jan 17, 2025
@cp-pratik-k cp-pratik-k changed the title Implement clean up space screen Implement clean up space Jan 17, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🧹 Nitpick comments (5)
data/lib/services/local_media_service.dart (1)

109-124: Consider adding indexes for frequently queried columns.

The table creation looks good, but consider adding indexes on provider and created_at columns as they are likely to be frequently used in WHERE clauses and sorting operations.

 await db.execute(
   'CREATE TABLE IF NOT EXISTS ${LocalDatabaseConstants.cleanUpTable} ('
   'id TEXT PRIMARY KEY, '
   'provider TEXT NOT NULL, '
   'created_at TEXT NOT NULL, '
   'provider_ref_id TEXT'
   ')',
 );
+await db.execute(
+  'CREATE INDEX IF NOT EXISTS idx_cleanup_provider ON ${LocalDatabaseConstants.cleanUpTable}(provider)'
+);
+await db.execute(
+  'CREATE INDEX IF NOT EXISTS idx_cleanup_created_at ON ${LocalDatabaseConstants.cleanUpTable}(created_at)'
+);
data/lib/models/clean_up/clean_up.freezed.dart (1)

24-24: Consider using camelCase for Dart property names.

The properties provider_ref_id and created_at use snake_case naming, which deviates from Dart naming conventions. Consider using camelCase:

  • providerRefId
  • createdAt

Also applies to: 47-47, 102-104, 211-213

app/lib/ui/flow/home/home_screen_view_model.dart (1)

631-636: Good improvement to deletion error handling.

The changes properly handle deletion results and prevent unnecessary notifications for failed deletions. Consider adding a debug log when returning early to help with troubleshooting.

     final res = await _localMediaService.deleteMedias(ids);

-    if (res.isEmpty) return;
+    if (res.isEmpty) {
+      _logger.d("No media was deleted successfully");
+      return;
+    }
data/lib/models/clean_up/clean_up.dart (2)

13-16: Use camelCase for field names to follow Dart conventions

The fields are currently named using snake_case, which is against Dart naming conventions. Consider renaming them to camelCase for consistency and maintainability. Use @JsonKey annotations to map the JSON keys.

Apply this diff to rename the fields:

       const factory CleanUpMedia({
           required String id,
-          String? provider_ref_id,
+          @JsonKey(name: 'provider_ref_id') String? providerRefId,
           required AppMediaSource provider,
-          @DateTimeJsonConverter() required DateTime created_at,
+          @DateTimeJsonConverter() @JsonKey(name: 'created_at') required DateTime createdAt,
         }) = _CleanUpMedia;

Also, update references to these fields throughout the codebase.


1-1: Remove unnecessary ignore comment

After renaming the fields to follow Dart conventions, the ignore_for_file directive is no longer needed.

Apply this diff to remove the unnecessary comment:

-// ignore_for_file: non_constant_identifier_names
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b1522f1 and e9f8eb5.

📒 Files selected for processing (17)
  • app/assets/locales/app_en.arb (2 hunks)
  • app/lib/ui/flow/accounts/components/settings_action_list.dart (2 hunks)
  • app/lib/ui/flow/clean_up/clean_up_screen.dart (1 hunks)
  • app/lib/ui/flow/clean_up/clean_up_state_notifier.dart (1 hunks)
  • app/lib/ui/flow/clean_up/clean_up_state_notifier.freezed.dart (1 hunks)
  • app/lib/ui/flow/home/home_screen_view_model.dart (1 hunks)
  • app/lib/ui/flow/main/main_screen.dart (2 hunks)
  • app/lib/ui/flow/media_preview/media_preview_view_model.dart (1 hunks)
  • app/lib/ui/navigation/app_route.dart (3 hunks)
  • app/lib/ui/navigation/app_route.g.dart (2 hunks)
  • data/lib/domain/config.dart (1 hunks)
  • data/lib/models/clean_up/clean_up.dart (1 hunks)
  • data/lib/models/clean_up/clean_up.freezed.dart (1 hunks)
  • data/lib/models/clean_up/clean_up.g.dart (1 hunks)
  • data/lib/repositories/media_process_repository.dart (3 hunks)
  • data/lib/services/google_drive_service.dart (1 hunks)
  • data/lib/services/local_media_service.dart (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • data/lib/models/clean_up/clean_up.g.dart
  • data/lib/services/google_drive_service.dart
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (10)
app/lib/ui/flow/clean_up/clean_up_screen.dart (1)

16-41: LGTM! Well-structured implementation with proper state management.

The screen is properly implemented with:

  • Clean separation of concerns using Riverpod
  • Proper error handling through state observation
app/lib/ui/flow/accounts/components/settings_action_list.dart (1)

15-15: LGTM! Clean implementation of the clean-up action.

The implementation follows the established patterns:

  • Consistent with other action items in the list
  • Proper use of localization
  • Clear navigation logic

Also applies to: 28-28, 36-51

app/assets/locales/app_en.arb (1)

166-167: LGTM! Well-structured localization entries.

The new clean-up related messages are:

  • Properly organized under a dedicated section
  • Follow consistent naming patterns
  • Use friendly and clear language

Also applies to: 168-172

data/lib/models/clean_up/clean_up.freezed.dart (1)

1-236: LGTM! Well-structured data model.

The CleanUpMedia model is well-implemented with:

  • Proper immutability using Freezed
  • Correct use of JSON serialization
  • Appropriate handling of DateTime using converter
app/lib/ui/navigation/app_route.g.dart (1)

12-12: LGTM! Clean implementation of the clean-up route.

The route implementation:

  • Follows the established routing patterns
  • Provides all necessary navigation methods
  • Uses a consistent path format

Also applies to: 153-173

app/lib/ui/flow/clean_up/clean_up_state_notifier.freezed.dart (1)

17-32: Well-structured state management for clean-up feature.

The state implementation properly tracks all necessary aspects of the clean-up process including:

  • Deletion loading states (both bulk and selected items)
  • Media items and selections
  • Error handling
app/lib/ui/flow/clean_up/clean_up_state_notifier.dart (1)

40-40: Ensure the nonNulls extension method is available

The use of value.nonNulls.toList() assumes the presence of a nonNulls extension method. Please verify that this extension is imported and available in the context to prevent runtime errors.

Run the following script to confirm the availability of the nonNulls extension:

✅ Verification successful

nonNulls is a built-in Dart extension method

The nonNulls extension method is a built-in Dart feature available on Iterable<T?> that filters out null values. Its widespread use across the codebase confirms it's working as expected.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for the definition of 'nonNulls' extension method.

# Search the codebase for 'nonNulls' extension.
rg --type dart --word-regexp 'extension.*nonNulls'

Length of output: 52


Script:

#!/bin/bash
# Search for any occurrence of nonNulls
echo "=== Searching for nonNulls usage ==="
rg --type dart "nonNulls"

echo -e "\n=== Checking imports in the file ==="
cat "app/lib/ui/flow/clean_up/clean_up_state_notifier.dart"

echo -e "\n=== Looking for extension method definitions ==="
ast-grep --pattern 'extension $_ {
  $$$
  nonNulls$_ {
    $$$
  }
  $$$
}'

Length of output: 5168

data/lib/domain/config.dart (1)

16-16: LGTM

The addition of cleanUpTable aligns with existing naming conventions in LocalDatabaseConstants.

app/lib/ui/flow/main/main_screen.dart (1)

7-7: LGTM! Good localization improvements.

The changes properly implement localization for tab labels using context.l10n, making the app more maintainable and ready for internationalization.

Also applies to: 28-28, 33-33, 38-38, 43-43

app/lib/ui/navigation/app_route.dart (1)

23-23: LGTM! Clean route implementation.

The new clean up route follows the established patterns:

  • Consistent path naming
  • Proper use of TypedGoRoute annotation
  • Matches the structure of other routes in the file

Also applies to: 81-88

Comment on lines +149 to +152
Future<void> clearCleanUpMediaDatabase() async {
final database = await openCleanUpDatabase();
await database.delete(LocalDatabaseConstants.cleanUpTable);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Ensure database closure after clearing.

Add try-finally block to ensure database is properly closed after the operation.

 Future<void> clearCleanUpMediaDatabase() async {
   final database = await openCleanUpDatabase();
+  try {
     await database.delete(LocalDatabaseConstants.cleanUpTable);
+  } finally {
+    await database.close();
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Future<void> clearCleanUpMediaDatabase() async {
final database = await openCleanUpDatabase();
await database.delete(LocalDatabaseConstants.cleanUpTable);
}
Future<void> clearCleanUpMediaDatabase() async {
final database = await openCleanUpDatabase();
try {
await database.delete(LocalDatabaseConstants.cleanUpTable);
} finally {
await database.close();
}
}

Comment on lines +140 to +147
Future<void> removeFromCleanUpMediaDatabase(List<String> ids) async {
final database = await openCleanUpDatabase();
await database.delete(
LocalDatabaseConstants.cleanUpTable,
where: 'id IN (${List.filled(ids.length, '?').join(',')})',
whereArgs: ids,
);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input validation and ensure database closure.

The SQL query is safe, but consider these improvements:

  1. Validate the input list is not empty
  2. Ensure database closure using try-finally
 Future<void> removeFromCleanUpMediaDatabase(List<String> ids) async {
+  if (ids.isEmpty) return;
   final database = await openCleanUpDatabase();
+  try {
     await database.delete(
       LocalDatabaseConstants.cleanUpTable,
       where: 'id IN (${List.filled(ids.length, '?').join(',')})',
       whereArgs: ids,
     );
+  } finally {
+    await database.close();
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Future<void> removeFromCleanUpMediaDatabase(List<String> ids) async {
final database = await openCleanUpDatabase();
await database.delete(
LocalDatabaseConstants.cleanUpTable,
where: 'id IN (${List.filled(ids.length, '?').join(',')})',
whereArgs: ids,
);
}
Future<void> removeFromCleanUpMediaDatabase(List<String> ids) async {
if (ids.isEmpty) return;
final database = await openCleanUpDatabase();
try {
await database.delete(
LocalDatabaseConstants.cleanUpTable,
where: 'id IN (${List.filled(ids.length, '?').join(',')})',
whereArgs: ids,
);
} finally {
await database.close();
}
}

Comment on lines +154 to +158
Future<List<CleanUpMedia>> getCleanUpMedias() async {
final database = await openCleanUpDatabase();
final res = await database.query(LocalDatabaseConstants.cleanUpTable);
return res.map((e) => CleanUpMedia.fromJson(e)).toList();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add pagination and ensure database closure.

Consider these improvements:

  1. Add pagination to handle large datasets efficiently
  2. Ensure database closure using try-finally
-Future<List<CleanUpMedia>> getCleanUpMedias() async {
+Future<List<CleanUpMedia>> getCleanUpMedias({
+  int limit = 50,
+  int offset = 0,
+}) async {
   final database = await openCleanUpDatabase();
+  try {
     final res = await database.query(
       LocalDatabaseConstants.cleanUpTable,
+      limit: limit,
+      offset: offset,
+      orderBy: 'created_at DESC',
     );
     return res.map((e) => CleanUpMedia.fromJson(e)).toList();
+  } finally {
+    await database.close();
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Future<List<CleanUpMedia>> getCleanUpMedias() async {
final database = await openCleanUpDatabase();
final res = await database.query(LocalDatabaseConstants.cleanUpTable);
return res.map((e) => CleanUpMedia.fromJson(e)).toList();
}
Future<List<CleanUpMedia>> getCleanUpMedias({
int limit = 50,
int offset = 0,
}) async {
final database = await openCleanUpDatabase();
try {
final res = await database.query(
LocalDatabaseConstants.cleanUpTable,
limit: limit,
offset: offset,
orderBy: 'created_at DESC',
);
return res.map((e) => CleanUpMedia.fromJson(e)).toList();
} finally {
await database.close();
}
}

Comment on lines +126 to +138
Future<void> addToCleanUpMediaDatabase({
required List<CleanUpMedia> medias,
}) async {
final database = await openCleanUpDatabase();
final batch = database.batch();
for (CleanUpMedia media in medias) {
batch.insert(
LocalDatabaseConstants.cleanUpTable,
media.toJson(),
);
}
await batch.commit();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling and ensure database closure.

While the batch operation is efficient, consider these improvements:

  1. Add error handling for duplicate key conflicts
  2. Ensure database closure using try-finally
 Future<void> addToCleanUpMediaDatabase({
   required List<CleanUpMedia> medias,
 }) async {
   final database = await openCleanUpDatabase();
-  final batch = database.batch();
-  for (CleanUpMedia media in medias) {
-    batch.insert(
-      LocalDatabaseConstants.cleanUpTable,
-      media.toJson(),
-    );
+  try {
+    final batch = database.batch();
+    for (CleanUpMedia media in medias) {
+      batch.insert(
+        LocalDatabaseConstants.cleanUpTable,
+        media.toJson(),
+        conflictAlgorithm: ConflictAlgorithm.replace,
+      );
+    }
+    await batch.commit();
+  } finally {
+    await database.close();
   }
-  await batch.commit();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Future<void> addToCleanUpMediaDatabase({
required List<CleanUpMedia> medias,
}) async {
final database = await openCleanUpDatabase();
final batch = database.batch();
for (CleanUpMedia media in medias) {
batch.insert(
LocalDatabaseConstants.cleanUpTable,
media.toJson(),
);
}
await batch.commit();
}
Future<void> addToCleanUpMediaDatabase({
required List<CleanUpMedia> medias,
}) async {
final database = await openCleanUpDatabase();
try {
final batch = database.batch();
for (CleanUpMedia media in medias) {
batch.insert(
LocalDatabaseConstants.cleanUpTable,
media.toJson(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
await batch.commit();
} finally {
await database.close();
}
}

Comment on lines +77 to +101
child: GridView.builder(
padding: const EdgeInsets.all(4),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: (context.mediaQuerySize.width > 600
? context.mediaQuerySize.width ~/ 180
: context.mediaQuerySize.width ~/ 100)
.clamp(1, 6),
crossAxisSpacing: 4,
mainAxisSpacing: 4,
),
itemCount: state.medias.length,
itemBuilder: (context, index) {
return AppMediaItem(
media: state.medias[index],
heroTag: "clean_up${state.medias[index].toString()}",
onTap: () async {
_notifier.toggleSelection(state.medias[index].id);
HapticFeedback.lightImpact();
},
isSelected: state.selected.contains(state.medias[index].id),
);
},
),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Optimize GridView performance.

The current implementation might cause performance issues:

  1. Using NeverScrollableScrollPhysics with shrinkWrap: true forces Flutter to measure all children
  2. Grid item sizing calculation could be simplified
 GridView.builder(
   padding: const EdgeInsets.all(4),
-  physics: const NeverScrollableScrollPhysics(),
-  shrinkWrap: true,
+  physics: const AlwaysScrollableScrollPhysics(),
   gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
-    crossAxisCount: (context.mediaQuerySize.width > 600
-            ? context.mediaQuerySize.width ~/ 180
-            : context.mediaQuerySize.width ~/ 100)
-        .clamp(1, 6),
+    crossAxisCount: (context.mediaQuerySize.width / 120).floor().clamp(2, 6),
     crossAxisSpacing: 4,
     mainAxisSpacing: 4,
   ),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
child: GridView.builder(
padding: const EdgeInsets.all(4),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: (context.mediaQuerySize.width > 600
? context.mediaQuerySize.width ~/ 180
: context.mediaQuerySize.width ~/ 100)
.clamp(1, 6),
crossAxisSpacing: 4,
mainAxisSpacing: 4,
),
itemCount: state.medias.length,
itemBuilder: (context, index) {
return AppMediaItem(
media: state.medias[index],
heroTag: "clean_up${state.medias[index].toString()}",
onTap: () async {
_notifier.toggleSelection(state.medias[index].id);
HapticFeedback.lightImpact();
},
isSelected: state.selected.contains(state.medias[index].id),
);
},
),
child: GridView.builder(
padding: const EdgeInsets.all(4),
physics: const AlwaysScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: (context.mediaQuerySize.width / 120).floor().clamp(2, 6),
crossAxisSpacing: 4,
mainAxisSpacing: 4,
),
itemCount: state.medias.length,
itemBuilder: (context, index) {
return AppMediaItem(
media: state.medias[index],
heroTag: "clean_up${state.medias[index].toString()}",
onTap: () async {
_notifier.toggleSelection(state.medias[index].id);
HapticFeedback.lightImpact();
},
isSelected: state.selected.contains(state.medias[index].id),
);
},
),

Comment on lines +651 to +661

await _localMediaService.addToCleanUpMediaDatabase(
medias: [
CleanUpMedia(
id: process.media_id,
provider_ref_id: res.id,
provider: AppMediaSource.dropbox,
created_at: DateTime.now(),
),
],
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Duplicate implementation pattern needs refactoring.

This code block duplicates the cleanup tracking logic from the Google Drive upload method. Consider extracting this into a shared helper method to maintain DRY principles.

+ private Future<void> _addToCleanUpDatabase(String mediaId, String providerRefId, AppMediaSource provider) {
+   return _localMediaService.addToCleanUpMediaDatabase(
+     medias: [
+       CleanUpMedia(
+         id: mediaId,
+         provider_ref_id: providerRefId,
+         provider: provider,
+         created_at: DateTime.now(),
+       ),
+     ],
+   );
+ }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +82 to +87
_logger.e(
"BinStateNotifier: Error occur while deleting selected bin items",
error: e,
stackTrace: s,
);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct the class name and grammar in log messages

The error log message refers to "BinStateNotifier" instead of "CleanUpStateNotifier" and contains a grammatical error.

Apply this diff to correct the log message:

           _logger.e(
-            "BinStateNotifier: Error occur while deleting selected bin items",
+            "CleanUpStateNotifier: Error occurred while deleting selected clean-up items",
             error: e,
             stackTrace: s,
           );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_logger.e(
"BinStateNotifier: Error occur while deleting selected bin items",
error: e,
stackTrace: s,
);
}
_logger.e(
"CleanUpStateNotifier: Error occurred while deleting selected clean-up items",
error: e,
stackTrace: s,
);

Comment on lines +106 to +111
_logger.e(
"BinStateNotifier: Error occur while deleting all bin items",
error: e,
stackTrace: s,
);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct the class name and grammar in log messages

The error log message refers to "BinStateNotifier" instead of "CleanUpStateNotifier" and has a grammatical error.

Apply this diff to correct the log message:

           _logger.e(
-            "BinStateNotifier: Error occur while deleting all bin items",
+            "CleanUpStateNotifier: Error occurred while deleting all clean-up items",
             error: e,
             stackTrace: s,
           );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_logger.e(
"BinStateNotifier: Error occur while deleting all bin items",
error: e,
stackTrace: s,
);
}
_logger.e(
"CleanUpStateNotifier: Error occurred while deleting all clean-up items",
error: e,
stackTrace: s,
);

Comment on lines +46 to +51
_logger.e(
"BinStateNotifier: Error occur while loading bin items",
error: e,
stackTrace: s,
);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct the class name and grammar in log messages

The error log message refers to "BinStateNotifier" instead of "CleanUpStateNotifier" and has a grammatical error. This can cause confusion during debugging.

Apply this diff to correct the log message:

           state = state.copyWith(loading: false, error: e);
-          _logger.e(
-            "BinStateNotifier: Error occur while loading bin items",
+          _logger.e(
+            "CleanUpStateNotifier: Error occurred while loading clean-up items",
             error: e,
             stackTrace: s,
           );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_logger.e(
"BinStateNotifier: Error occur while loading bin items",
error: e,
stackTrace: s,
);
}
_logger.e(
"CleanUpStateNotifier: Error occurred while loading clean-up items",
error: e,
stackTrace: s,
);

Comment on lines +234 to +235
final res = await _localMediaService.deleteMedias([id]);
if (res.isEmpty) return;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve error handling for failed deletions.

While checking for empty results is good, the current implementation silently fails when deletion is unsuccessful. Consider:

  1. Logging the failure
  2. Notifying the user of the deletion failure
  3. Potentially retrying the operation
   final res = await _localMediaService.deleteMedias([id]);
-  if (res.isEmpty) return;
+  if (res.isEmpty) {
+    _logger.e("Failed to delete media: $id");
+    state = state.copyWith(actionError: "Failed to delete media");
+    return;
+  }

Committable suggestion skipped: line range outside the PR's diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant