128 lines
5.5 KiB
Dart
128 lines
5.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import '../services/app_state.dart';
|
|
|
|
/// The very first thing shown on a fresh install — before the onboarding
|
|
/// tour, before anything else — gating [MainShell] entirely until the user
|
|
/// taps "I Agree" (see [AppRoot] in main.dart and
|
|
/// [AppState.hasAcceptedUserAgreement]/[AppState.acceptUserAgreement]).
|
|
/// Its whole purpose is the liability section below: this app stores data
|
|
/// on the user's own device (and, optionally, their own cloud storage
|
|
/// account) with no server or backend of ours involved, so we have no
|
|
/// ability to recover anything for them if it's lost.
|
|
class UserAgreementScreen extends StatelessWidget {
|
|
const UserAgreementScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final textTheme = Theme.of(context).textTheme;
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(title: const Text('User Agreement'), automaticallyImplyLeading: false),
|
|
body: SafeArea(
|
|
child: Column(
|
|
children: [
|
|
Expanded(
|
|
child: ListView(
|
|
padding: const EdgeInsets.all(20),
|
|
children: [
|
|
Text(
|
|
'Please read and accept the following before using Show Me The Fuel '
|
|
'Refund.',
|
|
style: textTheme.bodyLarge,
|
|
),
|
|
const SizedBox(height: 20),
|
|
_Section(
|
|
title: 'Your Data Lives on Your Device',
|
|
body:
|
|
'Every vehicle, fuel receipt, and photo you log is stored locally on '
|
|
'this device. If you connect a cloud storage account (Google Drive, '
|
|
'Dropbox, OneDrive, or your own WebDAV server) in Settings, a copy is '
|
|
'also kept there — in storage you control, not on any server we run. '
|
|
"We don't operate a backend, and we don't have a copy of your data.",
|
|
),
|
|
_Section(
|
|
title: 'We Are Not Responsible for Your Data or Any Data Loss',
|
|
body:
|
|
'The developer is not responsible for your data, or for any loss, '
|
|
'corruption, or unavailability of it, for any reason — including but '
|
|
'not limited to device loss, theft, or damage; an uninstall or app/OS '
|
|
'update; a bug in this app; or an outage or account issue with a cloud '
|
|
'storage provider you connect. Backing up your data (by connecting a '
|
|
'cloud storage account, and by keeping it connected and in good '
|
|
'standing) is entirely your responsibility. If you never connect a '
|
|
'backup, the only copy of your data is the one on this device.',
|
|
),
|
|
_Section(
|
|
title: 'Provided As-Is',
|
|
body:
|
|
'This app is provided "as is," without warranty of any kind, express or '
|
|
'implied. Fuel and gallon values are read automatically from your '
|
|
'receipt photos and may be misread — always review them before relying '
|
|
'on them, including for a refund claim.',
|
|
),
|
|
_Section(
|
|
title: 'Not Tax or Legal Advice',
|
|
body:
|
|
"This app helps you organize receipts for Missouri's Motor Fuel Tax "
|
|
'Refund program; it does not provide tax or legal advice, and does not '
|
|
'guarantee your eligibility for any refund. The program itself is set '
|
|
'by Missouri law, which can change at any time — always confirm current '
|
|
'eligibility and rates with the Missouri Department of Revenue.',
|
|
),
|
|
const SizedBox(height: 8),
|
|
],
|
|
),
|
|
),
|
|
const Divider(height: 1),
|
|
Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: OutlinedButton(
|
|
onPressed: () => SystemNavigator.pop(),
|
|
child: const Text('Decline'),
|
|
),
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: FilledButton(
|
|
onPressed: () => context.read<AppState>().acceptUserAgreement(),
|
|
child: const Text('I Agree'),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _Section extends StatelessWidget {
|
|
final String title;
|
|
final String body;
|
|
|
|
const _Section({required this.title, required this.body});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final textTheme = Theme.of(context).textTheme;
|
|
return Padding(
|
|
padding: const EdgeInsets.only(bottom: 20),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(title, style: textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w700)),
|
|
const SizedBox(height: 6),
|
|
Text(body, style: textTheme.bodyMedium),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|