Skip to content

Conversation

@FALLEN-01
Copy link

@FALLEN-01 FALLEN-01 commented Oct 28, 2025

This pull request introduces several foundational updates and major new features for the ScamPad project. The most significant change is the addition of the ChaosController class, which implements the core "chaotic" behaviors for the notepad application. The README has been completely rewritten to reflect the project's unique concept, features, and technical architecture. Additionally, project configuration files for Flutter and Dart analysis have been added for improved tooling and code quality.

Core Features and Architecture

  • Chaos System Implementation: Added lib/chaos/chaos_controller.dart, which defines the ChaosController class. This class manages random disruptive actions (cursor movement, deletions, letter/word swaps, punctuation, indentation) in the text editor, scheduled at random intervals and triggered on save. It uses weighted random selection for chaos actions and provides hooks for UI updates.

Documentation and Project Metadata

  • Comprehensive README Overhaul: The README.md now thoroughly documents ScamPad’s concept, team, technical details, features, chaos logic, class architecture, configuration options, usage scenarios, and workflow diagrams. Screenshots and demo links are included to illustrate functionality and user experience.
  • Flutter Project Metadata: Added .metadata file to track Flutter project properties, migration status, and unmanaged files, supporting future upgrades and tooling.
  • Dart Analysis Configuration: Introduced analysis_options.yaml to enable recommended lints for Flutter projects and provide a foundation for static code analysis and best practices.

Summary by CodeRabbit

  • New Features

    • Chaos Mode introduces randomized text editing disruptions including cursor displacement, character deletion, letter/word swapping, and punctuation modifications
    • Settings screen for Chaos Mode configuration and editor preferences
  • Documentation

    • Comprehensive README with project overview, features, setup instructions, and team information
  • Tests

    • Widget tests for core functionality
  • Chores

    • Flutter project initialization with Windows platform support and build configuration

@coderabbitai
Copy link

coderabbitai bot commented Oct 28, 2025

Walkthrough

This pull request initializes a complete Flutter project named "ScamPad" with desktop support for Windows. It introduces project configuration, Flutter application logic (a chaos-inducing text editor controller and settings UI), comprehensive Windows native runtime implementation (CMake build system, Win32 window management, entry point), plugin infrastructure, and supporting assets and documentation.

Changes

Cohort / File(s) Summary
Project Configuration
.gitignore, .metadata, pubspec.yaml, analysis_options.yaml
Adds project metadata, Flutter dependencies, Dart analyzer rules, and comprehensive build/IDE artifact exclusions.
Documentation & Readme
README.md
Expands placeholder README with project name (ScamPad), team details, comprehensive feature descriptions, architecture overview, chaos workflow diagrams, and media assets.
Flutter Application Logic
lib/chaos/chaos_controller.dart
Introduces ChaosController class orchestrating randomized text mutations (cursor displacement, deletion, letter/word swapping, punctuation insertion, indentation) via weighted action scheduling on a TextEditingController. Defines ChaosType enum and ChaosAction class for action configuration.
Flutter UI
lib/screens/chaos_settings_screen.dart
Adds ChaosSettingsScreen (stateful widget) displaying chaos mode status, active behaviors, and configurable editor settings (font size, theme, auto-save, chaos interval) with a persistent warning footer.
Testing
test/widget_test.dart
Adds basic Flutter widget test verifying counter increment functionality.
Windows Build System
windows/CMakeLists.txt, windows/runner/CMakeLists.txt
Configures top-level CMake project (C++17, multi-config support, standard settings) and runner executable target linking Flutter libraries, wrapper components, and Windows system libraries.
Windows Flutter Integration
windows/flutter/CMakeLists.txt, windows/flutter/generated_plugin_registrant.cc, windows/flutter/generated_plugin_registrant.h, windows/flutter/generated_plugins.cmake
Establishes Flutter library interface target, wrapper static libraries (plugin and app), custom build commands for Flutter tooling backend, plugin registration infrastructure, and dynamic plugin linking.
Windows Native Runner
windows/runner/flutter_window.cpp, windows/runner/flutter_window.h, windows/runner/main.cpp
Implements FlutterWindow (Win32 subclass hosting Flutter view), wWinMain entry point initializing COM, DartProject, and message loop, with console attachment and command-line argument handling.
Windows Win32 Abstraction
windows/runner/win32_window.cpp, windows/runner/win32_window.h
Provides Win32Window base class with DPI-aware window creation, theming (dark mode), child content hosting, lifecycle hooks (OnCreate/OnDestroy/MessageHandler), and WindowClassRegistrar for lazy window class registration.
Windows Utilities
windows/runner/utils.cpp, windows/runner/utils.h
Adds helper functions for console attachment, UTF-16 to UTF-8 string conversion, and command-line argument parsing.
Windows Resources & Manifest
windows/runner/Runner.rc, windows/runner/resource.h, windows/runner/runner.exe.manifest, windows/.gitignore
Defines Windows resource script with icon reference, version metadata (ScamPad 1.0.0), resource constants, DPI awareness manifest, and Windows-specific build artifact exclusions.

Sequence Diagram(s)

sequenceDiagram
    participant App as Flutter App
    participant Chaos as ChaosController
    participant Timer as Timer
    participant TextCtrl as TextEditingController
    
    App->>Chaos: startChaos()
    activate Chaos
    Chaos->>Timer: Start random interval (8–15s)
    activate Timer
    
    loop Until stopChaos()
        Timer-->>Chaos: Timer fires
        Chaos->>Chaos: Select action (weighted random)
        alt cursorDisplacement
            Chaos->>TextCtrl: Move caret, notify selection
        else randomDeletion | letterSwapping | wordSwapping
            Chaos->>TextCtrl: Mutate text
            Chaos->>App: onTextChanged(newText)
        else punctuationInsert | punctuationDuplicate
            Chaos->>TextCtrl: Insert/duplicate punctuation
            Chaos->>App: onTextChanged(newText)
        else randomIndentation
            Chaos->>Chaos: Schedule indentation on save
        end
        Chaos->>Timer: Schedule next event
    end
    
    App->>Chaos: stopChaos()
    Timer-->>Chaos: (timer cancelled)
    deactivate Timer
    deactivate Chaos
Loading
sequenceDiagram
    participant OS as Windows OS
    participant Main as wWinMain
    participant App as FlutterWindow
    participant Flutter as Flutter Engine
    participant Win32 as Win32Window
    
    OS->>Main: Launch process
    activate Main
    Main->>Main: Initialize COM
    Main->>Main: Create DartProject
    Main->>App: new FlutterWindow(project)
    activate App
    Main->>App: OnCreate()
    App->>Win32: Create win32_window_
    activate Win32
    Win32->>Win32: Register window class
    Win32->>OS: CreateWindowEx()
    deactivate Win32
    App->>Flutter: Create FlutterViewController
    activate Flutter
    Flutter->>App: engine, view ready
    deactivate Flutter
    App->>Flutter: RegisterPlugins()
    App->>Win32: AttachFlutterView()
    Main->>Win32: Show()
    OS->>OS: Message loop (GetMessage/DispatchMessage)
    OS->>Win32: WndProc (user interactions)
    Win32->>App: MessageHandler()
    App->>Flutter: (pass to Flutter)
    OS->>Main: WM_QUIT
    Main->>App: Destroy()
    App->>Flutter: Cleanup
    Main->>Main: COM uninitialize
    deactivate App
    Main-->>OS: EXIT_SUCCESS
    deactivate Main
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45–60 minutes

Areas requiring extra attention:

  • ChaosController logic (lib/chaos/chaos_controller.dart): Verify weighted action selection, timer interval randomization (8–15s), text mutation boundaries, cursor position validity, and callback invocation correctness.
  • ChaosSettingsScreen state (lib/screens/chaos_settings_screen.dart): Note that isChaosEnabled and onChaosToggle parameters are declared but unused in the current implementation; confirm whether this is intentional or incomplete.
  • Windows CMake configuration (windows/CMakeLists.txt, windows/flutter/CMakeLists.txt): Validate CMake syntax, Flutter tool backend integration, asset/AOT library paths, and install directives for multi-configuration builds.
  • Win32Window and FlutterWindow lifecycle (windows/runner/win32_window.cpp/h, flutter_window.cpp/h): Ensure proper cleanup on destruction, valid handle checks, and message handler delegation between Win32 and Flutter.
  • UTF-16/UTF-8 conversion and command-line parsing (windows/runner/utils.cpp): Verify error handling edge cases, buffer overflow prevention, and locale-specific character encoding.

🐰 A chaos controller springs to life,
Text twists and tumbles in digital strife,
Windows embraces the Flutter so fine,
ScamPad leaps forth—let the chaos align!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.15% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The PR title "ScramPad" is simply the project name without any descriptive information about the actual changes introduced in this pull request. While the changeset is substantial and multi-faceted—including a new ChaosController implementation, comprehensive README documentation, Flutter project metadata, analysis configuration, and numerous platform-specific files—the title provides no indication of what was actually added or modified. A developer scanning the git history would not understand the scope or nature of the changes based solely on this title, as it lacks any descriptive content about the key features, fixes, or updates being introduced. Consider revising the title to reflect the primary changes, such as "Add ChaosController and project setup files" or "Introduce chaos text editor implementation with Flutter scaffolding" to clearly communicate what this PR accomplishes. The title should help reviewers and future maintainers understand the main purpose of the changes at a glance.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

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

🧹 Nitpick comments (19)
windows/runner/main.cpp (1)

16-19: Ensure COM is uninitialized on early-return; optionally gate on HRESULT

If window creation fails, CoUninitialize isn’t called. Not harmful at process exit, but easy to tidy up. Also consider tracking HRESULT and uninitializing conditionally.

Apply:

-  ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+  HRESULT hr = ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
@@
-  if (!window.Create(L"ScamPad", origin, size)) {
-    return EXIT_FAILURE;
-  }
+  if (!window.Create(L"ScamPad", origin, size)) {
+    if (SUCCEEDED(hr)) { ::CoUninitialize(); }
+    return EXIT_FAILURE;
+  }
@@
-  ::CoUninitialize();
+  if (SUCCEEDED(hr)) { ::CoUninitialize(); }

Also applies to: 30-33, 41-43

windows/runner/Runner.rc (1)

92-99: Fill real product/publisher metadata (avoid placeholders).

Replace “com.example” and generic names with your org/publisher details to avoid shipping placeholder metadata.

-            VALUE "CompanyName", "com.example" "\0"
-            VALUE "FileDescription", "ScamPad" "\0"
+            VALUE "CompanyName", "Vanguard" "\0"
+            VALUE "FileDescription", "ScamPad" "\0"
             VALUE "FileVersion", VERSION_AS_STRING "\0"
-            VALUE "InternalName", "scampad" "\0"
-            VALUE "LegalCopyright", "Copyright (C) 2025 com.example. All rights reserved." "\0"
+            VALUE "InternalName", "scampad" "\0"
+            VALUE "LegalCopyright", "Copyright (C) 2025 Vanguard. All rights reserved." "\0"
             VALUE "OriginalFilename", "scampad.exe" "\0"
             VALUE "ProductName", "ScamPad" "\0"
             VALUE "ProductVersion", VERSION_AS_STRING "\0"
windows/runner/CMakeLists.txt (1)

23-28: Harden version macro definitions with safe defaults.

If FLUTTER_VERSION* aren’t set by the toolchain, these defines become empty and can break the RC include. Provide fallbacks.

+# Fallbacks if Flutter toolchain doesn't set these (defensive).
+if(NOT DEFINED FLUTTER_VERSION)        set(FLUTTER_VERSION "1.0.0")      endif()
+if(NOT DEFINED FLUTTER_VERSION_MAJOR)  set(FLUTTER_VERSION_MAJOR 1)       endif()
+if(NOT DEFINED FLUTTER_VERSION_MINOR)  set(FLUTTER_VERSION_MINOR 0)       endif()
+if(NOT DEFINED FLUTTER_VERSION_PATCH)  set(FLUTTER_VERSION_PATCH 0)       endif()
+if(NOT DEFINED FLUTTER_VERSION_BUILD)  set(FLUTTER_VERSION_BUILD 0)       endif()
 target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
 target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
 target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
 target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
 target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
windows/CMakeLists.txt (1)

40-46: Scope strict flags to avoid breaking plugins.

APPLY_STANDARD_SETTINGS is used by plugins; /WX and _HAS_EXCEPTIONS=0 can cause third‑party build failures. Restrict to runner, or gate with an option.

 function(APPLY_STANDARD_SETTINGS TARGET)
   target_compile_features(${TARGET} PUBLIC cxx_std_17)
-  target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
-  target_compile_options(${TARGET} PRIVATE /EHsc)
-  target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
+  target_compile_options(${TARGET} PRIVATE /W4 /wd"4100")
+  # Treat warnings as errors and disable STL exceptions only for the runner:
+  if(${TARGET} STREQUAL "${BINARY_NAME}")
+    target_compile_options(${TARGET} PRIVATE /WX)
+    target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
+  endif()
+  target_compile_options(${TARGET} PRIVATE /EHsc)
   target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
 endfunction()

Please confirm whether any plugins fail to build with /WX or _HAS_EXCEPTIONS=0 today.

lib/screens/chaos_settings_screen.dart (4)

4-11: Use ValueChanged and actually wire onChaosToggle.

Prefer ValueChanged over Function(bool), and ensure the toggle is used.

-  final bool isChaosEnabled;
-  final Function(bool) onChaosToggle;
+  final bool isChaosEnabled;
+  final ValueChanged<bool> onChaosToggle;

70-88: Replace “ALWAYS ON” pill with a real toggle bound to props.

This removes the unused props warning and lets users control chaos (if design permits).

-                      Container(
-                        padding: const EdgeInsets.symmetric(
-                          horizontal: 8,
-                          vertical: 4,
-                        ),
-                        decoration: BoxDecoration(
-                          color: Colors.red.shade200,
-                          borderRadius: BorderRadius.circular(12),
-                        ),
-                        child: Text(
-                          'ALWAYS ON',
-                          style: TextStyle(
-                            fontSize: 10,
-                            fontWeight: FontWeight.w700,
-                            color: Colors.red.shade800,
-                          ),
-                        ),
-                      ),
+                      Switch(
+                        value: widget.isChaosEnabled,
+                        onChanged: widget.onChaosToggle,
+                        activeColor: Colors.red.shade600,
+                      ),

If chaos must be immutable, remove the props to avoid confusion instead.


38-41: Make the page scrollable; Spacer in a Column can overflow on small windows.

Switch to a ListView with padding and drop Spacer.

-      body: Padding(
-        padding: const EdgeInsets.all(16.0),
-        child: Column(
+      body: SafeArea(
+        child: ListView(
+          padding: const EdgeInsets.all(16.0),
           crossAxisAlignment: CrossAxisAlignment.start,
           children: [
@@
-            const Spacer(),
+            const SizedBox(height: 24),

Test on a small window to ensure no overflow/”Bottom overflowed” warnings.

Also applies to: 128-129, 188-188, 190-218


253-281: Accessibility + theming nits (optional).

Use Theme colors/typography and ListTile for better semantics; current tiny fonts (10–12) may hurt readability.

README.md (4)

67-67: Heading level increment (MD001).

Promote this to H2 to keep 1‑level increments.

-### Project Documentation
+## Project Documentation

110-134: Add a language to fenced code blocks (MD040).

Mark as text for diagrams/ASCII blocks.

-```
+```text
 ChaosManager
 ├── Timer-based chaos scheduling (4-8 second intervals)
@@

---

`216-273`: **Add a language to workflow diagram (MD040) and avoid emphasis-as-heading (MD036).**

Use text fences and a proper heading.

```diff
-## ScamPad Chaos Workflow
-```
+## ScamPad Chaos Workflow
+```text
@@
-```
-*This diagram shows how ScamPad's three parallel chaos systems work together to progressively disrupt the user experience based on document length, typing speed, and activity level*
+```
+#### Diagram notes
+This diagram shows how ScamPad's three parallel chaos systems work together to progressively disrupt the user experience based on document length, typing speed, and activity level.

152-157: Clarify “timer threads” (Dart timers aren’t OS threads).

Consider rewording to “separate timers on the main isolate/event loop” unless you actually use isolates.

windows/runner/flutter_window.cpp (1)

30-33: Use [this] capture in callback to avoid broad reference capture.

Narrow capture improves clarity and reduces accidental captures.

-  flutter_controller_->engine()->SetNextFrameCallback([&]() {
+  flutter_controller_->engine()->SetNextFrameCallback([this]() {
     this->Show();
   });
windows/runner/win32_window.cpp (2)

109-112: Pair UnregisterClass with the same HINSTANCE used in RegisterClass.

Pass the module handle for symmetry; avoids edge-case failures.

-void WindowClassRegistrar::UnregisterWindowClass() {
-  UnregisterClass(kWindowClassName, nullptr);
+void WindowClassRegistrar::UnregisterWindowClass() {
+  UnregisterClass(kWindowClassName, GetModuleHandle(nullptr));
   class_registered_ = false;
 }

221-221: Prefer passing hwnd to DefWindowProc.

window_handle_ should equal hwnd here, but using the parameter is clearer and avoids surprises if window_handle_ changes.

-  return DefWindowProc(window_handle_, message, wparam, lparam);
+  return DefWindowProc(hwnd, message, wparam, lparam);
lib/chaos/chaos_controller.dart (4)

14-14: Initialize _isActive to false for clearer lifecycle.

Prevents accidental assumptions that chaos is active before startChaos().

-  bool _isActive = true;
+  bool _isActive = false;

90-112: randomIndentation is unreachable from scheduled actions. Intentional?

It’s in the switch, but not in _chaosActions. Either add it with a weight or remove the case if it’s save-only.

Options:

  • Add to list:
-         ChaosAction(ChaosType.punctuationDuplicate, weight: 10),
+         ChaosAction(ChaosType.punctuationDuplicate, weight: 10),
+         // Very rare during typing:
+         // ChaosAction(ChaosType.randomIndentation, weight: 2),
  • Or remove the switch branch if it should only occur in handleSave().

Also applies to: 288-295


175-180: Use whitespace regex when splitting words.

split(' ') collapses multiple spaces incorrectly and yields empty tokens.

-    final words = text.split(' ');
+    final words = text.split(RegExp(r'\s+'));

Do the same in _swapWords.

Also applies to: 204-206


7-11: Avoid duplicate update pathways (controller listeners vs callbacks).

Setting textController.text already notifies listeners. Calling onTextChanged too can cause double renders/state updates.

Consider standardizing on one mechanism (prefer controller listeners) or gate onTextChanged to only fire when external listeners aren’t used.

Also applies to: 150-155, 167-170, 198-200, 218-220, 236-239, 258-260, 285-286

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 87fcdae and 1c3ffc9.

⛔ Files ignored due to path filters (7)
  • Screenshots/ScamPad_final.gif is excluded by !**/*.gif
  • Screenshots/ScamPad_final.mp4 is excluded by !**/*.mp4
  • Screenshots/final_state.png is excluded by !**/*.png
  • Screenshots/initial_state.png is excluded by !**/*.png
  • assets/icons/app_icon.ico is excluded by !**/*.ico
  • pubspec.lock is excluded by !**/*.lock
  • windows/runner/resources/app_icon.ico is excluded by !**/*.ico
📒 Files selected for processing (25)
  • .gitignore (1 hunks)
  • .metadata (1 hunks)
  • README.md (1 hunks)
  • analysis_options.yaml (1 hunks)
  • lib/chaos/chaos_controller.dart (1 hunks)
  • lib/screens/chaos_settings_screen.dart (1 hunks)
  • pubspec.yaml (1 hunks)
  • test/widget_test.dart (1 hunks)
  • windows/.gitignore (1 hunks)
  • windows/CMakeLists.txt (1 hunks)
  • windows/flutter/CMakeLists.txt (1 hunks)
  • windows/flutter/generated_plugin_registrant.cc (1 hunks)
  • windows/flutter/generated_plugin_registrant.h (1 hunks)
  • windows/flutter/generated_plugins.cmake (1 hunks)
  • windows/runner/CMakeLists.txt (1 hunks)
  • windows/runner/Runner.rc (1 hunks)
  • windows/runner/flutter_window.cpp (1 hunks)
  • windows/runner/flutter_window.h (1 hunks)
  • windows/runner/main.cpp (1 hunks)
  • windows/runner/resource.h (1 hunks)
  • windows/runner/runner.exe.manifest (1 hunks)
  • windows/runner/utils.cpp (1 hunks)
  • windows/runner/utils.h (1 hunks)
  • windows/runner/win32_window.cpp (1 hunks)
  • windows/runner/win32_window.h (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
windows/runner/utils.h (1)
windows/runner/utils.cpp (6)
  • CreateAndAttachConsole (10-22)
  • CreateAndAttachConsole (10-10)
  • Utf8FromUtf16 (44-65)
  • Utf8FromUtf16 (44-44)
  • GetCommandLineArguments (24-42)
  • GetCommandLineArguments (24-24)
windows/flutter/generated_plugin_registrant.h (1)
windows/flutter/generated_plugin_registrant.cc (2)
  • RegisterPlugins (10-11)
  • RegisterPlugins (10-10)
windows/runner/main.cpp (1)
windows/runner/utils.cpp (4)
  • CreateAndAttachConsole (10-22)
  • CreateAndAttachConsole (10-10)
  • GetCommandLineArguments (24-42)
  • GetCommandLineArguments (24-24)
windows/runner/flutter_window.h (3)
windows/runner/flutter_window.cpp (8)
  • FlutterWindow (7-8)
  • FlutterWindow (10-10)
  • OnCreate (12-40)
  • OnCreate (12-12)
  • OnDestroy (42-48)
  • OnDestroy (42-42)
  • MessageHandler (50-71)
  • MessageHandler (51-53)
windows/runner/win32_window.cpp (8)
  • Win32Window (114-116)
  • Win32Window (118-121)
  • OnCreate (266-269)
  • OnCreate (266-266)
  • OnDestroy (271-273)
  • OnDestroy (271-271)
  • MessageHandler (176-222)
  • MessageHandler (177-180)
windows/runner/main.cpp (1)
  • window (27-27)
windows/runner/win32_window.h (1)
windows/runner/win32_window.cpp (2)
  • Win32Window (114-116)
  • Win32Window (118-121)
windows/runner/win32_window.cpp (1)
windows/runner/flutter_window.cpp (6)
  • OnCreate (12-40)
  • OnCreate (12-12)
  • MessageHandler (50-71)
  • MessageHandler (51-53)
  • OnDestroy (42-48)
  • OnDestroy (42-42)
windows/runner/flutter_window.cpp (3)
windows/runner/flutter_window.h (1)
  • FlutterWindow (12-31)
windows/runner/win32_window.cpp (10)
  • OnCreate (266-269)
  • OnCreate (266-266)
  • GetClientArea (252-256)
  • GetClientArea (252-252)
  • SetChildContent (241-250)
  • SetChildContent (241-241)
  • OnDestroy (271-273)
  • OnDestroy (271-271)
  • MessageHandler (176-222)
  • MessageHandler (177-180)
windows/flutter/generated_plugin_registrant.cc (2)
  • RegisterPlugins (10-11)
  • RegisterPlugins (10-10)
🪛 Clang (14.0.6)
windows/runner/utils.h

[error] 4-4: 'string' file not found

(clang-diagnostic-error)

windows/flutter/generated_plugin_registrant.h

[error] 10-10: 'flutter/plugin_registry.h' file not found

(clang-diagnostic-error)

windows/runner/main.cpp

[error] 1-1: 'flutter/dart_project.h' file not found

(clang-diagnostic-error)

windows/runner/flutter_window.h

[error] 4-4: 'flutter/dart_project.h' file not found

(clang-diagnostic-error)

windows/runner/win32_window.h

[error] 4-4: 'windows.h' file not found

(clang-diagnostic-error)

🪛 LanguageTool
README.md

[style] ~19-~19: As an alternative to the over-used intensifier ‘quite’, consider replacing this phrase.
Context: ...lem (that doesn't exist) Notepad app is quite simple and convenient to use, but that's no fu...

(EN_WEAK_ADJECTIVE)


[grammar] ~90-~90: Ensure spelling is correct
Context: ...ext scrambling until user resumes typing - 500ms interval rapid swapping for maximum dis...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~179-~179: Ensure spelling is correct
Context: ...eout: 10 seconds - Rapid swap interval: 500ms - Word count thresholds: 40, 60 words ###...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.18.1)
README.md

67-67: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)


110-110: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


216-216: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


274-274: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


284-284: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🔇 Additional comments (18)
windows/.gitignore (1)

1-17: LGTM!

Standard Windows-specific ignore patterns for Flutter and Visual Studio artifacts are correctly configured.

analysis_options.yaml (1)

1-28: LGTM!

Standard Flutter lints configuration following best practices. The inline documentation provides clear guidance for customization.

.gitignore (1)

1-45: LGTM!

Comprehensive ignore patterns covering Flutter, Dart, IDE artifacts, and build outputs are well-organized and follow Flutter best practices.

.metadata (1)

28-30: Verify the unmanaged_files configuration.

Marking lib/main.dart as unmanaged is unusual since it's typically part of the Flutter template. This prevents the Flutter migrate tool from updating this file during version migrations. Ensure this is intentional and that you understand the implications for future Flutter upgrades.

windows/runner/utils.cpp (1)

24-42: LGTM!

The command-line argument conversion logic correctly handles UTF-16 to UTF-8 conversion, skips the executable name, and properly frees allocated memory.

windows/runner/win32_window.h (1)

1-102: LGTM!

Well-designed Win32 window abstraction with proper encapsulation, DPI awareness support, and clear separation of concerns through virtual hooks. The static analysis error about missing windows.h is a false positive—this header is provided by the Windows SDK in the actual build environment.

windows/runner/runner.exe.manifest (1)

1-14: LGTM!

Standard Windows application manifest correctly configured with PerMonitorV2 DPI awareness for high-DPI display support and Windows 10/11 compatibility declarations.

windows/flutter/generated_plugin_registrant.cc (1)

10-11: Generated registrant stub is fine

Empty body is expected when no plugins are declared. No action needed.

windows/flutter/generated_plugins.cmake (1)

13-23: CMake plugin wiring looks standard

foreach blocks and PLUGIN_BUNDLED_LIBRARIES handling match Flutter’s template. Good to go.

windows/runner/utils.h (1)

7-17: LGTM

API surface is minimal and consistent with the cpp implementation. Nothing to change.

windows/runner/resource.h (1)

5-15: LGTM

Resource IDs and APSTUDIO defaults are standard.

windows/runner/flutter_window.h (1)

11-31: LGTM

Class shape and ownership semantics (unique_ptr) are appropriate for the runner.

windows/flutter/generated_plugin_registrant.h (1)

10-13: No issues found—Flutter CMake wiring is properly configured.

The verification confirms that flutter/generated_plugins.cmake is correctly included in windows/CMakeLists.txt (line 58), which means the build system is properly wired through Flutter's generated CMake. The header flutter/plugin_registry.h will be found correctly at build time. The static-analysis hint is a false positive that can be safely ignored.

pubspec.yaml (1)

8-10: All sanity checks passed—no action needed.

  • assets/icons/ exists with expected files
  • file_picker is actively imported and used in lib/main.dart:6
  • ✓ SDK constraint is valid
  • CI configuration not present in repo (outside scope of this code change)
README.md (1)

206-213: All screenshot and video assets exist in the repository.

The verification confirms that all files referenced in the README are present:

  • initial_state.png
  • final_state.png
  • ScamPad_final.gif
  • ScamPad_final.mp4

No broken links exist.

windows/runner/Runner.rc (1)

55-55: No action required—app icon file is committed and present.

The verification confirms that windows/runner/resources/app_icon.ico exists in the repository and is accessible. The build will correctly reference this icon without falling back to a default.

lib/chaos/chaos_controller.dart (1)

146-154: Fix type mismatch in selection offset (compile-time error).

int.clamp returns num; TextSelection.collapsed expects int.

-    textController.selection = TextSelection.collapsed(
-      offset: deleteIndex.clamp(0, newText.length),
-    );
+    final clampedOffset = (deleteIndex <= newText.length)
+        ? deleteIndex
+        : newText.length;
+    textController.selection =
+        TextSelection.collapsed(offset: clampedOffset);

Likely an incorrect or invalid review comment.

windows/flutter/CMakeLists.txt (1)

63-64: No issues found—apply_standard_settings is properly defined and in scope.

The macro is defined in ./windows/CMakeLists.txt (lines 40–46) as a top-level function and is automatically available to child scopes via add_subdirectory(). The calls at lines 63 and 79 in windows/flutter/CMakeLists.txt will resolve correctly.

Likely an incorrect or invalid review comment.

Comment on lines +33 to +37
/// Start the chaos cycle
void startChaos() {
_isActive = true;
_scheduleNextChaos();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid double timers; cancel existing before (re)starting.

Calling startChaos multiple times stacks timers.

  void startChaos() {
-    _isActive = true;
-    _scheduleNextChaos();
+    _isActive = true;
+    _chaosTimer?.cancel();
+    _scheduleNextChaos();
  }
📝 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
/// Start the chaos cycle
void startChaos() {
_isActive = true;
_scheduleNextChaos();
}
/// Start the chaos cycle
void startChaos() {
_isActive = true;
_chaosTimer?.cancel();
_scheduleNextChaos();
}
🤖 Prompt for AI Agents
In lib/chaos/chaos_controller.dart around lines 33 to 37, startChaos currently
sets _isActive = true and schedules a new timer without cancelling any existing
one, which allows timers to stack if called repeatedly; modify startChaos to
first set _isActive = true, then check for an existing timer (e.g. if (_timer !=
null && _timer.isActive) _timer.cancel() or equivalent) and null it out before
calling _scheduleNextChaos so only a single timer is active; ensure the
controller's timer field is nullable and properly cleared when cancelled.

Comment on lines +179 to +181
'Chaos Interval',
'8-15 seconds',
Icons.timer_outlined,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Interval text mismatches README (4–8s vs 8–15s). Align to source of truth.

Update the UI strings or the controller config so both show the same interval.

Also applies to: 231-232


🏁 Script executed:

#!/bin/bash
# Grep for interval mentions in code/docs to pick a single source of truth.
rg -nI --hidden -C1 -e '8-15|4-8|interval' lib README.md

Length of output: 1418


🏁 Script executed:

#!/bin/bash
# Inspect the files containing the two different intervals
# Find files around the line numbers to identify context

rg -n '4-8 second|_scheduleNextChaos' lib --type dart -B5 -A5
rg -n '8-15 second|Random delay between' lib --type dart -B5 -A5

Length of output: 6081


Update README to reflect current 8-15 second chaos interval.

The chaos interval was increased from 4-8 to 8-15 seconds (as evidenced by the "(increased)" label in the UI). The current implementation in lib/chaos/chaos_controller.dart uses 8-15 seconds and the UI correctly displays this value. Only README.md needs updating at lines 112 and 176 to document the current 4-8 → 8-15 second interval change. The code at lib/screens/chaos_settings_screen.dart lines 179-181 and 231-232 is correct as-is.

🤖 Prompt for AI Agents
In README.md around lines 112 and 176, update the documented chaos interval from
"4-8 seconds" to "8-15 seconds" to match the current implementation
(lib/chaos/chaos_controller.dart) and the UI; the files
lib/screens/chaos_settings_screen.dart lines 179-181 and 231-232 are correct and
do not need changes. Ensure both README occurrences are changed to the exact
text "8-15 seconds" (and update any parenthetical notes like "(increased)" if
present) so the documentation matches the code and UI.

Comment on lines +41 to 44
# Clone the repository
git clone https://github.com/FALLEN-01/vanguard.git
cd vanguard

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix clone instructions to this repository.

Current URL points to vanguard repo; update to the PR repo name and folder.

-git clone https://github.com/FALLEN-01/vanguard.git
-cd vanguard
+git clone https://github.com/tinkerhub/useless_project_temp.git
+cd useless_project_temp
📝 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
# Clone the repository
git clone https://github.com/FALLEN-01/vanguard.git
cd vanguard
# Clone the repository
git clone https://github.com/tinkerhub/useless_project_temp.git
cd useless_project_temp
🤖 Prompt for AI Agents
In README.md around lines 41 to 44 update the clone instructions which currently
point to "https://github.com/FALLEN-01/vanguard.git" to use this repository's
correct URL and folder name; replace the example vanguard URL with the actual
repo URL for this project and adjust the cd command to match the repository
folder (e.g., git clone <correct-repo-url> followed by cd
<correct-repo-folder>).

Comment on lines +1 to +30
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:scampad/main.dart';

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

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Update test to match actual application functionality.

This test appears to be from the Flutter template, testing a basic counter increment. However, the PR objectives describe ScamPad as a chaos-inducing text editor with ChaosController functionality. The test should verify the actual application features rather than template counter behavior.

Consider adding tests for:

  • ChaosController initialization and configuration
  • Random action scheduling and execution
  • Text manipulation behaviors (cursor movement, deletions, swaps)
  • Chaos settings persistence

Would you like me to help draft tests for the chaos text editor functionality described in the PR objectives?

🤖 Prompt for AI Agents
In test/widget_test.dart lines 1-30, replace the default Flutter counter smoke
test with unit/widget tests that exercise the app's real functionality: create
and initialize a ChaosController (or obtain it from the app), configure
deterministic chaos settings (inject a seeded RNG or mock randomness and a
FakeAsync timer), assert initial state, schedule and fast-forward timers to
trigger random actions, and verify text manipulations (cursor moves, deletions,
swaps) and that action counts/flags update as expected; also add a test that
persists and restores settings using a mocked storage layer to verify
persistence. Ensure tests use dependency injection/mocks for RNG, timers, and
storage so behavior is deterministic and assertions validate the ChaosController
API and text editor widget rather than the default counter example.

Comment on lines +91 to +94
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/")
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix native assets install path (missing slash).

Currently resolves to “…/builddirnative_assets/windows/”. This breaks asset installs.

-set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/")
+set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}/native_assets/windows/")
📝 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
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/")
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}/native_assets/windows/")
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
🤖 Prompt for AI Agents
windows/CMakeLists.txt around lines 91 to 94: the set for NATIVE_ASSETS_DIR
concatenates PROJECT_BUILD_DIR and native_assets without a separating slash,
producing ".../builddirnative_assets/..."; fix by inserting a "/" between
${PROJECT_BUILD_DIR} and native_assets (e.g. set NATIVE_ASSETS_DIR to use
"${PROJECT_BUILD_DIR}/native_assets/windows/") so the install path resolves
correctly.

Comment on lines +65 to +67
case WM_FONTCHANGE:
flutter_controller_->engine()->ReloadSystemFonts();
break;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Guard against null Flutter controller in WM_FONTCHANGE (crash risk).

flutter_controller_ can be null after OnDestroy; dereferencing it here will crash. Guard before use.

Apply:

-    case WM_FONTCHANGE:
-      flutter_controller_->engine()->ReloadSystemFonts();
-      break;
+    case WM_FONTCHANGE:
+      if (flutter_controller_ && flutter_controller_->engine()) {
+        flutter_controller_->engine()->ReloadSystemFonts();
+      }
+      break;
🤖 Prompt for AI Agents
In windows/runner/flutter_window.cpp around lines 65 to 67, flutter_controller_
may be null after OnDestroy so calling
flutter_controller_->engine()->ReloadSystemFonts() can crash; add a null check
before dereferencing: verify flutter_controller_ is non-null and that
flutter_controller_->engine() is non-null, and only call ReloadSystemFonts()
when both are valid, otherwise skip the call.

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

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Fix inverted freopen_s logic.

The condition logic is incorrect. freopen_s returns 0 on success and a non-zero error code on failure. The current code calls _dup2 only when freopen_s fails, which is backwards.

Apply this diff to fix the logic:

 void CreateAndAttachConsole() {
   if (::AllocConsole()) {
     FILE *unused;
-    if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
+    if (!freopen_s(&unused, "CONOUT$", "w", stdout)) {
       _dup2(_fileno(stdout), 1);
     }
-    if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
+    if (!freopen_s(&unused, "CONOUT$", "w", stderr)) {
       _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)) {
_dup2(_fileno(stdout), 1);
}
if (!freopen_s(&unused, "CONOUT$", "w", stderr)) {
_dup2(_fileno(stdout), 2);
}
std::ios::sync_with_stdio();
FlutterDesktopResyncOutputStreams();
}
}
🤖 Prompt for AI Agents
In windows/runner/utils.cpp around lines 10-22, the freopen_s return checks are
inverted causing _dup2 to run on failure; change the conditions to check for
success (freopen_s(...) == 0) before calling _dup2, and for the stderr reopen
use _dup2(_fileno(stderr), 2) so the correct file descriptor is duplicated; keep
the rest of the flow (sync_with_stdio and FlutterDesktopResyncOutputStreams)
unchanged.

Comment on lines +44 to +65
std::string Utf8FromUtf16(const wchar_t* utf16_string) {
if (utf16_string == nullptr) {
return std::string();
}
unsigned 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);
std::string utf8_string;
if (target_length == 0 || target_length > utf8_string.max_size()) {
return utf8_string;
}
utf8_string.resize(target_length);
int converted_length = ::WideCharToMultiByte(
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
input_length, utf8_string.data(), target_length, nullptr, nullptr);
if (converted_length == 0) {
return std::string();
}
return utf8_string;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Fix unsigned integer underflow.

When WideCharToMultiByte fails, it returns 0. Subtracting 1 from 0 causes unsigned integer underflow, resulting in a very large target_length value (e.g., UINT_MAX) that bypasses the safety check on line 54.

Apply this diff to check for failure before subtracting:

 std::string Utf8FromUtf16(const wchar_t* utf16_string) {
   if (utf16_string == nullptr) {
     return std::string();
   }
-  unsigned int target_length = ::WideCharToMultiByte(
+  int raw_length = ::WideCharToMultiByte(
       CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
-      -1, nullptr, 0, nullptr, nullptr)
-    -1; // remove the trailing null character
+      -1, nullptr, 0, nullptr, nullptr);
+  if (raw_length == 0) {
+    return std::string();
+  }
+  unsigned int target_length = raw_length - 1; // remove the trailing null character
   int input_length = (int)wcslen(utf16_string);
   std::string utf8_string;
   if (target_length == 0 || target_length > utf8_string.max_size()) {
     return utf8_string;
   }
   utf8_string.resize(target_length);
   int converted_length = ::WideCharToMultiByte(
       CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
       input_length, utf8_string.data(), target_length, nullptr, nullptr);
   if (converted_length == 0) {
     return std::string();
   }
   return utf8_string;
 }
🤖 Prompt for AI Agents
In windows/runner/utils.cpp around lines 44 to 65, the code subtracts 1 from the
result of WideCharToMultiByte without checking for a zero return which causes
unsigned underflow; change the logic to first call WideCharToMultiByte to get
the required buffer size into a signed/unsigned integer variable, check if that
result is 0 and return an empty string on failure, then subtract 1 to remove the
trailing null only after confirming the call succeeded, and ensure subsequent
bounds checks and resize use the validated size; also keep the input length
consistent (use -1 when you want WideCharToMultiByte to include the null
terminator) so the second conversion call parameters match the first size
calculation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant