-
Notifications
You must be signed in to change notification settings - Fork 20
feat: Add image loader widget for IPFS/network image fetching issue #12 #30
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
base: main
Are you sure you want to change the base?
Conversation
WalkthroughIntroduces ImageLoaderWidget and CircularImageLoaderWidget for Flutter image loading with integrated progress indicators, error handling, and IPFS support. Consolidates duplicate Image.network implementations across six UI components and adds documentation and setup automation scripts. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20–25 minutes
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🧹 Nitpick comments (6)
run-app.ps1 (2)
9-15: Consider verifying Flutter availability.The script assumes Flutter is installed and available in PATH. If Flutter is missing, the error message may be cryptic.
Add a Flutter availability check:
Write-Host "`n[1/3] Getting dependencies..." -ForegroundColor Cyan + +# Verify Flutter is available +if (!(Get-Command flutter -ErrorAction SilentlyContinue)) { + Write-Host "✗ Flutter not found in PATH. Please install Flutter first." -ForegroundColor Red + Write-Host "Run setup-flutter.ps1 to install Flutter automatically." -ForegroundColor Yellow + exit 1 +} + & flutter pub get
17-18: Consider parameterizing build mode.The script always builds in release mode. During development, debug builds are faster and provide better error messages.
Add a parameter for build mode:
+param( + [string]$ProjectPath = $PSScriptRoot, + [ValidateSet("debug", "profile", "release")] + [string]$BuildMode = "release" +) + # ... (earlier code) Write-Host "`n[2/3] Building for web..." -ForegroundColor Cyan -& flutter build web --release +& flutter build web --$BuildModesetup-flutter.ps1 (2)
2-2: Clarify administrator requirement.The comment states "Run as Administrator," but the script modifies the User-level PATH (line 45), which doesn't require administrator privileges. Consider either:
- Removing the admin requirement comment if not needed
- Adding privilege verification if admin is actually required
- Clarifying when admin privileges are needed
If admin is required for other reasons, add verification:
# Flutter Setup Script for Windows -# Run as Administrator +# Requires Administrator privileges for system-wide installation + +# Verify admin privileges +$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) +if (!$isAdmin) { + Write-Host "✗ This script requires Administrator privileges" -ForegroundColor Red + Write-Host "Please run PowerShell as Administrator and try again" -ForegroundColor Yellow + exit 1 +}
52-56: Consider checking flutter doctor exit code.The script runs
flutter doctorbut doesn't check if it succeeds. If there are critical issues, the script still reports "Setup Complete," which could be misleading.Add error checking for flutter doctor:
Write-Host "`n[4/4] Verifying installation..." -ForegroundColor Cyan $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") & "C:\src\flutter\bin\flutter.bat" doctor + +if ($LASTEXITCODE -ne 0) { + Write-Host "`n⚠ Flutter doctor reported issues" -ForegroundColor Yellow + Write-Host "Please review the output above and resolve any critical issues" -ForegroundColor Yellow +} else { + Write-Host "`n✓ Flutter doctor completed successfully" -ForegroundColor Green +}lib/widgets/image_loader_widget.dart (1)
64-71: Consider alternative progress display for small images.The progress display always shows MB units, which could be confusing for small images (e.g., "0.0 MB / 0.1 MB"). Consider using KB for files under 1 MB or dynamically choosing the appropriate unit.
if (totalBytes != null) Padding( padding: const EdgeInsets.only(top: 12.0), child: Text( - '${(downloadedBytes / (1024 * 1024)).toStringAsFixed(1)} MB / ${(totalBytes / (1024 * 1024)).toStringAsFixed(1)} MB', + totalBytes < 1024 * 1024 + ? '${(downloadedBytes / 1024).toStringAsFixed(0)} KB / ${(totalBytes / 1024).toStringAsFixed(0)} KB' + : '${(downloadedBytes / (1024 * 1024)).toStringAsFixed(1)} MB / ${(totalBytes / (1024 * 1024)).toStringAsFixed(1)} MB', style: Theme.of(context).textTheme.bodySmall, ), ),lib/widgets/profile_widgets/user_profile_viewer_widget.dart (1)
159-171: Consider using a consistent error handling approach for CircularImageLoaderWidget across similar contexts.The CircularImageLoaderWidget implementation is correct—the
errorWidgetparameter is optional (as defined in the constructor atlib/widgets/image_loader_widget.dart:122). However, usage is inconsistent:organisation_details_page.dart(lines 408-410) provides a customerrorWidget, whileuser_profile_viewer_widget.dart(lines 160-163) andprofile_section_widget.dart(lines 379-382) rely on the widget's default error handling for similar profile image displays.To improve maintainability, either document the intentional difference in error handling across these contexts or standardize the approach.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (60)
node_modules/.package-lock.jsonis excluded by!**/node_modules/**node_modules/debug/.coveralls.ymlis excluded by!**/node_modules/**node_modules/debug/.eslintrcis excluded by!**/node_modules/**node_modules/debug/.npmignoreis excluded by!**/node_modules/**node_modules/debug/.travis.ymlis excluded by!**/node_modules/**node_modules/debug/CHANGELOG.mdis excluded by!**/node_modules/**node_modules/debug/LICENSEis excluded by!**/node_modules/**node_modules/debug/Makefileis excluded by!**/node_modules/**node_modules/debug/README.mdis excluded by!**/node_modules/**node_modules/debug/component.jsonis excluded by!**/node_modules/**node_modules/debug/karma.conf.jsis excluded by!**/node_modules/**node_modules/debug/node.jsis excluded by!**/node_modules/**node_modules/debug/package.jsonis excluded by!**/node_modules/**node_modules/debug/src/browser.jsis excluded by!**/node_modules/**node_modules/debug/src/debug.jsis excluded by!**/node_modules/**node_modules/debug/src/index.jsis excluded by!**/node_modules/**node_modules/debug/src/inspector-log.jsis excluded by!**/node_modules/**node_modules/debug/src/node.jsis excluded by!**/node_modules/**node_modules/flutter/.npmignoreis excluded by!**/node_modules/**node_modules/flutter/README.mdis excluded by!**/node_modules/**node_modules/flutter/package.jsonis excluded by!**/node_modules/**node_modules/flutter/src/API.jsis excluded by!**/node_modules/**node_modules/flutter/src/Flutter.jsis excluded by!**/node_modules/**node_modules/ms/index.jsis excluded by!**/node_modules/**node_modules/ms/license.mdis excluded by!**/node_modules/**node_modules/ms/package.jsonis excluded by!**/node_modules/**node_modules/ms/readme.mdis excluded by!**/node_modules/**node_modules/oauth/.npmignoreis excluded by!**/node_modules/**node_modules/oauth/LICENSEis excluded by!**/node_modules/**node_modules/oauth/Makefileis excluded by!**/node_modules/**node_modules/oauth/Readme.mdis excluded by!**/node_modules/**node_modules/oauth/examples/express-gdata/server.jsis excluded by!**/node_modules/**node_modules/oauth/examples/express-gdata/views/google_calendars.ejsis excluded by!**/node_modules/**node_modules/oauth/examples/express-gdata/views/google_contacts.ejsis excluded by!**/node_modules/**node_modules/oauth/examples/express-gdata/views/layout.ejsis excluded by!**/node_modules/**node_modules/oauth/examples/github-example.jsis excluded by!**/node_modules/**node_modules/oauth/examples/term.ie.oauth-HMAC-SHA1.jsis excluded by!**/node_modules/**node_modules/oauth/examples/twitter-example.jsis excluded by!**/node_modules/**node_modules/oauth/index.jsis excluded by!**/node_modules/**node_modules/oauth/lib/_utils.jsis excluded by!**/node_modules/**node_modules/oauth/lib/oauth.jsis excluded by!**/node_modules/**node_modules/oauth/lib/oauth2.jsis excluded by!**/node_modules/**node_modules/oauth/lib/sha1.jsis excluded by!**/node_modules/**node_modules/oauth/package.jsonis excluded by!**/node_modules/**node_modules/oauth/tests/oauth2tests.jsis excluded by!**/node_modules/**node_modules/oauth/tests/oauthtests.jsis excluded by!**/node_modules/**node_modules/oauth/tests/sha1tests.jsis excluded by!**/node_modules/**node_modules/oauth/tests/shared.jsis excluded by!**/node_modules/**node_modules/redis/.npmignoreis excluded by!**/node_modules/**node_modules/redis/README.mdis excluded by!**/node_modules/**node_modules/redis/connection_breaker.jsis excluded by!**/node_modules/**node_modules/redis/index.jsis excluded by!**/node_modules/**node_modules/redis/lib/commands.jsis excluded by!**/node_modules/**node_modules/redis/lib/parser/hiredis.jsis excluded by!**/node_modules/**node_modules/redis/lib/parser/javascript.jsis excluded by!**/node_modules/**node_modules/redis/lib/queue.jsis excluded by!**/node_modules/**node_modules/redis/lib/to_array.jsis excluded by!**/node_modules/**node_modules/redis/lib/util.jsis excluded by!**/node_modules/**node_modules/redis/package.jsonis excluded by!**/node_modules/**package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (13)
IMAGE_LOADER_USAGE.md(1 hunks)PR_DESCRIPTION.md(1 hunks)PR_TEMPLATE_FINAL.md(1 hunks)lib/pages/organisations_pages/organisation_details_page.dart(2 hunks)lib/widgets/image_loader_widget.dart(1 hunks)lib/widgets/nft_display_utils/recent_trees_widget.dart(2 hunks)lib/widgets/nft_display_utils/tree_nft_details_verifiers_widget.dart(2 hunks)lib/widgets/nft_display_utils/tree_nft_view_details_with_map.dart(2 hunks)lib/widgets/profile_widgets/profile_section_widget.dart(2 hunks)lib/widgets/profile_widgets/user_profile_viewer_widget.dart(2 hunks)package.json(1 hunks)run-app.ps1(1 hunks)setup-flutter.ps1(1 hunks)
🧰 Additional context used
🪛 LanguageTool
IMAGE_LOADER_USAGE.md
[uncategorized] ~234-~234: Do not mix variants of the same word (‘organization’ and ‘organisation’) within a single text.
Context: ...pages/organisation_details_page.dart) - Organization images --- For more information or is...
(EN_WORD_COHERENCY)
🪛 markdownlint-cli2 (0.18.1)
IMAGE_LOADER_USAGE.md
239-239: Bare URL used
(MD034, no-bare-urls)
🔇 Additional comments (9)
setup-flutter.ps1 (1)
36-50: LGTM!The PATH modification logic correctly checks for existing entries before adding and provides appropriate user feedback.
lib/widgets/nft_display_utils/recent_trees_widget.dart (1)
156-159: LGTM! Clean migration to ImageLoaderWidget.The replacement of
Image.networkwithImageLoaderWidgetis correctly implemented, maintaining the existingfitparameter while gaining automatic loading and error handling.lib/widgets/nft_display_utils/tree_nft_view_details_with_map.dart (1)
285-290: LGTM! Proper integration of ImageLoaderWidget.The migration correctly preserves all necessary parameters (height, width, fit) while delegating loading and error states to the centralized widget.
lib/widgets/profile_widgets/profile_section_widget.dart (1)
379-382: LGTM! Appropriate use of CircularImageLoaderWidget.The circular variant is well-suited for profile photos. The explicit radius parameter and simplified error handling improve code maintainability.
lib/widgets/nft_display_utils/tree_nft_details_verifiers_widget.dart (1)
811-823: LGTM! Well-configured ImageLoaderWidget usage.The implementation properly customizes both
placeholderColoranderrorWidgetfor the verification proof images context, maintaining appropriate visual feedback.lib/pages/organisations_pages/organisation_details_page.dart (2)
11-11: LGTM - Import added for centralized image loader.The import follows the project's structure conventions.
404-424: Rewrite the verification request - ImageLoaderWidget does not perform gateway resolution.The CircularImageLoaderWidget correctly handles dimensions and error fallback, but does not implement IPFS gateway resolution as claimed in the original comment. The widget passes the
imageUrldirectly toImage.networkand only sets a generic CORS header. It provides loading indicators with progress tracking and error widget support, but assumes the URL passed is already a complete HTTP(S) address. IforganisationLogoHashcontains an IPFS hash rather than a full gateway URL, this code will fail. Verify whether the backend returns complete gateway URLs (e.g.,https://gateway.pinata.cloud/ipfs/...) or raw IPFS hashes that require conversion.lib/widgets/profile_widgets/user_profile_viewer_widget.dart (1)
9-9: LGTM - Import added for centralized image loader.Consistent with the other files in this PR.
PR_DESCRIPTION.md (1)
1-78: Implementation verification reveals significant claim discrepancies in the PR description.The widget file exists at 175 lines (not 181 as claimed), and implements:
- ✅ Loading indicators with progress tracking showing "X.X MB / Y.Y MB" format (ImageLoaderWidget lines 68, CircularImageLoaderWidget shows progress without size)
- ✅ Error handling with customizable error widgets and fallback icons (Icons.error_outline for rectangles, Icons.person for circles)
- ✅ Basic customization (colors, dimensions, borders, headers)
However, the PR description's key feature claims are inaccurate:
✗ IPFS Support claim is false. The widget contains no Pinata, ipfs.io, or custom gateway handling. It is a generic
Image.network()wrapper with a hard-coded{'Access-Control-Allow-Origin': '*'}header. The codebase has separate IPFS services (lib/utils/services/ipfs_services.dart) for uploading to Pinata, but the image loader widget performs standard HTTP image fetching only.✗ CORS configuration is generic. The "pre-configured headers for cross-origin requests" claim overstates the implementation—both widgets simply default to a wildcard origin header without gateway-specific CORS setup.
Update the PR description to remove or correct the IPFS Support feature claim, clarify that the widget handles standard HTTP/network image loading (not IPFS-specific protocols), and correct the line count to 175.
| 2. [lib/widgets/profile_widgets/user_profile_viewer_widget.dart](lib/widgets/profile_widgets/user_profile_viewer_widget.dart) - User profiles | ||
| 3. [lib/widgets/nft_display_utils/recent_trees_widget.dart](lib/widgets/nft_display_utils/recent_trees_widget.dart) - NFT display | ||
| 4. [lib/widgets/nft_display_utils/tree_nft_view_details_with_map.dart](lib/widgets/nft_display_utils/tree_nft_view_details_with_map.dart) - Tree details | ||
| 5. [lib/pages/organisations_pages/organisation_details_page.dart](lib/pages/organisations_pages/organisation_details_page.dart) - Organization images |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix spelling inconsistency.
The text uses both "Organization" and "organisation" (British vs American spelling). Maintain consistent spelling throughout the documentation.
-5. [lib/pages/organisations_pages/organisation_details_page.dart](lib/pages/organisations_pages/organisation_details_page.dart) - Organization images
+5. [lib/pages/organisations_pages/organisation_details_page.dart](lib/pages/organisations_pages/organisation_details_page.dart) - Organisation images🧰 Tools
🪛 LanguageTool
[uncategorized] ~234-~234: Do not mix variants of the same word (‘organization’ and ‘organisation’) within a single text.
Context: ...pages/organisation_details_page.dart) - Organization images --- For more information or is...
(EN_WORD_COHERENCY)
🤖 Prompt for AI Agents
In IMAGE_LOADER_USAGE.md around line 234, the entry currently mixes
"Organization" with the repository path that uses British spelling
("organisations_pages"); change the text to consistently use the same spelling
as the rest of the docs (e.g., replace "Organization images" with "Organisation
images") and scan the surrounding lines to make sure all occurrences of
"organization/Organization" vs "organisation/Organisation" follow the chosen
spelling.
| final Color? placeholderColor; | ||
| final Widget? errorWidget; | ||
| final Map<String, String>? headers; | ||
| final Duration loadingDuration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unused parameter.
The loadingDuration parameter is defined but never used in the widget implementation. It should either be removed or implemented if duration-based loading animation is intended.
final Widget? errorWidget;
final Map<String, String>? headers;
- final Duration loadingDuration;
const ImageLoaderWidget({
super.key,
required this.imageUrl,
this.fit = BoxFit.cover,
this.width,
this.height,
this.borderRadius,
this.placeholderColor,
this.errorWidget,
this.headers,
- this.loadingDuration = const Duration(seconds: 2),
});Also applies to: 26-26
🤖 Prompt for AI Agents
In lib/widgets/image_loader_widget.dart around lines 14 and 26, the
loadingDuration parameter/field is declared but never used; either remove the
field and the constructor parameter (and update all callers to stop passing it)
or wire it into the widget's loading animation by using loadingDuration as the
duration for the animation (e.g., pass it to
AnimatedOpacity/AnimatedSwitcher/FadeTransition or a Timer that controls the
loading state). Update the constructor, field, and any documentation accordingly
and ensure callers are adjusted if you remove the parameter.
| child: Image.network( | ||
| imageUrl, | ||
| fit: fit, | ||
| headers: headers ?? {'Access-Control-Allow-Origin': '*'}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove ineffective CORS header.
Setting Access-Control-Allow-Origin in client-side request headers has no effect. CORS (Cross-Origin Resource Sharing) is enforced by browsers and controlled by server response headers, not client request headers. The server must send this header in its response for CORS to work.
If you're experiencing CORS issues, they must be resolved on the server/gateway side. Remove this misleading header:
- headers: headers ?? {'Access-Control-Allow-Origin': '*'},
+ headers: headers,The same issue exists on Line 135 for CircularImageLoaderWidget.
📝 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.
| headers: headers ?? {'Access-Control-Allow-Origin': '*'}, | |
| headers: headers, |
🤖 Prompt for AI Agents
In lib/widgets/image_loader_widget.dart around lines 39 and 135, the code sets a
client-side request header 'Access-Control-Allow-Origin' which is ineffective
for CORS; remove this header from the request options (and any default headers
map) so client requests no longer include it, and if CORS issues persist,
address them on the server/gateway by returning the appropriate
Access-Control-Allow-Origin response header instead.
| child: Image.network( | ||
| imageUrl, | ||
| fit: BoxFit.cover, | ||
| headers: headers ?? {'Access-Control-Allow-Origin': '*'}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same CORS header issue in CircularImageLoaderWidget.
As mentioned earlier, client-side CORS headers have no effect. Remove this from the circular variant as well.
- headers: headers ?? {'Access-Control-Allow-Origin': '*'},
+ headers: headers,📝 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.
| headers: headers ?? {'Access-Control-Allow-Origin': '*'}, | |
| headers: headers, |
🤖 Prompt for AI Agents
In lib/widgets/image_loader_widget.dart around line 135, the
CircularImageLoaderWidget is setting a client-side CORS response header
("Access-Control-Allow-Origin") which has no effect; remove that header
assignment so the widget does not add {'Access-Control-Allow-Origin': '*'} to
the request headers. Instead either pass null/omit the headers parameter or
forward only legitimate request headers; delete the explicit headers: headers ??
{'Access-Control-Allow-Origin': '*'} and ensure callers still work when headers
is null or absent.
| { | ||
| "dependencies": { | ||
| "flutter": "^0.0.5" | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Incorrect dependency management for Flutter project.
Flutter projects use pubspec.yaml for dependency management, not package.json. The package.json file is for Node.js/npm projects. Additionally, Flutter is a framework/SDK, not an npm package, and the version ^0.0.5 doesn't correspond to any valid Flutter release.
If this file was added by mistake, remove it. If you need to manage Flutter dependencies, use pubspec.yaml instead.
🤖 Prompt for AI Agents
In package.json around lines 1 to 5, this file incorrectly declares a "flutter"
dependency — Flutter projects must use pubspec.yaml and Flutter itself is not an
npm package; remove this package.json if it was added by mistake, or if a Node
project is intended keep package.json but delete the "flutter" dependency entry
and manage Flutter dependencies in pubspec.yaml (or replace package.json with a
proper pubspec.yaml containing the Flutter SDK and package entries).
| $projectPath = "C:\Users\achal\Desktop\Treee" | ||
| Set-Location $projectPath |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove hardcoded developer-specific path.
The hardcoded path C:\Users\achal\Desktop\Treee will fail for any other developer or CI/CD environment. This makes the script non-portable and unsuitable for version control.
Apply this diff to use the script's directory or accept a parameter:
-$projectPath = "C:\Users\achal\Desktop\Treee"
-Set-Location $projectPath
+# Use script's parent directory or current directory
+$projectPath = if ($PSScriptRoot) { $PSScriptRoot } else { Get-Location }
+Set-Location $projectPath
+
+# Verify we're in a Flutter project
+if (!(Test-Path "pubspec.yaml")) {
+ Write-Host "✗ Not a Flutter project directory (pubspec.yaml not found)" -ForegroundColor Red
+ exit 1
+}Alternatively, accept the path as a parameter:
+param(
+ [string]$ProjectPath = $PSScriptRoot
+)
+
-$projectPath = "C:\Users\achal\Desktop\Treee"
+$projectPath = $ProjectPath
Set-Location $projectPath📝 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.
| $projectPath = "C:\Users\achal\Desktop\Treee" | |
| Set-Location $projectPath | |
| # Use script's parent directory or current directory | |
| $projectPath = if ($PSScriptRoot) { $PSScriptRoot } else { Get-Location } | |
| Set-Location $projectPath | |
| # Verify we're in a Flutter project | |
| if (!(Test-Path "pubspec.yaml")) { | |
| Write-Host "✗ Not a Flutter project directory (pubspec.yaml not found)" -ForegroundColor Red | |
| exit 1 | |
| } |
🤖 Prompt for AI Agents
In run-app.ps1 around lines 6 to 7, the script uses a hardcoded
developer-specific path ("C:\Users\achal\Desktop\Treee") which breaks
portability; change it to derive the project path dynamically or accept it as a
parameter: replace the hardcoded $projectPath assignment with logic that sets
$projectPath to either a provided script parameter or the script's own
containing directory (using $PSScriptRoot), and update the Set-Location to use
that variable so the script works for other developers and CI environments.
|
|
||
| # 1. Download Flutter | ||
| Write-Host "`n[1/4] Downloading Flutter SDK..." -ForegroundColor Cyan | ||
| $flutterUrl = "https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_3.16.0-stable.zip" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
latest stable Flutter version December 2025
💡 Result:
The latest stable Flutter release as of December 13, 2025 is Flutter 3.38 (docs reflect Flutter 3.38.1). Release announced November 12, 2025. [1][2]
Sources:
[1] Flutter release notes / what's new — docs.flutter.dev (Flutter 3.38 announced Nov 12, 2025).
[2] Community release index (FlutterReleases) listing stable 3.38 / 3.38.1.
Update Flutter to latest stable version (3.38.1) or make version configurable.
The script pins Flutter 3.16.0 from November 2023, which is significantly outdated. The current stable version is 3.38.1 (released November 2025). This 22-version gap means users installing via this script receive a 2-year-old version missing security patches, performance improvements, and features available in current stable releases.
Either update the pinned version to 3.38.1 or refactor to accept a version parameter so it can be easily updated without modifying the script.
🤖 Prompt for AI Agents
In setup-flutter.ps1 around line 8, the script hardcodes Flutter version 3.16.0;
update it to the current stable 3.38.1 or make the version configurable: add a
parameter or environment variable (e.g., $FlutterVersion with default "3.38.1")
and build $flutterUrl using that variable (ensure correct URL pattern for
windows zip), validate the version string if provided, and keep a sensible
default fallback to "3.38.1" so installs use the latest stable without editing
the script.
| # Download | ||
| try { | ||
| Invoke-WebRequest -Uri $flutterUrl -OutFile $downloadPath -UseBasicParsing | ||
| Write-Host "✓ Downloaded successfully" -ForegroundColor Green | ||
| } catch { | ||
| Write-Host "✗ Download failed: $_" -ForegroundColor Red | ||
| exit 1 | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add checksum verification for security.
The downloaded Flutter SDK isn't verified for integrity. This creates a security risk if the download is compromised or corrupted.
Add SHA-256 checksum verification:
Write-Host "`n[1/4] Downloading Flutter SDK..." -ForegroundColor Cyan
$flutterUrl = "https://storage.googleapis.com/flutter_infra_release/releases/stable/windows/flutter_windows_3.16.0-stable.zip"
+$expectedHash = "EXPECTED_SHA256_HASH_HERE" # Get from Flutter releases page
$downloadPath = "$env:TEMP\flutter.zip"
$extractPath = "C:\src"
# Create directory
if (!(Test-Path $extractPath)) {
New-Item -ItemType Directory -Path $extractPath -Force | Out-Null
}
# Download
try {
Invoke-WebRequest -Uri $flutterUrl -OutFile $downloadPath -UseBasicParsing
Write-Host "✓ Downloaded successfully" -ForegroundColor Green
+
+ # Verify checksum
+ Write-Host "Verifying download integrity..." -ForegroundColor Cyan
+ $actualHash = (Get-FileHash -Path $downloadPath -Algorithm SHA256).Hash
+ if ($actualHash -ne $expectedHash) {
+ Write-Host "✗ Checksum verification failed!" -ForegroundColor Red
+ Write-Host "Expected: $expectedHash" -ForegroundColor Yellow
+ Write-Host "Got: $actualHash" -ForegroundColor Yellow
+ exit 1
+ }
+ Write-Host "✓ Checksum verified" -ForegroundColor Green
} catch {
Write-Host "✗ Download failed: $_" -ForegroundColor Red
exit 1
}The expected hash can be obtained from the Flutter releases page.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In setup-flutter.ps1 around lines 17 to 24, the script downloads the Flutter SDK
but does not verify its integrity; add SHA-256 checksum verification after the
Invoke-WebRequest succeeds: compute the file hash with Get-FileHash -Algorithm
SHA256 for $downloadPath, compare the computed hash (normalized to lowercase, no
spaces) to an $expectedHash variable (populate $expectedHash from the Flutter
releases page or pass it into the script), and if they differ, Write-Host a
clear error, remove the downloaded file, and exit 1; only proceed (and
Write-Host success) when the checksum matches.
| Write-Host "`n=== Setup Complete ===" -ForegroundColor Green | ||
| Write-Host "Next steps:" -ForegroundColor Yellow | ||
| Write-Host "1. Close and reopen PowerShell" | ||
| Write-Host "2. Navigate to: cd C:\Users\achal\Desktop\Treee" | ||
| Write-Host "3. Run: flutter pub get" | ||
| Write-Host "4. Run: flutter run" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove hardcoded developer-specific path from instructions.
The hardcoded path C:\Users\achal\Desktop\Treee in the completion message is developer-specific and will confuse other users.
Apply this diff to generalize the instructions:
Write-Host "`n=== Setup Complete ===" -ForegroundColor Green
Write-Host "Next steps:" -ForegroundColor Yellow
Write-Host "1. Close and reopen PowerShell"
-Write-Host "2. Navigate to: cd C:\Users\achal\Desktop\Treee"
+Write-Host "2. Navigate to your Flutter project directory"
Write-Host "3. Run: flutter pub get"
Write-Host "4. Run: flutter run"📝 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.
| Write-Host "`n=== Setup Complete ===" -ForegroundColor Green | |
| Write-Host "Next steps:" -ForegroundColor Yellow | |
| Write-Host "1. Close and reopen PowerShell" | |
| Write-Host "2. Navigate to: cd C:\Users\achal\Desktop\Treee" | |
| Write-Host "3. Run: flutter pub get" | |
| Write-Host "4. Run: flutter run" | |
| Write-Host "`n=== Setup Complete ===" -ForegroundColor Green | |
| Write-Host "Next steps:" -ForegroundColor Yellow | |
| Write-Host "1. Close and reopen PowerShell" | |
| Write-Host "2. Navigate to your Flutter project directory" | |
| Write-Host "3. Run: flutter pub get" | |
| Write-Host "4. Run: flutter run" |
🤖 Prompt for AI Agents
In setup-flutter.ps1 around lines 58 to 63, the completion message includes a
hardcoded, developer-specific path (C:\Users\achal\Desktop\Treee); replace that
with a generic instruction or dynamically-determined path: use Get-Location() or
$PWD to show the current directory, or print "cd <your-project-directory>" as a
placeholder, so the message becomes environment-agnostic and instructs users to
navigate to their project folder before running flutter pub get and flutter run.
🎯 Add Image Loader Widget for IPFS/Network Images
Problem Solved
Users see blank/loading state while images fetch from IPFS without any progress indication or error handling. This creates a poor UX experience.
Solution
Created a reusable
ImageLoaderWidgetthat displays:What Changed
New Widget:
lib/widgets/image_loader_widget.dart- 181 linesImageLoaderWidget- For rectangular imagesCircularImageLoaderWidget- For circular images (profiles, logos)Updated 6 Files:
profile_section_widget.dart- Profile photo loaderuser_profile_viewer_widget.dart- User profilesrecent_trees_widget.dart- Tree NFT imagesorganisation_details_page.dart- Organisation logostree_nft_view_details_with_map.dart- Photo gallerytree_nft_details_verifiers_widget.dart- Verification proofsCode Quality Impact
Image.network()implementationsHow It Works
Before:
After:
Testing Covered
No Breaking Changes
Image.network()Type: Enhancement
Impact: UI/UX
Risk: Low (isolated widget, no logic changes)
Summary by CodeRabbit
New Features
Improvements
Build Automation
✏️ Tip: You can customize this high-level summary in your review settings.