Scaffold the Flutter app with Italian l10n and region configuration

Creates the app skeleton and the seam everything else in the project hangs
off: region-specific data lives in an asset file, not in code, so adding a
region later is a new JSON file rather than a refactor.

Notable choices:

- applicationId and namespace are it.nuvolari.app rather than the doubled
  it.nuvolari.nuvolari that `flutter create` produces, with the Kotlin package
  and the iOS bundle identifiers moved to match.
- SDK levels are pinned instead of inherited from `flutter.*`. Google Play
  requires API 36, and that is a release blocker rather than something to let a
  Flutter upgrade change silently. minSdk 24 is the highest floor the planned
  dependencies impose.
- Riverpod and Dio-free for now, no code generation: see docs/stack-decisions.md.
- Italian is the l10n source language, so app_it.arb is the template rather
  than a translation of an English original.

The region parser rejects rather than repairs. An inverted bounding box, a map
centre outside its own bounds, an unknown adapter name, a duplicate zone code
or an empty attribution list all throw with the offending field named. Each of
those would otherwise fail silently and visibly wrong: a swapped latitude and
longitude renders the radar in the wrong place, an unknown adapter falling back
to mock would show demo frames where live data was expected, and a missing
attribution is a licence violation rather than a cosmetic gap.

Tests run against the asset that actually ships and against a captured copy of
the live ARPA CAP feed, so the eleven zone codes in the config are checked
against the eleven the feed really emits rather than against a list retyped
from documentation.

Verified: dart format clean, flutter analyze 0 issues, 50 tests passing,
flutter build appbundle --debug produces an AAB with applicationId
it.nuvolari.app, minSdk 24, targetSdk 36.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-10 11:24:26 +02:00
co-authored by Claude Opus 5
parent 3fcbb9f1c4
commit 85b2c99949
78 changed files with 4110 additions and 2 deletions
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>