diff --git a/Nuvolari/.vscode/extensions.json b/Nuvolari/.vscode/extensions.json new file mode 100644 index 0000000..0fb255c --- /dev/null +++ b/Nuvolari/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "dart-code.flutter", + "dart-code.dart-code", + "ms-vscode.powershell" + ] +} diff --git a/Nuvolari/.vscode/launch.json b/Nuvolari/.vscode/launch.json new file mode 100644 index 0000000..f222dc6 --- /dev/null +++ b/Nuvolari/.vscode/launch.json @@ -0,0 +1,75 @@ +{ + // Debug configurations for the Run and Debug panel (F5). + // + // Open the "Nuvolari" folder as the VS Code workspace root — these paths are + // relative to it, not to the repository root. + // + // Every configuration boots the Android emulator first via a preLaunchTask, + // so F5 works from a cold machine with no manual step. The task returns + // immediately if a device is already attached. + "version": "0.2.0", + "configurations": [ + { + // The everyday one: demo mode, no env.json needed, hot reload on save. + "name": "Nuvolari — debug (emulatore)", + "type": "dart", + "request": "launch", + "program": "${workspaceFolder}/app/lib/main.dart", + "cwd": "${workspaceFolder}/app", + "deviceId": "emulator-5554", + "flutterMode": "debug", + "preLaunchTask": "Avvia emulatore Android" + }, + { + // Debug builds run the Dart VM unoptimised, so animation always looks + // worse than it is. Judge the radar timeline here, never in debug. + "name": "Nuvolari — profile (misura le prestazioni)", + "type": "dart", + "request": "launch", + "program": "${workspaceFolder}/app/lib/main.dart", + "cwd": "${workspaceFolder}/app", + "deviceId": "emulator-5554", + "flutterMode": "profile", + "preLaunchTask": "Avvia emulatore Android" + }, + { + // Same as the first, but with real endpoints and keys. Requires env.json, + // which is git-ignored — copy env.example.json and fill it in. + "name": "Nuvolari — debug con env.json", + "type": "dart", + "request": "launch", + "program": "${workspaceFolder}/app/lib/main.dart", + "cwd": "${workspaceFolder}/app", + "deviceId": "emulator-5554", + "flutterMode": "debug", + "toolArgs": ["--dart-define-from-file=${workspaceFolder}/env.json"], + "preLaunchTask": "Avvia emulatore Android" + }, + { + // Runs on the workstation instead of a device: no emulator, no Android + // build, seconds to start. Good for UI work; the native map will not + // render here, so it is useless for anything map-related. + "name": "Nuvolari — debug su Windows (senza mappa)", + "type": "dart", + "request": "launch", + "program": "${workspaceFolder}/app/lib/main.dart", + "cwd": "${workspaceFolder}/app", + "deviceId": "windows", + "flutterMode": "debug" + }, + { + "name": "Test — tutti", + "type": "dart", + "request": "launch", + "program": "${workspaceFolder}/app/test", + "cwd": "${workspaceFolder}/app" + }, + { + "name": "Test — file corrente", + "type": "dart", + "request": "launch", + "program": "${file}", + "cwd": "${workspaceFolder}/app" + } + ] +} diff --git a/Nuvolari/.vscode/settings.json b/Nuvolari/.vscode/settings.json new file mode 100644 index 0000000..3b17c93 --- /dev/null +++ b/Nuvolari/.vscode/settings.json @@ -0,0 +1,31 @@ +{ + // Forward slashes on purpose: VS Code accepts them on Windows and they avoid + // the JSON backslash-escaping trap. + "dart.flutterSdkPath": "C:/src/flutter", + + // Format and fix imports on save; `dart format` is enforced by tool/verify.ps1 + // anyway, so catching it here avoids a failed verification later. + "[dart]": { + "editor.formatOnSave": true, + "editor.rulers": [80], + "editor.selectionHighlight": false, + "editor.tabCompletion": "onlySnippets", + "editor.wordBasedSuggestions": "off" + }, + + // Generated from lib/l10n/*.arb during pub get, and git-ignored. + "dart.analysisExcludedFolders": ["app/build", "app/.dart_tool"], + + "files.exclude": { + "**/.dart_tool": true, + "**/build": true, + "**/.gradle": true + }, + + // Radar frames are binary and numerous; keeping them out of search results + // makes finding code faster. + "search.exclude": { + "**/app/assets/mock/frames": true, + "**/app/lib/l10n/app_localizations*.dart": true + } +} diff --git a/Nuvolari/.vscode/tasks.json b/Nuvolari/.vscode/tasks.json new file mode 100644 index 0000000..d5ae234 --- /dev/null +++ b/Nuvolari/.vscode/tasks.json @@ -0,0 +1,62 @@ +{ + "version": "2.0.0", + "tasks": [ + { + // preLaunchTask for the emulator debug configurations. Idempotent: it + // exits at once when a device is already attached, so pressing F5 twice + // does not start two emulators. + "label": "Avvia emulatore Android", + "type": "shell", + "command": "powershell", + "args": [ + "-NoProfile", + "-ExecutionPolicy", "Bypass", + "-File", "${workspaceFolder}/tool/start_emulator.ps1" + ], + "problemMatcher": [], + "presentation": { + "reveal": "silent", + "panel": "shared", + "clear": true + } + }, + { + "label": "Verifica (format, analyze, test, build)", + "type": "shell", + "command": "powershell", + "args": [ + "-NoProfile", + "-ExecutionPolicy", "Bypass", + "-File", "${workspaceFolder}/tool/verify.ps1" + ], + "group": { "kind": "build", "isDefault": true }, + "problemMatcher": ["$dart-build_runner"] + }, + { + "label": "Verifica rapida (senza build)", + "type": "shell", + "command": "powershell", + "args": [ + "-NoProfile", + "-ExecutionPolicy", "Bypass", + "-File", "${workspaceFolder}/tool/verify.ps1", + "-SkipBuild" + ], + "problemMatcher": [] + }, + { + "label": "Rigenera i frame radar dimostrativi", + "type": "shell", + "command": "python", + "args": ["${workspaceFolder}/tool/generate_mock_frames.py"], + "problemMatcher": [] + }, + { + "label": "Spegni emulatore", + "type": "shell", + "command": "adb", + "args": ["emu", "kill"], + "problemMatcher": [] + } + ] +} diff --git a/Nuvolari/tool/start_emulator.ps1 b/Nuvolari/tool/start_emulator.ps1 new file mode 100644 index 0000000..6883fa5 --- /dev/null +++ b/Nuvolari/tool/start_emulator.ps1 @@ -0,0 +1,85 @@ +<# +.SYNOPSIS + Boots the Nuvolari Android emulator, unless one is already running. + +.DESCRIPTION + Used as the preLaunchTask for the VS Code debug configurations, so pressing + F5 works from a cold machine without a separate manual step. + + Idempotent on purpose: if a device is already attached the script returns + immediately, so re-launching the debugger does not stack emulator instances. + +.PARAMETER Avd + Name of the AVD to boot. Defaults to the one this project sets up. + +.PARAMETER TimeoutSeconds + How long to wait for the boot to complete. Quickboot snapshots are disabled + on this AVD to save disk, so a cold boot takes a minute or two. + +.EXAMPLE + .\tool\start_emulator.ps1 +#> +[CmdletBinding()] +param( + [string]$Avd = 'nuvolari', + [int]$TimeoutSeconds = 300 +) + +$ErrorActionPreference = 'Stop' + +$sdk = if ($env:ANDROID_HOME) { $env:ANDROID_HOME } + elseif ($env:ANDROID_SDK_ROOT) { $env:ANDROID_SDK_ROOT } + else { 'C:\Android\Sdk' } + +$adb = Join-Path $sdk 'platform-tools\adb.exe' +$emulator = Join-Path $sdk 'emulator\emulator.exe' + +foreach ($tool in @($adb, $emulator)) { + if (-not (Test-Path $tool)) { + throw "Not found: $tool. Set ANDROID_HOME or install the Android SDK." + } +} + +function Get-AttachedDevice { + # `adb devices` prints a header line, then "\tdevice" for each ready + # device. Anything in another state (offline, unauthorized) does not count. + $lines = & $adb devices 2>$null | Select-Object -Skip 1 + foreach ($line in $lines) { + if ($line -match '^(\S+)\s+device$') { return $Matches[1] } + } + return $null +} + +$existing = Get-AttachedDevice +if ($existing) { + Write-Host "Device already attached: $existing" -ForegroundColor Green + exit 0 +} + +$available = & $emulator -list-avds 2>$null +if ($available -notcontains $Avd) { + throw "AVD '$Avd' does not exist. Available: $($available -join ', '). See docs/roadmap.md for how it was created." +} + +Write-Host "Booting emulator '$Avd' (cold boot, snapshots are disabled)..." -ForegroundColor Cyan + +# Detached, with its own window, so the debug session does not own its lifetime +# and stopping the debugger leaves the emulator up for the next run. +Start-Process -FilePath $emulator ` + -ArgumentList @('-avd', $Avd, '-no-audio', '-no-boot-anim', '-gpu', 'host') ` + -WindowStyle Minimized | Out-Null + +$deadline = (Get-Date).AddSeconds($TimeoutSeconds) +while ((Get-Date) -lt $deadline) { + $device = Get-AttachedDevice + if ($device) { + $booted = (& $adb -s $device shell getprop sys.boot_completed 2>$null) -replace '\s', '' + if ($booted -eq '1') { + Write-Host "Emulator ready: $device" -ForegroundColor Green + exit 0 + } + } + Start-Sleep -Seconds 3 +} + +throw "Emulator '$Avd' did not finish booting within $TimeoutSeconds seconds."