diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index 1ea50ce..0000000 --- a/.drone.yml +++ /dev/null @@ -1,25 +0,0 @@ -kind: pipeline -type: kubernetes -name: build-apk - -clone: - depth: 1 - -steps: - - name: build - image: cirrusci/flutter:stable - pull: true - commands: - - flutter packages get - - flutter build apk --release --split-per-abi - - mkdir apks - - mv build/app/outputs/apk/*/*/*.apk apks - - - name: Publish APK - image: plugins/gitea-release - settings: - api_key: - from_secret: GITEA_TOKEN -trigger: - event: - - push \ No newline at end of file diff --git a/.gitea/workflows/build-android.yaml b/.gitea/workflows/build-android.yaml index 76305b1..b714b6c 100644 --- a/.gitea/workflows/build-android.yaml +++ b/.gitea/workflows/build-android.yaml @@ -1,5 +1,10 @@ -on: push -name: Test, Build and Release apk +on: + pull_request: + branches: + - main + +name: Build and release APK + jobs: build: name: Build APK @@ -10,6 +15,7 @@ jobs: run: | sudo apt-get update sudo apt-get install -y xz-utils unzip + - uses: https://gitea.com/actions/checkout@v4 - uses: https://github.com/actions/setup-java@v4 @@ -22,19 +28,22 @@ jobs: channel: stable flutter-version: 3.19.6 cache: true + - name: Setup Android SDK uses: https://github.com/android-actions/setup-android@v3 - run: flutter pub get - # - run: flutter test + - run: flutter build apk --debug --split-per-abi - + - name: Release APK uses: https://gitea.com/akkuman/gitea-release-action@v1 with: files: build/app/outputs/flutter-apk/*.apk + name: Testing release + release_name: testing tag: testing - release_name: Testing release + tag_name: testing release_body: "This is a testing release." prerelease: true token: ${{ secrets.GITEA_TOKEN }} diff --git a/.gitea/workflows/build-web.yaml b/.gitea/workflows/build-web.yaml index cc08a5e..cdb817c 100644 --- a/.gitea/workflows/build-web.yaml +++ b/.gitea/workflows/build-web.yaml @@ -1,21 +1,30 @@ -on: push -name: Test, Build and Release web +on: + pull_request: + branches: + - main + +name: Build web + jobs: build: name: Build Web runs-on: k8s steps: + - name: Install prerequisites run: | sudo apt-get update sudo apt-get install -y xz-utils - uses: actions/checkout@v4 + - uses: https://github.com/subosito/flutter-action@v2 with: channel: stable flutter-version: 3.19.6 cache: true - - run: flutter pub get - # - run: flutter test + + - run: flutter pub get + + - run: flutter build web diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml new file mode 100644 index 0000000..7f22525 --- /dev/null +++ b/.gitea/workflows/test.yaml @@ -0,0 +1,31 @@ +on: + push: + pull_request: + branches: + - main + + +name: Test code + +jobs: + test: + name: Test code + runs-on: k8s + steps: + + - name: Install prerequisites + run: | + sudo apt-get update + sudo apt-get install -y xz-utils + + - uses: actions/checkout@v4 + + - uses: https://github.com/subosito/flutter-action@v2 + with: + channel: stable + flutter-version: 3.19.6 + cache: true + + - run: flutter pub get + + - run: flutter test diff --git a/lib/modules/destination_card.dart b/lib/modules/destination_card.dart new file mode 100644 index 0000000..5829c5e --- /dev/null +++ b/lib/modules/destination_card.dart @@ -0,0 +1,40 @@ + + +import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; + + +class DestinationCard extends StatefulWidget { + final String title; + final String description; + final String image; + bool visited; + + @override + _DestinationCardState createState() => _DestinationCardState(); + + + DestinationCard(this.title, this.description, this.image, this.visited); + + Widget build() { + return Card( + child: ListTile( + leading: Icon(Icons.location_on), + title: Text(title), + subtitle: Text(description), + onTap: () { + // Navigator.pushNamed(context, '/destination'); + }, + ), + ); + } + +} + +class _DestinationCardState extends State { + @override + Widget build(BuildContext context) { + return Card(); + } + +} \ No newline at end of file diff --git a/lib/modules/navigation.dart b/lib/modules/navigation.dart index f7fcbcf..7bd62ac 100644 --- a/lib/modules/navigation.dart +++ b/lib/modules/navigation.dart @@ -1,13 +1,62 @@ +import 'package:fast_network_navigation/modules/destination_card.dart'; import 'package:flutter/material.dart'; -Widget singleDestination(BuildContext context, String title, String description, String image) { + +List loadDestinations() { + List cities = [ + singleDestination( + "New York", + "The Big Apple", + "https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/View_of_New_York_City.jpg/800px-View_of_New_York_City.jpg" + ), + singleDestination( + "Los Angeles", + "City of Angels", + "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/Los_Angeles_City_Hall_2013.jpg/800px-Los_Angeles_City_Hall_2013.jpg" + ), + singleDestination( + "Chicago", + "The Windy City", + "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6f/Chicago_skyline%2C_viewed_from_John_Hancock_Center.jpg/800px-Chicago_skyline%2C_viewed_from_John_Hancock_Center.jpg" + ), + singleDestination( + "San Francisco", + "The Golden City", + "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/San_Francisco_City_Hall_2013.jpg/800px-San_Francisco_City_Hall_2013.jpg" + ), + singleDestination( + "Miami", + "The Magic City", + "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Miami_collage.jpg/800px-Miami_collage.jpg" + ), + singleDestination( + "Las Vegas", + "Sin City", + "https://upload.wikimedia.org/wikipedia/commons/thumb/6/6e/Las_Vegas_Strip.jpg/800px-Las_Vegas_Strip.jpg" + ), + singleDestination( + "Seattle", + "Emerald City", + "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2f/Seattle_Kerry_Park_Skyline.jpg/800px-Seattle_Kerry_Park_Skyline.jpg" + ), + singleDestination( + "Boston", + "Beantown", + "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0f/Boston_skyline_from_Longfellow_Bridge_September_2017_panorama_2.jpg/800px-Boston" + ) + ]; + cities.shuffle(); + return cities; +} + +Widget singleDestination(String title, String description, String image) { return Card( child: ListTile( leading: Icon(Icons.location_on), title: Text(title), subtitle: Text(description), onTap: () { - Navigator.pushNamed(context, '/destination'); + // Navigator.pushNamed(context, '/destination'); }, ), ); diff --git a/lib/modules/overview.dart b/lib/modules/overview.dart index 7d6c0ed..ff03b9b 100644 --- a/lib/modules/overview.dart +++ b/lib/modules/overview.dart @@ -1,14 +1,74 @@ import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:sliding_up_panel/sliding_up_panel.dart'; +import 'package:latlong2/latlong.dart'; +import 'package:geocoding/geocoding.dart'; +import 'package:geocode/geocode.dart'; +import 'dart:async'; + import 'package:fast_network_navigation/modules/navigation.dart'; class MapPage extends StatefulWidget { @override _MapPageState createState() => _MapPageState(); } +class Debounce { + Duration delay; + Timer? _timer; + + Debounce( + this.delay, + ); + + call(void Function() callback) { + _timer?.cancel(); + _timer = Timer(delay, callback); + } + + dispose() { + _timer?.cancel(); + } +} + class _MapPageState extends State { + GeoCode geoCode = GeoCode(); + final mapController = MapController(); + String _currentCityName = "..."; + final Debounce _debounce = Debounce(Duration(seconds: 3)); + + void _setCurrentCityName() async { + if (mapController.camera.zoom < 9) { + return; // Don't bother if the view is too wide + } + var currentCoordinates = mapController.camera.center; + String? city; + + try{ + List placemarks = await placemarkFromCoordinates(currentCoordinates.latitude, currentCoordinates.longitude); + city = placemarks[0].locality.toString(); + } catch (e) { + debugPrint("Error: $e"); + try { + Address address = await geoCode.reverseGeocoding(latitude: currentCoordinates.latitude, longitude: currentCoordinates.longitude); + + if (address.city == null || address.city.toString().contains("Throttled!")){ + throw Exception("Probably rate limited"); + } + city = address.city.toString(); + } catch (e) { + debugPrint("Error: $e"); + + } + } + if (city != null) { + setState(() { + _currentCityName = city!; + }); + } else { + _debounce(() async {_setCurrentCityName();}); + } + } @override Widget build(BuildContext context) { @@ -18,8 +78,15 @@ class _MapPageState extends State { panel: _floatingPanel(theme), collapsed: _floatingCollapsed(theme), body: FlutterMap( + mapController: mapController, options: MapOptions( initialZoom: 11, + initialCenter: LatLng(51.509364, -0.128928), + onMapReady: () { + mapController.mapEventStream.listen((evt) {_debounce(() async {_setCurrentCityName();});}); + // And any other `MapController` dependent non-movement methods + }, + ), children: [ openStreetMapTileLayer, @@ -59,14 +126,7 @@ class _MapPageState extends State { children: [ Greeting(theme), Text("Got a lot to do today! Here is a rundown:"), - singleDestination(context, "Location 1", "some description", "Further information"), - singleDestination(context, "Location 2", "some description", "Further information"), - singleDestination(context, "Location 3", "some description", "Further information"), - singleDestination(context, "Location 4", "some description", "Further information"), - singleDestination(context, "Location 5", "some description", "Further information"), - singleDestination(context, "Location 6", "some description", "Further information"), - singleDestination(context, "Location 7", "some description", "Further information"), - singleDestination(context, "Location 8", "some description", "Further information"), + ...loadDestinations(), ], ), ), @@ -78,7 +138,7 @@ class _MapPageState extends State { Widget Greeting (ThemeData theme) { return Center( child: Text( - "Explore Kview", + "Explore ${_currentCityName}", style: TextStyle(color: theme.primaryColor, fontSize: 24.0, fontWeight: FontWeight.bold), ), ); diff --git a/lib/structs/destination.dart b/lib/structs/destination.dart new file mode 100644 index 0000000..bb8d086 --- /dev/null +++ b/lib/structs/destination.dart @@ -0,0 +1,31 @@ + +class Destination { + final double latitude; + final double longitude; + final String name; + final String description; + final DestinationType type; + final Duration duration; + final bool visited; + + Destination({ + required this.latitude, + required this.longitude, + required this.name, + required this.description, + required this.type, + required this.duration, + required this.visited, + }); +} + + +class DestinationType { + final String name; + final String description; + + DestinationType({ + required this.name, + required this.description, + }); +} diff --git a/pubspec.lock b/pubspec.lock index e8a2cb6..b88a8ef 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -83,6 +83,46 @@ packages: description: flutter source: sdk version: "0.0.0" + geocode: + dependency: "direct main" + description: + name: geocode + sha256: cf9727c369bb3703b97d6e440225962dc27b7f3c686662fe3cdcc91cbfb7074d + url: "https://pub.dev" + source: hosted + version: "1.0.3" + geocoding: + dependency: "direct main" + description: + name: geocoding + sha256: d580c801cba9386b4fac5047c4c785a4e19554f46be42f4f5e5b7deacd088a66 + url: "https://pub.dev" + source: hosted + version: "3.0.0" + geocoding_android: + dependency: transitive + description: + name: geocoding_android + sha256: "1b13eca79b11c497c434678fed109c2be020b158cec7512c848c102bc7232603" + url: "https://pub.dev" + source: hosted + version: "3.3.1" + geocoding_ios: + dependency: transitive + description: + name: geocoding_ios + sha256: "94ddba60387501bd1c11e18dca7c5a9e8c645d6e3da9c38b9762434941870c24" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + geocoding_platform_interface: + dependency: transitive + description: + name: geocoding_platform_interface + sha256: "8c2c8226e5c276594c2e18bfe88b19110ed770aeb7c1ab50ede570be8b92229b" + url: "https://pub.dev" + source: hosted + version: "3.2.0" http: dependency: transitive description: @@ -108,7 +148,7 @@ packages: source: hosted version: "0.19.0" latlong2: - dependency: transitive + dependency: "direct main" description: name: latlong2 sha256: "98227922caf49e6056f91b6c56945ea1c7b166f28ffcd5fb8e72fc0b453cc8fe" @@ -119,26 +159,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.4" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.3" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" lints: dependency: transitive description: @@ -183,10 +223,10 @@ packages: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.12.0" mgrs_dart: dependency: transitive description: @@ -203,6 +243,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" polylabel: dependency: transitive description: @@ -276,10 +324,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" typed_data: dependency: transitive description: @@ -308,10 +356,10 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.1" web: dependency: transitive description: @@ -330,4 +378,4 @@ packages: version: "2.0.0" sdks: dart: ">=3.3.4 <4.0.0" - flutter: ">=3.10.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/pubspec.yaml b/pubspec.yaml index 507aee5..53add6b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ -name: fast_network_navigation -description: "A new Flutter project." +name: "fast_network_navigation" +description: "An interactive city navigator." # 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 @@ -37,6 +37,9 @@ dependencies: cupertino_icons: ^1.0.6 flutter_map: ^6.1.0 sliding_up_panel: ^2.0.0+1 + latlong2: ^0.9.1 + geocoding: ^3.0.0 + geocode: ^1.0.3 dev_dependencies: flutter_test: