Skip to content
Snippets Groups Projects
Commit 92ae0150 authored by Sara Savanovic Djordjevic's avatar Sara Savanovic Djordjevic
Browse files

refactor: initial Flutter project organization

parent f268466b
No related branches found
No related tags found
No related merge requests found
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart'; // Import LatLng class from the latlong package
import 'dart:async';
import 'dart:io';
import 'dart:convert';
import 'pages_and_more/default_page.dart';
const String port = "8443";
const String serverURI = "https://127.0.0.1:$port/";
const String mapEndpoint = "update_map";
// NB: if http connection fails, run: adb reverse tcp:8443 tcp:8443
const int fetchInterval = 5;
// main is the entry point for the application, and starts the App() function
void main() {
runApp(const App());
runApp(MyApp());
}
class App extends StatelessWidget {
const App({super.key});
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const MaterialApp(
......@@ -27,193 +13,3 @@ class App extends StatelessWidget {
);
}
}
class DefaultPage extends StatefulWidget {
const DefaultPage({Key? key}) : super(key: key);
@override
_DefaultPageState createState() => _DefaultPageState();
}
// MarkerData holds data for the dynamicllay allocated markers
class MarkerData {
final LatLng location;
final double size;
final Color color;
final double radius;
MarkerData({required this.location, required this.size, required this.color, required this.radius});
}
// parseMarkerData parses jsonData into an object of type MakerData
List<MarkerData> parseMarkerData(String jsonString) {
final parsed = json.decode(jsonString);
return List<MarkerData>.from(parsed.map((data) => MarkerData(
location: LatLng(data['latitude'], data['longitude']),
size: data['size'].toDouble(),
color: parseColor(data['color']),
radius: data['radius'].toDouble(),
)));
}
// parseColor parses the color strings into Colors types
Color parseColor(String colorString) {
switch (colorString) {
case 'blue':
return Colors.blue;
case 'red':
return Colors.red;
case 'green':
return Colors.green;
default:
return Colors.black; // Default color if unrecognized
}
}
class _DefaultPageState extends State<DefaultPage> {
late Timer _timer;
List<MarkerData> markerList = [];
// fetchMarkerData requests data from the update_map endpoint
Future<void> fetchMarkerData() async {
try {
// Custom HTTP client
HttpClient client = HttpClient()
..badCertificateCallback = // NB: temporary disable SSL certificate validation
(X509Certificate cert, String host, int port) => true;
var request = await client.getUrl(Uri.parse(serverURI+mapEndpoint));
var response = await request.close();
// Parse json response to list of MarkerData objects if request is ok
if (response.statusCode == 200) {
var responseBody = await response.transform(utf8.decoder).join();
setState(() {
markerList = parseMarkerData(responseBody);
});
} else {
print('Request failed with status: ${response.statusCode}');
}
} catch (e) {
print('Failed to connect to the server: $e');
}
}
// Timer initializer
@override
void initState() {
super.initState();
// Call fetchMarkerData when the widget is first created
fetchMarkerData();
// Schedule fetchMarkerData to run periodically based on fetchInterval const
const Duration fiveMinutes = Duration(minutes: fetchInterval);
_timer = Timer.periodic(fiveMinutes, (timer) {
fetchMarkerData();
});
}
// Fetch timer
@override
void dispose() {
// Cancel timer on widget termination
_timer.cancel();
super.dispose();
}
// Main widget
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double boxWidth = 0.9;
double boxHeight = 1.5;
const double markerSize = 20;
return Scaffold(
appBar: AppBar(
title: const Text('IceMap'),
),
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container( // Map container
width: screenWidth * boxWidth,
height: screenWidth * boxHeight,
color: Colors.blue,
child: FlutterMap(
options: MapOptions(
center: LatLng(60.7666, 10.8471),
zoom: 9.0,
),
children: [
TileLayer(
urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
subdomains: const ['a', 'b', 'c'],
),
MarkerLayer(
// Dynamically allocate markers based on a list
markers: markerList.map((MarkerData markerData) {
return Marker(
width: markerData.size,
height: markerData.size,
point: markerData.location,
builder: (ctx) => GestureDetector(
onTap: () {
// NB: temporary print
print('Icon tapped');
// NB: trigger function to add contents to the next box
},
child: Image.asset(
'assets/icons/circle-red.png', // Path to your custom icon asset
color: markerData.color,
width: markerData.radius,
height: markerData.radius,
),
),
);
}).toList(),
),
/*PolygonLayer(
polygons: [
Polygon(
points: [
LatLng(60.7600, 10.8000),
LatLng(60.7600, 11.0000),
LatLng(60.7000, 11.0000),
LatLng(60.7000, 10.8000),
],
color: Colors.blue,
isFilled: true,
),
],
),*/
],
),
),
const SizedBox(height: 20),
Container( // Detailed info container
width: screenWidth * boxWidth,
height: screenWidth * boxHeight,
color: Colors.blue,
child: const Align(
alignment: Alignment.topLeft,
child: Padding(
padding: EdgeInsets.only(top: 10, left: 10), // Edge padding, text
child: Text(
'Placeholder text',
style: TextStyle(fontSize: 20, color: Colors.black),
),
),
),
),
const SizedBox(height: 20),
],
),
),
),
);
}
}
const String port = "8443";
const String serverURI = "https://127.0.0.1:$port/";
const String mapEndpoint = "update_map";
const int fetchInterval = 5;
\ No newline at end of file
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'marker_data.dart';
import 'consts.dart';
class DefaultPage extends StatefulWidget {
const DefaultPage({super.key});
@override
_DefaultPageState createState() => _DefaultPageState();
}
class _DefaultPageState extends State<DefaultPage> {
late Timer _timer;
List<MarkerData> markerList = [];
// fetchMarkerData requests data from the update_map endpoint
Future<void> fetchMarkerData() async {
try {
// Custom HTTP client
HttpClient client = HttpClient()
..badCertificateCallback = // NB: temporary disable SSL certificate validation
(X509Certificate cert, String host, int port) => true;
var request = await client.getUrl(Uri.parse(serverURI+mapEndpoint));
var response = await request.close();
// Parse json response to list of MarkerData objects if request is ok
if (response.statusCode == 200) {
var responseBody = await response.transform(utf8.decoder).join();
setState(() {
markerList = parseMarkerData(responseBody);
});
} else {
print('Request failed with status: ${response.statusCode}');
}
} catch (e) {
print('Failed to connect to the server: $e');
}
}
// Timer initializer
@override
void initState() {
super.initState();
// Call fetchMarkerData when the widget is first created
fetchMarkerData();
// Schedule fetchMarkerData to run periodically based on fetchInterval const
const Duration fiveMinutes = Duration(minutes: fetchInterval);
_timer = Timer.periodic(fiveMinutes, (timer) {
fetchMarkerData();
});
}
// Fetch timer
@override
void dispose() {
// Cancel timer on widget termination
_timer.cancel();
super.dispose();
}
// Main widget
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double boxWidth = 0.9;
double boxHeight = 1.5;
const double markerSize = 20;
return Scaffold(
appBar: AppBar(
title: const Text('IceMap'),
),
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container( // Map container
width: screenWidth * boxWidth,
height: screenWidth * boxHeight,
color: Colors.blue,
child: FlutterMap(
options: MapOptions(
center: LatLng(60.7666, 10.8471),
zoom: 9.0,
),
children: [
TileLayer(
urlTemplate: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
subdomains: const ['a', 'b', 'c'],
),
MarkerLayer(
// Dynamically allocate markers based on a list
markers: markerList.map((MarkerData markerData) {
return Marker(
width: markerData.size,
height: markerData.size,
point: markerData.location,
builder: (ctx) => GestureDetector(
onTap: () {
// NB: temporary print
print('Icon tapped');
// NB: trigger function to add contents to the next box
},
child: Image.asset(
'assets/icons/circle-red.png', // Path to your custom icon asset
color: markerData.color,
width: markerData.radius,
height: markerData.radius,
),
),
);
}).toList(),
),
/*PolygonLayer(
polygons: [
Polygon(
points: [
LatLng(60.7600, 10.8000),
LatLng(60.7600, 11.0000),
LatLng(60.7000, 11.0000),
LatLng(60.7000, 10.8000),
],
color: Colors.blue,
isFilled: true,
),
],
),*/
],
),
),
const SizedBox(height: 20),
Container( // Detailed info container
width: screenWidth * boxWidth,
height: screenWidth * boxHeight,
color: Colors.blue,
child: const Align(
alignment: Alignment.topLeft,
child: Padding(
padding: EdgeInsets.only(top: 10, left: 10), // Edge padding, text
child: Text(
'Placeholder text',
style: TextStyle(fontSize: 20, color: Colors.black),
),
),
),
),
const SizedBox(height: 20),
],
),
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:latlong2/latlong.dart';
import 'dart:convert';
// MarkerData holds data for the dynamically allocated markers
class MarkerData {
final LatLng location;
final double size;
final Color color;
final double radius;
MarkerData({required this.location, required this.size, required this.color, required this.radius});
}
// parseMarkerData parses jsonData into an object of type MakerData
List<MarkerData> parseMarkerData(String jsonString) {
final parsed = json.decode(jsonString);
return List<MarkerData>.from(parsed.map((data) => MarkerData(
location: LatLng(data['latitude'], data['longitude']),
size: data['size'].toDouble(),
color: parseColor(data['color']),
radius: data['radius'].toDouble(),
)));
}
// parseColor parses the color strings into Colors types
Color parseColor(String colorString) {
switch (colorString) {
case 'blue':
return Colors.blue;
case 'red':
return Colors.red;
case 'green':
return Colors.green;
default:
return Colors.black; // Default color if unrecognized
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment