Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ios/Flutter/Debug.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
1 change: 1 addition & 0 deletions ios/Flutter/Release.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
43 changes: 43 additions & 0 deletions ios/Podfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '13.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}

def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end

File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_ios_podfile_setup

target 'Runner' do
use_frameworks!

flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end

post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
8 changes: 4 additions & 4 deletions lib/database/database_helper.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart' as p;
import 'package:template_flutter/database/database_exceptions.dart';
import 'package:template_flutter/database/models/base_model.dart';
import 'package:template_flutter/database/models/trips.dart';
import 'package:template_flutter/database/models/user.dart';
import 'package:carbon_tracker/database/database_exceptions.dart';
import 'package:carbon_tracker/database/models/base_model.dart';
import 'package:carbon_tracker/database/models/trips.dart';
import 'package:carbon_tracker/database/models/user.dart';

class DatabaseHelper {
// Singleton pattern
Expand Down
2 changes: 1 addition & 1 deletion lib/database/models/trips.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:template_flutter/database/models/base_model.dart';
import 'package:carbon_tracker/database/models/base_model.dart';

class Trip extends BaseModel {
final DateTime date;
Expand Down
6 changes: 3 additions & 3 deletions lib/database/models/user.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import 'dart:convert';

import 'package:template_flutter/database/models/base_model.dart';
import 'package:carbon_tracker/database/models/base_model.dart';


class User extends BaseModel {
final List<dynamic> preferredTransports;
final List<dynamic> frequentTransports;
final List<String> preferredTransports;
final List<String> frequentTransports;
Comment on lines +7 to +8

Copy link
Copy Markdown

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

🏁 Script executed:

#!/bin/bash
# Verify List<String>-typed fields are currently assigned from raw jsonDecode outputs.
rg -n -C2 "final List<String> preferredTransports|final List<String> frequentTransports|preferredTransports:\s*jsonDecode|frequentTransports:\s*jsonDecode" lib/database/models/user.dart

Repository: AOSSIE-Org/CarbonTracker

Length of output: 593


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect User model around fromMap / constructor to see expected types and any additional conversions.
sed -n '1,120p' lib/database/models/user.dart

# Find other occurrences of fromMap or preferred_transports usage to understand how these fields are stored/decoded.
rg -n "preferred_transports|frequent_transports|fromMap\\(" -S lib | head -n 50

Repository: AOSSIE-Org/CarbonTracker

Length of output: 2906


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect User model around fromMap / constructor to see expected types and any additional conversions.
sed -n '1,120p' lib/database/models/user.dart

# Find other occurrences of fromMap or preferred_transports usage to understand how these fields are stored/decoded.
rg -n "preferred_transports|frequent_transports|fromMap\\(" -S lib | head -n 50

Repository: AOSSIE-Org/CarbonTracker

Length of output: 2906


Cast decoded transport arrays to List<String> in User.fromMap.
User.fromMap assigns raw jsonDecode(...) (for JSON arrays this is typically List<dynamic>) into fields typed as List<String>, which can fail with a runtime type error when constructing User.

Proposed fix
   factory User.fromMap(Map<String, dynamic> map) {
     return User(
       id: map['id'],
-      preferredTransports: jsonDecode(map['preferred_transports']),
-      frequentTransports: jsonDecode(map['frequent_transports']),
+      preferredTransports:
+          List<String>.from(jsonDecode(map['preferred_transports']) as List),
+      frequentTransports:
+          List<String>.from(jsonDecode(map['frequent_transports']) as List),
       trackingMode: map['tracking_mode'],
       weight: (map['weight'] as num).toDouble(),
       sustainabilityThoughts: map['sustainability_thoughts'],
       lastResetMonth: map['last_reset_month'],
       lastResetYear: map['last_reset_year'],
     );
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/database/models/user.dart` around lines 7 - 8, User.fromMap currently
assigns jsonDecode(...) results (List<dynamic>) directly to the typed fields
preferredTransports and frequentTransports which can cause runtime type errors;
update User.fromMap to convert/cast those decoded values to List<String> (e.g.
use List<String>.from(decoded) or decoded.map((e) => e.toString()).toList()) and
handle null or non-list values by providing an empty list default, ensuring
preferredTransports and frequentTransports are always List<String>.

final String trackingMode;// Default tracking mode; other modes will be supported later
final double weight;
final String? sustainabilityThoughts;
Expand Down
12 changes: 9 additions & 3 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import 'package:flutter/material.dart';

void main() {
import 'generated/app_localizations.dart';
import 'database/database_helper.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();
await DatabaseHelper().initDB();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use getDB() at startup to initialize the singleton DB handle.

Line 8 currently calls initDB(), but that path does not assign DatabaseHelper._database. The first later getDB() call will initialize again instead of using a prewarmed singleton path.

Proposed fix
 void main() async {
   WidgetsFlutterBinding.ensureInitialized();
-  await DatabaseHelper().initDB();
+  await DatabaseHelper().getDB();
   runApp(const MyApp());
 }
📝 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
await DatabaseHelper().initDB();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await DatabaseHelper().getDB();
runApp(const MyApp());
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/main.dart` at line 8, Replace the startup call to
DatabaseHelper().initDB() with a call to the singleton-initializing accessor
DatabaseHelper().getDB() so the DatabaseHelper._database field is populated and
reused; ensure you locate the startup invocation that currently calls initDB()
and change it to getDB() (keeping DatabaseHelper, initDB, getDB and _database as
the reference points).

runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Carbon Tracker',
debugShowCheckedModeBanner: false,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightGreen),
),
Expand All @@ -27,7 +33,7 @@ class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Carbon Tracker')),
appBar: AppBar(title: Text(AppLocalizations.of(context)?.hello ?? 'Carbon Tracker')),
body: const Center(child: Text('Welcome to Carbon Tracker!')),
);
}
Expand Down
24 changes: 12 additions & 12 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: a49d6cf99e8d8e7a8e93668d09ced0bbdb954d0b4fccc2f5f9241c6b87fad95c
sha256: "8d7ff3948166b8ec5da0fbb5962000926b8e02f2ed9b3e51d1738905fbd4c98d"
url: "https://pub.dev"
source: hosted
version: "99.0.0"
version: "93.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "663efa951fb8a45e06f491223a604c93820598f20e6a99c25617a1576065e8b7"
sha256: de7148ed2fcec579b19f122c1800933dfa028f6d9fd38a152b04b1516cec120b
url: "https://pub.dev"
source: hosted
version: "12.1.0"
version: "10.0.1"
args:
dependency: transitive
description:
Expand Down Expand Up @@ -252,10 +252,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.dev"
source: hosted
version: "1.18.0"
version: "1.17.0"
mime:
dependency: transitive
description:
Expand Down Expand Up @@ -481,26 +481,26 @@ packages:
dependency: transitive
description:
name: test
sha256: "8d9ceddbab833f180fbefed08afa76d7c03513dfdba87ffcec2718b02bbcbf20"
sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7"
url: "https://pub.dev"
source: hosted
version: "1.31.0"
version: "1.30.0"
test_api:
dependency: transitive
description:
name: test_api
sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
url: "https://pub.dev"
source: hosted
version: "0.7.11"
version: "0.7.10"
test_core:
dependency: transitive
description:
name: test_core
sha256: "1991d4cfe85d5043241acac92962c3977c8d2f2add1ee73130c7b286417d1d34"
sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51"
url: "https://pub.dev"
source: hosted
version: "0.6.17"
version: "0.6.16"
typed_data:
dependency: transitive
description:
Expand Down
10 changes: 3 additions & 7 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
name: template_flutter
description: "A new Flutter project."
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

## A version number is three numbers separated by dots, like 1.2.43following defines the version and build number for your application.
name: carbon_tracker
description: "A carbon emission tracking app that logs trips and calculates CO2 savings."
publish_to: 'none'
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
Expand Down
Empty file removed test/database_test.dart
Empty file.
27 changes: 5 additions & 22 deletions test/widget_test.dart
Original file line number Diff line number Diff line change
@@ -1,30 +1,13 @@
// 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:template_flutter/main.dart';
import 'package:carbon_tracker/main.dart';

void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
testWidgets('App renders welcome screen with localized hello',
(WidgetTester tester) async {
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);
expect(find.text('Hello'), findsOneWidget);
expect(find.text('Welcome to Carbon Tracker!'), findsOneWidget);
});
}
Loading