Skip to content
Merged
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
Binary file removed Assets/images/3.0.2+18_location_history.jpg
Binary file not shown.
Binary file removed Assets/images/3.0.2+18_map_view.jpg
Binary file not shown.
Binary file removed Assets/images/3.0.2+18_report_an_issue.jpg
Binary file not shown.
Binary file removed Assets/images/3.0.2+18_side_drawer.jpg
Binary file not shown.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Space Mapper is a mobile phone application that lets you see your daily movements in a map. Additionally, you can participate in citizen science by sharing your anonymized location history with research institutions to help scientists research about human mobility.

## Screenshots
<img src="https://github.com/ActivitySpaceProject/space_mapper/blob/development/Assets/images/3.0.2%2B18_screenshots.png" width="95%"></img>
<img src="https://github.com/ActivitySpaceProject/space_mapper/blob/master/Assets/images/3.0.2%2B18_screenshots.png" width="95%"></img>

## How to contribute
Do you want to contribute?
Expand Down
27 changes: 27 additions & 0 deletions Space_Mapper/lang/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"side_drawer_title": "Space Mapper Menu",
"take_survey": "Take Survey",
"locations_history": "Locations History",
"share_locations": "Share Locations",
"visit_project_website": "Visit Project Website",
"report_an_issue": "Report an Issue",
"report_summary": "Help us improve by either reporting an issue or requesting a useful feature.",
"github_description": "Report issues on github to get the fastest solution.",
"github_button": "Go to Github Issues",
"email_description": "As an alternative, you can send us an email.",
"report_email_btn1": "Report an issue by email",
"report_email_btn2": "Request a feature by email",
"activity": "Activity",
"speed": "Speed",
"altitude": "Altitude",
"record_contact": "Record Contact",
"male": "Male",
"female": "Female",
"other": "Other",
"was_the_contact_male_female?": "Was the contact male or female?",
"about_how_old_were_they": "About how old were they",
"select_age_group": "Select age group",
"submit": "Submit",
"reset": "Reset",
"gender": "gender"
}
27 changes: 27 additions & 0 deletions Space_Mapper/lang/es.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"side_drawer_title": "Menú de Space Mapper",
"take_survey": "Haz una encuesta",
"locations_history": "Historial de ubicaciones",
"share_locations": "Compartir ubicaciones",
"visit_project_website": "Visita nuestra web",
"report_an_issue": "Reporta un problema",
"report_summary": "Ayúdanos a mejorar informando un problema o solicitando una mejora.",
"github_description": "Informe problemas en github para obtener la solución más rápida.",
"github_button": "Ir a Github Issues",
"email_description": "Como alternativa, puede enviarnos un email.",
"report_email_btn1": "Reporta un problema por email",
"report_email_btn2": "Solicita una mejora por email",
"activity": "Actividad",
"speed": "Velocidad",
"altitude": "Altitud",
"record_contact": "Registrar Contacto",
"male": "Hombre",
"female": "Mujer",
"other": "Otro",
"was_the_contact_male_female?": "¿El contacto fué hombre o mujer?",
"about_how_old_were_they": "¿Qué edad tenían?",
"select_age_group": "Selecciona grupo de edad",
"submit": "Enviar",
"reset": "Restablecer",
"gender": "género"
}
70 changes: 70 additions & 0 deletions Space_Mapper/lib/app_localizations.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class AppLocalizations {
final Locale locale;

AppLocalizations(this.locale);

// Helper method to keep the code in the widgets concise
// Localizations are accessed using an InheritedWidget "of" syntax
static AppLocalizations? of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}

// Static member to have a simple access to the delegate from the MaterialApp
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();

Map<String, String> _localizedStrings = Map<String, String>();

Future<bool> load() async {
// Load the language JSON file from the "lang" folder
String jsonString =
await rootBundle.loadString('lang/${locale.languageCode}.json');
Map<String, dynamic> jsonMap = json.decode(jsonString);

_localizedStrings = jsonMap.map((key, value) {
return MapEntry(key, value.toString());
});

return true;
}

// This method will be called from every widget which needs a localized text
String translate(String key) {
if (_localizedStrings[key] == null)
return "Error. No translation found";
else
return _localizedStrings[key]!;
}
}

// LocalizationsDelegate is a factory for a set of localized resources
// In this case, the localized strings will be gotten in an AppLocalizations object
class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {
// This delegate instance will never change (it doesn't even have fields!)
// It can provide a constant constructor.
const _AppLocalizationsDelegate();

@override
bool isSupported(Locale locale) {
// Include all of your supported language codes here
return ['en', 'es'].contains(locale.languageCode);
}

@override
Future<AppLocalizations> load(Locale locale) async {
// AppLocalizations class is where the JSON loading actually runs
AppLocalizations localizations = new AppLocalizations(locale);
await localizations.load();
return localizations;
}

@override
bool shouldReload(_AppLocalizationsDelegate old) => false;
}
28 changes: 28 additions & 0 deletions Space_Mapper/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import 'package:asm/util/env.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart'
as bg;
import 'package:background_fetch/background_fetch.dart';

import 'app_localizations.dart';
import 'ui/home_view.dart';
import 'package:uuid/uuid.dart';

Expand Down Expand Up @@ -128,6 +130,32 @@ class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: appName,
supportedLocales: [
Locale('en',
''), // English, no country code. The first element of this list is the default language
Locale('es', ''), // Spanish, no country code
//Locale('ca', '') // Catalan, no country code
],
localizationsDelegates: [
//A class which loads the translations from JSON files
AppLocalizations.delegate,
// Built-in localization of basic text for Material widgets
GlobalMaterialLocalizations.delegate,
// Built-in localization for text direction LTR/RTL
GlobalWidgetsLocalizations.delegate,
],
// Returns a locale which will be used by the app
localeResolutionCallback: (locale, supportedLocales) {
// Check if the current device locale is supported
for (var supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale!.languageCode) {
return supportedLocale;
}
}
// If the locale of the device is not supported, use the first one
// from the list (English, in this case).
return supportedLocales.first;
},
home: HomeView(appName),
);
}
Expand Down
16 changes: 12 additions & 4 deletions Space_Mapper/lib/models/list_view.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart'
as bg;

import '../app_localizations.dart';

class CustomLocationsManager {
static List<CustomLocation> customLocations = [];

Expand Down Expand Up @@ -51,18 +54,23 @@ class CustomLocation {
late bool _toDelete = false;

/// Checks if data is valid and then displays 3 lines with: Activity, Speed and Altitude
String displayCustomText(num maxSpeedAccuracy, num maxAltitudeAccuracy) {
String displayCustomText(
num maxSpeedAccuracy, num maxAltitudeAccuracy, BuildContext context) {
String ret = "";

ret += " \nActivity: " + _activity;
String activity = AppLocalizations.of(context)!.translate("activity");
String speed = AppLocalizations.of(context)!.translate("speed");
String altitude = AppLocalizations.of(context)!.translate("altitude");

ret += " \n$activity: $_activity";

/// Speed has to be both valid and accurate
if (_speed != -1 && _speedAccuracy != -1) {
if (_speedAccuracy <= maxSpeedAccuracy)
ret += " \nSpeed: " + _speed.toString() + " m/s";
ret += " \n$speed: " + _speed.toString() + " m/s";
}
if (_altitudeAccuracy <= maxAltitudeAccuracy)
ret += "\nAltitude: " + _altitude.toString() + " m";
ret += "\n$altitude: " + _altitude.toString() + " m";

return ret;
}
Expand Down
35 changes: 22 additions & 13 deletions Space_Mapper/lib/ui/form_view.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';

import '../app_localizations.dart';

class FormView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Record Contact'),
title: Text(AppLocalizations.of(context)!.translate("record_contact")),
),
body: MyCustomForm(),
);
Expand All @@ -33,7 +35,6 @@ class MyCustomFormState extends State<MyCustomForm> {
//GlobalKey<FormFieldState>();

//ValueChanged _onChanged = (val) => print(val);
var genderOptions = ['Male', 'Female', 'Other'];

@override
Widget build(BuildContext context) {
Expand All @@ -53,29 +54,37 @@ class MyCustomFormState extends State<MyCustomForm> {
child: Column(
children: <Widget>[
FormBuilderChoiceChip(
name: 'gender',
name: AppLocalizations.of(context)!.translate("gender"),
decoration: InputDecoration(
labelText: 'Was the contact male or female?'),
labelText: AppLocalizations.of(context)!
.translate("was_the_contact_male_female?")),
options: [
FormBuilderFieldOption(
value: 1,
child: Text('Male'),
child:
Text(AppLocalizations.of(context)!.translate("male")),
),
FormBuilderFieldOption(
value: 2,
child: Text('Female'),
child: Text(
AppLocalizations.of(context)!.translate("female")),
),
FormBuilderFieldOption(
value: 3,
child: Text('Other'),
child: Text(
AppLocalizations.of(context)!.translate("other")),
),
],
),
FormBuilderDropdown(
name: 'age',
decoration:
InputDecoration(labelText: "About how old were they?"),
hint: Text('Select Age Group'),
decoration: InputDecoration(
labelText: AppLocalizations.of(context)!
.translate("about_how_old_were_they"),
),
hint: Text(
AppLocalizations.of(context)!.translate("select_age_group"),
),
items: [
'0-9',
'10-19',
Expand All @@ -85,7 +94,7 @@ class MyCustomFormState extends State<MyCustomForm> {
'50-59',
'60-69',
'70-79',
'80 or over'
'80+'
]
.map((age) =>
DropdownMenuItem(value: age, child: Text("$age")))
Expand All @@ -97,15 +106,15 @@ class MyCustomFormState extends State<MyCustomForm> {
Row(
children: <Widget>[
MaterialButton(
child: Text("Submit"),
child: Text(AppLocalizations.of(context)!.translate("submit")),
onPressed: () {
if (_fbKey.currentState!.saveAndValidate()) {
print(_fbKey.currentState!.value);
}
},
),
MaterialButton(
child: Text("Reset"),
child: Text(AppLocalizations.of(context)!.translate("reset")),
onPressed: () {
_fbKey.currentState!.reset();
},
Expand Down
11 changes: 7 additions & 4 deletions Space_Mapper/lib/ui/list_view.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import '../app_localizations.dart';
import '../models/list_view.dart';
import 'package:flutter/material.dart';
import 'package:flutter_background_geolocation/flutter_background_geolocation.dart'
Expand Down Expand Up @@ -100,13 +101,15 @@ class _STOListViewState extends State<STOListView> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Locations History")),
appBar: AppBar(
title: Text(
AppLocalizations.of(context)!.translate("locations_history"))),
body: ListView.builder(
itemCount: customLocations.length,
itemBuilder: (context, index) {
CustomLocation thisLocation = customLocations[index];
return Dismissible(
child: _tile(thisLocation),
child: _tile(thisLocation, context),
background: Container(
child: Container(
margin: EdgeInsets.only(right: 10.0),
Expand All @@ -133,15 +136,15 @@ class _STOListViewState extends State<STOListView> {
));
}

ListTile _tile(CustomLocation thisLocation) {
ListTile _tile(CustomLocation thisLocation, BuildContext context) {
String title = thisLocation.getLocality() +
", " +
thisLocation.getSubAdministrativeArea() +
", " +
thisLocation.getISOCountryCode();
String subtitle =
thisLocation.getTimestamp() + "\n" + thisLocation.getStreet();
String text = thisLocation.displayCustomText(10.0, 10.0);
String text = thisLocation.displayCustomText(10.0, 10.0, context);
return ListTile(
title: Text(title,
style: TextStyle(
Expand Down
Loading