Skip to content

Fix build crash when key.properties is missing and add example config#802

Open
Shweta-281 wants to merge 1 commit intoAOSSIE-Org:masterfrom
Shweta-281:fix/key-properties-setup
Open

Fix build crash when key.properties is missing and add example config#802
Shweta-281 wants to merge 1 commit intoAOSSIE-Org:masterfrom
Shweta-281:fix/key-properties-setup

Conversation

@Shweta-281
Copy link
Copy Markdown
Contributor

@Shweta-281 Shweta-281 commented Mar 26, 2026

🐛 Fix: Build crash due to missing key.properties

This PR fixes a crash that occurs when key.properties is not present.

✅ Changes:

  • Removed unsafe casting (as String) from keystoreProperties
  • Ensured debug signing is used when keystore is unavailable
  • Added key.properties.example for contributor setup guidance
  • Updated .gitignore to exclude sensitive files

🚀 Result:

  • Project now runs without requiring keystore setup
  • Improves onboarding experience for new contributors

Fixes #801

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking CHANGE which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (does not change functionality, e.g. code style improvements, linting)
  • Documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

Please include screenshots below if applicable.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules
  • I have checked my code and corrected any misspellings

Maintainer Checklist

Summary by CodeRabbit

Release Notes

  • New Features

    • Extended platform support to Linux, macOS, Web, and Windows alongside existing Android and iOS platforms.
  • Improvements

    • Migrated package dependencies from Git-based sources to pub-hosted semantic versioning for improved consistency and maintainability.
    • Enhanced Android signing configuration to support optional keystore properties with safer defaults.
  • Tests

    • Added foundational test infrastructure for widget testing.

@Shweta-281 Shweta-281 requested a review from M4dhav as a code owner March 26, 2026 14:56
@github-actions
Copy link
Copy Markdown
Contributor

🎉 Welcome @Shweta-281!
Thank you for your pull request! Our team will review it soon. 🔍

  • Please ensure your PR follows the contribution guidelines. ✅
  • All automated tests should pass before merging. 🔄
  • If this PR fixes an issue, link it in the description. 🔗

We appreciate your contribution! 🚀

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 26, 2026

📝 Walkthrough

Walkthrough

This PR establishes cross-platform native project infrastructure for a Flutter application. It adds build configurations, native source files, and platform-specific setup for iOS, Linux, macOS, and Windows, resolves Android keystore handling issues, and updates project metadata and dependencies.

Changes

Cohort / File(s) Summary
Android Signing Configuration
android/app/build.gradle.kts, android/key.properties.example, .gitignore
Modified keystore property handling to treat values as nullable with empty string defaults; added example configuration file and excluded actual key.properties from version control.
iOS Native Project
ios/Runner/SceneDelegate.swift, ios/RunnerTests/RunnerTests.swift
Added SceneDelegate class and placeholder test case for iOS runner target.
Linux Build System
linux/CMakeLists.txt, linux/flutter/CMakeLists.txt, linux/flutter/generated_plugins.cmake
Established CMake-based build configuration with Flutter integration, plugin management, and build artifact handling.
Linux Native Application
linux/runner/CMakeLists.txt, linux/runner/main.cc, linux/runner/my_application.cc, linux/runner/my_application.h, linux/.gitignore
Implemented GTK-based Linux application with plugin registration and configuration.
Linux Plugin Registrant
linux/flutter/generated_plugin_registrant.cc, linux/flutter/generated_plugin_registrant.h
Generated plugin registration infrastructure for Linux platform.
macOS Build Infrastructure
macos/Flutter/Flutter-Debug.xcconfig, macos/Flutter/Flutter-Release.xcconfig, macos/Flutter/GeneratedPluginRegistrant.swift
Added Xcode configuration files and plugin registrant for macOS builds.
macOS Xcode Project
macos/Runner.xcodeproj/project.pbxproj, macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist, macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme, macos/Runner.xcworkspace/contents.xcworkspacedata, macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
Established complete Xcode project structure with build targets, schemes, and workspace configuration.
macOS Native Application
macos/Runner/AppDelegate.swift, macos/Runner/MainFlutterWindow.swift, macos/Runner/Base.lproj/MainMenu.xib, macos/Runner/Info.plist, macos/RunnerTests/RunnerTests.swift, macos/.gitignore
Implemented macOS application delegates, main window, UI resources, and test placeholder.
macOS Build Configurations
macos/Runner/Configs/AppInfo.xcconfig, macos/Runner/Configs/Debug.xcconfig, macos/Runner/Configs/Release.xcconfig, macos/Runner/Configs/Warnings.xcconfig
Defined build settings for application metadata, build types, and compiler warnings.
macOS App Assets & Entitlements
macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json, macos/Runner/DebugProfile.entitlements, macos/Runner/Release.entitlements
Added icon configuration and platform entitlements for debug/release builds.
Windows Build System
windows/CMakeLists.txt, windows/flutter/CMakeLists.txt, windows/flutter/generated_plugins.cmake
Established CMake-based build configuration with Flutter integration, plugin assembly, and wrapper library generation for Windows.
Windows Native Application
windows/runner/CMakeLists.txt, windows/runner/main.cpp, windows/runner/flutter_window.cpp, windows/runner/flutter_window.h, windows/runner/win32_window.cpp, windows/runner/win32_window.h, windows/runner/utils.cpp, windows/runner/utils.h, windows/.gitignore
Implemented Win32-based Flutter application with DPI awareness, message handling, and utility functions for console/argument/encoding management.
Windows Resources & Configuration
windows/runner/Runner.rc, windows/runner/resource.h, windows/runner/runner.exe.manifest
Added Windows resource script, icon definitions, and application manifest with DPI awareness.
Windows Plugin Registrant
windows/flutter/generated_plugin_registrant.cc, windows/flutter/generated_plugin_registrant.h
Generated plugin registration infrastructure for Windows platform.
Web Static Assets
web/index.html, web/manifest.json
Added HTML entry point and Web App Manifest for Flutter web build.
Project Metadata & Dependencies
.metadata, pubspec.yaml
Updated Flutter tool metadata with new platform revisions and changed dependency sources for textfield_tags and flutter_lyric from Git refs to semantic versioning constraints.
Testing
test/widget_test.dart
Added placeholder widget test for counter UI interactions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • kmk142789

Poem

🐰 Cross-platforms bloom beneath the Flutter tree,
Windows, Linux, macOS—now they're all set free!
With CMake, Xcode, and native code so fine,
The rabbit hops between them on this build-system line.
From iOS to the web, each platform now resounds,
A symphonic build that spins the whole thing 'round! 🎵

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes extensive out-of-scope platform setup files (iOS/macOS/Linux/Windows runners, web assets) unrelated to the key.properties fix for Android, creating significant scope creep beyond the stated objective. Remove platform-specific setup files (ios/, macos/, linux/, windows/, web/). Focus the PR solely on the Android key.properties fix, .gitignore update, and example config file.
Docstring Coverage ⚠️ Warning Docstring coverage is 20.83% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely describes the main changes: fixing a build crash when key.properties is missing and adding an example config file.
Linked Issues check ✅ Passed The PR addresses all coding requirements from issue #801: safely handles null values in keystoreProperties [801], adds key.properties.example file [801], and updates .gitignore to exclude sensitive files [801].
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
android/app/build.gradle.kts (1)

50-63: ⚠️ Potential issue | 🟠 Major

Release signing config override negates fallback to debug, causing failures when key.properties is missing.

Lines 61 and 62 both assign signingConfig: Line 61 sets it to "debug" as intended fallback, but Line 62 unconditionally overwrites it with "release". Combined with empty-string credentials on Lines 50/51/53 (when keystore properties are absent), the release config will be applied with invalid credentials, breaking the build.

Suggested fix
+    val hasReleaseKeystore = listOf("keyAlias", "keyPassword", "storeFile", "storePassword")
+        .all { !keystoreProperties.getProperty(it).isNullOrBlank() }
+
     buildTypes {
         signingConfigs {
         create("release") {
-            keyAlias = keystoreProperties["keyAlias"] as String? ?: ""
-            keyPassword = keystoreProperties["keyPassword"] as String? ?: ""
-            storeFile = keystoreProperties["storeFile"]?.let { file(it) }
-            storePassword = keystoreProperties["storePassword"] as String? ?: ""
+            keyAlias = keystoreProperties.getProperty("keyAlias")
+            keyPassword = keystoreProperties.getProperty("keyPassword")
+            storeFile = keystoreProperties.getProperty("storeFile")?.let { file(it) }
+            storePassword = keystoreProperties.getProperty("storePassword")
         }
     }
         release {
             isMinifyEnabled = false
             isShrinkResources = false
-            signingConfig = signingConfigs.getByName("debug")
-            signingConfig = signingConfigs.getByName("release")
+            signingConfig = if (hasReleaseKeystore) {
+                signingConfigs.getByName("release")
+            } else {
+                signingConfigs.getByName("debug")
+            }
         }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@android/app/build.gradle.kts` around lines 50 - 63, The release build block
currently sets signingConfig twice (signingConfig =
signingConfigs.getByName("debug") then signingConfig =
signingConfigs.getByName("release")) which overwrites the intended debug
fallback and causes invalid release signing when keystoreProperties (keyAlias,
keyPassword, storeFile, storePassword) are missing; modify the release block so
signingConfig is only set to the debug signingConfig by default and only
switched to the release signingConfig when valid keystoreProperties exist (e.g.,
check storeFile/keyAlias or use signingConfigs.findByName("release")
conditionally), ensuring signingConfig is not unconditionally reassigned to
"release".
🧹 Nitpick comments (9)
web/manifest.json (1)

8-8: Customize the generic description.

Similar to index.html, the manifest description "A new Flutter project." is boilerplate that should be replaced with a meaningful description of the Resonate app.

📝 Suggested improvement
-    "description": "A new Flutter project.",
+    "description": "Resonate - A music streaming and social audio platform.",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/manifest.json` at line 8, Replace the boilerplate description value in
the web/manifest.json "description" property ("A new Flutter project.") with a
meaningful, app-specific description for Resonate; locate the "description"
field in web/manifest.json and update its string to succinctly describe
Resonate's purpose and core functionality.
web/index.html (1)

21-21: Customize the generic description.

The description "A new Flutter project." is boilerplate text that should be replaced with an accurate description of the Resonate app.

📝 Suggested improvement
-  <meta name="description" content="A new Flutter project.">
+  <meta name="description" content="Resonate - A music streaming and social audio platform.">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/index.html` at line 21, Replace the boilerplate meta description value in
the HTML meta tag with a concise, accurate summary of the Resonate app by
updating the <meta name="description"> content attribute to describe Resonate's
purpose, key features, and target audience (e.g., collaborative music discovery,
personalized playlists, social sharing) so the page no longer uses "A new
Flutter project." and reflects the app's actual functionality.
linux/.gitignore (1)

1-1: Minor inconsistency: consider adding trailing slash for directory pattern.

Other platform .gitignore files in this PR (e.g., windows/.gitignore, macos/.gitignore) use trailing slashes for directory patterns (flutter/ephemeral/). Consider adding the trailing slash here for consistency.

Suggested change
-flutter/ephemeral
+flutter/ephemeral/
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@linux/.gitignore` at line 1, The gitignore entry "flutter/ephemeral" should
be made consistent with other platform files by adding a trailing slash to
indicate a directory; update the entry in linux/.gitignore from
"flutter/ephemeral" to "flutter/ephemeral/" so it matches the style used in
windows/.gitignore and macos/.gitignore.
android/key.properties.example (1)

1-4: Good addition that directly addresses the PR objective.

This example file guides contributors on keystore setup. Consider adding brief comments to clarify path expectations.

📝 Suggested improvement with comments
+# Android keystore configuration for release signing
+# Copy this file to key.properties and fill in your values
 storePassword=your_password
 keyPassword=your_password
 keyAlias=upload
-storeFile=path_to_keystore
+# Path to your keystore file (relative to android/app/ or absolute)
+storeFile=../your-keystore.jks
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@android/key.properties.example` around lines 1 - 4, Add short inline comments
to the key.properties.example file explaining what each property represents and
how to set the storeFile path (e.g., relative vs absolute path and typical
keystore filenames). Specifically annotate the properties storePassword,
keyPassword, keyAlias, and storeFile so contributors know which values to
replace and how to reference the keystore (relative path under android/ or
absolute path), and mention any common default alias like "upload".
macos/RunnerTests/RunnerTests.swift (1)

7-10: Replace placeholder test with a real assertion-based check.

Right now this test provides no validation and can give false confidence in CI results.

Suggested direction
 class RunnerTests: XCTestCase {
 
   func testExample() {
-    // If you add code to the Runner application, consider adding tests here.
-    // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
+    // Add at least one smoke assertion for current macOS runner behavior.
   }
 
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@macos/RunnerTests/RunnerTests.swift` around lines 7 - 10, The placeholder
testExample in the RunnerTests test case contains no assertions—replace it with
a real assertion-based check to ensure CI fails on regressions; update the
testExample method (or add a new test in the RunnerTests class) to perform a
concrete XCTAssert call (e.g., XCTAssertNotNil/XCTAssertTrue/XCTAssertEqual
depending on what you want to validate) against a deterministic value or runtime
property (bundle identifier, known computation, or a simple sanity check) so the
test actually verifies behavior rather than being empty.
windows/runner/utils.cpp (1)

48-56: Potential unsigned integer wraparound when WideCharToMultiByte fails.

If WideCharToMultiByte fails and returns 0, subtracting 1 from the unsigned int target_length causes wraparound to UINT_MAX. While the subsequent max_size() check catches this, the logic is fragile and unclear.

♻️ Suggested improvement for clarity
-  unsigned int target_length = ::WideCharToMultiByte(
+  int target_length = ::WideCharToMultiByte(
       CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
-      -1, nullptr, 0, nullptr, nullptr)
-    -1; // remove the trailing null character
-  int input_length = (int)wcslen(utf16_string);
+      -1, nullptr, 0, nullptr, nullptr);
+  if (target_length <= 1) {
+    return std::string();
+  }
+  target_length -= 1; // remove the trailing null character
   std::string utf8_string;
-  if (target_length == 0 || target_length > utf8_string.max_size()) {
+  if (static_cast<size_t>(target_length) > utf8_string.max_size()) {
     return utf8_string;
   }
+  int input_length = static_cast<int>(wcslen(utf16_string));
   utf8_string.resize(target_length);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@windows/runner/utils.cpp` around lines 48 - 56, Avoid unsigned wraparound by
checking WideCharToMultiByte's return before subtracting: call
::WideCharToMultiByte and store its result in a signed/size_t temporary (e.g.,
raw_target_len), if raw_target_len == 0 return empty utf8_string (or handle the
error), else compute target_length = raw_target_len - 1; update references to
target_length and keep the existing max_size() guard. Reference symbols:
::WideCharToMultiByte, utf16_string, target_length, raw_target_len (new), and
utf8_string.
windows/runner/win32_window.cpp (2)

221-221: Using window_handle_ instead of hwnd parameter.

At line 221, DefWindowProc is called with window_handle_ instead of the hwnd parameter passed to MessageHandler. While these should typically be the same, using the parameter directly is more consistent and avoids potential issues if they ever differ (e.g., during destruction when window_handle_ may be null).

♻️ Suggested fix
-  return DefWindowProc(window_handle_, message, wparam, lparam);
+  return DefWindowProc(hwnd, message, wparam, lparam);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@windows/runner/win32_window.cpp` at line 221, In MessageHandler, replace the
use of the member variable window_handle_ when calling DefWindowProc with the
incoming hwnd parameter so the call becomes DefWindowProc(hwnd, message, wparam,
lparam); locate the call at the end of MessageHandler and update the argument
list to use hwnd instead of window_handle_.

89-107: Missing error handling for RegisterClass.

RegisterClass can fail (returning 0), but the return value is not checked. While unlikely to fail in practice, checking the result would make the code more robust.

🛡️ Suggested defensive check
 const wchar_t* WindowClassRegistrar::GetWindowClass() {
   if (!class_registered_) {
     WNDCLASS window_class{};
     window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
     window_class.lpszClassName = kWindowClassName;
     window_class.style = CS_HREDRAW | CS_VREDRAW;
     window_class.cbClsExtra = 0;
     window_class.cbWndExtra = 0;
     window_class.hInstance = GetModuleHandle(nullptr);
     window_class.hIcon =
         LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
     window_class.hbrBackground = 0;
     window_class.lpszMenuName = nullptr;
     window_class.lpfnWndProc = Win32Window::WndProc;
-    RegisterClass(&window_class);
-    class_registered_ = true;
+    if (RegisterClass(&window_class)) {
+      class_registered_ = true;
+    }
   }
   return kWindowClassName;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@windows/runner/win32_window.cpp` around lines 89 - 107, The RegisterClass
call in WindowClassRegistrar::GetWindowClass is unchecked; update the function
to verify RegisterClass (or RegisterClassW) returns nonzero, only set
class_registered_ on success, and on failure retrieve the OS error via
GetLastError and handle it (e.g., log the error with context and return nullptr
or throw an exception) so callers don't assume the class was registered when it
wasn't.
windows/runner/flutter_window.cpp (1)

43-45: Redundant null check before assignment.

The conditional check is unnecessary when assigning nullptr - the assignment is safe regardless.

♻️ Suggested simplification
 void FlutterWindow::OnDestroy() {
-  if (flutter_controller_) {
-    flutter_controller_ = nullptr;
-  }
+  flutter_controller_ = nullptr;
 
   Win32Window::OnDestroy();
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@windows/runner/flutter_window.cpp` around lines 43 - 45, Remove the redundant
conditional around resetting the flutter_controller_ member: always assign
flutter_controller_ = nullptr without checking its current value (replace the if
(flutter_controller_) { flutter_controller_ = nullptr; } pattern with a direct
assignment to flutter_controller_). This simplifies the code and avoids an
unnecessary null check while preserving the intended behavior of the
destructor/cleanup path that touches flutter_controller_.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/widget_test.dart`:
- Around line 13-29: The current widget_test.dart contains the Flutter template
boilerplate that asserts a Counter UI which doesn't exist in your app; replace
the failing test by removing the Counter-specific expectations and the Icons.add
interaction in the testWidgets block and instead write tests that exercise
MyApp/GetMaterialApp startup and real app behaviors (e.g., verify that MyApp
builds without exceptions, that GetMaterialApp shows expected localized strings,
theme elements, or key widgets for the Resonate UI). Locate the test function
named testWidgets in widget_test.dart and update its assertions to look for
actual widgets/text/keys present in MyApp (or add new tests that pump MyApp and
assert presence of localization keys, navigation routes, or specific widget keys
used by the app).

In `@windows/runner/flutter_window.cpp`:
- Around line 64-68: The WM_FONTCHANGE case in
FlutterWindow::HandleTopLevelWindowProc calls flutter_controller_->engine()
without ensuring flutter_controller_ is non-null; update the WM_FONTCHANGE
handler to first check flutter_controller_ (and/or
flutter_controller_->engine()) before calling ReloadSystemFonts(),
returning/ignoring the message if the controller or engine is null. Locate the
switch handling message in HandleTopLevelWindowProc and add a null guard around
the flutter_controller_->engine()->ReloadSystemFonts() invocation to prevent a
potential null pointer dereference.

In `@windows/runner/utils.cpp`:
- Around line 10-22: The error check for freopen_s is inverted in
CreateAndAttachConsole: freopen_s returns 0 on success, but the code calls _dup2
only when freopen_s returns non-zero; change the condition so that
_dup2(_fileno(stdout), 1) runs when freopen_s(&unused, "CONOUT$", "w", stdout)
returns 0, and likewise _dup2(_fileno(stdout), 2) runs when freopen_s(&unused,
"CONOUT$", "w", stderr) returns 0; keep the rest of the function (AllocConsole,
std::ios::sync_with_stdio(), FlutterDesktopResyncOutputStreams()) unchanged.

---

Outside diff comments:
In `@android/app/build.gradle.kts`:
- Around line 50-63: The release build block currently sets signingConfig twice
(signingConfig = signingConfigs.getByName("debug") then signingConfig =
signingConfigs.getByName("release")) which overwrites the intended debug
fallback and causes invalid release signing when keystoreProperties (keyAlias,
keyPassword, storeFile, storePassword) are missing; modify the release block so
signingConfig is only set to the debug signingConfig by default and only
switched to the release signingConfig when valid keystoreProperties exist (e.g.,
check storeFile/keyAlias or use signingConfigs.findByName("release")
conditionally), ensuring signingConfig is not unconditionally reassigned to
"release".

---

Nitpick comments:
In `@android/key.properties.example`:
- Around line 1-4: Add short inline comments to the key.properties.example file
explaining what each property represents and how to set the storeFile path
(e.g., relative vs absolute path and typical keystore filenames). Specifically
annotate the properties storePassword, keyPassword, keyAlias, and storeFile so
contributors know which values to replace and how to reference the keystore
(relative path under android/ or absolute path), and mention any common default
alias like "upload".

In `@linux/.gitignore`:
- Line 1: The gitignore entry "flutter/ephemeral" should be made consistent with
other platform files by adding a trailing slash to indicate a directory; update
the entry in linux/.gitignore from "flutter/ephemeral" to "flutter/ephemeral/"
so it matches the style used in windows/.gitignore and macos/.gitignore.

In `@macos/RunnerTests/RunnerTests.swift`:
- Around line 7-10: The placeholder testExample in the RunnerTests test case
contains no assertions—replace it with a real assertion-based check to ensure CI
fails on regressions; update the testExample method (or add a new test in the
RunnerTests class) to perform a concrete XCTAssert call (e.g.,
XCTAssertNotNil/XCTAssertTrue/XCTAssertEqual depending on what you want to
validate) against a deterministic value or runtime property (bundle identifier,
known computation, or a simple sanity check) so the test actually verifies
behavior rather than being empty.

In `@web/index.html`:
- Line 21: Replace the boilerplate meta description value in the HTML meta tag
with a concise, accurate summary of the Resonate app by updating the <meta
name="description"> content attribute to describe Resonate's purpose, key
features, and target audience (e.g., collaborative music discovery, personalized
playlists, social sharing) so the page no longer uses "A new Flutter project."
and reflects the app's actual functionality.

In `@web/manifest.json`:
- Line 8: Replace the boilerplate description value in the web/manifest.json
"description" property ("A new Flutter project.") with a meaningful,
app-specific description for Resonate; locate the "description" field in
web/manifest.json and update its string to succinctly describe Resonate's
purpose and core functionality.

In `@windows/runner/flutter_window.cpp`:
- Around line 43-45: Remove the redundant conditional around resetting the
flutter_controller_ member: always assign flutter_controller_ = nullptr without
checking its current value (replace the if (flutter_controller_) {
flutter_controller_ = nullptr; } pattern with a direct assignment to
flutter_controller_). This simplifies the code and avoids an unnecessary null
check while preserving the intended behavior of the destructor/cleanup path that
touches flutter_controller_.

In `@windows/runner/utils.cpp`:
- Around line 48-56: Avoid unsigned wraparound by checking WideCharToMultiByte's
return before subtracting: call ::WideCharToMultiByte and store its result in a
signed/size_t temporary (e.g., raw_target_len), if raw_target_len == 0 return
empty utf8_string (or handle the error), else compute target_length =
raw_target_len - 1; update references to target_length and keep the existing
max_size() guard. Reference symbols: ::WideCharToMultiByte, utf16_string,
target_length, raw_target_len (new), and utf8_string.

In `@windows/runner/win32_window.cpp`:
- Line 221: In MessageHandler, replace the use of the member variable
window_handle_ when calling DefWindowProc with the incoming hwnd parameter so
the call becomes DefWindowProc(hwnd, message, wparam, lparam); locate the call
at the end of MessageHandler and update the argument list to use hwnd instead of
window_handle_.
- Around line 89-107: The RegisterClass call in
WindowClassRegistrar::GetWindowClass is unchecked; update the function to verify
RegisterClass (or RegisterClassW) returns nonzero, only set class_registered_ on
success, and on failure retrieve the OS error via GetLastError and handle it
(e.g., log the error with context and return nullptr or throw an exception) so
callers don't assume the class was registered when it wasn't.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: abeebef2-f31e-4e9c-b61e-3cd598e9b390

📥 Commits

Reviewing files that changed from the base of the PR and between bf1dbe2 and 1d77c1d.

⛔ Files ignored due to path filters (29)
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png is excluded by !**/*.png
  • ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png is excluded by !**/*.png
  • macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png is excluded by !**/*.png
  • macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png is excluded by !**/*.png
  • macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png is excluded by !**/*.png
  • macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png is excluded by !**/*.png
  • macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png is excluded by !**/*.png
  • macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png is excluded by !**/*.png
  • macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png is excluded by !**/*.png
  • pubspec.lock is excluded by !**/*.lock
  • web/favicon.png is excluded by !**/*.png
  • web/icons/Icon-192.png is excluded by !**/*.png
  • web/icons/Icon-512.png is excluded by !**/*.png
  • web/icons/Icon-maskable-192.png is excluded by !**/*.png
  • web/icons/Icon-maskable-512.png is excluded by !**/*.png
  • windows/runner/resources/app_icon.ico is excluded by !**/*.ico
📒 Files selected for processing (58)
  • .gitignore
  • .metadata
  • android/app/build.gradle.kts
  • android/key.properties.example
  • ios/Runner/SceneDelegate.swift
  • ios/RunnerTests/RunnerTests.swift
  • linux/.gitignore
  • linux/CMakeLists.txt
  • linux/flutter/CMakeLists.txt
  • linux/flutter/generated_plugin_registrant.cc
  • linux/flutter/generated_plugin_registrant.h
  • linux/flutter/generated_plugins.cmake
  • linux/runner/CMakeLists.txt
  • linux/runner/main.cc
  • linux/runner/my_application.cc
  • linux/runner/my_application.h
  • macos/.gitignore
  • macos/Flutter/Flutter-Debug.xcconfig
  • macos/Flutter/Flutter-Release.xcconfig
  • macos/Flutter/GeneratedPluginRegistrant.swift
  • macos/Runner.xcodeproj/project.pbxproj
  • macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  • macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
  • macos/Runner.xcworkspace/contents.xcworkspacedata
  • macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  • macos/Runner/AppDelegate.swift
  • macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
  • macos/Runner/Base.lproj/MainMenu.xib
  • macos/Runner/Configs/AppInfo.xcconfig
  • macos/Runner/Configs/Debug.xcconfig
  • macos/Runner/Configs/Release.xcconfig
  • macos/Runner/Configs/Warnings.xcconfig
  • macos/Runner/DebugProfile.entitlements
  • macos/Runner/Info.plist
  • macos/Runner/MainFlutterWindow.swift
  • macos/Runner/Release.entitlements
  • macos/RunnerTests/RunnerTests.swift
  • pubspec.yaml
  • test/widget_test.dart
  • web/index.html
  • web/manifest.json
  • windows/.gitignore
  • windows/CMakeLists.txt
  • windows/flutter/CMakeLists.txt
  • windows/flutter/generated_plugin_registrant.cc
  • windows/flutter/generated_plugin_registrant.h
  • windows/flutter/generated_plugins.cmake
  • windows/runner/CMakeLists.txt
  • windows/runner/Runner.rc
  • windows/runner/flutter_window.cpp
  • windows/runner/flutter_window.h
  • windows/runner/main.cpp
  • windows/runner/resource.h
  • windows/runner/runner.exe.manifest
  • windows/runner/utils.cpp
  • windows/runner/utils.h
  • windows/runner/win32_window.cpp
  • windows/runner/win32_window.h

Comment thread test/widget_test.dart
Comment on lines +13 to +29
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());

// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);

// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();

// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if MyApp contains counter-related elements
rg -n "Icons\.add|findsOneWidget.*'0'|Text\('0'\)" --type=dart lib/
# Check what MyApp actually renders
ast-grep --pattern $'class MyApp extends $_ {
  $$$
}'

Repository: AOSSIE-Org/Resonate

Length of output: 498


🏁 Script executed:

#!/bin/bash
# Find and read the main.dart file to see MyApp definition
find . -name "main.dart" -type f | head -5

Repository: AOSSIE-Org/Resonate

Length of output: 78


🏁 Script executed:

#!/bin/bash
# Check if test/widget_test.dart exists and read it
if [ -f "test/widget_test.dart" ]; then
  echo "=== test/widget_test.dart exists ===" 
  cat -n test/widget_test.dart | head -50
else
  echo "=== test/widget_test.dart NOT found ==="
  find . -name "widget_test.dart" -o -name "*_test.dart" | head -10
fi

Repository: AOSSIE-Org/Resonate

Length of output: 1368


🏁 Script executed:

#!/bin/bash
# Check what MyApp class actually looks like in lib/main.dart
rg -A 20 "class MyApp extends" lib/main.dart

Repository: AOSSIE-Org/Resonate

Length of output: 746


This test is Flutter template boilerplate and will fail.

The test expects a counter app with text widgets displaying '0' and '1' plus an Icons.add button, but MyApp is a StatelessWidget that returns a GetMaterialApp configured for the Resonate audio streaming app with localization and theming. These expected UI elements do not exist, causing the test to fail. This file should be replaced with tests appropriate for the actual app functionality.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/widget_test.dart` around lines 13 - 29, The current widget_test.dart
contains the Flutter template boilerplate that asserts a Counter UI which
doesn't exist in your app; replace the failing test by removing the
Counter-specific expectations and the Icons.add interaction in the testWidgets
block and instead write tests that exercise MyApp/GetMaterialApp startup and
real app behaviors (e.g., verify that MyApp builds without exceptions, that
GetMaterialApp shows expected localized strings, theme elements, or key widgets
for the Resonate UI). Locate the test function named testWidgets in
widget_test.dart and update its assertions to look for actual widgets/text/keys
present in MyApp (or add new tests that pump MyApp and assert presence of
localization keys, navigation routes, or specific widget keys used by the app).

Comment on lines +64 to +68
switch (message) {
case WM_FONTCHANGE:
flutter_controller_->engine()->ReloadSystemFonts();
break;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Potential null pointer dereference in WM_FONTCHANGE handler.

The WM_FONTCHANGE case accesses flutter_controller_->engine() without checking if flutter_controller_ is non-null. The null check on line 55 only guards HandleTopLevelWindowProc - execution can still reach the switch statement when flutter_controller_ is null.

🐛 Proposed fix
   switch (message) {
     case WM_FONTCHANGE:
-      flutter_controller_->engine()->ReloadSystemFonts();
+      if (flutter_controller_) {
+        flutter_controller_->engine()->ReloadSystemFonts();
+      }
       break;
   }
📝 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
switch (message) {
case WM_FONTCHANGE:
flutter_controller_->engine()->ReloadSystemFonts();
break;
}
switch (message) {
case WM_FONTCHANGE:
if (flutter_controller_) {
flutter_controller_->engine()->ReloadSystemFonts();
}
break;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@windows/runner/flutter_window.cpp` around lines 64 - 68, The WM_FONTCHANGE
case in FlutterWindow::HandleTopLevelWindowProc calls
flutter_controller_->engine() without ensuring flutter_controller_ is non-null;
update the WM_FONTCHANGE handler to first check flutter_controller_ (and/or
flutter_controller_->engine()) before calling ReloadSystemFonts(),
returning/ignoring the message if the controller or engine is null. Locate the
switch handling message in HandleTopLevelWindowProc and add a null guard around
the flutter_controller_->engine()->ReloadSystemFonts() invocation to prevent a
potential null pointer dereference.

Comment thread windows/runner/utils.cpp
Comment on lines +10 to +22
void CreateAndAttachConsole() {
if (::AllocConsole()) {
FILE *unused;
if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
_dup2(_fileno(stdout), 1);
}
if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
_dup2(_fileno(stdout), 2);
}
std::ios::sync_with_stdio();
FlutterDesktopResyncOutputStreams();
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Flutter Windows runner CreateAndAttachConsole freopen_s usage pattern

💡 Result:

In Flutter Windows runner, the CreateAndAttachConsole function in utils.cpp allocates a new console using AllocConsole and redirects stdout/stderr to it using freopen_s with "CONOUT$". The standard usage pattern is: void CreateAndAttachConsole { if (::AllocConsole) { FILE unused; if (freopen_s(&unused, "CONOUT$", "w", stdout)) { _dup2(_fileno(stdout), 1); } if (freopen_s(&unused, "CONOUT$", "w", stderr)) { _dup2(_fileno(stdout), 2); } std::ios::sync_with_stdio; FlutterDesktopResyncOutputStreams; } } This pattern first calls AllocConsole to create the console if needed. Then freopen_s is used twice: once for stdout and once for stderr, redirecting both to "CONOUT$" in write mode. A dummy FILE pointer 'unused' captures the new stream handle. If freopen_s succeeds, _dup2 duplicates the file descriptor to the standard handles (1 for stdout, 2 for stderr) to ensure proper inheritance. Finally, std::ios::sync_with_stdio syncs C++ iostreams with C stdio, and FlutterDesktopResyncOutputStreams resyncs Flutter engine streams. This is called conditionally in main.cpp, typically when no parent console exists and a debugger is present: if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent) { CreateAndAttachConsole; } The pattern ensures console output works during debugging or when explicitly needed, common in Flutter Windows desktop apps built as GUI (SUBSYSTEM:WINDOWS) without automatic console.

Citations:


🏁 Script executed:

find . -name "utils.cpp" -path "*/windows/runner/*" | head -5

Repository: AOSSIE-Org/Resonate

Length of output: 89


🏁 Script executed:

# Once we locate the file, read the relevant lines
fd -e cpp -p "*windows/runner*" | grep utils

Repository: AOSSIE-Org/Resonate

Length of output: 358


🏁 Script executed:

cat -n ./windows/runner/utils.cpp | head -30

Repository: AOSSIE-Org/Resonate

Length of output: 1023


🏁 Script executed:

# Also check Microsoft documentation about freopen_s return value
web_search
Microsoft freopen_s return value errno_t documentation

Repository: AOSSIE-Org/Resonate

Length of output: 161


🌐 Web query:

Microsoft freopen_s return value errno_t documentation

💡 Result:

The Microsoft freopen_s function returns an errno_t value: zero (0) on success, or a non-zero error code on failure. If an error occurs, the original file associated with oldStream is closed, and NULL is written to *stream (unless stream is also NULL). For details on specific error codes, refer to errno, _doserrno, _sys_errlist, and _sys_nerr. Syntax: errno_t freopen_s(FILE stream, const char *fileName, const char *mode, FILE *oldStream); Example usage checks if(err != 0) to detect failure.

Citations:


Inverted error check for freopen_s.

freopen_s returns 0 on success and a non-zero error code on failure. The current logic executes _dup2 only when freopen_s fails, which is the opposite of the intended behavior.

🐛 Proposed fix
 void CreateAndAttachConsole() {
   if (::AllocConsole()) {
     FILE *unused;
-    if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
+    if (freopen_s(&unused, "CONOUT$", "w", stdout) == 0) {
       _dup2(_fileno(stdout), 1);
     }
-    if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
+    if (freopen_s(&unused, "CONOUT$", "w", stderr) == 0) {
       _dup2(_fileno(stdout), 2);
     }
     std::ios::sync_with_stdio();
     FlutterDesktopResyncOutputStreams();
   }
 }
📝 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
void CreateAndAttachConsole() {
if (::AllocConsole()) {
FILE *unused;
if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
_dup2(_fileno(stdout), 1);
}
if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
_dup2(_fileno(stdout), 2);
}
std::ios::sync_with_stdio();
FlutterDesktopResyncOutputStreams();
}
}
void CreateAndAttachConsole() {
if (::AllocConsole()) {
FILE *unused;
if (freopen_s(&unused, "CONOUT$", "w", stdout) == 0) {
_dup2(_fileno(stdout), 1);
}
if (freopen_s(&unused, "CONOUT$", "w", stderr) == 0) {
_dup2(_fileno(stdout), 2);
}
std::ios::sync_with_stdio();
FlutterDesktopResyncOutputStreams();
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@windows/runner/utils.cpp` around lines 10 - 22, The error check for freopen_s
is inverted in CreateAndAttachConsole: freopen_s returns 0 on success, but the
code calls _dup2 only when freopen_s returns non-zero; change the condition so
that _dup2(_fileno(stdout), 1) runs when freopen_s(&unused, "CONOUT$", "w",
stdout) returns 0, and likewise _dup2(_fileno(stdout), 2) runs when
freopen_s(&unused, "CONOUT$", "w", stderr) returns 0; keep the rest of the
function (AllocConsole, std::ios::sync_with_stdio(),
FlutterDesktopResyncOutputStreams()) unchanged.

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.

Build fails when key.properties is missing (null cast error in build.gradle.kts)

1 participant