-
Notifications
You must be signed in to change notification settings - Fork 14
Bug hunting #556
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
Bug hunting #556
Conversation
WalkthroughRenames Android APK base name to "whitenoise" and updates build scripts/paths accordingly. Normalizes several copy-to-clipboard toast messages across UI. Adjusts donate screen copy helper to include address type. Replaces collapsible relay ExpansionTile with a static header and always-visible content, adding explicit info and add actions. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant UI as RelayExpansionTile (UI)
participant VM as RelayState/Notifiers
rect rgba(200,220,255,0.25)
note over UI: Non-collapsible header
User->>UI: Tap title
note over UI: No expand/collapse occurs
end
User->>UI: Tap info icon (if shown)
UI-->>User: Show info/tooltip (onInfoTap)
User->>UI: Tap "Add" action
UI->>VM: _showAddRelayBottomSheet / _addRelay
VM-->>UI: Success or Error
alt Success
UI-->>User: Relay added, list updates
else Error
UI-->>User: Show error toast
end
sequenceDiagram
actor User
participant UI as DonateScreen
participant Utils as ClipboardUtils
User->>UI: Tap copy Lightning address
UI->>Utils: copyWithToast(text=lnAddr, success="Copied lightning address")
Utils-->>User: Toast shown
User->>UI: Tap copy Bitcoin address
UI->>Utils: copyWithToast(text=btcAddr, success="Copied bitcoin address")
Utils-->>User: Toast shown
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Suggested reviewers
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. 📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
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: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (7)
lib/ui/settings/profile_keys/profile_keys_screen.dart (3)
65-68: Leak: _publicKeyController not disposedDispose both controllers to avoid leaks.
Apply:
@override void dispose() { - _privateKeyController.dispose(); + _publicKeyController.dispose(); + _privateKeyController.dispose(); super.dispose(); }
38-45: Guard null/empty npub before copyingIf npub isn’t loaded yet, passing null may throw or show a bad toast. Early-return.
void _copyPublicKey() { - final npub = ref.read(nostrKeysProvider).npub; - ClipboardUtils.copyWithToast( + final String? npub = ref.read(nostrKeysProvider).npub; + if (npub == null || npub.isEmpty) { + return; + } + ClipboardUtils.copyWithToast( ref: ref, textToCopy: npub, successMessage: 'Public key copied', ); }
16-21: Add SHA-256 checksum and verification steps to docs
The README/docs lack the APK’s SHA-256 hash and instructions for verifying with apksigner or AppVerifier.scripts/build.sh (1)
352-356: Do not put signing-certificate SHA-256 into .sha256 files; compute file hash separatelyCurrent flow conflates the APK signing cert fingerprint (from apksigner) with the file hash and writes that value into “.apk.sha256”. That misleads verification and breaks tooling that expects a file checksum.
Fix:
- Keep using apksigner output as the “signing cert SHA-256 fingerprint”.
- Always compute the file’s SHA-256 for .apk.sha256.
- When capturing function output, strip log lines.
Minimal diffs (ARM64 shown; mirror for ARMv7/x86_64 and debug):
- ARM64_HASH="" + ARM64_HASH="" # signing cert SHA-256 (fingerprint) + ARM64_FILE_HASH="" # file SHA-256 ARMV7_HASH="" X86_64_HASH="" + ARMV7_FILE_HASH="" + X86_64_FILE_HASH=""- if [ -f "$ARM64_APK_PATH" ]; then - ARM64_HASH=$(generate_apk_hash "$ARM64_APK_PATH" "arm64-v8a") - fi + if [ -f "$ARM64_APK_PATH" ]; then + ARM64_HASH=$(generate_apk_hash "$ARM64_APK_PATH" "arm64-v8a" | tail -n1) + ARM64_FILE_HASH=$(shasum -a 256 "$ARM64_APK_PATH" | cut -d' ' -f1) + fi- if [ -n "$ARM64_HASH" ]; then - print_info " SHA-256: $ARM64_HASH" - # Create hash file - echo "$ARM64_HASH whitenoise-${VERSION_NAME}-arm64-v8a.apk" > "$OUTPUT_DIR/whitenoise-${VERSION_NAME}-arm64-v8a.apk.sha256" + if [ -n "$ARM64_FILE_HASH" ]; then + print_info " File SHA-256: $ARM64_FILE_HASH" + echo "$ARM64_FILE_HASH whitenoise-${VERSION_NAME}-arm64-v8a.apk" > "$OUTPUT_DIR/whitenoise-${VERSION_NAME}-arm64-v8a.apk.sha256" + fi + if [ -n "$ARM64_HASH" ]; then + print_info " Signing cert SHA-256: $ARM64_HASH" fiRepeat analogous replacements for ARMv7/x86_64 blocks and for the debug section (use ARM64_DEBUG_FILE_HASH, etc.). Also update build_info.txt population to list both the file SHA-256 (for .sha256) and the signing cert SHA-256 separately.
Also applies to: 369-380, 384-396, 400-406
lib/ui/chat/chat_info/widgets/group_member_bottom_sheet.dart (1)
48-56: Align toast messages with new conventions and publish signing certificate hash
- lib/utils/clipboard_utils.dart (defaults at lines 35, 40, 70, 78) & test/utils/clipboard_utils_test.dart (lines 59, 199): replace legacy defaults (‘Copied to clipboard’, ‘Failed to copy to clipboard’) with the new pattern (e.g. ‘… copied’, ‘No text to copy’).
- lib/ui/settings/wallet/wallet_screen.dart:83 & lib/ui/chat/services/chat_dialog_service.dart:130: remove “to clipboard” suffix (e.g. change ‘Connection secret copied to clipboard’ → ‘Connection secret copied’).
- Donation flows: no occurrences of ‘Copied bitcoin address’ or ‘Copied lightning address’ in lib—add the missing implementations and/or tests.
- README.md/docs: there’s no published SHA-256 app signing certificate hash (only code in scripts/build.sh). Add the final hash per #409.
lib/ui/chat/chat_info/dm_chat_info.dart (1)
111-119: Standardize copy-to-clipboard toast messages
Non-standard toasts remain; all copy-to-clipboard messages must start with “Copied”, drop the “to clipboard” suffix, and have no trailing period.• lib/ui/settings/profile_keys/profile_keys_screen.dart (line 43)
• lib/ui/settings/profile/share_profile_screen.dart (line 52)
• lib/ui/contact_list/widgets/user_profile.dart (line 32)
• lib/ui/chat/chat_info/dm_chat_info.dart (line 116)
• lib/ui/chat/chat_info/widgets/group_member_bottom_sheet.dart (line 53)
– Change
successMessage: 'Public key copied'
→
successMessage: 'Copied public key'• lib/ui/settings/wallet/wallet_screen.dart (line 83)
– Change
successMessage: 'Connection secret copied to clipboard'
→
successMessage: 'Copied connection secret'• lib/ui/chat/services/chat_dialog_service.dart (line 130)
– Change
Text('Message copied to clipboard')
→
Text('Copied message')Review and update the fallback in lib/utils/clipboard_utils.dart (default
successMessagefrom'Copied to clipboard'→'Copied').lib/src/rust/api/error.freezed.dart (1)
1-1636: Document app signing certificate SHA-256 fingerprint
Add the app signing certificate’s SHA-256 fingerprint (as output byapksigner verify --print-certs) to README.md (or docs/release.md) under the Release section, separate from the APK file checksums.
🧹 Nitpick comments (11)
lib/ui/settings/profile/share_profile_screen.dart (1)
48-54: Remove unused context param or use it for i18n.context is not used in
_copyToClipboard. Either remove it or leverage it for AppLocalizations. Minimal removal:- void _copyToClipboard(BuildContext context, String text) { + void _copyToClipboard(String text) { ClipboardUtils.copyWithToast( ref: ref, textToCopy: text, successMessage: 'Public key copied', ); } ... - InkWell( - onTap: () => _copyToClipboard(context, npub), + InkWell( + onTap: () => _copyToClipboard(npub),Also applies to: 142-144
lib/ui/settings/profile_keys/profile_keys_screen.dart (1)
106-114: Localize hardcoded stringsMove UI text to AppLocalizations to follow project guidelines and enable translations.
Also applies to: 128-136, 165-171, 189-195
lib/ui/settings/donate/donate_screen.dart (1)
18-24: Clipboard toast copy updates match #550; reduce magic strings and prep for i18n
- Messages conform to the spec (“Copied lightning address” / “Copied bitcoin address”). Good.
- To avoid typos and ease reuse, avoid raw 'lightning'/'bitcoin' literals; define constants (or an enum) and reference them at call sites. Consider routing the success text through AppLocalizations next.
Apply within the shown ranges and add the constants near the top of the class/file:
+ static const String _lightningType = 'lightning'; + static const String _bitcoinType = 'bitcoin';- void _copyToClipboard(WidgetRef ref, String type, String text) { + void _copyToClipboard(WidgetRef ref, String type, String text) { ClipboardUtils.copyWithToast( ref: ref, textToCopy: text, - successMessage: 'Copied $type address', + successMessage: 'Copied $type address', ); }- onTap: () => _copyToClipboard(ref, 'lightning', kLightningAddress), + onTap: () => _copyToClipboard(ref, _lightningType, kLightningAddress),- 'bitcoin', + _bitcoinType,Optional (outside ranges): if localization is available, derive the message via AppLocalizations for consistent translations.
Also applies to: 108-113, 137-146
scripts/build.sh (3)
53-56: sort -V is not portable on macOS; add fallbackmacOS BSD sort lacks -V. Use gsort if present, or ls -1v as a fallback.
- LATEST_BUILD_TOOLS=$(ls "$BUILD_TOOLS_DIR" | sort -V | tail -n 1) + if command -v gsort >/dev/null 2>&1; then + LATEST_BUILD_TOOLS=$(ls "$BUILD_TOOLS_DIR" | gsort -V | tail -n 1) + else + LATEST_BUILD_TOOLS=$(ls -1v "$BUILD_TOOLS_DIR" | tail -n 1) + fi
49-56: Support ANDROID_SDK_ROOT in addition to ANDROID_HOMEModern setups often export ANDROID_SDK_ROOT. Use either.
- if [ -n "$ANDROID_HOME" ]; then + if [ -n "$ANDROID_HOME" ] || [ -n "$ANDROID_SDK_ROOT" ]; then - BUILD_TOOLS_DIR="$ANDROID_HOME/build-tools" + SDK_DIR="${ANDROID_HOME:-$ANDROID_SDK_ROOT}" + BUILD_TOOLS_DIR="$SDK_DIR/build-tools"Also applies to: 66-71
539-614: Surface signing cert hash per #409 in docsYou now emit fingerprints and .sha256 files in versioned output. Add a short README snippet explaining:
- how to verify the APK file hash (.sha256)
- how to verify the signing cert fingerprint via apksigner/AppVerifier
- where the “expected” cert SHA-256 is published
justfile (1)
211-211: android-build no longer produces versioned artifacts; confirm consumersSwitching to “./scripts/build.sh --full --android” stops producing OUTPUT_DIR, .sha256, and build_info for this recipe. Ensure any downstream steps (manual QA, distribution to testers) don’t rely on versioned outputs. If they do, consider adding an android-build-versioned target.
lib/ui/settings/network/widgets/relay_expansion_tile.dart (2)
117-118: Localize the error string and avoid hard-coded EnglishMove "Error Loading Relays" into AppLocalizations and drop const since it uses context.
- else if (widget.relayState.error != null) - const Center(child: Text('Error Loading Relays')) + else if (widget.relayState.error != null) + Center(child: Text(AppLocalizations.of(context)!.errorLoadingRelays))Add import (top of file):
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
41-56: Reduce runtime type checks with Dart 3 pattern matching (cleaner, safer)Replace chained is/cast blocks with exhaustive type-pattern switch. It’s clearer and avoids accidental wrong casts. Add a default to catch unsupported notifier types.
Future<void> _addRelay(String url) async { try { - // Call the appropriate notifier's addRelay method - if (widget.relayNotifier is NormalRelaysNotifier) { - return await (widget.relayNotifier as NormalRelaysNotifier).addRelay(url); - } - if (widget.relayNotifier is InboxRelaysNotifier) { - return await (widget.relayNotifier as InboxRelaysNotifier).addRelay(url); - } - if (widget.relayNotifier is KeyPackageRelaysNotifier) { - return await (widget.relayNotifier as KeyPackageRelaysNotifier).addRelay(url); - } + switch (widget.relayNotifier) { + case NormalRelaysNotifier n: + await n.addRelay(url); + case InboxRelaysNotifier n: + await n.addRelay(url); + case KeyPackageRelaysNotifier n: + await n.addRelay(url); + default: + ref.showErrorToast('Unknown relay notifier'); + } } catch (e) { ref.showErrorToast('Failed to add relay: $e'); } } Future<void> _deleteRelay(String url) async { try { - // Call the appropriate notifier's deleteRelay method - if (widget.relayNotifier is NormalRelaysNotifier) { - return await (widget.relayNotifier as NormalRelaysNotifier).deleteRelay(url); - } - if (widget.relayNotifier is InboxRelaysNotifier) { - return await (widget.relayNotifier as InboxRelaysNotifier).deleteRelay(url); - } - if (widget.relayNotifier is KeyPackageRelaysNotifier) { - return await (widget.relayNotifier as KeyPackageRelaysNotifier).deleteRelay(url); - } + switch (widget.relayNotifier) { + case NormalRelaysNotifier n: + await n.deleteRelay(url); + case InboxRelaysNotifier n: + await n.deleteRelay(url); + case KeyPackageRelaysNotifier n: + await n.deleteRelay(url); + default: + ref.showErrorToast('Unknown relay notifier'); + } } catch (e) { ref.showErrorToast('Failed to delete relay: $e'); } }Also applies to: 58-73
lib/ui/chat/chat_info/widgets/group_member_bottom_sheet.dart (1)
49-55: Toast text now matches #550 style guide"Public key copied" (lowercase k, no period) adheres to the new convention. Consider localizing both success and noText messages via AppLocalizations for consistency.
lib/ui/chat/chat_info/dm_chat_info.dart (1)
116-118: Avoid hard-coded user-facing strings; use AppLocalizations or central constants.To keep translations consistent and avoid drift across screens, reference a localized key or a shared constant instead of a raw string.
textToCopy: npub, - successMessage: 'Public key copied', + successMessage: ToastMessages.publicKeyCopied, noTextMessage: 'No public key to copy',Example constant (place in a shared constants file and import here):
// lib/config/constants/toast_messages.dart class ToastMessages { static const String publicKeyCopied = 'Public key copied'; static const String noPublicKeyToCopy = 'No public key to copy'; }Prefer AppLocalizations if keys exist (e.g., context.l10n.publicKeyCopied).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (2)
ios/Podfile.lockis excluded by!**/*.lockpubspec.lockis excluded by!**/*.lock
📒 Files selected for processing (29)
android/app/build.gradle.kts(1 hunks)justfile(1 hunks)lib/config/states/auth_state.freezed.dart(6 hunks)lib/config/states/chat_search_state.freezed.dart(13 hunks)lib/config/states/chat_state.freezed.dart(7 hunks)lib/config/states/group_state.freezed.dart(6 hunks)lib/config/states/nostr_keys_state.freezed.dart(3 hunks)lib/config/states/profile_state.freezed.dart(3 hunks)lib/config/states/theme_state.freezed.dart(6 hunks)lib/config/states/toast_state.freezed.dart(12 hunks)lib/config/states/welcome_state.freezed.dart(3 hunks)lib/src/rust/api.dart(1 hunks)lib/src/rust/api/accounts.dart(2 hunks)lib/src/rust/api/error.dart(1 hunks)lib/src/rust/api/error.freezed.dart(18 hunks)lib/src/rust/api/groups.dart(2 hunks)lib/src/rust/api/relays.dart(1 hunks)lib/src/rust/api/users.dart(1 hunks)lib/src/rust/api/utils.dart(1 hunks)lib/src/rust/frb_generated.dart(104 hunks)lib/src/rust/frb_generated.io.dart(15 hunks)lib/ui/chat/chat_info/dm_chat_info.dart(1 hunks)lib/ui/chat/chat_info/widgets/group_member_bottom_sheet.dart(1 hunks)lib/ui/contact_list/widgets/user_profile.dart(1 hunks)lib/ui/settings/donate/donate_screen.dart(3 hunks)lib/ui/settings/network/widgets/relay_expansion_tile.dart(1 hunks)lib/ui/settings/profile/share_profile_screen.dart(1 hunks)lib/ui/settings/profile_keys/profile_keys_screen.dart(2 hunks)scripts/build.sh(4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.dart
📄 CodeRabbit inference engine (.cursor/rules/flutter.mdc)
**/*.dart: Always declare the type of each variable and function (parameters and return value). Avoid using 'any'. Create necessary types.
Don't leave blank lines within a function.
One export per file.
Use PascalCase for classes.
Use camelCase for variables, functions, and methods.
Use underscores_case for file and directory names.
Use UPPERCASE for environment variables. Avoid magic numbers and define constants.
Start each function with a verb.
Use verbs for boolean variables. Example: isLoading, hasError, canDelete, etc.
Use complete words instead of abbreviations and correct spelling, except for standard and well-known abbreviations (API, URL, i, j, err, ctx, req, res, next).
Write short functions with a single purpose. Less than 20 instructions.
Name functions with a verb and something else. If it returns a boolean, use isX or hasX, canX, etc. If it doesn't return anything, use executeX or saveX, etc.
Avoid nesting blocks by early checks and returns, or extraction to utility functions.
Use higher-order functions (map, filter, reduce, etc.) to avoid function nesting. Use arrow functions for simple functions (less than 3 instructions). Use named functions for non-simple functions.
Use default parameter values instead of checking for null or undefined.
Reduce function parameters using RO-RO: use an object to pass multiple parameters and to return results. Declare necessary types for input arguments and output.
Use a single level of abstraction in functions.
Don't abuse primitive types and encapsulate data in composite types.
Avoid data validations in functions and use classes with internal validation.
Prefer immutability for data. Use readonly for data that doesn't change. Use 'as const' for literals that don't change.
Declare interfaces to define contracts.
Write small classes with a single purpose. Less than 200 instructions, less than 10 public methods, less than 10 properties.
Use exceptions to handle errors you don't expect. If you catch an exception, it sh...
Files:
lib/src/rust/api/relays.dartlib/src/rust/api/error.dartlib/ui/contact_list/widgets/user_profile.dartlib/ui/settings/profile/share_profile_screen.dartlib/ui/chat/chat_info/dm_chat_info.dartlib/ui/chat/chat_info/widgets/group_member_bottom_sheet.dartlib/ui/settings/profile_keys/profile_keys_screen.dartlib/config/states/profile_state.freezed.dartlib/src/rust/api/users.dartlib/config/states/auth_state.freezed.dartlib/src/rust/api.dartlib/src/rust/api/accounts.dartlib/config/states/toast_state.freezed.dartlib/config/states/chat_search_state.freezed.dartlib/config/states/group_state.freezed.dartlib/ui/settings/donate/donate_screen.dartlib/config/states/welcome_state.freezed.dartlib/src/rust/api/utils.dartlib/config/states/nostr_keys_state.freezed.dartlib/src/rust/frb_generated.io.dartlib/src/rust/api/error.freezed.dartlib/config/states/chat_state.freezed.dartlib/ui/settings/network/widgets/relay_expansion_tile.dartlib/config/states/theme_state.freezed.dartlib/src/rust/frb_generated.dartlib/src/rust/api/groups.dart
🧠 Learnings (5)
📚 Learning: 2025-08-08T13:39:00.500Z
Learnt from: CR
PR: parres-hq/whitenoise_flutter#0
File: .cursor/rules/flutter.mdc:0-0
Timestamp: 2025-08-08T13:39:00.500Z
Learning: Applies to **/*.dart : Use freezed to manage UI states.
Applied to files:
lib/config/states/profile_state.freezed.dartlib/config/states/auth_state.freezed.dartlib/config/states/toast_state.freezed.dartlib/config/states/chat_search_state.freezed.dartlib/config/states/group_state.freezed.dartlib/config/states/welcome_state.freezed.dartlib/config/states/nostr_keys_state.freezed.dartlib/config/states/chat_state.freezed.dartlib/config/states/theme_state.freezed.dart
📚 Learning: 2025-08-29T09:11:07.251Z
Learnt from: erskingardner
PR: parres-hq/whitenoise_flutter#530
File: rust/src/api/utils.rs:23-26
Timestamp: 2025-08-29T09:11:07.251Z
Learning: In the nostr-sdk Rust library, PublicKey::parse method accepts both hex and bech32 (npub) encoded strings, so there's no need to use format-specific methods like PublicKey::from_bech32 when parsing public keys from string input.
Applied to files:
lib/src/rust/api/utils.dart
📚 Learning: 2025-08-12T11:21:53.640Z
Learnt from: josefinalliende
PR: parres-hq/whitenoise_flutter#455
File: lib/ui/settings/profile/switch_profile_bottom_sheet.dart:0-0
Timestamp: 2025-08-12T11:21:53.640Z
Learning: In the whitenoise_flutter codebase, ContactModel.publicKey can be stored in either npub format (from metadata cache) or hex format (from account storage). The activeAccountProvider may return either format depending on how the account was originally stored, so normalization to hex format is required when comparing with other hex-normalized keys in sorting logic.
Applied to files:
lib/src/rust/api/utils.dartlib/src/rust/frb_generated.dart
📚 Learning: 2025-08-08T13:39:00.500Z
Learnt from: CR
PR: parres-hq/whitenoise_flutter#0
File: .cursor/rules/flutter.mdc:0-0
Timestamp: 2025-08-08T13:39:00.500Z
Learning: Applies to **/*.dart : Use the whitenoise rust crate (via flutter_rust_bridge) as the source of all data and only way to trigger changes in our data model.
Applied to files:
lib/src/rust/frb_generated.io.dartlib/src/rust/frb_generated.dart
📚 Learning: 2025-08-08T13:39:00.500Z
Learnt from: CR
PR: parres-hq/whitenoise_flutter#0
File: .cursor/rules/flutter.mdc:0-0
Timestamp: 2025-08-08T13:39:00.500Z
Learning: Applies to **/*.dart : Use flutter_rust_bridge to access core functionality of the app.
Applied to files:
lib/src/rust/frb_generated.dart
🔇 Additional comments (38)
lib/ui/contact_list/widgets/user_profile.dart (1)
32-33: Toast text standardized correctly.Matches the spec: "Public key copied" (sentence case, no period). LGTM.
lib/ui/settings/profile/share_profile_screen.dart (1)
52-53: Toast text standardized correctly."Public key copied" aligns with #550. LGTM.
lib/config/states/auth_state.freezed.dart (1)
29-31: Generated code reflow only; no behavioral changes.Changes are formatting/line-wrapping to copyWith and equality; signatures and defaults unchanged. Safe to keep.
Also applies to: 47-49, 95-101, 112-118, 192-194, 239-241
android/app/build.gradle.kts (1)
13-15: archivesBaseName correctly prefixes APK outputs and matches build.sh. No further action needed.lib/config/states/group_state.freezed.dart (1)
21-23: Generated code reflow only; no behavioral changes.Formatting changes to getters, copyWith accessors, and equality. No API or logic impact. LGTM.
Also applies to: 37-39, 293-295, 349-351, 409-411
lib/config/states/profile_state.freezed.dart (3)
33-34: Generated code reflow only — OKFormatting-only change to copyWith getter; no behavioral impact.
148-170: Generated copyWith interface wrapping — OKPure indentation/line-wrap adjustments; signatures unchanged.
289-303: Equality check rewrapped — OKLine breaks only; semantics unchanged.
lib/ui/settings/profile_keys/profile_keys_screen.dart (2)
43-44: Toast text matches #550 spec“Public key copied” uses lowercase “key” and no period.
53-54: Toast text matches #550 spec“Private key copied” standardized correctly.
lib/config/states/toast_state.freezed.dart (1)
30-31: Freezed reformat only — OKAll hunks are whitespace/line-wrap changes to generated copyWith/equality; no semantic changes.
Also applies to: 112-128, 229-233, 298-300, 366-380, 456-467, 510-512, 522-524, 539-541, 597-599, 695-697
lib/config/states/nostr_keys_state.freezed.dart (1)
28-30: Generated file wrapping only — OKCopyWith getter/interface and equality rewrapped; behavior unchanged.
Also applies to: 91-101, 180-182
lib/config/states/theme_state.freezed.dart (1)
25-27: Generated file formatting — OKLine-wrap/indentation only; no logic changes.
Also applies to: 40-42, 68-77, 80-83, 124-126, 150-152
lib/config/states/welcome_state.freezed.dart (1)
28-29: Formatting-only Freezed changes look fineNo functional impact detected. Safe to keep in sync with generated output.
Also applies to: 96-101, 210-212
scripts/build.sh (2)
228-236: Creating OUTPUT_DIR after cleaning is correctPrevents it from being wiped by flutter clean. Nice.
Also applies to: 275-279
345-348: Renamed APK paths depend on Gradle archivesBaseName; verify CI alignmentIf android/app/build.gradle(.kts) sets archivesBaseName = "whitenoise", these paths are correct; otherwise, the script will miss artifacts. Confirm CI/build cache uses the same setting.
Also applies to: 441-443
lib/config/states/chat_search_state.freezed.dart (1)
29-31: Generated formatting only; no behavioral changesLooks consistent with other Freezed outputs.
Also applies to: 104-110, 222-224, 286-288, 354-368, 514-516, 527-535, 569-577, 648-650, 682-684
lib/ui/settings/network/widgets/relay_expansion_tile.dart (1)
77-113: Non-collapsible header solves #553Switching from ExpansionTile to a static Column/Row removes the accidental collapse behavior when tapping the title. The help icon is explicitly the only actionable in the header, and the Add button is clearly isolated. Looks good.
lib/src/rust/api/users.dart (1)
47-51: Formatting-only change to hashCode; OKNo behavioral impact; consistent with the multi-line formatting style used elsewhere.
lib/src/rust/api/utils.dart (1)
21-24: Formatting-only change; OKLine-wrapping the return expression is fine. No semantic changes.
lib/src/rust/api.dart (1)
45-46: Formatting-only change; OKMulti-line return for getAppSettings is consistent with the rest of the FRB wrappers.
lib/ui/chat/chat_info/widgets/group_member_bottom_sheet.dart (1)
185-192: Remove normalization suggestion—npub comparison is already normalizedBoth
admin.publicKeyandcurrentUserNpubare converted to npub (vianpubFromHexPubkeyin the provider and.toNpub()in the bottom sheet), so they’re already in the same format and the equality check won’t misidentify admins. No additional normalization needed.Likely an incorrect or invalid review comment.
lib/ui/chat/chat_info/dm_chat_info.dart (1)
116-116: Toast text matches the standard."Public key copied" follows the capitalization and no-period rule from #550.
lib/src/rust/api/relays.dart (2)
14-16: Formatting-only FRB wrapper changes look good.Arrow funcs wrapped to next line without semantic change; safe in generated code.
Also applies to: 17-19, 20-21
14-21: Titles are static Text widgets without tap handlers—no UX changes needed. RelayExpansionTile renders the title as a plain Text (no GestureDetector/InkWell), with only the help and add icons wrapped for taps.Likely an incorrect or invalid review comment.
lib/src/rust/api/groups.dart (1)
102-106: Generated wrapper reflow only; no behavior change.Method bodies just wrap to multiple lines; API surface identical.
Also applies to: 107-111, 112-116, 162-165
lib/config/states/chat_state.freezed.dart (1)
1-444: Freezed-generated formatting changes are fine.No semantic diffs detected. Continues to align with prior guidance to use Freezed for UI states.
lib/src/rust/api/error.freezed.dart (1)
1-1636: Freezed error unions reflowed only; safe to merge.Formatting/copyWith wrapping changes only; constructors and union variants unchanged.
lib/src/rust/frb_generated.dart (6)
22-23: Conditional import rewrap is fineNo behavioral change. Keeps the standard FRB conditional import pattern.
84-89: Verify FFI loader stem/path match produced artifactsConfirm that the stem “rust_lib_whitenoise” and ioDirectory/webPrefix align with actual library names/locations for all targets (Android/iOS/desktop/web). A mismatch will cause runtime load failures.
64-69: Getter wrapping onlyPure formatting of apiImplConstructor/wireConstructor; no semantic changes.
386-391: TaskConstMeta getters: formatting-onlyAll these “TaskConstMeta get … => const TaskConstMeta(…)” changes are line-wraps only.
Also applies to: 417-421, 449-454, 482-487, 520-525, 590-595, 627-632, 658-663, 689-694, 771-775, 806-811, 841-845, 901-905, 936-941, 969-974, 1004-1009, 1039-1043, 1069-1072, 1098-1103, 1129-1133, 1158-1163, 1191-1196, 1224-1229, 1255-1259, 1319-1324, 1351-1355, 1385-1389, 1416-1421, 1447-1451, 1482-1485, 1512-1516, 1548-1552, 1581-1586, 1612-1616, 1642-1646, 1672-1676, 1708-1712, 1741-1745, 1773-1777, 1803-1807, 1834-1838, 1866-1870, 1906-1910, 1943-1947, 1987-1991, 2021-2025, 2053-2056, 2087-2091, 2122-2126, 2156-2160, 2194-2198, 2225-2229, 2256-2260
2368-2374: Decode helpers reflowedDCO/SSE decode wrappers rewrapped; signatures and behavior unchanged.
Also applies to: 3071-3079, 3118-3127, 3194-3203, 3231-3239, 3267-3275
3961-3971: Encode helpers reflowedSSE encode helpers line-wrapped only; no logic change.
Also applies to: 4000-4010, 4013-4023, 4099-4109, 4112-4119, 4122-4129, 4145-4155, 4158-4165, 4178-4188
lib/src/rust/api/error.dart (1)
46-50: Multiline returns are OKPure formatting; calls remain identical to the FRB API.
Also applies to: 52-55
lib/src/rust/frb_generated.io.dart (2)
32-34: Getter wrapping is fineFormatting-only for CrossPlatformFinalizerArg getter.
1034-1040: Constructor/_lookup reflowOnly layout changed; symbol lookup remains the same.
lib/src/rust/api/accounts.dart (1)
16-18: Return-expression rewraps are fineAll three are formatting-only; behavior unchanged.
Also applies to: 22-24, 25-28
lib/src/rust/api/accounts.dart
Outdated
| pubkey.hashCode ^ | ||
| lastSyncedAt.hashCode ^ | ||
| createdAt.hashCode ^ | ||
| updatedAt.hashCode; |
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.
Null-safety bug in hashCode (nullable lastSyncedAt)
Accessing lastSyncedAt.hashCode when lastSyncedAt is null will fail static analysis and can NPE. Use Object.hash (null-safe) or null-aware operator.
Apply this diff:
- int get hashCode =>
- pubkey.hashCode ^
- lastSyncedAt.hashCode ^
- createdAt.hashCode ^
- updatedAt.hashCode;
+ int get hashCode =>
+ Object.hash(pubkey, lastSyncedAt, createdAt, updatedAt);📝 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.
| pubkey.hashCode ^ | |
| lastSyncedAt.hashCode ^ | |
| createdAt.hashCode ^ | |
| updatedAt.hashCode; | |
| int get hashCode => | |
| Object.hash(pubkey, lastSyncedAt, createdAt, updatedAt); |
🤖 Prompt for AI Agents
In lib/src/rust/api/accounts.dart around lines 130 to 133, the current hashCode
expression accesses lastSyncedAt.hashCode directly which breaks null-safety when
lastSyncedAt can be null; replace the combined XOR expression with a null-safe
approach—either use Object.hash(pubkey, lastSyncedAt, createdAt, updatedAt) or
change lastSyncedAt.hashCode to (lastSyncedAt?.hashCode ?? 0) so the hashCode
computation is null-safe and static-analysis clean.
josefinalliende
left a 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.
✅ LGTM! Coudn't check the build command, but the toast messages and fixes in relays screen work fine in my ios emulator! Approved! 🚀
Collection of a few bug fixes:
Fixes #550
Fixes #553
Fixes #409
Summary by CodeRabbit
Refactor
Style
Chores