Rebuild the Flutter/DJI-MSDK-V4 Fly App to the v2 UI kit and wire the full SDK surface behind it. Native (Kotlin): split DjiSdkBridge into a method/event router delegating to per-subsystem SubBridge helpers sharing a BridgeCtx — FlightController (takeoff/land/RTH + rich telemetry), Camera (mode/record/photo/exposure), Gimbal, Mission (Waypoint + ActiveTrack; QuickShots via ActiveTrack QUICK_SHOT), Media (MediaManager list/thumbnail/download), and optional DJI account login. Manifest gains scoped media permissions. Flutter: ten screens under lib/ui/ (Flight HUD, capture modes, camera settings, settings menu, map+waypoints, home, album, academy, profile, routes/flight logs), driven by an expanded FlightModel. New PVIcon renders the kit's SVG paths via flutter_svg; map uses flutter_map + latlong2. Pin transitive androidx.core/browser down to SDK-35-compatible versions so the newer plugins don't force AGP 8.9.1 onto the DJI toolchain. Verified with `flutter build apk --debug` (compiles Dart + all Kotlin); runtime behaviour is untested here — it needs a physical DJI-connected device. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
55 lines
1.8 KiB
Dart
55 lines
1.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../theme.dart';
|
|
import 'pv_icons.dart';
|
|
|
|
/// A plain portrait scaffold with a back title and a centered empty state —
|
|
/// shared chrome for the Routes and Flight-logs library screens (which have no
|
|
/// persisted content yet).
|
|
class SimpleListPage extends StatelessWidget {
|
|
const SimpleListPage({
|
|
super.key,
|
|
required this.title,
|
|
required this.emptyIcon,
|
|
required this.emptyText,
|
|
this.child,
|
|
});
|
|
|
|
final String title;
|
|
final String emptyIcon;
|
|
final String emptyText;
|
|
final Widget? child;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final PVScheme s = PVScheme.of(context);
|
|
return Scaffold(
|
|
backgroundColor: s.bgApp,
|
|
body: SafeArea(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
Padding(
|
|
padding: const EdgeInsets.fromLTRB(12, 6, 20, 12),
|
|
child: Row(children: <Widget>[
|
|
IconButton(onPressed: () => Navigator.of(context).maybePop(), icon: PVIcon('chevronLeft', size: 24, color: s.textSecondary)),
|
|
Text(title, style: TextStyle(fontFamily: PV.fontSans, fontSize: 20, fontWeight: FontWeight.w700, letterSpacing: -0.4, color: s.textPrimary)),
|
|
]),
|
|
),
|
|
Expanded(
|
|
child: child ??
|
|
Center(
|
|
child: Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
|
PVIcon(emptyIcon, size: 40, stroke: 1.4, color: s.textTertiary),
|
|
const SizedBox(height: 12),
|
|
Text(emptyText, textAlign: TextAlign.center, style: TextStyle(fontFamily: PV.fontSans, fontSize: 14, color: s.textSecondary)),
|
|
]),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|